2

so I have this android app at work, if I understand it right the DAO/services/UI layers is to "decouple" the UI from the database. I have 2 problems with that :

1/ Decoupling

Like this if things changes in the DAO layer/database schema I just have to touch the service layer and the UI stays untouched.

Allright, why? I still have to change stuff in 1 layer to adapt to the DAO layer change, why does it matter that I don't have to change the UI layer? in the end I still have to rewrite the services layer.

2/we are making one service per DAO

Client Info Screen : display info about the client

So I'm in a screen, the only information I currently have is the "current intervention ID"

to get the client address I need to get the InterventionEntity in order to know the client, then I need the ClientDao in order to retrieve the ClientEntity with it's address.

so I need access to 2 DAO, but I will call 1 service. choosing in which service to implement that is confusing.

Wouldn't it be better to have 1 service per screen?

I would have a ClientInfosScreenService that would have "getClientAdress" using both the InterventionDAO and ClientDAO.

Thanks.

  • I understand it right the DAO/services/UI layers is to "decouple" the UI from the database this is a very naive introduction of what decoupling is for. I would suggest you read a little bit more about decoupling and its implementation. Your "problems" are the proof of a failed implementation of this best practice. Don't follow blindly any practice. No matter how good they are. Do understand well the problem they solve or you will find yourself taking design decisions based on false premises. What it has all the receipts for the disaster. This we are making one service per DAO is the proof. – Laiv Aug 4 '18 at 20:48
  • Take a look at this question. Ahiv puts the hit on the nail when he introduces the concept of "loose coupling". What comes to say that is going to be always a sort of coupling somewhere in the code. – Laiv Aug 4 '18 at 20:51
  • @Laiv can you recommend any good books? I was browsing amazon but a lot of them have bad reviews saying that those books where only made to make money, I don't know what to read. – sliders_alpha Aug 4 '18 at 21:32
  • 1
    Sorry, I'm not a big fan of IT books or authors. They tend to produce acolytes in mass and I prefer to keep a critical thinking. I do search, read, distrut and do search again till i reach my own conclusions. Experience makes the process easier too. – Laiv Aug 4 '18 at 21:57
3

1/ Decoupling

Like this if things changes in the DAO layer/database schema I just have to touch the service layer and the UI stays untouched.

Allright, why? I still have to change stuff in 1 layer to adapt to the DAO layer change, why does it matter that I don't have to change the UI layer?

Consider that each layer abstracts the next layer, and therefore often centralizes usage.

Consider an example of where you have 4 views which can all update the person's email address (person@example.com). All four of them contain logic to update the person's email address.

Suppose you want to introduce a change, where you now save an email as two separate fields: EmailIdentity (person) and EmailDomain (example.com). You have to change the update logic of the person's email address. There are 4 views, which means you have to change four things.

If you had had a DAO layer, there would've been one UpdateEmailAddress(int personId, string emailAddress) method. Therefore, if you wanted to implement the same change, you would only have to change one thing.

In the example I used, when you only do 3 changes and you didn't know the 4th location existed, you would run into compiler issues, so you'd quickly see that you forgot something. However, if the applied change is not breaking, it will lead to a successful compilation and you will not be reminded that you forget any other updates.

Tangentially, while different layers are often represented as different projects, that is not inherently required. If your UI project already has a separate PersonUpdateHelper class, you could arguably call that the DAO layer. A class can be a layer too, as long as it is inbetween the database and the UI (so those two never interact directly).
I would suggest using projects as your layers for other reasons (library dependencies, the ability to meaningfully use access modifiers to prevent circumventing the layer, ...) but it is not technically a requirement for it to be considered a layer.


2/we are making one service per DAO

Wouldn't it be better to have 1 service per screen?

No. As per the previous example, the updating of a person's email address occurs on 4 separate views, and therefore you'd be forced to create the same logic in 4 services (one per view).

However, there is some merit to the underlying foundation of your issue:

so I need access to 2 DAO, but I will call 1 service. choosing in which service to implement that is confusing.

I completely agree with this. But I do want to point out here that there is no requirement for the dao and service to work on the same scope.

When your service only depends on one DAO (FooDao), then it usually makes sense for the service to take the same name (FooService). But when the service relies on more than one DAO (FooDao, BarDao), then the service should be named based on the purpose it serves.

I'll give you a real world example. I work on an application used for delivery truck drivers, to track which parcels they have delivered.

Delivery drivers have three distinct jobs. These jobs are what I mean when I say "the purpose a service serves".

  • Loading the parcels into their truck.
  • Delivering the parcels at the recipient.
  • Retrieving parcels from a sender (to later be delivered).

