The 1000 steps program to MDriven Chapter 15
No edit summary
No edit summary
Tag: 2017 source edit
(36 intermediate revisions by 3 users not shown)
Line 1: Line 1:
Chapter 15
This is '''Chapter 15'''. If you want to go back to the beginning, [[The 1000 steps program to MDriven Chapter 1|you can find it here: Chapter 1.]] Or link to [[The_1000_steps_program_to_MDriven_Chapter_14|Chapter 14.]]


In this chapter we create some methods to assign a new registration number - we then import the SysAsyncTicket model pattern that is recognised by the MDrivenServer. The SysAsyncTicket pattern is a big facilitator when it comes to things that must be serialized - like assigning a new number from a common store. If the assignment is not serialized we will always run the risk of giving the same number to 2 different cars (due to 2 users of our system does assignment roughly the same time).
== Video 15: Importing SysAsyncTicket ==
<html>


Video: https://youtu.be/04ssHZbuZyk
<p class="video-warn">
  To make your experience smooth, we set the main tags mentioned in the video to the right bar menu of this mini-player. Choose an interesting subtitle on the list and immediately get to the exact theme navigation item place in the video. Now you can pick any topic to be instructed on without watching the whole video.
</p>


<div class="video">
  <div class="video__wrapper">
    <iframe src="https://www.youtube.com/embed/04ssHZbuZyk?si=qvPvkt1mRHHdQ5fp" title="YouTube video player" frameborder="0" allowfullscreen></iframe>
  </div>
  <div class="video__navigation">
<span data-video="04ssHZbuZyk" data-start="00" tabindex="0"> <strong> Steps 462 - 492 </strong> </span>
    <span class="navigation-item" data-video="04ssHZbuZyk" data-start="00" tabindex="0"> Introduction </span>
    <span class="navigation-item" data-video="04ssHZbuZyk" data-start="29" tabindex="0"> Create a new method </span>
    <span class="navigation-item" data-video="04ssHZbuZyk" data-start="75" tabindex="0"> Write logic for a new Registration number </span>
    <span class="navigation-item" data-video="04ssHZbuZyk" data-start="1314" tabindex="0"> Upload the model to MdrivenServer </span>
    <span class="navigation-item" data-video="04ssHZbuZyk" data-start="1354" tabindex="0"> Verify the method </span>
    <span class="navigation-item" data-video="04ssHZbuZyk" data-start="2075" tabindex="0"> Merge SysAsyncTicket </span>
    <span class="navigation-item" data-video="04ssHZbuZyk" data-start="2465" tabindex="0"> Upload the model and run the app </span>
  </div>
</div>


462 Create a new method on the car class that GetNewRegistrationNumber():String
</html>


463 We are going to write logic to create a new Registration number in the format ABC123
== Chapter 15: Part 1 - Assign a new registration number ==
- we want the logic to count upwards - and not give the same number twice
'''In this chapter, we create some methods to assign a new registration number and import the SysAsyncTicket model pattern that is recognised by the MDrivenServer.'''
- to enable that we need to remember how the last number was generated so that we can increase by 1 for the next
- We will place this "memory" on SysSingleton in a four attributes


464 Create new attributes on SysSingleton:
* '''The SysAsyncTicket pattern is a major facilitator when it comes to things that must be serialized, like assigning a new number from a common store. If the assignment is not serialized, we will always run the risk of giving the same number to 2 different cars (due to 2 users, the system does the assignment roughly at the same time).'''
RegNumberLetter1Current:Integer?
RegNumberLetter2Current:Integer?
RegNumberLetter3Current:Integer?
RegNumberNumberPartCurrent: Integer?


465 Now watch the video until 20:00 - follow along and write the same code - the resulting code is repeated here - but you should be able to understand why it works
462. Create a new method on the class '''Car''' called <code>GetNewRegistrationNumber():String</code>


