开发者

How to handle views in a multilayer-application

开发者 https://www.devze.com 2023-03-27 02:40 出处:网络
I\'m working on a project which has basically three layers: Presentation, business and data. Each layer is on a different project and all layers use DTO\'s defined in another project.

I'm working on a project which has basically three layers: Presentation, business and data. Each layer is on a different project and all layers use DTO's defined in another project. business layer and data layer return DTO's or Lists of DTOs when querying the database.

So far so good, but now we have to query views and those views of course do not match an existant DTO. What we have done until now is just create a special DTO, business- and data-layer classes so they were treated like normal entities (minus insert, update etc.)

But it does not se开发者_JS百科em correct. Why should the be treated like normal entities when they are clearly not. Well the DTO seems necessary, but creating "business logic" and a datalayer-class for every view seems rather akward. So I thought I create one generic business- and datalayer class which holds the logic/code for all views (I still would have to create a DTO for every different view, perhaps I could use anonymous types)

What do you think about me idea or how would you solve this issue?

EDIT: 9. August 2011 Sorry, the post may have been unclear. By views I meant Views from a sql-server.


I feel your pain completely. The fact is that in almost every non trivial project with decent complexity you will get to the point where the things you have to show to the users on UI overlap, aggregate or are simply a subset of data of business entities. The way I tend to approach this is to accept this fact and go even further - separate the query side from the business logic side both logically and physically. The fact is that you need your entities only for actual business operations and keeping the business constraints valid, and when does this happen? Only when someone changes the data. So there is no need to even build entities when you display the data. The way I like to structure the solutions is:

User opens the view -> Query is performed only to get the specific data for the view -> Returned data is the model (although you could call it a DTO as well, in this case it's the same thing)

User changes something -> Controller (or service) builds the full entity from repo, business logic action is performed on the entity -> changes are persisted -> result is returned

What I want to say is, it is ok to treat your read side separately from write side. It is ok to have different infrastructure for this as well. When you start to treat it differently, you will see the benefits - for example you can tailor you queries to what you need on UI. You can even get to the point where your infrastructure will allow to build your queries with different techniques, for example using LINQ or plain SQL queries - what is best for certain scenarios.


I would advise against using DTOs between layers. I'm not convinced that there's any benefit, but I'll be happy to take instruction if you think you have some.

The harm comes in maintaining multiple parallel hierarchies that express the same idea (business objects plus multiple DTOs between layers). It means lots more code to maintain and greater possibility of errors.

Here's how I'd layer applications:

view <--- controller <--- service <--- + <--- model
                                       + <--- persistence

This design decouples views from services; you can reuse services with different views. The service methods implement use cases, validate inputs according to business rules, own units of work and transactions, and collaborate with model and persistence objects to fulfill requests.

Controller and view are tightly coupled; change the view, change the controller. The view does nothing other than render data provided by the controller. The controller is responsible for validation, binding, choosing the appropriate services, making response data available, and routing to the next view.

Cross cutting concerns such as logging, transactions, security, etc. are applied at the appropriate layer (usually the services).

Services and persistence should be interface-based.


I've dropped most layered architectures like this as they are a pain to manage all the transformations and are over-complicated. It's typical astronaut architecture. I've been using the following:

  1. View models for forms/views in ASP.Net MVC. This is an important decoupling step. The UI will evolve separately to the model typically.
  2. No service layer, instead replacing it with "command handlers" (mutating operations) and "finders" (query operations) which represent small operations and queries respectively (CQS - Command Query Separation).
  3. Model persistence with NHibernate and ALL domain logic inside the model.
  4. Any external services talk to the finders and command handlers as well

This leads to a very flat manageable architecture with low coupling and all these problems go away.

0

精彩评论

暂无评论...
验证码 换一张
取 消