For either loading or delivery, we need to update two entities: Parcel (to change its status) and Signature (to add the recipient's signature). When retrieving, we only need to update Parcel entities (no signature required).

So this is our setup:

DAO

  • The ParcelDao handles updates to the [Parcels] table.
  • The SignatureDao handles updates to the [Signatures] table.

Services

  • The LoadingService depends on both the ParcelDao and SignatureDao.
  • The DeliveryService depends on both the ParcelDao and SignatureDao.
  • The RetrievalService depends on the ParcelDao.

The driver doesn't care about which entities are affected. The driver (and his mobile application) simply calls FinishLoading() and doesn't care if this updates one or more entities.

This is why layer separation is so useful. To an external caller, it looks like the application has functional features (load/deliver/retrieve). But internal to the application, there is a more complicated data logic at play, which the external caller doesn't need to know about.

As a second example, restaurants similarly separate their cooks (DAO), their waiters (services) and their UI (customers).

The room where customers eat is quiet and calm, even if the kitchen is hectic and busy. If the cooks and the customers sat in the same room, they would get in each other's way. But by separating them into their own separate rooms, each can have what they need (peace and quiet for the customers, the ability to work fast for the cooks), and neither the cooks nor the customers need to worry about what happens in the other room.

DAO

Separating the kitchens means that every kitchen can be tailored to a specific cuisine.

  • The sushi chef has his own kitchen.
  • The grill chef has his own kitchen.
  • The salads are made in a separate kitchen.
  • The wine is stored in the wine cellar.

I'm aware that real life restaurants often only have one kitchen. But if you look at large-scale kitchens, like the ones you find on a massive cruise ship, you'll see that there are several kitchens each with their own cuisine and staff.

Services

The waiters serve as the layer between the cooks and the customers. Because the waiters are there, the cooks and the customers never interact with each other. The waiters know what the customers have ordered. The waiters will figure out where they need to get the meals from.

  • The waiters will fetch the meals from the appropriate kitchens. They do not fetch wine.
  • The sommelier (wine advisor) will fetch the wine from the wine cellar. They do not fetch meals.

UI

The customer doesn't care who makes the food or where they make it. They just want to eat what they have ordered.

  • The customers expect their waiter to bring the food to their table.
  • The customers expect the sommelier to bring the wine they asked for.
  • The customers don't care where the waiter got the food from. Whether they picked it up in one location, or picked it up from multiple locations, it really doesn't matter to the customer.
-1

I did some digging and found the following, please downvote me if I'm wrong :

the DAO/Services part is in fact about database transactions management. it makes sense in a website for example when multiple users can access the services at the same times.

However in an android app, where the app has only one users at the same times it is not usefull.

source : https://softwareengineering.stackexchange.com/a/162426/312152

As for decoupling, one must follow the "tell don"t ask" principle.

Meaning you do not ask the values of internal properties of an objetc to make a decision.

You must implement a method in that object that you call and the object will tell you what to do.

for example :

int age = user.getAge()
if (age>18) {
    //do stuff
}

is bad

if (user.isMajor()) {
    //do stuff
}

is good

this way if User changes, you change the isMajor() method and you do not have to modify the rest of the code

  • Correct: "the DAO/Services can provide things such as database transactions" Incorrect: "if we don't need database transactions, we therefore don't need the DAO/Service layers". This is a logical fallacy. As an analogy to what you said: I can use my car to drive to the beach today. But since I'm not driving to the beach today, I should therefore sell my car! – Flater Sep 4 '18 at 9:51
  • Furthermore, even when you have a single user, database transactions are meaningful. Consider an example where the user launches 1 web request which should then create 3 new objects in the database. The first two objects are created successfully, but the third gives an error. Since not everything succeeded, you therefore want none of the three items to be saved to the database (it's all or nothing). You need a transaction to be able to do this, regardless of whether you have one or more users. – Flater Sep 4 '18 at 9:53
  • 1
    I mean this without offense, but I suspect that you are Googling words/concepts you come across, do not spend enough time truly understanding them, and then start applying your flawed and naive approach to make complex business decisions that go againt the commonly accepted grain. I highly suggest that whenever you read about a rule ("you should do X when you want Y") that you then ascertain why that is the case (is this rule correct? is there no other way to achieve Y? Why is X the best way? Is this a global rule or could my situation be different?) – Flater Sep 4 '18 at 9:55
  • All systems doesn't require transactions, transactions can be seen as a specific case of persistance with some additional constraint. DAO are used when you need persistance, even without transaction. You can have a DAO Layer working on XML Files. Also decoupling have nothing to do with magic value (18). Decoupling stand at a higher level where you don't want numerous class to depend on a specific concrete implementation, but on a defined abstracted API (java interface) which concrete instance is injected (manually or by a DI framework for you). And in some states the majority is at 21. – Walfrat Oct 4 '18 at 13:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.