466 Follow the discussion on semicolon in the video - semicolon is used to seperate expressions. In OCL (in all functional languages) we must return exactly 1 result (the result can be 1 list - that is still 1 result) - this means that when we want to create a method that does multiple things we need a way to stack multiple expressions together and ignore all the results but the last result. That is what the semicolon does for us. So expr1;expr2 will return result of expr2,  expr1;expr2;expr3 will return result of expr3 and expr1;expr2;expr3; is actually wrong - because we cannot end on a semicolon.
463. We will write logic to create a new Registration number in the format '''ABC123'''. We want the logic to count upwards without giving the same number twice. To enable that, we need to remember how the last number was generated to increase it by 1 the next time. We will place this "memory" on SysSingleton in four attributes.


467 Assign default values and default db-values RegNumberLetter1Current=65 (A), and for RegNumberLetter2Current and RegNumberLetter3Current
464. Create new attributes on SysSingleton:


468 Assign default values and default db-values RegNumberNumberPartCurrent=1
* RegNumberLetter1Current:Integer?
* RegNumberLetter2Current:Integer?
* RegNumberLetter3Current:Integer?
* RegNumberNumberPartCurrent: Integer?
465. Now, '''watch''' the video until '''20:00'''. Follow along with the video and write the same code or find it [[1000 Steps Program: Chapter 15 - Code Snippets|here]]. You should be able to understand why it works.


469 Ensure that your MDrivenServer is running - upload the model to the mdriven server - we expect to see that it evolves the database with the new attributes we added
466. Follow the discussion on '''semicolons''' in the video.


470 Press the play button and go into the debugger - with persistence set to MDrivenServer
* The '''semicolon''' (''';''') is used to separate expressions.
* In OCL (in all functional languages), we must return exactly 1 result (the result can be 1 list - that is, still 1 result).
* This means that when we want to create a method that does multiple things, we need a way to stack multiple expressions together and ignore all the results but the last result. That is what the semicolon does for us. So '''<code>expr1;expr2</code>''' will return a result of '''<code>expr2, expr1;expr2;expr3</code>'''. A result of '''<code>expr3</code>''' and '''<code>expr1;expr2;expr3;</code>''' is actually wrong - because we ''cannot'' end on a semicolon.


471 Open a debugger search win for Cars, search , drag the first car onto a expressions-green-dot in the debugger - we do this to give "self" the value of the car in the debugger expression
467. Assign default values and default DB-values “'''=65'''”.


472 Switch the debugger expression to Action and execute self.GetNewRegistrationNumber to see what happens
* RegNumberLetter1Current=65
* RegNumberLetter2Current=65
* RegNumberLetter3Current=65
* Set the InitialValue for all three to “65” as well.


473 Discover that the method does not behave a s we expect. Start the expression with "Step" in the debugger.
468. Assign InitialValue to the NumberPart: '''RegNumberNumberPartCurrent=1'''.


474 Step through the expression. Use the Step Into to get into the code of the method. Familiar yourself with the debug stepper - it will be used frequently to discover the true logic of what you have
469. Ensure your MDrivenServer is running. Upload the model to the MdrivenServer. We expect to see that it evolves the database with the new attributes we added.


475 Watch the video to (around 26 minutes in) to see that you understand the issue - then correct the method
470. Press the play button and go into the debugger with persistence set to MDrivenServer.


476 Once corrected we upload the model again. It is important that the Server is given the latest model - or it will continue to have the errors from the old model.
471. Open a debugger search window for Cars, search, and drag the first car onto an Expressions green dot in the debugger (we do this to give "self" the value of the car in the debugger expression).


477 If you have the debugger still up remember to press "Re-read model", this is important for the same reason as above.
472. Switch the debugger expression to Action and execute <code>self.GetNewRegistrationNumber</code> to see what happens.


478 Use a search win to find a car and drag in a self on the green dot to the expression - then execute the self.GetNewRegistrationNumber again
473. Discover that the method does not behave as we expect. Start the expression with the "'''Step'''" function in the debugger.


