What is ORM?
Object-relational mapping (ORM) is a mechanism that makes it possible to address, access and manipulate objects without having to consider how those objects relate to their data sources. ORM lets programmers maintain a consistent view of objects over time, even as the sources that deliver them change.
Each ORM object hides and encapsulates changes in the data source, so that when the data source changes, only the ORM needs to be changed to sync up. The applications that use the ORM are then insulated from additional change efforts.
You can read about ORM objects in many places on the Internet. ORM is not a Pattern, it’s actually a technique of managing database rows through an application. Because of this, we can combine ORM with MVC giving our architecture to a new level of abstraction.
The advantages of ORM usage
The main advantage of the use of ORM is the new level of abstraction from the Database representation of the objects. Many times we have an object that represented in a Database is composed of many entities with relationships, as an example an invoice with entities for the header and footer information, and the entity that contains the lines, related with the header by a “one to many relationship”. With ORM we can create an Object that abstracts this relationship and obtain from the database an object called TInvoiceOrm, which has a property Lines, consistent in a generic List of Items of type TInvoiceLineOrm.
We can solicit from a model layer, MyInvoice := FModel.GetInvoice(101); that returns an instance of type TInvoiceOrm that contains the lines encapsulated inside. We can call MyInvoice.Add(Line); and after, call a method Calculate. At last we can, for example, call FModel.SaveInvoice(MyInvoice); or FModel.UpdateInvoice(MyInvoice); or ignore all the changes making MyInvoice.Free;
As we are going to see in the next entries, there are a lot of additional advantages. The use of ORM with MVC provides us with the Magic part of this architecture. In my projects, I associate in a View, an ORM Object with each TreeViewItem. When the user Drags and Drops a TTreeViewItem between forms he is, literally, dragging and Object with all its properties…not a reference! But this is part of the View. Now we are speaking about ORM.
https://bitbucket.org/juanc_cilleruelo/sencillemvc
Remember that the Branch described in this entry is called scORM.
The ORM Generator
We introduce in this branch of code, the first tool. This is an external program that generates the ORM Classes that we need in our program. As we can make this program’s classes independent of the Database used, ORMGenerator is based on the information contained in the TDataSets inside application DataModules. Because of this, its important to generate the TFields of each Dataset at design time.
To accomplish this part, we have created in this episode all the Datamodules that we think are going to be required by the Application.
First version of Northwind application.
We now have the base version of the framework, and a Datamodule for each program module, and at last one ORM class for each one. We can organize these into different folders and construct the seed of our Northwind application.
The application at this point compiles and, if you run it, only shows a main form with no functionality. But in the next post we are going to see how all the pieces fit with the Model Layer.
The Tests!!!!
To complete our implementation of an architecture based on MVC pattern, we want to improve the construct process to accomplish a better final result. What could help produce a better result? I think that code without errors that demonstrates itself that all the functionalities have been proven and then protects these functionalities over the changes made over time. This will produce better and trusted code!
To accomplish all these tasks, we count on help from Automated Unit Tests. These tests are part of our development process, and shall be maintained with the whole of our code. This tests can be executed every time we need to demonstrate that all the functionalities are implemented. If a functionality changes, we should change the tests conveniently as required.
Which parts of the code shall be covered by these types of Tests? My recommendation is clear: Each public method of each Controller and each Model shall have at least one Test.
These types of tests are going to be presented on the next post of this series. Here we present the tests that we will do for this first stage of the application.
If you check the project ORMTest, you can see three tests units:
SmokeTest_DM: contains a set of smoke tests over all Datamodules. Open each DataSet, insert a new item and post it. Edit an existing Item, which will be the current Item, and post it. Finally delete this item. With these tests, we assure a good connection to database for each Dataset, as well as the existence of the TFields at design time, etc.
SmokeTest_ORM: These are a group of very basic tests over each ORM Class in the application. These are similar to the DM tests, but oriented to the ORM Classes.
Test_CategoryORM: This is an almost complete battery of tests over the TCategoryORM class. In these tests, we try to demonstrate that each functionality of this class is created and runs correctly. (I recommend reviewing the code to understand all the tests, and at the same time, the functionality of each).
Why we don’t make a battery of tests like this last, over each ORMClass? Because it’s an automatically generated code! If one of this classes works well, we can assure in the 99.99% of the time, that all the auto-generated classes are going to run with the same correctness.
That’s all at this moment!!!
Next entry of this series: The Model Layer.
Juan Carlos Cilleruelo
Randy Sill (Editor/Collaborator)