📜 ⬆️ ⬇️

Paradigms of programming. Data Driven vs Domain Driven

Information technologies are developing in leaps and bounds, new devices, platforms, operating systems are emerging, and with it the range of tasks that developers have to solve grows. But, not everything is so bad - new development tools, ide'shiki, new programming languages, methodologies, etc. are rushing to help programmers. The list of programming paradigms alone is impressive, and taking into account modern multi-paradigm PL (for example, C #), the question is reasonable: “How to deal with all this? What to choose?".

Let's try to understand a little.

Where did so many paradigms come from?


In fact, the answer has already sounded in this post - different types of tasks are easier and faster to solve using the appropriate paradigms. Accordingly, with the development of IT, new types of tasks appeared (or old ones became relevant), and solving them using the old approaches was inconvenient, which entailed rethinking and the emergence of new techniques.

What to choose?


It all depends on what needs to be done. It is worth noting that all development tools are different, some support one, others support another. For example, PHP with a “standard” set of modules does not support aspect-oriented programming . Therefore, the choice of methodology is quite closely related to the development platform. Well, and do not forget that you can combine different approaches, which leads us to the choice of a stack of paradigms.
')
To categorize paradigms, I use 4 dimensions that are inherent in almost any task:


You can go further and delve into this idea: come up with qualitative characteristics for these four measures, add strict rules and a bit of mathematics, but this is perhaps a topic for a separate post. I think most system architects define these characteristics for a specific task based on their knowledge and experience.

After you analyze your task on these 4 dimensions, you will most likely see that a certain dimension is more pronounced than the rest. And this, in turn, will make it possible to determine the programming paradigm, since they are usually aimed at a single dimension.

Consider examples:


And what in practice?


In our company, we are developing business applications (startups, web services, websites, application programs, etc.), so we’ll talk further about programming paradigms that are found both in our practice and in other teams working in this field.

Based on my experience, I can say that in this area two approaches prevail: data orientation (Data Driven) and logic orientation (Domain Driven). In fact, they are competing methodologies, but in practice they can be combined in symbiosis, which are often known anti-patterns.

One of the advantages of Data Driven compared to Domain Driven is its ease of use and implementation. Therefore, Data Drivens begin to be used wherever you need to apply Domain Driven (and often this happens unconsciously). The problems arise from the fact that Data Driven is poorly compatible with the concepts of object-oriented programming (of course, if you use OOP at all). On small applications, these problems are almost imperceptible. On medium-sized applications, these problems are already noticeable and are beginning to lead to anti-patterns, well, and on large projects, the problems become serious and require appropriate measures.

In turn, Domain Driven is advantageous on large projects, and on small projects it complicates the solution and requires more resources for development, which is often critical from the business point of view (bring the project to the asap market, for a small budget).

In order to understand the difference in approaches, we consider a more specific example. Suppose we need to develop an order accounting system. We have such entities as:


Having decided that we have a clear context, we begin to design a database. We create the corresponding tables, run the ORM, generate the entity classes (well, or in the case of the smart orm, we prescribe the scheme somewhere separately, for example, in xml, and already generate the base and the essence classes from it). As a result, we obtain for each entity a separate, independent class. We rejoice in life, work with objects is easy and simple.

Time passes, and we need to add additional logic to the program - for example, to find the goods with the highest price from the order. There may already be problems if your orm does not support external relations (i.e., entity classes do not know anything about the data context), in this case, you will have to create a service in which there will be a method - to return the required product on an order. But, our orm is good, can work with external relations, and we simply add a method to the order class. We enjoy life again, the goal has been achieved, a method has been added to the class, we have almost the real PLO.

Time passes, and we need to add the same method for the quota, for the invoice and for other similar entities. What to do? We can simply register this method in all classes, but this will, in fact, duplicate code and backfire with support and testing. We do not want to complicate and simply copy the method to all classes. Then similar methods appear, the entity classes begin to swell with the same code.

Time passes, and logic appears, which cannot be described by external links in the database, and therefore it is not possible to place it in the essential classes. We are starting to create services that perform these functions. As a result, we find that the business logic is scattered throughout the essential classes and services; it is becoming increasingly difficult to understand where to look for the desired method. We decide to refactor and render, for example, repetitive code to services — select the general functionality of the interface (for example, we make the interface IProductable, that is, something that contains products), services can work with these interfaces, thereby winning a little in abstraction. But fundamentally this does not solve the problem, we get more methods in services and decide for the unity of the picture to transfer all the methods from the essential classes to the services. Now we know where to look for methods, but our essential classes are deprived of all logic, and we got the so-called “Anemic Model” (Anemic Model).

At this stage, we completely left the concept of OOP - objects store only data, all logic is in separate classes, neither encapsulation nor inheritance.

It is worth noting that this is not as bad as it may seem - nothing prevents to introduce unit testing, and indeed development through testing, implement dependency management patterns, etc., in general, you can live with it. Problems will arise when the application grows into a large one, when there are so many entities that it is impossible to keep them in mind, and there is no need to talk about interaction. In this case, the support and development of such an application will become a problem.

As you may have guessed, this scenario describes the use of the Data Driven approach and its problems.
In the case of Domain Driven, we would do the following. First, about any design of the database at the first stage of speech would not go. We would need to carefully analyze the contextual area of ​​the problem, model it and transfer it to the PLO language.

For example, we can create an abstract document model that has a set of basic properties. Inherit from it a document that has products, inherit a “payment” document from it, with a price and billing address, and so on. With this approach, add a method that gets the most expensive product, it is easy - we just add it to the appropriate base class.

As a result, the contextual area of ​​the task will be described using OOP to its fullest.
But there are obvious problems: how to save data in the database? Actually, for this, you will need to create functionality for mepping data from our models onto fields in the database. Such meppers can be quite complex, and as models change, meppers will have to be changed.

Moreover, you are not insured against modeling errors, which can lead to complex refactoring.

So, let's summarize the Data Driven vs Domain Driven:
Data Driven :


Domain Driven:


So, what the hell should I choose?


Unfortunately, there is no definite answer. Analyze your problem, your resources, development prospects, goals and objectives. The right choice is always a compromise.

Source: https://habr.com/ru/post/158277/


All Articles