Announcement Announcement Module
Collapse
No announcement yet.
Merging service layer and DAO layer into single layer Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Merging service layer and DAO layer into single layer

    I would like to here some opinion on following topic.

    I used to build my application with service layer and DAO layer - quite standard. Service layer contains interfaces (e.g. ProductService) and their implementations (e.g. ProductServiceImpl). It has dependency on DAO layer, consisting of interfaces (e.g. ProductDao) and implementations (e.g. ProductDaoImpl). This worked very well especially with JdbcTemplate-based DAOs, where the service sometimes had to call several DAOs for completing the task (call ProductDao, OrderDao, UserDao).
    With Spring 2.5 stereotypes I would mark all service implementation classes with @Service, and all Dao implementation classes with @Repository, which gives me DataAccessExceptions translation for Dao classes.

    However, now, when I'm usually using JPA-based persistence, I observe that in many cases the service classes simply pass all the calls to Dao, almost untouched. So I have the "saveProduct" method in service, which starts the transaction (by AOP) and simply calls the "saveProduct" method on Dao, which calls entityManager.persist(). This way separation of service and dao layer only complicates the life of developer, because two levels of inerfaces means more work to do to come to the source which really does the job, and service layer does not add any value.

    So the solution would be to throw away one layer. Which one? I saw that the samples of Spring Web Flow do not have the separate Dao level, only service layer. Service has EntityManager injected, and directly calls entityManager.persist() in such a case. I would say that the EntityManager plays in fact the role of DAO here. This sounds reasonable and makes the code cleaner.

    However, now I don't have the DataSourceExceptions translation, which was earlier done by @Repository adnotation on Dao layer. This is not crucial, but I like this DataSourceException abstraction offered by Spring. Can I combine it with this approach? I can mark my service layer with @Repository instead of @Service, but this is probably incorrect semantically. Or should I mark it with both @Service and @Repository?

    What's your opinion on this?

  • #2
    The Service APIs define the use cases the service is meant to implement. The DAO provides the specific implementation of data access. Obviously, these are different things. The point of separating the two is to keep the possibility open for changing/replacing the data access strategy/technology/logic -- if that becomes necessary -without affecting the application clients that use the service. (I understand that your question concerns the specific case when a service does little more than redirect to a DAO. In cases of some serious business logic, there are no options, really. Business and data access logic should be kept separate.)


    In your example, your Product service directly uses the UserDao, OrderDao, instead of accessing the user and order data through the User and Order services. That, probably implies that some Product API methods make a series of different DAO calls, e.g. to a User DAO method, and then to the Order DAO method. There is always a possibility that such kind of logic might change with changes in the DB schema, etc, while the use cases for each service remain the same. You don't want to change your service API each time the database schema changes, or when you come up with a more efficient logic to extract the data from multiple data domains (user, product, order, etc.) - for a single use case (single API call.) If you are using DAOs, your Product service should only be exposed to the User and Order APIs - that is, services - not the implementation details of their data access. A DAO, as the implementation detail of the particular service, must never be exposed to another service directly. Such things should always be hidden from the service's client, including another service. If you feel comfortable with hard-coding your data access logic and technology into you service once and for all, then, I guess, you can merge the two.

    These are all architectural decisions that must be made regardless of the frameworks and technologies you are using, so I don't think it should have anything to do with which Spring annotations you will use and how.

    Comment


    • #3
      Yes, you are right that in this example Product service should rather use User and Order services, instead of User/Order DAO. However, in such a case it is still possible that each service use directly EntityManager as the actual DAO implementation, instead of separate DAO-layer class written by a developer.

      In really complicated applications the separate service and DAO implementation can be beneficial, if both layers are complicated. But in the simple application (CRUD + some additional application specific logic) this creates only more classes with very little logic inside (say method "save" in DAO, which calls only entityManager.persist) - so no benefit in fact, as this can be done directly from service.

      What it has to do with Spring? As I said earlier, I like the translation of DataAccessExceptions provided by Spring. But if i remove the DAO layer, I would probably have to add this translation directly on the EntityManager method calls, which makes it a bit more complicated (though still possible, I think - I can inject EntityManager proxy - but I'm not sure if I can make it to work with Spring processing of @PersistenceContext annotations). On the other hand, if I decided to use JPA's EntityManager then perhaps it is simpler just to use the JPA exceptions directly in such a case.

      Comment


      • #4
        Originally posted by grzegorzborkowski View Post
        Yes, you are right that in this example Product service should rather use User and Order services, instead of User/Order DAO. However, in such a case it is still possible that each service use directly EntityManager as the actual DAO implementation, instead of separate DAO-layer class written by a developer.

        In really complicated applications the separate service and DAO implementation can be beneficial, if both layers are complicated. But in the simple application (CRUD + some additional application specific logic) this creates only more classes with very little logic inside (say method "save" in DAO, which calls only entityManager.persist) - so no benefit in fact, as this can be done directly from service.

        What it has to do with Spring? As I said earlier, I like the translation of DataAccessExceptions provided by Spring. But if i remove the DAO layer, I would probably have to add this translation directly on the EntityManager method calls, which makes it a bit more complicated (though still possible, I think - I can inject EntityManager proxy - but I'm not sure if I can make it to work with Spring processing of @PersistenceContext annotations). On the other hand, if I decided to use JPA's EntityManager then perhaps it is simpler just to use the JPA exceptions directly in such a case.
        I totally understand your point. At the same time, I immediately see the flaws in your approach, to begin with. You assume from the start that your business logic is basically data access logic, and, moreover, that logic will be implemented using only one particular technology, e.g. JPA. Your architecture becomes data-access-driven architecture, not just architecture. More importantly, you see your middle tier as something that implements data access, not use cases! While it may work just fine for your specific case, I would strongly recommend against such mentality.

        Here's my point. On a very high level, you have a client application, and you have - potentially reusable - services that implement some body of work. What is a service?

        My definition: A service is a software component that implements a set of specific use cases in the given area of functionality. The service exposes these use cases through its public API, and abstracts everything else! The Domain Model for the area of functionality covered by the service is part of the service API. In other words, to the outside world, the service is defined by the use cases and domain model (entities it operates on.) A service may depend on other services that also expose their domain model and API. The domain model is shared between the service and the clients. One thing that should never, ever be exposed to the clients is any notion of data access, or any existence of a data store, for that matter. Let's say, you have some Order service, a User service, and a Product service. The order service may implement a use case called "Place Order". The API may look like this

        placeOrder(User user, product Product);

        or something of that kind... That's the only thing the client should know. Ever. If the service needs to call the Product service to check if the product is available, update the list of products, check some user data against the User service, etc. - all of that must be abstracted within this single use case API. The client doesn't care where the data is stored and whether it is retrieved from the data base, file system, web service, etc. All such things are strictly implementation details that must not be exposed.

        The Data Access logic is nothing but the implementation details of a service. Implementations may differ. DAOs are not database access objects, as many people, for some strange reason, believe. DAOs are meant to abstract any kind of data access and data source implementation: database, files, web services, any type of data resource. The fact that many people use DAOs to access only databases doesn't make the above statement false.

        This makes perfect sense. When you pull up a web page, you only are interested in the information that is displayed on the screen. You, as a user, don't care where it came from, which databases it is stored in. This is the most basic principle of software design: impose as little burden on the consumer as possible by abstracting as much complexity of the provider as possible, minimizing the knowledge requirements for the consumer. It is one thing for the client application to know that it can place an order by providing the product info and user info. It is just a basic abstract use case that will never change. It is completely different - and inappropriate - to force some additional notion of a data store on the clients by having them communicate with data access concepts directly.

        Based on all this, my approach is to always use the service layer as the generic use case abstraction. Within that abstraction, provide specific implementations of data access (if appropriate) - by injecting them, of course. Never expose the data access technology via the service API/domain model. (I know that the latter is extremely popular, unfortunately.)

        Theoretically, in your case, if your service use cases are nothing but CRUD operations, you could skip the DAO layer within the service and just code your data access logic within your service API. The bad thing about this, ofo course, is that it will be more difficult to swap the data access implementations if it becomes necessary. I think, even if your service APIs only act as simple pass-through methods to your DAO methods, it is a very small price to pay for ensuring flexibility and clean design.

        Any architect (or programmer) should always approach the MT design with a clear understanding of one basic thing: we are ultimately implementing Use Cases, not data access! Use cases are the real thing, data access is an implementation detail. So, always think Services (see the definition above), not DAOs, repositories, or other data access concepts...

        HTH,
        Constantine

        Comment


        • #5
          I think the definitions of service/repositories in Domain Driven Design can clarify many points in this discussion. You are focused on the technology (how to have DataSourceExceptions?), but services are much more than a layer to access the repository.

          I strongly suggest a read on Domain Driven Design Quickly and then a read on Domain-Driven Design: Tackling Complexity in the Heart of Software by Eric Evans.

          Comment


          • #6
            Originally posted by juk View Post
            You are focused on the technology (how to have DataSourceExceptions?),
            Wrong! i think the main point of this - and many other architectural discussions in this forums - is that the technology is just an implementation detail and should always be abstracted. This conversation was NOT focused on technology, but rather on how to abstract it behind the public API exposed by a service.

            but services are much more than a layer to access the repository.
            And where in the above discussion did you find any evidence of someone saying that the services' only purpose is to abstract the data source? Perhaps, you should have read the thread carefully first.

            I strongly suggest a read on Domain Driven Design Quickly and then a read on Domain-Driven Design: Tackling Complexity in the Heart of Software by Eric Evans.
            I think most of us - at least those who contributed to this thread - have read the DDD book. And, personally, I have never liked the idea of repositories promoted in that book. I think it is a bogus pattern. I am not the only one. So think Christian Bauer and Gavin King, the authors of Hibernate.
            Last edited by constv; Mar 11th, 2009, 01:09 PM.

            Comment


            • #7
              Originally posted by constv View Post
              I think most of us - at least those who contributed to this thread - have read the DDD book. And, personally, I have never liked the idea of repositories promoted in that book. I think it is a bogus pattern. I am not the only one. So think Christian Bauer and Gavin King, the authors of Hibernate.
              Well, thats a controversial point. Gaving King was much blamed for the comments about DDD on his blog (and he did much of it before reading DDD). The DDD concepts for repositories are being well accepted by ppl like Martin Fowler (reference) and I thing he is a better reference than King on the oo design environment.

              The service-based approach tends to generate "useless" services like the example on this thread. The domain services should be used only as a thin layer to control iteractions between objects. A ProductService that access a ProductDAO to call saveProduct should be replaced by the object Product accessing his repository.

              Comment


              • #8
                Originally posted by juk View Post
                Well, thats a controversial point. Gaving King was much blamed for the comments about DDD on his blog (and he did much of it before reading DDD). The DDD concepts for repositories are being well accepted by ppl like Martin Fowler (reference) and I thing he is a better reference than King on the oo design environment.

                The service-based approach tends to generate "useless" services like the example on this thread. The domain services should be used only as a thin layer to control iteractions between objects. A ProductService that access a ProductDAO to call saveProduct should be replaced by the object Product accessing his repository.
                Personally, I don't care who supports the idea and who doesn't, really. I have my own brain. Both, King and Bauer have strongly spoken against the repository pattern - specifically, after reading the DDD book. I respect Fowler, but no one has the ultimate authority on any subject. It seems to me, Gavin and Bauer have contributed quite a bit to the software development industry - in practice, not theory - lately, so their opinion has just as much weight if not more as any theoretician's. They both, especially Bauer - from what I have seen, have presented many intelligent arguments against that pattern that in my view are very valid. I think - as they have also stated - that the pattern is based on a weird premise/assumptions, in the first place. A DAO is not just for data bases, it is for accessing ANY data sources. So, saying that repositories unlike DAOs abstract the type of data source is ridiculous... Also, I fundamentally disagree with the concept of objects being aware of their own persistence. It is just wrong. Enough of object zealotry. One should use common sense instead. I have said it before in other threads, and I am not going to get into this again in detail, but an object must only implement the kind of functionality that is essential to the definition of the object's nature. Objects must not implement business logic that may - or may not! - be applied to them, and they should not be aware of any persistence mechanism/technology used to store them. You may think differently, and that's your right.
                Last edited by constv; Mar 11th, 2009, 01:59 PM.

                Comment


                • #9
                  Originally posted by constv View Post
                  Personally, I don't care who supports the idea and who doesn't, really. I have my own brain. Both, King and Bauer have strongly spoken against the repository pattern - specifically, after reading the DDD book. I respect Fowler, but no one has the ultimate authority on any subject. It seems to me, Gavin and Bauer have contributed quite a bit to the software development industry - in practice, not theory - lately, so their opinion has just as much weight if not more as any theoretician's. They both, especially Bauer - from what I have seen, have presented many intelligent arguments against that pattern that in my view are very valid. I think - as they have also stated - that the pattern is based on a weird premise/assumptions, in the first place. A DAO is not just for data bases, it is for accessing ANY data sources. So, saying that repositories unlike DAOs abstract the type of data source is ridiculous... Also, I fundamentally disagree with the concept of objects being aware of their own persistence. It is just wrong. Enough of object zealotry. One should use common sense instead. I have said it before in other threads, and I am not going to get into this again in detail, but an object must only implement the kind of functionality that is essential to the definition of the object's nature. Objects must not implement business logic that may - or may not! - be applied to them, and they should not be aware of any persistence mechanism/technology used to store them. You may think differently, and that's your right.
                  I was not the one caring for the supporters of the argument there. You came with Gaving King and Christian Bauer and I just told you I think Fowler is a better reference on software design. I saw a post on Bauer's blog and is clear to me that he doesn't know exactly how to use repositories. He wrote more than once that you will create a new layer and thats not true, since many implementations of DDD suggests to create a repository interface (located on the domain) with some infrastructure concrete class (usually a DAO) implementing it. You dont't have to build a concrete repository unless you need to place some logic there (maybe getting some data from a database and some data from a xml file).

                  We have different opinions there, and I respect your oppinion. I am posting only my point of view and like you I don't really care about the supporters of the idea. I am using some DDD concepts on my projects and it seems to work well for me.

                  Comment


                  • #10
                    Unfortunately, people just love to label things. Labels later may become buzzwords, and, eventually, there will be situations when the common sense gives way to some blind dogma following and buzzword-joggling. Domain-driven design is a great thing. But it should not mean that one single object should know everything about itself including how to store itself (even if it only means storing a reference to a storage mechanism.) In the real world, things don't have any built-in notion of the location they are supposed to come from. An orange is an orange regardless of whether you picked it directly from a tree, or from a shelf in a grocery store. When you describe the qualities of an orange it would be ridiculous to add the notion of its storage. Well, if you describe a grocery store, than maybe you will have to include some way to point to a location where oranges can be found. But that would be a whole different subject, an external context. Entities in the Domain model are just things, items. Someone may decide to store them somewhere, but that has nothing to do with the nature of the item itself. Do not make things in software more crafty then they have to be! Many people think its smart and sexy to put all those notions into a single class. I think it is NOT. Sometimes, you will make things quite convenient for yourself - in one particular context. But it may render the object completely not applicable in other contexts. Often, it makes things less natural, and therefore, more complicated and convoluted. I am all for DDD. Except I define a functional Domain as a combination of domain entities and domain operations/use cases that may (or may not, depending on the circumstances) be applied to those entities. Services are also objects in the Domain system. They are the objects that encapsulate the business operations, the use cases. Such operations, in my opinion, absolutely must be de-coupled from the essential properties and behavior of the entities/actors in the same Domain. There is no violation of OO principles here at all. It is all about the appropriate and thoughtful de-coupling of things and concerns that should not be molded together. I am sure that in many cases you can put everything into a single object and it will work fine. But such object becomes less generic, and your whole domain model becomes less flexible and specific to a given set of circumstances. This is not my idea of software architecture. I prefer less assumptions, less dependencies, more flexibility and compartmentalization of concerns and functionality. And I can say the same thing: it has worked very well for me.

                    Cheers,
                    C

                    Comment


                    • #11
                      Originally posted by constv View Post
                      Unfortunately, people just love to label things. Labels later may become buzzwords, and, eventually, there will be situations when the common sense gives way to some blind dogma following and buzzword-joggling. Domain-driven design is a great thing. But it should not mean that one single object should know everything about itself including how to store itself (even if it only means storing a reference to a storage mechanism.)
                      The object don't know how to store itself, thats wrong. It have a reference to another domain member, the repository. The repository is part of the domain. The object only knows that there is a repository (and it can be anything that implements the repository interface).

                      Originally posted by constv View Post
                      In the real world, things don't have any built-in notion of the location they are supposed to come from. An orange is an orange regardless of whether you picked it directly from a tree, or from a shelf in a grocery store. When you describe the qualities of an orange it would be ridiculous to add the notion of its storage. Well, if you describe a grocery store, than maybe you will have to include some way to point to a location where oranges can be found. But that would be a whole different subject, an external context.
                      Exactly. On your example on a DDD approach, the orange does not know about any tree or shelf. It only knows about the repository (domain). On your example you can change the 'tree' to a 'DAO'. On DDD the object does not know about the DAO or watherver mechanism do be stored, so your example is wrong. He knows only about other member of the domain, the repository.

                      Originally posted by constv View Post
                      Entities in the Domain model are just things, items.
                      Wrong. On the domain model, things are value objects. Entities should be identified and stored.

                      Originally posted by constv View Post
                      Someone may decide to store them somewhere, but that has nothing to do with the nature of the item itself. Do not make things in software more crafty then they have to be! Many people think its smart and sexy to put all those notions into a single class. I think it is NOT. Sometimes, you will make things quite convenient for yourself - in one particular context. But it may render the object completely not applicable in other contexts.
                      In any context an entity it should be stored and have an identification. If it does not have it, it is not an entity. So in any context an entity should have a repository. It is not tied to a DAO or anything.

                      Originally posted by constv View Post
                      Often, it makes things less natural, and therefore, more complicated and convoluted. I am all for DDD. Except I define a functional Domain as a combination of domain entities and domain operations/use cases that may (or may not, depending on the circumstances) be applied to those entities. Services are also objects in the Domain system. They are the objects that encapsulate the business operations, the use cases.
                      Services do not encapsulate use cases. Services encapsulates business logic between object interations. All business logic that belongs to one single object should be placed there. If you place this logic on the services you will probably have duplicated code, since when you are developing a new service you will reuse business logic placed on the object, and not in other service (maybe you doesn't know other services at all).

                      Originally posted by constv View Post
                      Such operations, in my opinion, absolutely must be de-coupled from the essential properties and behavior of the entities/actors in the same Domain. There is no violation of OO principles here at all. It is all about the appropriate and thoughtful de-coupling of things and concerns that should not be molded together. I am sure that in many cases you can put everything into a single object and it will work fine. But such object becomes less generic, and your whole domain model becomes less flexible and specific to a given set of circumstances. This is not my idea of software architecture. I prefer less assumptions, less dependencies, more flexibility and compartmentalization of concerns and functionality. And I can say the same thing: it has worked very well for me.
                      We are not putting everything in the object. We are putting everything that belongs to the Entity on it. It is not less generic, since a Repository is a member of the domain and you are not making your Entity dependent of any concrete classes (like a DAO, or a tree). It is not less flexible at all.

                      Comment


                      • #12
                        A data source - or any abstraction of it - is NOT part of the domain, sorry. That's just wrong. And that weird assumption is the basis of the repository pattern, as well as of all your arguments. In addition, you have misinterpreted and twisted every single thing I said, and I see no point in arguing with you.

                        Comment


                        • #13
                          Originally posted by constv View Post
                          A data source - or any abstraction of it - is NOT part of the domain, sorry. That's just wrong. And that weird assumption is the basis of the repository pattern, as well as of all your arguments.
                          From Domain Driven Design Quickly:

                          "It can be noted that the implementation of a repository can be
                          closely liked to the infrastructure, but that the repository
                          interface will be pure domain model."

                          If you dont think the repository is part of the domain you disagree with a big part of the DDD concept.

                          Originally posted by constv View Post
                          In addition, you have misinterpreted and twisted every single thing I said, and I see no point in arguing with you.
                          Sorry, but you said you read the DDD book and said that you agree with it (only disagree with Repository), but your concept of Entity is very wrong. You described an entity exactly how DDD describes a VO. And I agree, there is not point arguing with you too, since I dont think you ever read a DDD book in your life and you are posting blind opinions like Gavin King did.
                          Last edited by juk; Mar 11th, 2009, 04:22 PM.

                          Comment


                          • #14
                            but you said you read the DDD book and said that you agree with it (only disagree with Repository), but your concept of Entity is very wrong. You described an entity exactly how DDD describes a VO. And I agree, there is not point arguing with you too, since I dont think you ever read a DDD book in your life and you are posting blind opinions like Gavin King did.
                            Nonsense. Of course, I have read that book, and I have never said that I agreed with everything in it. I don't blindly follow everything I read. A lot in that book did not sit well with me, and yes, my concept of entity is different - obviously - from the DDD book. The book is your bible, not mine. I said that I see nothing wrong with DDD, except my vision of DDD is not exactly the one the book offers. And that does not make my approach wrong. It's just too arrogant and immature to state that. Tells more about you than you think.

                            My "entities" have nothing to do with VOs, because I have always advocated putting behavior inside entities, not just data. (If you had read this very thread instead of skimming it, you would have noticed that.) Except, I believe, such behavior must be the kind that makes up the essence, the nature of the entity, not the business logic. I also think that it is incompetent to state that each "item" represented by an class must be a persistent object in its own right. Many don't have to be. And it is wrong to approach application design (or object modeling) from the persistence point of view, as many people mistakenly do. Persistence is just one concern that may or may not be part of a use case. And the public interface exposed by Domain (the kind that is accepted by the school of thought i belong to) should only represent the logical use cases, nothing else. Not the fact that something gets saved, but what actually makes sense to the client of the service. If you are placing an order on the web site, you don't think of saving something in the database, you are thinking of pressing a button and expect theh product delivered to your door in a few days. That's the use case. The implementations may be whatever, the clients should not care. You should not even have APIs like "saveOrder". Instead it should state "placeOrder", or submitOrder.

                            We have discussed these subjects to death in this forum, the differences between various approaches, including the Evans book - long before you showed up. Many people here have read many books, not one, and have built many successful and practical projects, using various philosophies and methodologies - before they came to certain conclusions on their own, based on education and experience, not dogmas. So, if you are here to offer your opinion, suggestion, or, better yet a working solution, you are very welcome. If you are here to tell me that you've read a book, and everyone who disagrees with it or doesn't take it as a bible is dead wrong, you need to grow up.

                            Comment


                            • #15
                              Originally posted by constv View Post
                              Nonsense. Of course, I have read that book, and I have never said that I agreed with everything in it. I don't blindly follow everything I read. A lot in that book did not sit well with me, and yes, my concept of entity is different - obviously - from the DDD book. The book is your bible, not mine.
                              It is not my bible. I just agree with most of it, and thats completly different.

                              Originally posted by constv View Post
                              My "entities" have nothing to do with VOs, because I have always advocated putting behavior inside entities, not just data.
                              I was talking about DDD VOs, and they are not just data. On DDD, VOs have business logic. Maybe you are confused about DDD VOs and other VO pattern (the old DTO).

                              Originally posted by constv View Post
                              We have discussed these subjects to death in this forum, the differences between various approaches, including the Evans book - long before you showed up. Many people here have read many books, not one, and have built many successful and practical projects, using various philosophies and methodologies - before they came to certain conclusions on their own, based on education and experience, not dogmas. So, if you are here to offer your opinion, suggestion, or, better yet a working solution, you are very welcome. If you are here to tell me that you've read a book, and everyone who disagrees with it or doesn't take it as a bible is dead wrong, you need to grow up.
                              I am sorry, but I am only giving my opinion. On this thread, and on other threads, you say many things are "wrong" and I see it as your opinion, not as a dogma. I am just defending things that I believe are correct and saying that I have success with it, not saying that it is correct.

                              I disagree with some points on the DDD book, but not the reps/services concepts. It is not my bible at all.
                              Last edited by juk; Mar 11th, 2009, 08:16 PM.

                              Comment

                              Working...
                              X