Appropriate model & context class separation (Architecture) - c#

I'm currently wondering what's the suggested way to separate plain model classes (for e.g. using them in Entity Framework, Web API, MVC, WCF...) from their application logic parts (server side tasks, threads etc.) utilizing the DRY principe.
Consider this pseduo example:
public class HorseOfDoom {
private Thread _hungerThread;
private Laser _headMountedLaser = new Laser();
public int Age { get; set; }
public string Name { get; set; }
public int Health { get; set; }
public int HungerLevel { get; set; }
public HorseOfDoom() {
_hungerThread.Start();
}
public void PewPew() {
_headMountedLaser.PewPew();
}
}
In this class we have both - model properties that describe the model (age, name,..), but also a thread and methods. I can use this class in Entity Framework, WCF and so on.. but what if I want to use the model in a ASP.NET MVC client application without exposing the methods, threads? Do I have to write the same class again? Do I need managers, adapters and facades? Could I use the buddy class pattern?

Use a model fit for the context. DRY is not about repeating lines of code, it's about repeating behaviour. Your view model can have the same properties (copy paste ftw) as the business model, minus the methods. You can use Automapper to map one to the other. Chances are your view model will have more than only those properties, including validation attributes or other data neede by the view in a certain format.
A model to rule'm all is not good on the long term. Clean models will alow you to focus better on the context and avoid coupling to other contexts, which might use a very similar or identical model. Things change in time and it's easier to work with a specific model from the beginning even if that involves copy paste and it seems that you're repeating yourself.

I understand that a combination as you show it in your sample is not really desirable - my main point of critique would be the thread that already implies a very concrete way on how the object should behave. The probability is high that the thread contained in the class itself will make it harder to use the class in some environments. From my point of view, the platform that integrates the class should be able to choose how to orchestrate the actions of the class - of course the class can make some restrictions like "not to be used in a separate thread as the class is not implemented in a thread-safe way".
As for the point of whether to combine properties and methods in a class: I don't think that there is a clear and always valid answer. It depends very much on how big the architecture of your application is and whether you are willing to pay the price for the separation in terms of complexity and overhead.
The concept of combining properties and methods in a single class is usually referred to as "Domain Model". It is a very natural approach to design complex business logic.
If you have an architecture that sets out to separate the layers very well, you'd have a Domain Model in the business logic that implements the business rules. These classes combine properties and methods, but these classes are mapped to simpler versions (e.g. DTOs) that only transport the data to other layers. This way, you also de-couple a service interface from the domain model and change them with minimal influences on the other layers. For instance, if you have complex classes in the domain model and you want to present only a part of this information in a web interface or through a service layer, you could create one or more DTO classes that contain exactly the data that is needed. Changes to the domain model will not necessarily affect clients so that you gain freedom in this respect.
In a smaller architecture however, you might not need to separate the layers with DTOs if you can live with the consequences.
As for the mentioned example of WCF, you have separate service and data contracts that you typically implement in different classes. If you have additional methods in a class that serves as a data contract those methods will not be part of the data contract. You'd have to explicitly make the methods that you want to publish part of a service contract. If you don't share the classes with a service client (e.g. through a class library), the client will not even know that these methods exist.

Related

CQRS with MediatR and re-usability of commands

