One of the interesting types of programming is tracking behaviour. Most enterprise design patterns are about structure. For example, the Data Source Layer patterns introduced in lecture L08 are structural patterns. They deal with moving data to and from the database. They try to solve the impedance mismatch problem. However, they do not have any logic as to when and under what circumstances data should be loaded to from the database and when written. Clearly accessing the database is slow, and doing so needlessly hurts performance. This is where behavioral programming comes in.
Consider the problem of maintaining multiple objects in memory and working with them. Having updated them we need to persist them back. One way to do this is to load the object from the database, change them, then persist them again. Clearly that is easy to do and avoids any possible errors, for example forgetting to save the object back. Most request-response sites would do it like this. But what if you want to keep the objects in memory and write them to the database when the session is over? One way is to just flush everything out to the database but that does not take into account that many of the objects might not have changed. Then how would we keep track of objects that are changed and those that are not. The solution is to use Unit of Work design pattern.
The Unit of Work (UoW) pattern defines a data structure that keeps track of objects and their state. When an object is loaded, it is registered as clean within the UoW. Any update to the object and the status is changed to dirty. When time comes to save objects, the UofW knows which objects are changed and can save them to the database.
Another problem is due to loading of multiple objects. Let’s say you need to load objects and it may happen that the same object is loaded twice. This can cause multiple of problems, not only space and time complexity but also the risk of concurrency problems as two or more objects might be updated in memory with different updates. To solve this we can use Identity Map (IM), a data structure that holds all objects loaded. Whenever an object is needed we can consult the IM, get it there, but if it is not there, get it from the database and put it in the IM. Clearly combining the UoW and IM is a good choice. As a bonus, the IM works as a cache as objects that are needed multiple of times, are already in memory.
The third problem is with loading objects that have references to other objects. So if you load an orders object (to take the classical example) should you load the customer object also since the order object has a reference to the customer. One way to solve this is not to have object references to other objects in general but use ids and keep each object separate. However, we find ourselves with a solution which has a rich object graph and we need to solve this loading problem. This is where the design pattern Lazy Load (LL) comes in handy. With LL we place markers in the object indicating that the reference is not loaded, but when a get method is called, we will load the referred object and change the marker to indicate that the object is loaded.
In lecture L09 Behavioural Programming we look at these behavioural problem. How to solve issues like writing only changed record back into the database, loading only the needed data once, and how to load the data model partially. We introduce the three design patterns mentioned: Unit of Work, Identity Map and Lazy Load.