Background
I like Jeffrey Palermo's Onion Architecture model (similar to Hexagonal Architecture) which prescribes that the Domain Model be at the 'center' and the concrete implementations of infrastructure, specifically Concrete Repositories be on the periphery.
So say I have a Domain Model:
//https://libphonenumber.codeplex.com/
using libphonenumber;
namespace MyApplication.Domain
{
public class Speaker
{
public virtual string Name {get;set;}
public virtual PhoneNumber PhoneNumber {get;set;}
}
}
Now I need to expose this Domain Model to other teams:
The UI Team hypothetically wants to add several Data Validation attributes and custom JSON serialization attributes.
The Infrastructure Team hypothetically wants to add XML Serialization attributes and some custom attributes from a 3rd party Database implementation.
The Public API Team hypothetically wants to add WCF attributes.
I don't want to give every team carte blanche to add their Attributes to my Domain Model and I especially don't want them adding all of their "layer specific" dependencies to my model assembly.
And this case is made more complicated because I'm using 3rd party 'domain models' in my own (in this case using Google's LibPhoneNumber to handle the Phone Number).
Ideally, they'd each need to create their own wrapper class like:
using MyApplication.Domain;
namespace MyApplication.UI.DomainWrappers
{
public class UISpeaker
{
private Speaker _speaker;
public class UISpeaker(Speaker speaker = null)
{
_speaker = speaker ?? new Speaker();
}
[Required]
public virtual string Name {
get{ return _speaker.Name; }
set{ _speaker.Name = value; }
}
[Required]
public virtual PhoneNumber PhoneNumber {
get{ return _speaker.PhoneNumber ; }
set{ _speaker.PhoneNumber = value; }
}
//Conversion operators
public static implicit operator UISpeaker(Speaker s)
{
return new UISpeaker(s);
}
public static implicit operator Speaker(UISpeaker s)
{
return s._speaker;
}
}
}
Question
Writing and maintaining the UISpeaker class is a pain and is boring boilerplate code.
Is there either a better way to add the Attributes each team wants to add without letting them directly edit the Domain Model? Or is there some tooling that can help generate these wrapper classes (I was thinking possibly a weaving tool like Fody or T4 Templates, but I'm not familiar enough with either to know if they could help in this use case).
Research
I looked around Stackoverflow and found some similar questions, but none that hit the full scope I'm looking for:
Avoid using the JsonIgnore attribute in a domain model - Concluded to just use .NET native attributes on the Domain Model so you didn't have to take a dependency on Json.Net
Add an attribute to another assembly's class - Discussed using CustomReflectionContext to add Attributes to an existing type. This looks really cool, but unfortunatly, the model would be handed off to 3rd party code (ORMs, EF, Json.Net, etc) for reflection so I don't think this will work here.
Having Separate Domain Model and Persistence Model in DDD - Confirmed that each layer should have it's own version of the Domain Model, but didn't discuss if there's any tooling / strategies to make writing / maintaining that code any easier.
You can use these options to simplify the job:
Metadata Classes
Object to Object Mappers
Code Generation
Metadata Classes
You can create metadata classes and add attributes like data annotations and validation attributes to those metadata classes and then relate these metadata classes to your main domain classes using AssociatedMetadataTypeTypeDescriptionProvider. Such metadata classes are only attribute containers and using type descriptor mechanisms add attributes to your main classes.
For example, you can register a metadata class for your model this way, and let all infrastructures that benefit TypeDescriptor see your metadata attributes for your model:
var provider = new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Model),
typeof(ModelMetadata));
TypeDescriptor.AddProvider(provider, typeof(Model));
Object to Object Mappers
You can have view models, business models and domain models in different layers and using decorate them with attributes that you need for each layer, then using an object to object mapper like AutoMapper simplify the task of mapping those classes to each other.
AutoMapper is an object-object mapper. Object-object mapping works by
transforming an input object of one type into an output object of a
different type. What makes AutoMapper interesting is that it provides
some interesting conventions to take the dirty work out of figuring
out how to map type A to type B. As long as type B follows
AutoMapper's established convention, almost zero configuration is
needed to map two types.
Code Generation
You can make creating metadata classes or view model classes more easy using some code generation tools. For example you can create the wrapper classes simply using a code generation mechanism like T4 Templates.
In Visual Studio, a T4 text template is a mixture of text blocks and
control logic that can generate a text file. The control logic is
written as fragments of program code in Visual C# or Visual Basic. The
generated file can be text of any kind, such as a Web page, or a
resource file, or program source code in any language.
Related
c# supports using a MetadataType class for applying additional decorators to classes which you don't want to edit directly (perhaps they're generated classes from Entity Framework, for example)
As a trivial example:
//auto generated class definition
public partial class DataClass
{
public string DisplayName {get;set;}
}
//apply a metadata definition
[MetadataType(typeof(DataClassMetadata))]
public partial class DataClass
{
}
//implement the metadata
public class DataClassMetadata
{
[Display(Name = "Display Name")]
public string DisplayName {get;set;}
}
This is all fine and dandy, until you have a another custom decorator to add which relies on dependencies you don't want to add to your business layer. For example, MVC remote validation which requires references to the MVC libraries.
What I'd like to be able to do is add another layer of metadata in the web project without losing the metadata defined in the business layer.
I thought about using some kind of inheritance, perhaps something like:
public class RemoteDataClassModelMetadata : DataClassMetadata
{
[Remote("DataDisplayNameIsValid", "Validation")]
public string DisplayName { get; set; }
}
and then having a view model which used this metadata definition - but it seems this just hides the decorators on the base class. Making the class partial won't work because the duplicate members won't even compile.
The problem can be avoided by either adding all the MVC references to the business layer (but this means that non web applications that rely on the business layer must now take on a web dependency for no good reason) or by duplicating the decorators in the web project (but this seems like the kind of thing that will lead to curious bugs and odd behaviour later on a project where a new dev doesn't realize they are defined in two places).
Is there a way to combine decorators from different metadata classes for this kind of use case? (Or is there a better solution to this problem that I'm totally overlooking?)
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.
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.
I have just started working on an MVC project and things are going ok but it looks like I am creating alot of spaghetti code with just too many objects. Can anyone see how I can simplify this solution before the whole projects gets out of hand?
ok, here's my set up:
DAL - has Entity framework connections and methods to obtain data then convert the data to my model objects in the model layer
BLL - sends the data back up to the UI
Model - this contains all the model objects that are used throughout the site, anything coming from the DAL is converted into these objects by creating a new object then populating the variables.
UI - my MVC solution
The DAL,BLL and Model are also used by other solutions.
Now with MVC, I am trying to use the validation annotations ([Required], etc) which means I have to re-create the model objects with the annotations. This is fine but if I want to save the data back into the database I need to convert the classes which is just messy.
Can anyone see how I can use my current model class library with MVC model objects that use the validation annotations?
If I have not explained myself clearly please let me know and I will provide more details.
Thanks
Ideally there needs to be a separation from the domain models on one hand and MVC models (they are really ViewModels) on the other hand. This separation is really crucial and strongly advised.
These will look a lot similar in most cases although ViewModel can contain extra stuff. Then you can use AutoMapper to convert from one to the other.
For example:
public class User // in entity DLL
{
[Required]
public string Name {get; set;}
}
public class UserViewModel : User // in MVC DLL
{
public string LastVisitedPage {get; set;} // which only MVC needs to know
}
Mapper.Map<User, UserViewModel>();
Mapper.Map<UserViewModel, User>();
you can put the metadata in metadata objects without recreating the model objects. Here is a very simple way of doing it, however it does require that the model objects themselves are marked as partial. I hope that is OK if not this solution will not work for you.
[MetadataType(typeof(PreviousResultsMetaData))]
public partial class PreviousResults
{
public class PreviousResultsMetaData
{
[DisplayName("Class Ranking Score")]
[Required]
[Range(0.0, 100.0)]
public object ClassRankingScore { get; set; }
}
}
in the example above there is a data model object called PreviousResults that is created elsewhere by some scaffolding code. It defines the POCO object that is sent to and from database using LINQ. The MetadataType attribute indicates the class that will be used to hold the metadata. Then you simply create plain objects that match the names of your real data members and annotate them.
I hope this helps.
You can use FluentValidation framework for validation. Look here
http://fluentvalidation.codeplex.com/
You can perfectly add attributes to your BLL (the business entities). Just add a reference and add a using statement for System.ComponentModel.DataAnnotations. Apart from that, you can implement the IValidatableObject interface (which is pretty easy, see below).
For the mapping, you can use for example AutoMapper, so you don't have to write to much of mapping logic yourself (if you can take advantage of the name mapping magic).
Validate example:
ICollection<ValidationResult> validationErrors = new List<ValidationResult>();
var validationContext = new ValidationContext(this, null, null);
Validator.TryValidateObject(this, validationContext, ValidationErrors, true);
return validationErrors;
How would you design an application (classes, interfaces in class library) in .NET when we have a fixed database design on our side and we need to support imports of data from third party data sources, which will most likely be in XML?
For instance, let us say we have a Products table in our DB which has columns
Id
Title
Description
TaxLevel
Price
and on the other side we have for instance Products:
ProductId
ProdTitle
Text
BasicPrice
Quantity.
Currently I do it like this:
Have the third party XML convert to classes and XSD's and then deserialize its contents into strong typed objects (what we get as a result of this process is classes like ThirdPartyProduct, ThirdPartyClassification, etc.).
Then I have methods like this:
InsertProduct(ThirdPartyProduct newproduct)
I do not use interfaces at the moment but I would like to. What I would like is implement something like
public class Contoso_ProductSynchronization : ProductSynchronization
{
public void InsertProduct(ContosoProduct p)
{
Product product = new Product(); // this is our Entity class
// do the assignments from p to product here
using(SyncEntities db = new SyncEntities())
{
// ....
db.AddToProducts(product);
}
}
// the problem is Product and ContosoProduct have no arhitectural connection right now
// so I cannot do this
public void InsertProduct(ContosoProduct p)
{
Product product = (Product)p;
using(SyncEntities db = new SyncEntities())
{
// ....
db.AddToProducts(product);
}
}
}
where ProductSynchronization will be an interface or abstract class. There will most likely be many implementations of ProductSynchronization. I cannot hardcode the types - classes like ContosoProduct, NorthwindProduct might be created from the third party XML's (so preferably I would continue to use deserialization).
Hopefully someone will understand what I'm trying to explain here. Just imagine you are the seller and you have numerous providers and each one uses their own proprietary XML format. I don't mind the development, which will of course be needed everytime new format appears, because it will only require 10-20 methods to be implemented, I just want the architecture to be open and support that.
In your replies, please focus on design and not so much on data access technologies because most are pretty straightforward to use (if you need to know, EF will be used for interacting with our database).
[EDIT: Design note]
Ok, from a design perspective I would do xslt on the incoming xml to transform it to a unified format. Also very easy to verify the result xml towards a schema.
Using xslt I would stay away from any interface or abstract class, and just have one class implementation in my code, the internal class. It would keep the code base clean, and the xslt's themselves should be pretty short if the data is as simple as you state.
Documenting the transformations can easily be done wherever you have your project documentation.
If you decide you absolutely want to have one class per xml (or if you perhaps got a .net dll instead of xml from one customer), then I would make the proxy class inherit an interface or abstract class (based off your internal class, and implement the mappings per property as needed in the proxy classes. This way you can cast any class to your base/internal class.
But seems to me doing the conversion/mapping in code will make the code design a bit more messy.
[Original Answer]
If I understand you correctly you want to map a ThirdPartyProduct class over to your own internal class.
Initially I am thinking class mapping. Use something like Automapper and configure up the mappings as you create your xml deserializing proxy's. If you make your deserialization end up with the same property names as your internal class, then there's less config to do for the mapper. Convention over Configuration.
I'd like to hear anyones thoughts on going this route.
Another approach would be to add a .ToInternalProduct( ThirdPartyClass ) in a Converter class. And keep adding more as you add more external classes.
The third approach is for XSLT guys. If you love XSLT you could transform the xml into something which can be deserialized into your internal product class.
Which one of these three I'd choose would depend on the skills of the programmer, and who will maintain adding new external classes. The XSLT approach would require no recompiling or compiling of code as new formats arrived. That might be an advantage.