Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I know there's quite a bit out there on this topic, but I couldn't seem to find any that completely answers my questions. I was told to use a Service->DAO->Low level code architecture . I'm having a hard time wrapping my head around is the exact role of the Service class, will one Service class work for a Book DAO and also a user DAO? I was going to have a Service class for each, haveing the Service clas talk to the DAO, take the resulting string and store it in my Book class and User class, then send that object back to the Controller. In my thinking, the Service class is the high level class that delegates all the work to other classes. Thanks for your help.
A collection of service classes, known as a service tier, is responsible for carrying out the business logic of an enterprise application. Service classes usually don't map directly to DAOs, since they represent business operations that might involve a large number of domain objects. An example is an order-submission process, where the code responsible for accepting an order has to work with the objects representing orders, customer accounts, financial accounts, and inventory.
Separating the various business operations into different service classes is a design decision that depends on the complexity of the operations, how closely they're related, and so on. Some designers might decide that each business operation should be essentially a separate class (similar to the Command pattern), while others prefer a more comprehensive interface with a richer variety of methods.
The concept of a service tier exists to make sure that all of the business logic is stored in one place and not duplicated. Many modern systems will have several interfaces into the backend, such as a Web application (perhaps with Spring MVC Controllers), a SOAP or REST interface (perhaps with Jersey), and specialized adapters for legacy terminals or other systems. Making these interfaces all adapters around a common service tier ensures that they all behave in a consistent way and that any changes to the service tier are applied to all of the access interfaces.
In your particular case, since you're needing to ask, a single service object will probably be sufficient for your needs. It's always a good idea to list all of the service methods on a separate interface and code to that so that you can replace the implementation for testing or future upgrades.
Service class may be acting as a layer of abstraction so DAO or data layer is hidden from the "business layer".
The service may talk to multiple DAOs to perform a function in which case it's acting more of a Facade pattern, hiding the complexity of communicating with DAOs to perform the required functionality.
This sort of pattern is seen in the port and adapter or hexagonal architecture in that the business logic is insulated from lower level protocols.
http://c2.com/cgi/wiki?PortsAndAdaptersArchitecture
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 months ago.
Improve this question
Can a Plain Old Java Object have methods that deal with business logic other than just the getter/setter methods?
I see possibly mixed answers for this so is there no rigorous definition for this? I know a POJO cannot implement an interface, extend a class, and not use annotation.
You seem to be getting caught up in details of a formal definition that does not exist.
“POJO” is not a precise formal term. “POJO” is a catchy casual term coined by Martin Fowler, Rebecca Parsons, and Josh MacKenzie back in 2000.
The idea of a POJO is an object that is not enmeshed in a complicated framework. Any experienced Java programmer should be able to read and understand the source code of a POJO without needing to learn some framework, and without needing to look up third-party documentation.
Annotations
So, a POJO will generally have few annotations only because because Java bundles few annotation classes. Most annotations come from external frameworks. So if we are avoiding the complications of external frameworks, we are avoiding most annotations.
Personally, I would add an exception for one framework: Jakarta Bean Validation (Wikipedia). This framework is relatively simple, does not involve any elaborate involvement, and focuses on the validity/integrity of the POJO’s own internal field values. The validation rules are applied as annotations.
Logging might be another framework exception. And maybe Java Management Extensions (JMX) monitoring too. Notice that all three of my own personal choice in framework exceptions are focused on the POJOs themselves, as opposed to orchestrating some elaborate involvement with other objects.
Business logic
And, yes, a POJO can have business logic, especially regarding its own internal state, and regarding its need to communicate its changes with the outside world such as persisting data and notifying other interested parties.
Indeed, you can learn about:
Hexagonal Architecture by Dr. Alistair Cockburn(and related variations, Onion Architecture, etc.)
Domain-driven design (see book by Eric Evans)
… to see how you can use POJOs as domain objects (“business objects”, with core business logic) while keeping them separate and protected from various elaborate frameworks operating in other parts of your app.
Data-only objects
Some classes are intended to simply carry data. All such data-only classes are POJOs. But not all POJOs are data-only classes.
I suggest you learn about Data Transfer Objects and Value Objects, as kinds of data-only classes.
If the main purpose of your class is to communicate data transparently and immutably, use the records feature in Java 16+. In a record, by default, the compiler implicitly creates the constructor, getters, equals & hashCode, and toString.
And let me be clear: there is nothing wrong necessarily with elaborate complicated frameworks. They can be exquisitely useful, obviously. That's why they were invented. Each framework has a purpose and a place.
The term POJO was invented so that in discussions about programming and system architecture/design we can make the distinction between classes that are simple and not entwined versus those classes that are complicated and entwined.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I'm developing a Spring Boot MVC application and, after reading many guides and comments, I still have some doubts that I have not unmarked.
1: I do not want an anemic pattern, so I do not have a monolithic service where all the services are called each other, but these communicate only with repository instantiating entity, inside which I put the business logic, correct?
2: where to put the conversion functions entitiy-> dto? I read that someone puts them in the Controller, others in the Service, others on the same domain .. at the moment the cleanest solution and I prefer to have a Builder of the DTO that lends the entity input, okay I have contraindications?
3: polymorphism and inheritance: I have a service that composes some menu levels according to an attribute of the entity in question. I do not want to have blocks of if anywhere, I wanted to be able to put this logic in a single point, to instantiate the correct class (which I do not know a priori) and to exploit the polymorphism, how can I do? considered to involve service, entity and related logic ..
thank you so much
Your questions are more related to software design in general rather than specific to the Spring framework. Allowing the framework to dictate how to organize your code, has some downsides.
But to answer your questions:
Depending on how complex and interrelated your model is, there are different options, for the cases where there is not big interdependence between the entities in the model, the 3 layer approach is simple and good enough, but if your model is more complex, you could take a look into the concept of Aggregates, and keep the invariants hidden inside.
Constructing the DTO with the Entity as parameter is a good solution, whenever changes needs to be made to either the DTO or the Entity, the amount of code to maintain is not as much as with other approaches, it is not just about the conversion code, it is also about methods signatures, and all of the usages. This approach also follows the Dependency Inversion principle which states that low level modules (presentation in this case) should depend on high level policies (business logic) and not the other way around. But it is not the only valid solution, it always depends on your concrete case.
If you want to return an object from your service that can be an instance of different types, there are different ways to do so, a way to do so (but not the only one, and again, the best way always depends on your concrete case):
For the type control, one option would be to make the method return type an interface, and then have the possible different objects that can be returned to extend that interface.
For the construction of the different objects, you can encapsulate it inside of the service in a private function if that is the only place you are going to use it, or if you are going to use it in more places, then you could extract it to a factory and use it as a colaborator of the service. For the construction you won't be able to avoid the if checks, but outside the service, once you serve the different instances, then you won't need to do more if checks.
and finally in the service return the instance that you constructed, as it implements the interface, the compiler will still be happy about it.
Hope it helps!
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
Designing application tier is not trivial. At the end of the day, in every project we write (huge) number of so-called business methods (sometimes called service methods, although it is not related to services as in public APIs) that perform some business logic and usually do some database/storage operations (via storage tier). But designing/organizing/naming your application methods is not trivial as it sounds; people often have rules on project how application classes and methods should be designed. I am looking for pragmatic set of such rules for designing the application tier, so here are some questions:
Grouping methods in classes: by return type or?
For example, method that updates a user belongs to class eg UserService. Or method that finds a user by some criteria belongs to the same class. But what happens when some method works on several types, like e.g. registerUserForCompetition()? Should this be in UserService or CompetitionService? The same question for the method findUserCompetition() - where would you put it?
I often see a rule that says that this depends on methods return type. In our example, if method returns User (or collection of users etc) it should belong to UserService.
Method parameters: simple types (primitives, String...) or entities (e.g. User, Competition, Registration...)?
This question is often asked, and people usually (statistically:) choose the first approach, using simple types as service arguments. But what to do when one such method calls the other method on the same resource? Let me give you an example: registerUser(userId, competitionId) may internally call checkCompetition(competitionId). Both methods fetch the Competition from the storage. Obviously, this is done twice and, since we already have the Competition object we can use it to checkCompetition with it. So should we add overloaded method, or we should ignore this and just really on caching mechanism to prevent double fetching?
On the other hand, having full types as parameters can not be universal rule, as many times the full information is not needed and there is no reason to fetch the full object while you need just it's id, that you already may have it.
Naming methods: how verbose methods name should be?
Especially for finder methods. Should we have eg:
findCompetition(userId, year) or
findCompetitionWithVenue(userId, year) (since every Competition object has linked Venue); or
findCompetitionForUserAndYear(userId, year) or
findCompetitionByUserIdAndYear(userId, year) or just
findUserCompetitionForYear(userId, year)?
When number of different criteria rises, it is easy to make a mess with finder method names, and I often see rules like this: find<return-type>By<names-of-parameters> or similar.
Do you have naming convention for application classes?
Do your classes names end with Service? Do you separate managers from services, where manager deals with entities and services accept only simple types? Do you group all your business classes in the same package, or group them together with other related classes (model, controller...), based on functionality?
Please share your experience with focus on being pragmatic - for me it means that new developer can easily figure where to find business methods and how to write new ones, so everyone gets more productive. Also, if you have established rules, please share how your team is managed to follow them.
group services by functionality. in the same package should be also controler, part of model etc. there are better approaches then layered architecture. try DDD. it perfectly isolates functionality, makes it easier to find and change
usually it's good to have entities (model) hidden from the client and communicate with controllers through DTOs and ValueObjects. just in case you want to change your model in the future
they must be meaningful for your domain and consistent. and don't be affraid to refactor if your team says they are not clear. personally i would go with findCompetition(user, year) with non-primitive types because you can use method overloading but then in invocations you have to use constants or reading enablers like findCompetition(forUserId(userId), forYear(year)) to explicitly tell the reader which version you are invoking.
what is manager? it means nothing. similarly to helper, handler etc. Service contains the logic that converts DTO to entities and the logic can't be pushed to the domain/entity because the logic operates on many entities. as stated before i group components (not only services) by functionality and therefore i add the 'Service' suffix because it helps me quickly find the logic in specific package (which contains model, controller, service, repository etc)
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Increasingly in our spring (or equivalent) wired world of services, the Java code I see seems more & more procedural, with not much emphasis on modelling the problem in OO.
For example, a service that has stuff to do may well inline that in the service method in the singleton service class – maybe over several hundred lines. Alternatively, local methods may be created, but because the service is stateless, these are invariably called with a stack (no pun intended) of needed args. It’s noisy.
Guess this maybe my original OO background in Smalltalk to the fore here, but modelling the problem in OO has always seemed to me to be the way to go. That is, modelling with objects which have state as well as behaviour.
An alternative approach might be to create a stateful prototype delegate invoked from the service, which is either wired or loaded with the necessary (entities, singleton DAO/services etc) In addition some other decorators might be created to wrap entities (esp collections) to provide some model list behaviour (I have a list af accounts, I have some list based behaviour – this must be a class holding the list, it must not be just the technical List class and its usage behaviour inlined in the service (but usually is))
But.
Creating some objects of this kind uses memory, and in a high throughput environment, this might result in the creation of thousands of small strategy/decorator instances.
So what is the real world impact of that? Will the extra GC screw the performance or, assuming a JVM instance around a couple of GB, can Java cope?
Has anyone delivered a Java SOA based on these principles? Are there any papers on the subject?
Thanks for reading this far.
Real-world problems usually are a mix of object-based and procedural logic, especially in the business world where transactions involve needing to manipulate a number of distinct objects simultaneously. Certainly most real code could use improvement and refactoring, especially after a few years of moving-target requirements, and better understanding and use of AspectJ could clean up a lot of the procedural boilerplate, but it doesn't make sense to force all logic into a strong OOP pattern if it doesn't match the way that a real-world instructor would describe it to a trainee.
What you're describing is basically the Command pattern, and while there are situations where it is useful (it's essentially the role of Runnable), it's usually not worth using unless there are time-based considerations (serial execution, parallelism) or the transaction itself needs to be persistent (such as for banking).
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
One mentor I respect suggests that a simple bean is a waste of time - that value objects 'MUST' contain some business logic to be useful.
Another says such code is difficult to maintain and that all business logic must be externalized.
I realize this question is subjective. Asking anyway - want to know answers from more perspectives.
The idea of putting data and business logic together is to promote encapsulation, and to expose as little internal state as possible to other objects. That way, clients can rely on an interface rather than on an implementation. See the "Tell, Don't Ask" principle and the Law of Demeter. Encapsulation makes it easier to understand the states data can be in, easier to read code, easier to decouple classes and generally easier to unit test.
Externalising business logic (generally into "Service" or "Manager" classes) makes questions like "where is this data used?" and "What states can it be in?" a lot more difficult to answer. It's also a procedural way of thinking, wrapped up in an object. This can lead to an anemic domain model.
Externalising behaviour isn't always bad. For example, a service layer might orchestrate domain objects, but without taking over their state-manipulating responsibilities. Or, when you are mostly doing reads/writes to a DB that map nicely to input forms, maybe you don't need a domain model - or the painful object/relational mapping overhead it entails - at all.
Transfer Objects often serve to decouple architectural layers from each other (or from an external system) by providing the minimum state information the calling layer needs, without exposing any business logic.
This can be useful, for example when preparing information for the view: just give the view the information it needs, and nothing else, so that it can concentrate on how to display the information, rather than what information to display. For example, the TO might be an aggregation of several sources of data.
One advantage is that your views and your domain objects are decoupled. Using your domain objects in JSPs can make your domain harder to refactor and promotes the indiscriminate use of getters and setters (hence breaking encapsulation).
However, there's also an overhead associated with having a lot of Transfer Objects and often a lot of duplication, too. Some projects I've been on end up with TO's that basically mirror other domain objects (which I consider an anti-pattern).
You should better call them Transfer Objects or Data transfer objects (DTO).
Earlier this same j2ee pattern was called 'Value object' but they changed the name because it was confused with this
http://dddcommunity.org/discussion/messageboardarchive/ValueObjects.html
To answer your question, I would only put minimal logic to my DTOs, logic that is required for display reasons.
Even better, if we are talking about a database based web application, I would go beyond the core j2ee patterns and use Hibernate or the Java Persistence API to create a domain model that supports lazy loading of relations and use this in the view.
See the Open session in view.
In this way, you don't have to program a set of DTOs and you have all the business logic available to use in your views/controllers etc.
It depends.
oops, did I just blurt out a cliche?
The basic question to ask for designing an object is: will the logic governing the object's data be different or the same when used/consumed by other objects?
If different areas of usage call for different logic, externalise it. If it is the same no matter where the object travels to, place it together with the class.
My personal preference is to put all business logic in the domain model itself, that is in the "true" domain objects. So when Data Transfer Objects are created they are mostly just a (immutable) state representation of domain objects and hence contain no business logic. They can contain methods for cloning and comparing though, but the meat of the business logic code stays in the domain objects.
What Korros said.
Value Object := A small simple object, like money or a date range, whose equality isn't based on identity.
DTO := An object that carries data between processes in order to reduce the number of method calls.
These are the defintions proposed by Martin Fowler and I'd like to popularize them.
I agree with Panagiotis: the open session in view pattern is much better than using DTOs. Put otherwise, I've found that an application is much much simpler if you traffic in your domain objects(or some composite thereof) from your view layer all the way down.
That said, it's hard to pull off, because you will need to make your HttpSession coincident with your persistence layer's unit of work. Then you will need to ensure that all database modifications (i.e. create, updates and deletes) are intentional. In other words, you do not want it be the case that the view layer has a domain object, a field gets modified and the modification gets persisted without the application code intentionally saving the change. Another problem that is important to deal with is to ensure that your transactional semantics are satisfactory. Usually fetching and modifying one domain object will take place in one transactional context and it's not difficult to make your ORM layer require a new transaction. What is challenging is is a nested transaction, where you want to include a second transactional context within the first one opened.
If you don't mind investigating how a non-Java API handles these problems, it's worth looking at Rails' Active Record, which allows Ruby server pages to work directly with the domain model and traverse its associations.