Does it make sense to create commands that just hold objects? For example:
public class CreateCommand : IRequest
{
SomeDTO SomeDTO { get; set; }
}
public class UpdateCommand : IRequest
{
SomeDTO SomeDTO { get; set; }
}
Or perhaps something like this (deriving):
public class UpdateCommand : SomeDTO, IRequest
{
}
Or commands/requests should be treated as DTOs themselves? I'm confused because I saw many ways of doing things. Also copying all properties to command/request classes doesn't sound like a nice thing to do.
How do you do this in your projects?
Do you map your commands directly to your domain models or you use commands just to pass DTOs?
In case of using MVC framework what should be the input of my controller actions? Should it be a command, or should I create command inside my action implementation and send it? (I guess that will depend on how I model my commands)
Does it make sense to create commands that just hold objects?
No, there is no value added to the extra class: no semantics, no behavior...
Or commands/requests should be treated as DTOs themselves?
Commands (in the CQRS sense of the term) are DTO's by nature. They are dumb data bags that circulate between layers/tiers.
Do you map your commands directly to your domain models
It depends if you favor a task-based UI over a CRUD-based UI. If you do DDD/rich domain model - some would even say basic OO encapsulation - you wouldn't map them. Command names would maybe match entity methods, but their contents are not automatically mapped to domain model fields.
In case of using MVC framework what should be the input of my
controller actions? Should it be a command, or should I create command
inside my action implementation and send it?
I would say both are legit and applicable, except the occasional technical quirk with MVC model binding.
Commands and domain objects, at least in my world, have different design constraints. In particular, commands are part of the API surface - they are part of the contract with other services - and therefore need to have compatible definitions over long periods of time. Domain objects, on the other hand, are local to our current way of doing things - they are part of our organization of data within the black box. So we can change those at any cadence we like.
Commands that cross process boundaries are messages, which is to say byte[]s. That's the bit that needs to be stable, both in form and semantics.
byte[] is domain agnostic, and it's fairly common to pass through several other domain agnostic intermediate stages in "parsing" the message
byte[] -> utf8
utf8 -> DOM
DOM -> Dictionary
...
but we're generally driving toward a domain specific expression of the contract.
See, for instance Mark Seemann
At the boundaries, applications are not object-oriented.
A DTO is a representation of such a piece of data mapped into an object-oriented language.
Having coerced the byte[] into a form that is convenient for querying, then we can start thinking about whether or not we want to use that data to start initializing "objects".
The other question that you may be asking - is there value in a having the message data within a generic metadata "envelope". That kind of pattern occurs all the time - the most familiar example being that an HTTP POST is a bunch of generic headers attached to a message-body.
The data and the metadata are certainly separate concerns; it definitely makes sense to keep them distinct in your solution.
I think compositing the data structures, rather than inheriting them, is going to be the more maintainable option.
public class Envelope<Message> ....
might be a reasonable starting point.
You should treat the command as a "verbal sentence" instructing your domain to do something. For example the "UpdateCommand" instructs your domain to update something. Inside the command you should include the specifics of the command (in your case that dto is fine)...
However be very carefull with those DTO's. You do not want your domain to be dependent on MVC but the other way around. Be sure that the assembly where the dto is living is not of a higher (in the direction of MVC) level than the domain logic.
In your MVC you should have only:
Dependency injection setup
Controllers & Views
Controllers should only contain the code required to transform from the method (http) parameters (witch are unsecure) to the dto required by the domain, and calling the domain.
At least that is the way I'm doing it.

Can you have an interface be dependent on a class?

I'm studying SOLID principles and have a question about dependency management in relation to interfaces.
An example from the book I'm reading (Adaptive Code via C# by Gary McLean Hall) shows a TradeProcessor class that will get the trade data, process it, and store it in the database. The trade data is modeled by a class called TradeRecord. A TradeParser class will handle converting the trade data that is received into a TradeRecord instance(s). The TradeProcessor class only references an ITradeParser interface so that it is not dependent on the TradeParser implementation.
The author has the Parse method (in the ITradeParser interface) return an IEnumerable<TradeRecord> collection that holds the processed trade data. Doesn't that mean that ITradeParser is now dependent on the TradeRecord class?
Shouldn't the author have done something like make an ITradeRecord interface and have Parse return a collection of ITradeRecord instances? Or am I missing something important?
Here's the code (the implementation of TradeRecord is irrelevant so it is omitted):
TradeProcessor.cs
public class TradeProcessor
{
private readonly ITradeParser tradeParser;
public TradeProcessor(ITradeParser tradeParser)
{
this.tradeParser = tradeParser;
}
public void ProcessTrades()
{
IEnumerable<string> tradeData = "Simulated trade data..."
var trades = tradeParser.Parse(tradeData);
// Do something with the parsed data...
}
}
ITradeParser.cs
public interface ITradeParser
{
IEnumerable<TradeRecord> Parse(IEnumerable<string> tradeData);
}
This is a good question that goes into the tradeoff between purity and practicality.
Yes, by pure principal, you can say that ITradeParser.Parse should return a collection of ITraceRecord interfaces. After all, why tie yourself to a specific implementation?
However, you can take this further. Should you accept an IEnumerable<string>? Or should you have some sort of ITextContainer? I32bitNumeric instead of int? This is reductio ad absurdum, of course, but it shows that we always, at some point, reach a point where we're working on something, a concrete object (number, string, TraceRecord, whatever), not an abstraction.
This also brings up the point of why we use interfaces in the first place, which is to define contracts for logic and functionality. An ITradeProcessor is a contract for an unknown implementation that can be replaced or updated. A TradeRecord isn't a contract for implementation, it is the implementation. If it's a DTO object, which it seems to be, there would be no difference between the interface and the implementation, which means there's no real purpose in defining this contract - it's implied in the concrete class.
The author has the Parse method (in the ITradeParser interface) return an IEnumerable collection that holds the processed trade data.
Doesn't that mean that ITradeParser is now dependent on the TradeRecord class?
Yes, ITradeParser is now tightly coupled with TradeRecord. Given the more academic approach of this question, I can see where you are coming from. But what is TradeRecord? A record, by definition, is generally a simple, non-intelligent piece of data (sometimes called POCO, DTO, or Model).
At some point, the potential gain of abstraction is less valuable than the complexities it causes. This approach is pretty common in practice - Models (as I refer to them) are sealed types that flow through the layers of an application. Layers that act upon the models are abstracted to interfaces, so that each layer may be mocked and tested separately.
For example, a client application may have a View, ViewModel, and Repository layer. Each layer knows how to work with the concrete record type. But the ViewModel could be wired up to work with a mocked IRepository, which builds up the concrete types with hardcoded, mocked data. There's no benefit to an abstracted IModel at this point - it just has straight data.

