Business objects
I want to understand and discuss how profitable "domain model» ( the Domain Model ) architecture WEB-applications (eg PHP), from a different point of view. What shortcomings, advantages you see in it and what can be opposed to it.
A business object ( Business Object ), this is such an object in the OOP, which represent a certain entity from a particular "domain", that is, the industry for which the application is developed. For example, for an accounting program, objects can be:
Typically, business objects encapsulate data and complex logic, so the class interface almost reflects reality. This approach to programming is also called "domain model» ( the Domain Model ), and in it there is of opposites ORM paradigm and Database-centric architecture and a whole approach to the development of architecture, based on a technology and not a business model.
Why am I using the Domain Model and not using the Database-centric architecture and similar approach?
Especially at the "highest level". There is no difference at the method level, usually a separate method of a business object is a rather complicated logic, for example, making a payment or setting an auction bid, however even in this case there is no need to keep in mind something other than a specific problem (base structure, payment interface systems).
In the application (in the controllers), everything looks clear and is read almost humanly:
$ payment = Payment :: makeNew ($ contractor, $ amount);
$ invoice = $ contractor-> lastInvoice ();
$ invoice-> markSettled ($ payment);
Who needs this? Imagine that after 2-3 months you needed to make changes, or a bug was discovered. After all, the user will not tell you “I have a bug in the method that is responsible for payments. this is most likely due to the database. ” no, he will say, “payment doesn’t go through with me”. And you know where to look for the problem (at least where to start - from the controller). And if he (the user) says: “my account amounts are rounded up incorrectly”, you again know where to go - you don’t need to go to the controller - the matter is the method responsible for “total”.
This is especially beneficial when a new person comes to the project.
Of course, there is a nuance here - reuse can only be when a new application is being developed from the same “domain”. For example, a properly designed Invoice class is unlikely to need to be changed much in a new application. Of course, the same is true for other approaches. It is even possible to a fuller extent, however, if “utilitarian” classes such as Profile, Form are successfully developed, developed with a “Domain Model” (in this case, the “domain” is “WEB, Server Side Application”), their reuse it will also be almost 100% and will not depend on the main business domain.
The code is surprisingly “non-conflict”, both from the point of view of the programming language, and from the point of view of the programmer as a person. Provided that all components are based on the Bussness Model. If, for example, you need to "cross" the auction and the store, then the Payment class will remain common for them, and the Product class will most likely become a "lot" for the auction. Class prefixes are needed only when you need to create a specific class, say FastshopProduct, while related classes will still accept an object of such a class as a parameter if it inherits from Product and interacts with it.
The problem here arises when you need to use third-party code. And most often you have to modify the supporter classes so that everything is “smooth”.
Indeed, if classes, methods and variables are named “humanly” and not somehow “user_data”, you rarely need to resort to comments in the code. In general, I try not to overload the code with unnecessary comments. If the method returns an object of the Profile class, there is no need to write "the method returns the profile" - this is so visible.
If you really need it, you can generate documentation based on code. And, again, a novice will be able to figure it out faster, because various BaseObject, BaseDbRow, user_data and all that will not “flash before his eyes”. Knowing what the project is about (the “domain” of the project) it is easier for the programmer to delve into the abstraction.
Of course, there is, as they say, in this barrel and a spoon. If each object encapsulates everything in itself, including data (and this is the main distinguishing feature of this model), then, for example, when displaying, for example, the search results, each object reads itself from the database independently, as a result, on the page, depending on the situation, there may be hundreds and more requests. Personally, I do not see tragedy in this, with this, of course, something needs to be done. Simple caching allows you to speed up everything by an order of magnitude.
A business object ( Business Object ), this is such an object in the OOP, which represent a certain entity from a particular "domain", that is, the industry for which the application is developed. For example, for an accounting program, objects can be:
- invoice
- Payment
- counterparty (Contractor)
- Posting
Typically, business objects encapsulate data and complex logic, so the class interface almost reflects reality. This approach to programming is also called "domain model» ( the Domain Model ), and in it there is of opposites ORM paradigm and Database-centric architecture and a whole approach to the development of architecture, based on a technology and not a business model.
Why am I using the Domain Model and not using the Database-centric architecture and similar approach?
The code is much clearer
Especially at the "highest level". There is no difference at the method level, usually a separate method of a business object is a rather complicated logic, for example, making a payment or setting an auction bid, however even in this case there is no need to keep in mind something other than a specific problem (base structure, payment interface systems).
In the application (in the controllers), everything looks clear and is read almost humanly:
$ payment = Payment :: makeNew ($ contractor, $ amount);
$ invoice = $ contractor-> lastInvoice ();
$ invoice-> markSettled ($ payment);
Who needs this? Imagine that after 2-3 months you needed to make changes, or a bug was discovered. After all, the user will not tell you “I have a bug in the method that is responsible for payments. this is most likely due to the database. ” no, he will say, “payment doesn’t go through with me”. And you know where to look for the problem (at least where to start - from the controller). And if he (the user) says: “my account amounts are rounded up incorrectly”, you again know where to go - you don’t need to go to the controller - the matter is the method responsible for “total”.
This is especially beneficial when a new person comes to the project.
Code reuse
Of course, there is a nuance here - reuse can only be when a new application is being developed from the same “domain”. For example, a properly designed Invoice class is unlikely to need to be changed much in a new application. Of course, the same is true for other approaches. It is even possible to a fuller extent, however, if “utilitarian” classes such as Profile, Form are successfully developed, developed with a “Domain Model” (in this case, the “domain” is “WEB, Server Side Application”), their reuse it will also be almost 100% and will not depend on the main business domain.
No conflict
The code is surprisingly “non-conflict”, both from the point of view of the programming language, and from the point of view of the programmer as a person. Provided that all components are based on the Bussness Model. If, for example, you need to "cross" the auction and the store, then the Payment class will remain common for them, and the Product class will most likely become a "lot" for the auction. Class prefixes are needed only when you need to create a specific class, say FastshopProduct, while related classes will still accept an object of such a class as a parameter if it inherits from Product and interacts with it.
The problem here arises when you need to use third-party code. And most often you have to modify the supporter classes so that everything is “smooth”.
The code is self-documenting
Indeed, if classes, methods and variables are named “humanly” and not somehow “user_data”, you rarely need to resort to comments in the code. In general, I try not to overload the code with unnecessary comments. If the method returns an object of the Profile class, there is no need to write "the method returns the profile" - this is so visible.
If you really need it, you can generate documentation based on code. And, again, a novice will be able to figure it out faster, because various BaseObject, BaseDbRow, user_data and all that will not “flash before his eyes”. Knowing what the project is about (the “domain” of the project) it is easier for the programmer to delve into the abstraction.
Of course, there is, as they say, in this barrel and a spoon. If each object encapsulates everything in itself, including data (and this is the main distinguishing feature of this model), then, for example, when displaying, for example, the search results, each object reads itself from the database independently, as a result, on the page, depending on the situation, there may be hundreds and more requests. Personally, I do not see tragedy in this, with this, of course, something needs to be done. Simple caching allows you to speed up everything by an order of magnitude.