479 Verify that it now works better - press F5 to execute and hold it down to loop execute - see what happens when the first letter reach Z and continue to watch the second letter reach Z. Cancel the changes when you are done.
474. Press '''Start''' to step through the expression. Use the '''Step into''' to get into the code of the method. Familiarise yourself with the OCL stepper - it will be used frequently to discover the true logic of what you have.


=== Chapter 15, part 2 , the SysAsyncTicket, starts at about 22 minutes into the video ===
475. '''Watch''' the video up to '''26 minutes''' to see that you understand the issue - then correct the method.
480 In the State BrandNew for Car (in the StateDiagram for Car) add an entry action that assigns the RegistrationNumber property a value from our method GetNewRegistrationNumber


481 Save and upload the model to MDrivenServer, use a browser to check your application, create a new car and see that it gets a new registration number
476. Once corrected, upload the model again. It is important that the Server is given the latest model, or it will continue to have errors from the old model.


482 Now open another browser as another chrome user , or incognito mode, log in again - you now have two different server contextes. Place the browser next to each other on the screen, both showing the Car-seeker, press NewCar in both apps, Notice they are given the same number -> not good
477. If you still have the debugger up, remember to press "'''Re-Read Model'''" - this is important for the same reason as the above (Step 476).


483 Think about this problem for a minute - it is a common problem in all information systems - we want the system to behave asynchrounsly in 99.9% of the cases so that 1 user is not blocked by another user doing lengthy operations. But in cases like this we still want a serialization of the number generation and assignment to ensure that a confligt never can happen - not even in theory...
478. Use a search window to find a car and drag in a self on the green dot to the expression - then execute (F5) the <code>self.GetNewRegistrationNumber</code> again.


484 Now go to the wiki and find the merge model for SysAsyncTicket - download this and merge it into your model
479. Verify that it now works better. Press F5 to execute and hold it down to loop execute. See what happens when the first letter reaches Z and continue to watch the second letter reach Z. Cancel the changes when you are done.


