The 1000 steps program to MDriven Chapter 15
No edit summary
No edit summary
Line 1: Line 1:
Chapter 15
This is Chapter 15.


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).
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, the system does the assignment roughly at the same time).


Video: https://youtu.be/04ssHZbuZyk
The Chapter 15 video: https://youtu.be/04ssHZbuZyk


462. Create a new method on the car class that GetNewRegistrationNumber():String


462 Create a new method on the car class that GetNewRegistrationNumber():String
463. We are going to 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 so that we can increase it by 1 the next time. We will place this "memory" on SysSingleton in four attributes.


463 We are going to write logic to create a new Registration number in the format ABC123
464. Create new attributes on SysSingleton:
- we want the logic to count upwards - and not give the same number twice
- 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:
RegNumberLetter1Current:Integer?
RegNumberLetter1Current:Integer?
RegNumberLetter2Current:Integer?
RegNumberLetter2Current:Integer?
RegNumberLetter3Current:Integer?
RegNumberLetter3Current:Integer?RegNumberNumberPartCurrent: 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
465. Now watch the video until 20:00. Follow along and write the same code - the resulting code is repeated here. You should be able to understand why it works.


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.
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 and will return 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 RegNumberLetter1Current=65 (A), and for RegNumberLetter2Current and RegNumberLetter3Current  
467. Assign default values and default DB-values RegNumberLetter1Current=65 (A), and for RegNumberLetter2Current and RegNumberLetter3Current.


468 Assign default values and default db-values RegNumberNumberPartCurrent=1
468. Assign default values and default DB-values RegNumberNumberPartCurrent=1


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
469. Ensure that 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
470. Press the play button and go into the debugger with persistence set to MDrivenServer.


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
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
472. Switch the debugger expression to Action and execute self.GetNewRegistrationNumber to see what happens.


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


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
474. Step through the expression. Use the Step Into to get into the code of the method. Familiarise yourself with the debug stepper - it will be used frequently to discover the true logic of what you have.


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


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.
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 errors from the old model.


477 If you have the debugger still up remember to press "Re-read model", this is important for the same reason as above.
477. If you still have the debugger up, remember to press "Re-read model" - this is important for the same reason as above.


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
478. Use a search window to find a car and drag in a self on the green dot to the expression - then execute 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 reach Z and continue to watch the second letter reach Z. Cancel the changes when you are done.
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 22 minutes into the video ===
=== Chapter 15, Part 2: The SysAsyncTicket (Starts at about 22 minutes into the video) ===
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
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
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 , 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
482. Now open another browser as another Chrome user, 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. Press NewCar in both apps. Notice that they are given the same number - 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 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...
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 still 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 this and merge it into your model
484. Now go to the Wiki and find the merge model for SysAsyncTicket. Download this and merge it into your model.


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
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)
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 same signature - and this is the effect that we are after
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 - run the app again - create a new car - save - wait for the New registrationnumber to come back from the server
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
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 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)
490. Familiarise yourself with the MDrivenServer by logging into its admin UI - a 1234, http://localhost:5000 (or the port you have in the Cloud-connect dialog).


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)
491. Head back to the 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 that's true everywhere this is shown in the UI (switching to IsStatic would also work).


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.
492. Find the RegistrationNumber attribute and click on 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 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]]
[[File:AfterChapter15.zip|none|thumb]]


[[Category:1000 Steps Program]]
[[Category:1000 Steps Program]]

Revision as of 10:21, 25 January 2023

This is Chapter 15.

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, the system does the assignment roughly at the same time).

The Chapter 15 video: https://youtu.be/04ssHZbuZyk

462. Create a new method on the car class that GetNewRegistrationNumber():String

463. We are going to 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 so that we can 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 and write the same code - the resulting code is repeated 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 and will return 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 RegNumberLetter1Current=65 (A), and for RegNumberLetter2Current and RegNumberLetter3Current.

468. Assign default values and default DB-values RegNumberNumberPartCurrent=1

469. Ensure that 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 "Step" in the debugger.

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

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

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 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 above.

478. Use a search window to find a car and drag in a self on the green dot to the expression - then execute 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 22 minutes into the video)

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.

482. Now open another browser as another Chrome user, 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. Press NewCar in both apps. Notice that they are given the same number - 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 still 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 this 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 by logging into its admin UI - a 1234, http://localhost:5000 (or the port you have in the Cloud-connect dialog).

491. Head back to the 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 that's true everywhere this is shown in the UI (switching to IsStatic would also work).

492. Find the RegistrationNumber attribute and click on 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 and upload the model. Test to create a new car and notice that the RegistrationNumber comes back faster than before.

File:AfterChapter15.zip

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