architecturedomain-driven-designdton-tier-architecturemulti-tier

Multi-Tier Architecture - Responsibility questions


I'm developing an application which implements multi-tier pattern where MySQL is used for persistence. There is a WCF service which provides access to data and provides DTOs.

Further, I plan to implement the following patterns: - DTOs - MVP (not yet sure if passive view or supervising controller) - Code against interfaces where applicable

Currently, I rawly have the following project structure:

+-------------------------------+
|     MySQL DB Server           |
+------+------------------------+
       ^
       | Uses Entity Framework 5.0
       |
       +
+-------------------------------------------------------------------------------+
| Application Server                                                            |
|-------------------------------------------------------------------------------|
|+------------------+ +----------------+ +--------------+ +--------------------+|
|| Data Access Layer| | Contracts      | | Communication| | Business Layer     ||
||------------------| |----------------| |--------------| |--------------------||
|| - EF 5.0 Entities| | - WCF Contracts| | - WCF Service| | - Actual Service   ||
||                  | |                | |   Hosts      | | - Session management|
||                  | |                | |              | | - Security and     ||
|+------------------+ +----------------+ +--------------+ +--------------------+|
+-------------------------------------------------------------------------------+
        ^
        | Communicates via DTOs which are acutally wrappers for Entities
        | eg. GetUserByID() or SaveUser(userDTO)
        |
        |
+-------+-----------------------------------------------------------------------+
| Clients                                                                       |
|-------------------------------------------------------------------------------|
|+-------------------+                                     +-------------------+|
|| Business Layer    |+----------------------------------->| GUI (Winforms)    ||
||-------------------|  BLL receives DTOs and creates      |-------------------||
|| -Provide WCF Servi|  Domain Objects (eg. User) which are| -Implementation of||
||  ce Access        |  Processed by presenters and passed |  View Interfaces  ||
|| -Service Reference|  to views where they are bound to   |                   ||
|| -Implementation of|  controls.                          |                   ||
||  Presenter Interf.|                                     |                   ||
|+-------------------+                                     +-------------------+|
+-------------------------------------------------------------------------------+



+------------------------------------------------------------------------+
| General                                                                |
|------------------------------------------------------------------------|
|+---------------------+ +--------------------+ +-----------------------+|
|| DTOs                | | Interfaces         | | Library               ||
||---------------------| |--------------------| |-----------------------||
|| -DTO Definitions    | | -View Interfaces   | | -General Helper Classe||
||                     | | -Presenter Interf. | |  s eg. Cryptography   ||
||                     | | -Domain Model IF.  | |                       ||
|+---------------------+ +--------------------+ +-----------------------+|
+------------------------------------------------------------------------+

Outer boxes are project folders in Visual Studio. Inner boxes are C# Projects

Before I continue coding and spend more time in actual implementation, I just like to get some feedback about the structure / architecture of my project.

I'm wrapping my head around following questions:

  1. Is the above structure "best-practice"-conform? eg. location of Interfaces, DTOs
  2. Is it ok to have two business layers or rather split the business layer into client and server? Server BLL is meant to provide general functions like Session management and security while client BLL provides service access. It controls the views by its presenters as well.
  3. Server side does not know about the domain objects at present. Would it be better to use them here as well? This would result in mapping my entities to domain objects and then to DTOs
  4. Is it common to receive DTOs from WCF service or should I use domain objects (I know that has been discussed here a lot, but from what I understand, it would be applicable if the domain objects are not that complicated and could save mapping and coding efford when changing my domain objects and database) Wouldn't this result in a very hard to maintain communication chain like: Entities<->Domain Object<->DTO<->Domain Object
  5. Where do you put validation? I thought to put basic validation into the views or presenters (eg. formatting, null/not null values, ...) while main validation goes to the domain objects...?
  6. When creating a new record in the database, lets say a new user, should the client also pass a new DTO to the server or is it better to create a service method that accepts simple data typs such as string and int?

Sorry for this long post, but I thougt it would be better to combine my questions into one post and provide the project structure within.

Thanks in advance for any kind of answer.

Regards


Solution

  • The structure that you propose is quite similar (mutatis mutandis) to one of our application that was deployed in production 2 years ago. It works, but you have to carefully design the domain model, separating in different bounded context the various aspect of the application.

    So these are my own answers:

    1. No, there's no "best-practice" to conform here. After 5 years of DDD practice in financial applications, my own opinion is that DDD is still a research field. However, it proves very well if applied correctly to projects whose value resides in the experience of a domain expert. However you have to distinguish business needs (that are relevant to the domain) and technological requirements (that can help drawing the components and tiers that your application needs)
    2. Business Layer (if you need to identify one) should handle the business rules only. It's the layer of the domain models, in a DDD application.
    3. In my experience, if you can trust the client machine and you correctly design the domain model, you should not need any Application Server, at all. However, if you really need it (for example because clients cannot connect to the db), I would make it as simple and stateless as possible. An useful consideration here is that most of times, the business rules already prevent concurrent access to mutable entities. Don't try to handle concurrent access to such entities in that case, simply build a mutual exclusion mechanism.
    4. For inter-process comunications, use only DTOs. You can choose, however, to move the whole domain into the Application Server (that will become much more complex and stateful), and use a simpler MVC pattern in the client. This is simpler from the client's developer point of view, but more expensive overall (in particular, it can be hard to scale).
    5. Simple type validation of input fields can be done in the view (integers, date times and so on), but you should model each relevant type of value with a custom value object before passing it to the domain. For example you should never pass strings or decimal to domain objects, but Email or Money. Moreover the domain in the only responsible for business invariant: it should throw expressive exceptions when an operation can not be performed.
    6. DTO are more expressive, thus easier to debug.

    Before you start, I think you should ask yourself some questions:

    1. Do I need a domain expert or I can learn enough of the business by reading Wikipedia or a set of well written specifications? Tip: no need for (at least) a domain expert == no need for DDD.
    2. Can I trust the machines where the client will be deployed? If you can't, you should consider moving the domain into the Application Server (and adopt an MVC pattern client side to handle WCF requests and DTO bindings).

    Finally, if you really need DDD, and you are new to it, you could find the Epic's modeling patterns useful (disclaimer, I'm one of the Epic devs and I designed all of them during the last 5 years of DDD trial and errors).