485 Ensure that your current packages has the SysSuperClass as the defaultsuperclass (meaning that all classes without an explicit superclass will inherit from SysSuperClass) - this is good so that we get access to the method DoAsync that the pattern added for us
== Chapter 15: Part 2 - The SysAsyncTicket (Starts at [https://youtu.be/04ssHZbuZyk?si=Po9L9lrwddjVTZ7K&t=1700 about 28 minutes into the Video]) ==
480. In the State '''BrandNew''' for '''Car''' (in the State Diagram for Car), add an Entry action that assigns the '''RegistrationNumber''' property, a value from our method '''GetNewRegistrationNumber'''.


486 Change the Entry action of Car BrandNew state to self.ActuallyAssignNewNumber and move the old code into this new method instead (you need to create the method on car)
·      Write <code>self.RegistrationNumber:=self.GetNewRegistrationNumber</code>


487 Again change the Entry action to use self.DoAsync('ActuallyAssignNewNumber') instead of calling it directly - this will move the execution to the server - and the server will serialize jobs with same signature - and this is the effect that we are after
481. Save and upload the model to MDrivenServer. Use a browser to check your application. Create a new Car and see that it gets a new Registration Number.


488 Upload the model - run the app again - create a new car - save - wait for the New registrationnumber to come back from the server
482. Now open another browser as another Chrome user ('''b@b.se'''), or in incognito mode, and log in again. You now have two different server contexts. Place the browsers next to each other on the screen, both showing the Car Seeker.


489 Have the two different apps next to each other again - verify that you cannot get the same number on two new cars no matter how hard you try
* '''Note''': the '''b''' user does not have the right to create a New Car. Log in as the '''a''' user ('''a@a.se''') instead.
* Press '''New Car''' in both windows. Notice that they are given the same number - this is not right.


490 Familiar yourself with mdrivenserver by logging into its admin UI - a 1234 , http://localhost:5000 (or the port you have in the Cloud-connect dialog)
483. Think about this problem for a minute.


491 Head back to model and check the "Change by - cross reference" on the RegistrationNumber attribute. We want to limit the manual ability to set this value by setting a read only expression to true everywhere this is shown in the UI (switching to IsStatic would also work)
* It is a common problem in all information systems.
* We want the system to behave asynchronously in 99.9% of the cases so that 1 user is not blocked by another user doing lengthy operations.
* In cases like this, we will want a serialization of the number generation and assignment to ensure that a conflict can never happen - not even in theory.


492 Find the RegistrationNumber attribute and click up the TaggedValues dialog - we want to give this the tag value of Realtime=true - you can read about Realtime here https://wiki.mdriven.net/index.php/SignalR_and_Realtime - save - upload model - test to create a new car and notice that the Registrationnumber comes back faster than before.
484. Now go to the Wiki and find the merge model for [[/wiki.mdriven.net/AsyncTicket|SysAsyncTicket]]. Download and merge it into your model.
[[File:AfterChapter15.zip|thumb]]


485. Ensure that your current packages have the SysSuperClass as the default superclass (meaning that all classes without an explicit superclass will inherit from SysSuperClass). This is good - we get access to the method '''DoAsync''' that the pattern added for us.
486. Change the Entry action of '''Car''' <u>BrandNew</u> state to <code>self.ActuallyAssignNewNumber</code> and move the old code into this new method instead (you need to create the method on Car).  
487. Again, change the Entry action to use <code>self.DoAsync('ActuallyAssignNewNumber')</code> instead of calling it directly. This will move the execution to the Server, and the Server will serialize jobs with the same signature. This is the effect that we are after.
488. Upload the model and run the app again. Create a new car and save. Wait for the new registration number to come back from the Server.
489. Have the two different apps next to each other again. Verify that you cannot get the same number on two new cars no matter how hard you try.
490. Familiarise yourself with the MDrivenServer '''<nowiki>http://localhost:5000</nowiki>''' by logging into its admin UI '''a''', password '''123456''',  (or the port you have in the Cloud-connect dialog).
* Go to <u>Running</u>, then <u>PeriodicActions</u>. Observe the actions that check for SysAsyncTicket and delete old SysAsyncTickets.
* Go to <u>Running</u>, then <u>Data in A0</u>. Click on SysAsyncTicket. Press “Search”. Observe the data for '''Car.ActuallyAssignNewNumber'''. There are no reported issues.
* Go to <u>Running</u>, then <u>WorkInfo</u>. View the different events tracked in the Server.
491. Head back to the model and check the "Changed by - Cross Reference" on the '''RegistrationNumber''' attribute. We want to limit the manual ability to set this value by setting a read-only expression that's true everywhere this is shown in the UI (switching to '''IsStatic''' would also work).
* Click on “ViewModelColumn ProperCarView.RegistrationNumber R/W”
* Select '''RegistrationNumber''' and in the Readonly Expression box, write: '''<code>true</code>'''
* Go back to the model and check the "Changed by - Cross Reference" on the '''RegistrationNumber''' attribute. You’ll find the value shows also on '''TheTemplateForCarTransferOwnershipDocumentReport'''. Click on it.
* In the ViewModel window, press on '''TheTemplateForCarTransferOwnershipDocumentReport''' and set the Readonly Expression to '''true''' to avoid further confusion.
492. Find and select the '''RegistrationNumber''' attribute in '''Car'''. Click on the <u>Tagged Values</u> dialog. We want to give this the tag value of <code>Realtime=true</code>. (Read about Realtime [[Documentation:SignalR and Realtime|here]].)
* In the Tagged Values dialog, press “Refresh From Wiki”. Click on “<Create Empty TV>” and select '''Realtime'''. Close the dialog.
* Save and upload the model.
* Test to create a new car and notice that the '''RegistrationNumber''' comes back faster than before.
[[File:AfterChapter15.zip|none|thumb]]
'''Next Chapter'''
[[The_1000_steps_program_to_MDriven_Chapter_16]]
[[Category:1000 Steps Program]]
[[Category:1000 Steps Program]]

Revision as of 05:18, 22 April 2024

This is Chapter 15. If you want to go back to the beginning, you can find it here: Chapter 1. Or link to Chapter 14.

Video 15: Importing SysAsyncTicket

To make your experience smooth, we set the main tags mentioned in the video to the right bar menu of this mini-player. Choose an interesting subtitle on the list and immediately get to the exact theme navigation item place in the video. Now you can pick any topic to be instructed on without watching the whole video.

Steps 462 - 492 Introduction Create a new method Write logic for a new Registration number Upload the model to MdrivenServer Verify the method Merge SysAsyncTicket Upload the model and run the app

Chapter 15: Part 1 - Assign a new registration number

In this chapter, we create some methods to assign a new registration number and import the SysAsyncTicket model pattern that is recognised by the MDrivenServer.

  • The SysAsyncTicket pattern is a major facilitator when it comes to things that must be serialized, like assigning a new number from a common store. If the assignment is not serialized, we will always run the risk of giving the same number to 2 different cars (due to 2 users, the system does the assignment roughly at the same time).

462. Create a new method on the class Car called GetNewRegistrationNumber():String

463. We will write logic to create a new Registration number in the format ABC123. We want the logic to count upwards without giving the same number twice. To enable that, we need to remember how the last number was generated to increase it by 1 the next time. We will place this "memory" on SysSingleton in four attributes.

464. Create new attributes on SysSingleton:

  • RegNumberLetter1Current:Integer?
  • RegNumberLetter2Current:Integer?
  • RegNumberLetter3Current:Integer?
  • RegNumberNumberPartCurrent: Integer?

465. Now, watch the video until 20:00. Follow along with the video and write the same code or find it here. You should be able to understand why it works.

466. Follow the discussion on semicolons in the video.

  • The semicolon (;) is used to separate expressions.
  • In OCL (in all functional languages), we must return exactly 1 result (the result can be 1 list - that is, still 1 result).
  • This means that when we want to create a method that does multiple things, we need a way to stack multiple expressions together and ignore all the results but the last result. That is what the semicolon does for us. So expr1;expr2 will return a result of expr2, expr1;expr2;expr3. A result of expr3 and expr1;expr2;expr3; is actually wrong - because we cannot end on a semicolon.

467. Assign default values and default DB-values “=65”.

  • RegNumberLetter1Current=65
  • RegNumberLetter2Current=65
  • RegNumberLetter3Current=65
  • Set the InitialValue for all three to “65” as well.

468. Assign InitialValue to the NumberPart: RegNumberNumberPartCurrent=1.

469. Ensure your MDrivenServer is running. Upload the model to the MdrivenServer. We expect to see that it evolves the database with the new attributes we added.

470. Press the play button and go into the debugger with persistence set to MDrivenServer.

471. Open a debugger search window for Cars, search, and drag the first car onto an Expressions green dot in the debugger (we do this to give "self" the value of the car in the debugger expression).

472. Switch the debugger expression to Action and execute self.GetNewRegistrationNumber to see what happens.

473. Discover that the method does not behave as we expect. Start the expression with the "Step" function in the debugger.

474. Press Start to step through the expression. Use the Step into to get into the code of the method. Familiarise yourself with the OCL stepper - it will be used frequently to discover the true logic of what you have.

475. Watch the video up to 26 minutes to see that you understand the issue - then correct the method.

476. Once corrected, upload the model again. It is important that the Server is given the latest model, or it will continue to have errors from the old model.

477. If you still have the debugger up, remember to press "Re-Read Model" - this is important for the same reason as the above (Step 476).

478. Use a search window to find a car and drag in a self on the green dot to the expression - then execute (F5) the self.GetNewRegistrationNumber again.

479. Verify that it now works better. Press F5 to execute and hold it down to loop execute. See what happens when the first letter reaches Z and continue to watch the second letter reach Z. Cancel the changes when you are done.

Chapter 15: Part 2 - The SysAsyncTicket (Starts at about 28 minutes into the Video)

480. In the State BrandNew for Car (in the State Diagram for Car), add an Entry action that assigns the RegistrationNumber property, a value from our method GetNewRegistrationNumber.

·      Write self.RegistrationNumber:=self.GetNewRegistrationNumber

481. Save and upload the model to MDrivenServer. Use a browser to check your application. Create a new Car and see that it gets a new Registration Number.

482. Now open another browser as another Chrome user (b@b.se), or in incognito mode, and log in again. You now have two different server contexts. Place the browsers next to each other on the screen, both showing the Car Seeker.

  • Note: the b user does not have the right to create a New Car. Log in as the a user (a@a.se) instead.
  • Press New Car in both windows. Notice that they are given the same number - this is not right.

483. Think about this problem for a minute.

  • It is a common problem in all information systems.
  • We want the system to behave asynchronously in 99.9% of the cases so that 1 user is not blocked by another user doing lengthy operations.
  • In cases like this, we will want a serialization of the number generation and assignment to ensure that a conflict can never happen - not even in theory.

484. Now go to the Wiki and find the merge model for SysAsyncTicket. Download and merge it into your model.

485. Ensure that your current packages have the SysSuperClass as the default superclass (meaning that all classes without an explicit superclass will inherit from SysSuperClass). This is good - we get access to the method DoAsync that the pattern added for us.

486. Change the Entry action of Car BrandNew state to self.ActuallyAssignNewNumber and move the old code into this new method instead (you need to create the method on Car).  

487. Again, change the Entry action to use self.DoAsync('ActuallyAssignNewNumber') instead of calling it directly. This will move the execution to the Server, and the Server will serialize jobs with the same signature. This is the effect that we are after.

488. Upload the model and run the app again. Create a new car and save. Wait for the new registration number to come back from the Server.

489. Have the two different apps next to each other again. Verify that you cannot get the same number on two new cars no matter how hard you try.

490. Familiarise yourself with the MDrivenServer http://localhost:5000 by logging into its admin UI a, password 123456,  (or the port you have in the Cloud-connect dialog).

  • Go to Running, then PeriodicActions. Observe the actions that check for SysAsyncTicket and delete old SysAsyncTickets.
  • Go to Running, then Data in A0. Click on SysAsyncTicket. Press “Search”. Observe the data for Car.ActuallyAssignNewNumber. There are no reported issues.
  • Go to Running, then WorkInfo. View the different events tracked in the Server.

491. Head back to the model and check the "Changed by - Cross Reference" on the RegistrationNumber attribute. We want to limit the manual ability to set this value by setting a read-only expression that's true everywhere this is shown in the UI (switching to IsStatic would also work).

  • Click on “ViewModelColumn ProperCarView.RegistrationNumber R/W”
  • Select RegistrationNumber and in the Readonly Expression box, write: true
  • Go back to the model and check the "Changed by - Cross Reference" on the RegistrationNumber attribute. You’ll find the value shows also on TheTemplateForCarTransferOwnershipDocumentReport. Click on it.
  • In the ViewModel window, press on TheTemplateForCarTransferOwnershipDocumentReport and set the Readonly Expression to true to avoid further confusion.

492. Find and select the RegistrationNumber attribute in Car. Click on the Tagged Values dialog. We want to give this the tag value of Realtime=true. (Read about Realtime here.)

  • In the Tagged Values dialog, press “Refresh From Wiki”. Click on “<Create Empty TV>” and select Realtime. Close the dialog.
  • Save and upload the model.
  • Test to create a new car and notice that the RegistrationNumber comes back faster than before.

File:AfterChapter15.zip

Next Chapter

The_1000_steps_program_to_MDriven_Chapter_16

This page was edited 1 days ago on 05/16/2024. What links here