Log in

The 1000 steps program to MDriven Chapter 15

From MDrivenWiki

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_MDrivenEducationVideo:

Chapter 15: Part 1

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

462. Create a new method on the car class called 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.

(insert code)

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

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 - 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 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 password 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. Read about Realtime here:

  • Save and upload the model.
  • Test to create a new car and notice that the RegistrationNumber comes back faster than before.

Next Chapter