OO vs. Layered; balancing the "purity of OO" with the implementation

I believe in OO, but not to the extent that inappropriate constructs / implementations should only be used to be “OO compatible”.

So, how to work with the tiered Serlvet / EJB / DataContainer architecture:

  • Servlets receive requests and invoke a "business layer" (such as an EJB session).
  • The business layer finds and manages DataContainers from the database to implement the business logic.
  • DataContainers do not contain real code, just get / install the appropriate database.

This approach has an appeal; DataContainers are understandable in what they do, and it is very easy to know where the data comes from.

Besides being non-OO, this leads to fuzzy Business Layer classes that are hard to name and hard to organize.

Even if we were trying to be more "OO" (for example, by putting some of these methods in DataConatiners), some of these operations work with more than one data set.

How do you keep your business layer from procedural confusion but not polluting your DataContainers with business logic?

Example

class UserServlet { handleRequest() { String id = request.get("id"); String name = request.get("name"); if (UserBizLayer.updateUserName(id,name)) response.setStatus(OK); else response.setStatus(BAD_REQUEST); } } class UseBizLayer { updateUserName(String id, String name) { long key = toLong(id); user = userDAO.find(key); if user == null return false; if (!validateUserName(name)) return false; user.setName(name); userDAO.update(user); return true; } validateUserName(String name) { // do some validations and return } } class User { long key; String name; String email; // imagine getters/setters here } 
  • We do not want validateUserName for the user, since it only works with the name; I suppose this might go into another class, but then we have another procedural class "uti"
  • We do not need retention methods for the user, as there is value in decoupling data structures from their retention strategy.
  • We do not need the business logic in our Servlet, as we may need to reuse this logic elsewhere
  • We do not want our business logic to be in our User, as this is too complicated for the User class, which makes it difficult to reuse the business logic and associates the user with his retention strategy.

I understand that this example is not so bad, but imagine 10 DataContainers and 20 BizLayer objects in several ways. Imagine that some of these operations are not “centered” on a particular data container.

How do we keep this from a procedural mess?

+4
source share
6 answers

Therefore, I will consider my thoughts on this subject in several points:

  • It seems that at some point in the Java EE system you have to deal with Java EE plumbing, plumbing does not always benefit from OO concepts, but it certainly can evolve and work a little. For example, you could take advantage of things like AbstractFactory, etc., to help make the most of this infrastructure.
  • What you're watching is discussed in Eric Evans' excellent book, Domain Driven Design. I highly recommend that you take a look at it, as it solves the problem of expressing domain knowledge and deals with the technical infrastructure to support it.
  • After reading and putting aside part of the DDD, I encapsulate my technical infrastructure in the repository. All repositories will be written to use a persistence strategy based on your session EJBs. You should write a standard implementation that knows how to talk to your EJBS session. To do this, you need to add a little symbol and indicate the agreement / contract on your interfaces. Repositories do all CRUD and should only do more if absolutely necessary. If you said, “My DAOS are my repositories,” then I would agree.
  • So go on with this. You need something to encapsulate the unit of work expressed in UseBizLayer. At this level, I think the nature of this is that you are stuck writing code that will all be a transaction script. You create a separation of responsibility and status. As a rule, I saw how this was done on Java EE systems as the default architecture. But it is not object oriented. I would try to study the model and see if I can at least try to summarize some of the behaviors that are recorded in BizClasses.
  • Another approach that I used earlier is to get rid of the BizLayer classes and then proxy the calls from the Domain to the actual Repositories / DAO performing the operation. However, this may require some investment in infrastructure construction. But you can do a lot with a framework like Spring and use some AOP concept to do this job well and reduce the amount of custom infrastructure you need.
+3
source

since you implement classes and objects, your decision will be OO no matter how you impose things - this may not be very well structured depending on your situation / needs !; -)

for your specific question, in some cases it would be advisable for validateUserName to belong to the User class, as each user would like to have a valid name. Or you can have a validation utility class, assuming other things have names that use the same validation rules. The same goes for email. You can divide them into NameValidator and EmailValidator classes, which would be a great solution if they will be used a lot. You can also provide the validateUserName function in a User object, which is just called a utility class method. All of them are valid solutions.

One of the greatest joys about OOD / OOP is that when the design is right, you know that it’s right, because the mass just drops out of the model that you can do, which you could not do before.

In this case, I would make the NameValidator and EmailValidator classes, because it seems likely that in the future other objects will have names and email addresses, but I would provide the validateName and validateEmailAddress functions in the User class, because it makes a more convenient interface for objects biz.

the rest of the “we don't want” bullets are correct; they are necessary not only for proper delamination, but also for a clean OO design.

Layering and OO go hand in hand, based on the separation of problems between layers. I think you have the right idea, but you will need some utility classes for the general validations presented

+1
source

Think about how these tasks will be carried out if there is no computer, and model your system in this way.

A simple example ... A client fills out a form for requesting a widget, submits it to an employee, an employee checks the client’s identifier, processes the form, receives the widget, provides the widget and records the transaction to the client and keeps a record of the transaction somewhere for the company.

Does the client save their data? No, the employee does. What role does an employee play in storing customer data? Storage of customer records.

Does the form verify that it was filled in correctly? No, the employee does. What role does an employee take when he does this? Form handler.

Who gives the client a widget? Employee acting as a widget distributor

And so on...

To insert this into a Java EE implementation ...

The servlet acts on behalf of the Client, filling out the form (pulling data from the HTTP request and creating the corresponding Java object) and passing it to the appropriate employee (EJB), who then does with the form that needs to be done. When processing an EJB request, you may need to transfer it to another EJB, which specializes in various tasks, some of which will include access / placement of information from / to the storage (your data level). The only thing that should not be directly correlated with the analogy should be the specifics of how your objects interact with each other, and how your data layer communicates with your storage.

+1
source

I had the same thoughts.

In traditional MVC, the most important thing is to split the View into Model and Controller parts. It seems like a good idea to separate the controller and model simply because you can end up with bloated model objects:

 public class UserModel extends DatabaseModel implements XMLable, CRUDdy, Serializable, Fooable, Barloney, Baznatchy, Wibbling, Validating { // member fields // getters and setters // 100 interface methods }
public class UserModel extends DatabaseModel implements XMLable, CRUDdy, Serializable, Fooable, Barloney, Baznatchy, Wibbling, Validating { // member fields // getters and setters // 100 interface methods } 

While for many interfaces you can have separate controllers (or whole templates), and yes, this is more of a procedural nature, but I assume that everything works today. Alternatively, you can understand that some interfaces do the same thing (CRUDdy - storing and retrieving the database, Serializable - the same as for the binary format, XMLable, the same for XML), so you must create a single system for this, with each potential backend is a separate implementation that the system processes. God, this is very poorly written.

Perhaps there is something like “co-classes” that allow you to have separate source files for implementing the controller, which act as if they are members of the model class on which they operate.

As for business rules, they often work with several models at the same time, and therefore they must be separate.

0
source

I think this is a "separation of concerns" issue. You seem to have come a long way along the right track with your layered architecture, but maybe you need to do more than what I created - for example, to create architectural layers in your Java EE layers?

The DataContainer is very similar to a data transfer object (DTO) template.

OO's modern design has many small classes, each of which is associated with a small number of “friends,” for example. through the composition. This can lead to a lot more classes and a Java boiler room than you really feel comfortable with, but it should lead to a design that is easier to put on and easier to unit test and maintain.

(+ 1 for the question, +1 for the answer about when you know that you have the right to bundle)

0
source

Roughly, the “We Don't Want” section should go. Either you want it to be correct, or you want it to remain as it is. It makes no sense not to create a class when you need it. “We have a lot” is a bad excuse.

Indeed, it is bad to expose all inner classes, but, in my experience, creating a class for each concept (i.e., user, identifier, database concept ...) always helps.

In addition, is the facade template something crucial for the existence of the loads of BizRules classes hidden behind one well-organized and clean interface?

-1
source

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


All Articles