Is using DTO's the best way to solve this problem?
I am working on a client / server system:
There is a database, an application server and a user interface (client) app. The application server handles connections from the client applications which in turn talks to the database when the client app requests a list of users for instance, or a particular object by id.
Currently I have a set of data objects like "user", "area", etc. which map to tables in the database. These data objects开发者_运维百科 are defined in a shared library that gets linked into the client and the appserver on compile. They inherit a class that allows them to be serialised so they can pass between client and server, and they take a "data provider" as a dependency injection to allow the commit to either send to the application server or send to the database depending on if they're being used at the client or the server end.
When the user of the client app wants to edit a user, it requests that object from the app server, uses it to populate the user interface with the current values, allows the user to edit those values, and then "commits" the object back to the appserver which in turn commits it to the database.
This is fine for this very simple scenario, but as it gets more complicated the user interface will want objects that are perhaps consisting of several of the bottom layer database objects so I'm thinking I need to abstract away from the database model to some degree.
This being the case, I should not be passing what I suppose would be called "DAL" objects to the user interface (via the serialisation), so I'm thinking I need some DTOs (data transfer objects).
I'm also finding in the application service where I do the business logic, I'm currently handling it all by switching on the type of object being committed from the client, doing whatever is neccessary and then committing to the database. I'm thinking perhaps here I need business objects instead, which each object knowing how to validate and act.
So I'd perhaps end up with:
Shared:
* UserDTO (data transfer object)
Application Server:
* UserDAL (data access object)
* UserBO (business object, contains UserDAL)
* UserDTO (data transfer object as defined in shared lib)
Client:
* UserDTO (data transfer object as defined in shared lib)
So, the client requests a user DTO, displays or updates as neccessary, the "save" method is called, it gets serialised and sent to the application server which de-serializes it, creates the business object which does whatever it likes with it (such as validate, save to DB, etc.).
This means removing all my serialisation logic from the DAL objects to the DTO objects, and removing my big business logic class, and would stop the presentation layer (client) having to know anything about the database structure.
Does this sound about right?
Someone else did suggest having the business objects in a shared library and not having data transfer objects. The problem with this though is I have business logic in 2 places, and it'd nice to be able to update the business logic in one place, rather than potentially having to update 100's of client apps talking to the one application service. It also means the business objects would have to also have all the get/set routines of the DTO objects.
I hope this makes sense. Any thoughts would be appreciated :-)
My initial thought is - what's your actual problem? Because from what I can see you're not doing anything wrong.
Yes - putting multiple objects into a DTO, and then serializing that for transfer "over the wire" between client / server sounds right to me.
Yes - having a shared library of types / business objects is fine; I'm assuming they are nothing more than really 'dumb' data structures with no logic, and that they don't change often.
so I'm thinking I need to abstract away from the database model to some degree.
Yes. You could possibly do the same between client and server. If you were in using the Microsoft platform / .Net you could use WCF which allows for different types of binding, so no more manual serialization.
The problem with this though is I have business logic in 2 places
Yes havingit in two places is not ideal - but it does have some advantages. One advantage of duplicating some of the business logic at the client-end (I'm thinking of "validation" rules here) is that the UI could provide a much more interactive experience for users, in that they wouldn't have to wait for a round-trip to tell them they can't add their surname into the phone number field. You'd still provide proper validation and full business rules on the server-end: "defense in depth" so to speak.
精彩评论