ViewModels in MVC / MVVM / Separation of layers- best practices?

I'm fairly new to the using ViewModels and I wonder, is it acceptable for a ViewModel to contain instances of domain models as properties, or should the properties of those domain models be properties of the ViewModel itself? For example, if I have a class Album.cs
public class Album
{
public int AlbumId { get; set; }
public string Title { get; set; }
public string Price { get; set; }
public virtual Genre Genre { get; set; }
public virtual Artist Artist { get; set; }
}
Would you typically have the ViewModel hold an instance of the Album.cs class, or would you have the ViewModel have properties for each of the Album.cs class' properties.
public class AlbumViewModel
{
public Album Album { get; set; }
public IEnumerable<SelectListItem> Genres { get; set; }
public IEnumerable<SelectListItem> Artists { get; set; }
public int Rating { get; set; }
// other properties specific to the View
}
public class AlbumViewModel
{
public int AlbumId { get; set; }
public string Title { get; set; }
public string Price { get; set; }
public IEnumerable<SelectListItem> Genres { get; set; }
public IEnumerable<SelectListItem> Artists { get; set; }
public int Rating { get; set; }
// other properties specific to the View
}
tl;dr
Is it acceptable for a ViewModel to contain instances of domain models?
Basically not because you are literally mixing two layers and tying them together. I must admit, I see it happen a lot and it depends a bit on the quick-win-level of your project, but we can state that it's not conform the Single Responsibility Principle of SOLID.
The fun part: this is not limited to view models in MVC, it's actually a matter of separation of the good old data, business and ui layers. I'll illustrate this later, but for now; keep in mind it applies to MVC, but also, it applies to many more design patterns as well.
I'll start with pointing out some general applicable concepts and zoom in into some actual scenario's and examples later.
Let's consider some pros and cons of not mixing the layers.
What it will cost you
There is always a catch, I'll sum them, explain later, and show why they are usually not applicable
duplicate code
adds extra complexity
extra performance hit
What you'll gain
There is always a win, I'll sum it, explain later, and show why this actually makes sense
independent control of the layers
The costs
duplicate code
It's not DRY!
You will need an additional class, which is probably exactly the same as the other one.
This is an invalid argument. The different layers have a well defined different purpose. Therefore, the properties which lives in one layer have a different purpose than a property in the other - even if the properties have the same name!
For example:
This is not repeating yourself:
public class FooViewModel
{
public string Name {get;set;}
}
public class DomainModel
{
public string Name {get;set;}
}
On the other hand, defining a mapping twice, is repeating yourself:
public void Method1(FooViewModel input)
{
//duplicate code: same mapping twice, see Method2
var domainModel = new DomainModel { Name = input.Name };
//logic
}
public void Method2(FooViewModel input)
{
//duplicate code: same mapping twice, see Method1
var domainModel = new DomainModel { Name = input.Name };
//logic
}
It's more work!
Really, is it? If you start coding, more than 99% of the models will overlap. Grabbing a cup of coffee will take more time ;-)
"It needs more maintenance"
Yes it does, that's why you need to unit test your mapping (and remember, don't repeat the mapping).
adds extra complexity
No, it does not. It adds an extra layer, which make it more complicated. It does not add complexity.
A smart friend of mine, once stated it like this:
"A flying plane is a very complicated thing. A falling plane is very complex."
He is not the only one using such a definition, the difference is in predictability which has an actual relation with entropy, a measurement for chaos.
In general: patterns do not add complexity. They exist to help you reduce complexity. They are solutions to well known problems. Obviously, a poorly implemented pattern doesn't help therefore you need to understand the problem before applying the pattern. Ignoring the problem doesn't help either; it just adds technical debt which has to be repaid sometime.
Adding a layer gives you well defined behavior, which due to the obvious extra mapping, will be a (bit) more complicated. Mixing layers for various purposes will lead to unpredictable side-effects when a change is applied. Renaming your database column will result in a mismatch in key/value-lookup in your UI which makes you do a non existing API call. Now, think of this and how this will relate to your debugging efforts and maintenance costs.
extra performance hit
Yes, extra mapping will lead to extra CPU power to be consumed. This, however (unless you have a raspberry pi connected to a remote database) is negligible compared to fetching the data from the database. Bottom line: if this is an issue: use caching.
The win
independent control of the layers
What does this mean?
Any combination of this (and more):
creating a predictable system
altering your business logic without affecting your UI
altering your database, without affecting your business logic
altering your ui, without affecting your database
able to change your actual data store
total independent functionality, isolated well testable behavior and easy to maintain
cope with change and empower business
In essence: you are able to make a change, by altering a well defined piece of code without worrying about nasty side effects.
beware: business counter measures!
"this is to reflect change, it's not going to change!"
Change will come: spending trillions of US dollar annually cannot simply pass by.
Well that's nice. But face it, as a developer; the day you don't make any mistakes is the day you stop working. Same applies to business requirements.
fun fact; software entropy
"my (micro) service or tool is small enough to cope with it!"
This might be the toughest one since there is actually a good point here. If you develop something for one time use, it probably is not able to cope with the change at all and you have to rebuild it anyway, provided you are actually going to reuse it. Nevertheless, for all other things: "change will come", so why make the change more complicated? And, please note, probably, leaving out layers in your minimalistic tool or service will usually puts a data layer closer to the (User)Interface. If you are dealing with an API, your implementation will require a version update which needs to be distributed among all your clients. Can you do that during a single coffee break?
"lets do it quick-and-simple, just for the time being...."
Is your job "for the time being"? Just kidding ;-) but; when are you going to fix it? Probably when your technical debt forces you to. At that time it cost you more than this short coffee break.
"What about 'closed for modification and open for extension'? That's also a SOLID principle!"
Yes, it is! But this doesn't mean you shouldn't fix typo's. Or that every applied business rule can be expressed as an sum of extensions or that you are not allowed to fix things that are broken. Or as Wikipedia states it:
A module will be said to be closed if it is available for use by other modules. This assumes that the module has been given a well-defined, stable description (the interface in the sense of information hiding)
which actually promotes separation of layers.
Now, some typical scenarios:
ASP.NET MVC
Since, this is what you are using in your actual question:
Let me give an example. Imagine the following view model and domain model:
note: this is also applicable to other layer types, to name a few: DTO, DAO, Entity, ViewModel, Domain, etc.
public class FooViewModel
{
public string Name {get; set;}
//hey, a domain model class!
public DomainClass Genre {get;set;}
}
public class DomainClass
{
public int Id {get; set;}
public string Name {get;set;}
}
So, somewhere in your controller you populate the FooViewModel and pass it on to your view.
Now, consider the following scenarios:
1) The domain model changes.
In this case you'll probably need to adjust the view as well, this is bad practice in context of separation of concerns.
If you have separated the ViewModel from the DomainModel, a minor adjustment in the mappings (ViewModel => DomainModel (and back)) would be sufficient.
2) The DomainClass has nested properties and your view just displays the "GenreName"
I have seen this go wrong in real live scenarios.
In this case a common problem is that the use of #Html.EditorFor will lead to inputs for the nested object. This might include Ids and other sensitive information. This means leaking implementation details! Your actual page is tied to your domain model (which is probably tied to your database somewhere). Following this course, you'll find yourself creating hidden inputs. If you combine this with a server side model binding or automapper it's getting harder to block the manipulation of hidden Id's with tools like firebug, or forgetting to set an attribute on your property, will make it available in your view.
Although it's possible, maybe easy, to block some of those fields, but the more nested Domain/Data objects you have, the more trickier it will become to get this part right. And; what if you are "using" this domainmodel in multiple views? Will they behave the same? Also, bear in mind, that you might want to change your DomainModel for a reason that's not necessarily targeting the view. So with every change in your DomainModel you should be aware that it might affect the view(s) and the security aspects of the controller.
3) In ASP.NET MVC it is common to use validation attributes.
Do you really want your domain to contain metadata about your views? Or apply view-logic to your data-layer? Is your view-validation always the same as the domain-validation? Does it has the same fields (or are some of them a concatenation)? Does it have the same validation logic? Are you are using your domain-models cross application? etc.
I think it's clear this is not the route to take.
4) More
I can give you more scenario's but it's just a matter of taste to what's more appealing. I'll just hope at this point you'll get the point :) Nevertheless, I promised an illustration:
Now, for really dirty and quick-wins it will work, but I don't think you should want it.
It's just a little more effort to build a view-model, which usually is for 80+% similar to the domain model. This might feel like doing unnecessary mappings, but when the first conceptual difference arises, you'll find that it was worth the effort :)
So as an alternative, I propose the following setup for a general case:
create a viewmodel
create a domainmodel
create a datamodel
use a library like automapper to create mapping from one to the other (this will help to map Foo.FooProp to OtherFoo.FooProp)
The benefits are, e.g.; if you create an extra field in one of your database tables, it won't affect your view. It might hit your business layer or mappings, but there it will stop. Of course, most of the time you want to change your view as well, but in this case you don't need to. It therefore keeps the problem isolated in one part of your code.
Web API / data-layer / DTO
First a note: here's a nice article on how DTO (which is not a viewmodel), can be omitted in some scenario's - on which my pragmatic side fully agrees ;-)
Another concrete example of how this will work in a Web-API / ORM (EF) scenario:
Here it's more intuitive, especially when the consumer is a third party, it's unlikely your domain model matches the implementation of your consumer, therefore a viewmodel is more likely to be fully self-contained.
note: The name "domain model", is sometimes mixed with DTO or "Model"
Please note that in Web (or HTTP or REST) API; communications is often done by a data-transfer-object (DTO), which is the actual "thing" that's being exposed on the HTTP-endpoints.
So, where should we put these DTO's you might ask. Are they between domain model and view models? Well, yes; we have already seen that treating them as viewmodel would be hard since the consumer is likely to implement a customized view.
Would the DTO's be able to replace the domainmodels or do they have a reason to exists on their own? In general, the concept of separation would be applicable to the DTO's and domainmodels as well. But then again: you can ask yourself (,and this is where I tend to be a bit pragmatic,); is there enough logic within the domain to explicitly define a domainlayer? I think you'll find that if your service get smaller and smaller, the actual logic, which is part of the domainmodels, decreases as well and may be left out all together and you'll end up with:
EF/(ORM) Entities ↔ DTO/DomainModel ↔ Consumers
disclaimer / note
As #mrjoltcola stated: there is also component over-engineering to keep in mind. If none of the above applies, and the users/programmers can be trusted, you are good to go. But keep in mind that maintainability and re-usability will decrease due to the DomainModel/ViewModel mixing.
Opinions vary, from a mix of technical best practices and personal preferences.
There is nothing wrong with using domain objects in your view models, or even using domain objects as your model, and many people do. Some feel strongly about creating view models for every single view, but personally, I feel many apps are over-engineered by developers who learn and repeat one approach that they are comfortable with. The truth is there are several ways to accomplish the goal using newer versions of ASP.NET MVC.
The biggest risk, when you use a common domain class for your view model and your business and persistence layer, is that of model injection. Adding new properties to a model class can expose those properties outside the boundary of the server. An attacker can potentially see properties he should not see (serialization) and alter values he should not alter (model binders).
To guard against injection, use secure practices that are relevant to your overall approach. If you plan to use domain objects, then make sure to use white lists or black lists (inclusion / exclusion) in the controller or via model binder annotations. Black lists are more convenient, but lazy developers writing future revisions may forget about them or not be aware of them. White lists ([Bind(Include=...)] are obligatory, requiring attention when new fields are added, so they act as an inline view model.
Example:
[Bind(Exclude="CompanyId,TenantId")]
public class CustomerModel
{
public int Id { get; set; }
public int CompanyId { get; set; } // user cannot inject
public int TenantId { get; set; } // ..
public string Name { get; set; }
public string Phone { get; set; }
// ...
}
or
public ActionResult Edit([Bind(Include = "Id,Name,Phone")] CustomerModel customer)
{
// ...
}
The first sample is a good way to enforce multitenant safety across the application. The second sample allows customizing each action.
Be consistent in your approach and clearly document the approach used in your project for other developers.
I recommend you always use view models for login / profile related features to force yourself to "marshall" the fields between the web constroller and the data access layer as a security exercise.

What is the best practice to deal with navigation properties when using DTO and POCO objects?

I'm trying to wrap my head around Domain Driven Development. I want to make sure I have a good foundation and understanding of it, so it would be great if recommendations to use AutoMapper or similar are avoided here. My architecture currently involves the following:
The WCF service is responsible for persistence (using Entity Framework) and server-side validation. It converts POCO's to DTO's, and DTO's are transferred to the client.
The Client, receives DTO's and converts them to POCO's. The class that converts POCO's and DTO's is shared between the service and the client.
The POCO's implement IValidatableObject and INotifyPropertyChanged and are used by both the server and the client, but they are not used for data transfer. The DTO's are, which are just property bags containing no behavior.
(1) Question #1. Is this architecture appropriate for a Domain Driven Design.
(2) Question #2. Is it appropriate for POCO's to contain navigation properties? It really feels wrong for POCO's to contain navigation properties in a DDD architecture to me, because it doesn't make sense to me to have a navigation property that may or may not be serialized. It would make more sense to me to have a specialized DTO.
For example, here is a POCO/DTO looks like in my architecture.
// Enforces consistency between a POCO and DTO
public interface IExample
{
Int32 Id { get; set; }
String Name { get; set; }
}
// POCO
public class Example : IExample, INotifyPropertyChanged, IValidatableObject
{
private int id;
private string name;
public Int32 Id {
get { return this.id; }
set {
this.id = value;
OnPropertyChanged("Id");
}
}
public String Name {
get { return this.name; }
set {
this.name = value;
OnPropertyChanged("Name ");
}
}
public ICollection<Example2> ChildExamples {
get { ... }
set { ... }
}
// INotifyPropertyChanged Members
// IValidatableObject Members
}
// DTO
public class ExampleInfo : IExample
{
public Int32 Id { get; set; }
public String Name { get; set; }
public ICollection<Example2Info> ChildExamples { get; set; }
}
It doesn't seem right though, because you may not always need the navigation property, and having an empty (null) object (or collection) seems very wrong in an object-oriented architecture. You also have to deal with serializing and converting deep object hierarchies at times, which is not trivial. It would make more sense for a specialized DTO so there isn't a problem with the constant possibility of empty navigation properties that may or may not need serialized or populated.
public class ComplexInfo
{
public Example ExampleInfo { get; set; }
public ICollection<Example2Info> ChildExamples { get; set; }
}
How are these situations handled in real-world enterprise DDD style architectures and what other advice can be given here?
I agree with Jehof about sending the DTO's to your client and keeping the domain model clean on the server side under your WCF.
With respect to navigation properties, one point Eric Evans emphasizes in Domain Driven Design is to respect invariants. So, in your example above ask yourself if Id and Name are really going to change in the lifetime of the object, or are they invariants? A lot of DDD-style developers would not even put a setter on those properties. Instead build the object's invariant state through a constructor. If Name can change, you probably want a method called Rename(string newName), because there's probably some kind of business rules you'd want to put there anyway.
A red flag in your layers above is that you have your whole object model in the DAL. What you call your assemblies really isn't a big deal but I think it points to your tendency to keep thinking of the application from a data perspective. The point of DDD is to think of your object model in terms of logic and behavior, not data and structure. I (and most other DDD developers, I think) think of the data access layer as Repository classes which return Aggregate Roots. The repositories are responsible for returning your hydrated poco/entity objects from the DAL(repository) to the business layer (and above, such as an application/service layer class or your WCF in your above example). In your case of using EF, you'd have the repositories wrap your DataContext calls and return the entity objects.
I could go on and on, because your question is really targeting the basic fundamentals of DDD, of which there are several. I would recommend 1) Read Eric Evans book, "Domain Driven Design". 2) Keep in mind that DDD targets complex business software. If you're trying to apply it to a simple CRUD application which really is just UI forms and data binding to DB tables, its hard to see a DDD approach take shape, because the problems it addresses just aren't there. So keep that in perspective.
Is this architecture appropriate for a Domain Driven Design?
Not entirely. Take a look at hexagonal architecture for a description of a more modern architectural style which fits nicely with DDD. Within hexagonal, your domain is at the core and various components "attach" to it. For example, a WCF service would be considered an adapter in a hexagonal architecture because it adapts your domain to a communication technology such as TCP or HTTP. Typically, you would have an application service which establishes a facade over your domain and effectively represents use cases. This application service can be referenced by a WCF service to expose functionality over HTTP. Unfortunately, the "service" terminology can be a bit conflating.
Is it appropriate for POCO's to contain navigation properties?
It is appropriate, but the right answer is that it depends. One of the issues with navigational properties that you state is that they may or may not be serialized for a specific DTO. This is telling me that you are talking about queries. Some queries need only a subset of attributes on an aggregate/entity (POCO) and thus the corresponding DTO only has those required properties. It seems wasteful to retrieve an entire entity together with navigational properties. To address this issue you can employ lazy loading. A more salable approach however, is to use read-models for queries. Also, as stated by others, an entity/aggregate certainly can and should contain navigational properties if they are a reflection of the domain. How these "navigational" properties are implemented can vary. Sometimes it can be better to split an aggregate into multiple aggregates. Take a look at Effective Aggregate Design by Vaughn Vernon.
As pointed out by Jehof, you should try to have clients of the WCF service only depend on the contract of that service itself, not on the domain entities (POCOs) that the service encapsulates. Typically, POCOs should not implement INotifyPropertyChanged and IValidatableObject because those interfaces support UI concerns and should be handled by the DTOs or ViewModels.
Domain Driven Design isn't about POCO's or DTO's. It's about Entities, Aggregate Roots, Value Objects. About rich domain objects that can encapsulate behavior in addition to data.
Is it appropriate for POCO's to contain navigation properties ?
It's not clear to me what the POCOs are for in your scenario, but if they are your domain entities, then they can and should certainly contain navigation properties. Actually, using the navigation properties of an Aggregate Root (a special kind of domain entity) is often the only way for external objects to access entities enclosed in that Aggregate. Navigation through association properties is a key concept in DDD.
Also, the recommended architecture in DDD looks more or less like :
Presentation Layer (UI)
Application layer
Domain Layer
Infrastructure layer (includes persistence/DAL)
The key here is the Single Responsibility Principle. You don't want a service that does persistence, server-side validation and DTO mapping at the same time. You need decoupling. You need a clear distribution of responsibilities among your layers so that they are more easily maintainable, extensible and portable.
Another suggestion: think very hard whether to share the mapping code (and by implication the classes they are mapped to) between the client the server.
There is nothing wrong with sharing code, but be careful you are not mixing client concerns and server concerns. It may start with small compromises "I need this property only on the client, but everything else is the same", but you might end up with flags to tell the class whether to use client or server behavior and other nastiness.
Having separate implementations of the POCO's may seem as code duplication at first, but it frees you to have an implementation fitted to the task.
That's why using Automapper and the like makes sense, it lowers the barrier of writing the mapping code.
Another reason to do this (which has been also mentioned) is that the DTO's should be a way to implement a communication API, and not the API itself: i.e. the DTO's are there for WCF to implement a SOAP API (or REST or whatever), but the client should be free to implement the communication layer using only the API specification, without any hidden logic in the mapping code.
This also ensures your API remains language agnostic. You might want to provide client libraries (in any of several appropriate languages) to ease the interaction with your API, but these should not be a requirement.

Entity Framework business object transformation

I am trying to create a small personal project which uses EF to handle data access. My project architecture has a UI layer, a service layer, a business layer and a data access layer. The EF is contained within the DAL. I don't think it's right to then make reference to my DAL, from my UI. So I want to create custom classes for 'business objects' which is shared between all my layers.
Example: I have a User table. EF creates a User entity. I have a method to maybe GetListOfUsers(). That, in the presentation, shouldn't reply on a List, as the UI then has a direct link to the DAL. I need to maybe have a method exposed in the DAL to maybe be something like:
List<MyUserObject> GetListOfUsers();
That would then call my internal method which would GetListOfUsers which returns a list of user entities, and then transforms them into my MyUserObejcts, which is then passed back through the layers to my UI.
Is that correct design? I don't feel the UI, or business layer for that matter, should have any knowledge of the entity framework.
What this may mean, though, is maybe I need a 'Transformation layer' between my DAL and my Business layer, which transforms my entities into my custom objects?
Edit:
Here is an example of what I am doing:
I have a data access project, which will contain the Entity Framework. In this project, I will have a method to get me a list of states.
public class DataAccessor
{
taskerEntities te = new taskerEntities();
public List<StateObject> GetStates()
{
var transformer = new Transformer();
var items = (from s in te.r_state select s).ToList();
var states = new List<StateObject>();
foreach (var rState in items)
{
var s = transformer.State(rState);
states.Add(s);
}
return states;
}
}
My UI/Business/Service projects mustn't know about entity framework objects. It, instead, must know about my custom built State objects. So, I have a Shared Library project, containing my custom built objects:
namespace SharedLib
{
public class StateObject
{
public int stateId { get; set; }
public string description { get; set; }
public Boolean isDefault { get; set; }
}
}
So, my DAL get's the items into a list of Entity objects, and then I pass them through my transformation method, to make them into custom buily objects. The tranformation takes an EF object, and outputs a custom object.
public class Transformer
{
public StateObject State (r_state state)
{
var s = new StateObject
{
description = state.description,
isDefault = state.is_default,
stateId = state.state_id
};
return s;
}
}
This seems to work. But is it a valid pattern?
So, at some point, your UI will have to work with the data and business objects that you have. It's a fact of life. You could try to abstract farther, but that would only succeed in the interaction being deferred elsewhere.
I agree that business processes should stand alone from the UI. I also agree that your UI should not directly act with how you access your data. What have you suggested (something along the lines of "GetListOfUsers()") is known as the Repository Pattern.
The purpose of the repository pattern is to:
separate the logic that retrieves the data and maps it to the entity
model from the business logic that acts on the model. The business
logic should be agnostic to the type of data that comprises the data
source layer
My recommendation is to use the Repository Pattern to hide HOW you're accessing your data (and, allow a better separation of concerns) and just be concerned with the fact that you "just want a list of users" or you "just want to calculate the sum of all time sheets" or whatever it is that you want your application to actually focus on. Read the link for a more detailed description.
First, do you really need all that layers in your 'small personal project'?
Second, I think your suggested architecture is a bit unclear.
If I get you right, you want to decouple your UI from your DAL. For that purpose you can for example extract interface of MyUserObject (defined in DAL obviously) class, lets call it IMyUserObject, and instead of referencing DAL from UI, reference some abstract project, where all types are data-agnostic. Also, I suggest that you'd have some service layer which would provide your presentation layer (UI) with concrete objects. If you utilize MVC you can have a link to services from your controller class. Service layer in turn can use Repository or some other technique to deal with DAL (it depends on the complexity you choose)
Considering transformation layer, I think people deal with mapping from one type to another when they have one simple model (DTO) to communicate with DB, another one - domain model, that deals with all the subtleties of business logic, and another one - presentational model, that is suited best to let user interact with. Such layering separates concerns to good measure, making each task simpler, but making app more complicated in general.
So you may end having MyUserObjectDTO, MyUserObject and MyUserObjectView and some mapping or transformation btw them.

Categories

Resources