I've been in the process of re-writing the back-end for a web site and have been moving it towards a three-tiered architecture.
My intention is to structure it so:
Web site <--> WCF Service (1) <--> Business Layer (2) <--> Data Layer (3)
My issue is with the placement of the DTO's within this structure. I'll need to use DTO's to move data between the business layer and the WCF service and from the WCF service to the consuming web site.
During my research on here I've read some excellent discussions though I've been left scratching my head a bit:
Davide Piras makes some great points in this post and if I were to follow this design then I'd declare interfaces for the POCOs in a separate project. These would then be implemented by tiers (1) and (2). Whilst I like the use of interfaces it does seem like I'd be making more work for myself by declaring POCOs in (1) and (2) and then copying their data back and forth using something like AutoMapper.
This post uses a system where a business objects project is created which would be referenced by all tiers. This seems to be simplier than the other solution and seems to lead me to a solution that would be
Web site <--> WCF Service (1) <--> Business Layer (2) <--> Data Layer (3)
^ ^ ^
| | |
[ -- Business Objects Referenced here --]
My question is this: is there a code smell from sharing the business objects across three layers of the solution or are the two methods I've listed above just two different ways of cracking the same nut?
Let's think of your UI (website) and service (WCF + BL + DAL) as two distinct entities.
If you have 100% control over both, you should choose approach #2 since it will avoid translation between WCF proxy objects and your business objects in the UI layer.
Else, you are better off with approach #1 since one of the entities is kind of a 'black box' and is subject to change by external stakeholders. So, it's safer to maintain an internal set of business objects. This will need translation between your business objects and the WCF proxy objects (through Extension methods or a translator framework).
Now, not exactly sure of your UI layer complexity or its implementation (MVC, WebForms, etc.), so you may or may not need View specific objects (lighter for data-binding, faster to serialize to JSON, etc.), let's call this object as the Model.
If you don't need a distinct UI specific Model, suggest to mark your business objects as DataContract (in the context of WCF) and use them across layers. Don't forget to explicitly mark entities as Serializable if you are invoking WCF via the web ($.ajax).
Else, use DataContract in the service and a translator to convert DataContract to Model in the UI layer. A Service Adapter is a good fit here - it sits in the UI layer and is responsible for consuming the WCF service and translating between DataContract and Model. You may use a Service Proxy in the UI layer, which is a wrapper over your WCF service and is consumable over the web.
Lastly, aren't you are missing a reference to the Business Objects in your Data Layer? I believe you will populate your Business Objects from the data-store in the Data Layer itself.
I would say that it often depends on the complexity of the project you're building. For smaller projects that I've built, I shared my 'entities' (they were just simple DTOs, serializable data buckets with getters and setters) across the layers and didn't care too much about this. On of the biggest downsides was that the logic got scattered across the project (not only in the 'Business Layer') and had a procedural-style all around. This really seems like the Anemic Domain Model, but the complexity didn't creep in as the project didn't grow too much. Entity Framework has some templates you can build you entities off of as such (if I'm not mistaken they're called self tracking entities?).
For medium/bigger projects, I wouldn't use this approach and would keep entities and DTOs separately as they would serve different roles. The DTOs might have a totally different shape than your entities and trying to share them between the tiers/layers would be often smelly.
Related
To give you a quick overview of my application architecture, I have the following layers in my application:
Domain Model - Models the problem domain and business rules.
Service Model - Models the service contract consumed by the application.
Data Access Layer - Persistence of domain models, in this case using EF.
Services - Implementations of the service model.
Website - MVC web application.
Web API - RESTful web service API.
Now the problem is that the Web API came later; the MVC web application was the first thing that was built on top of the architecture.
I find myself having to replicate business logic and ViewModels (MVC) and Messages (Web API)...According to the DRY principle, I shouldn't be doing this, so the natural solution is to push the business logic into its own layer which is independent of the application layers.
But...this means that the business logic layer needs it's own set of models which sit between the application layer and the business logic layer. In this respect, it would not be applicable to use domain models, since these really shouldn't ever hit the application layer.
So in short, I'm looking for an industry accepted standard for business logic modelling. Is there an accepted standard for how this should work, and if so, what type of model (i.e. it's not a domain model, and it's not a view model) belongs to the business logic layer?
You have stumbled upon a contested point of discussion. I myself have struggled with this for a long time.
Object bigots will argue that you shouldn't even have a service layer. Your domain model could then be directly consumed which would eliminate the duplication of logic. Granted, those were the good old days of software modeling. With the advent of the web, apis and SOAs, we are forced to look at alternative ways of modeling our software. Enter Anemic Domain models.
Anemic Domain models essentially consist of light weight objects that resemble DTOs more than anything, with underlying services that do the heavy lifting.
The architecture you have described above seems to be a hybrid design. I am guessing by now you must have run into the issue of mapping EF classes to domain objects, which creates yet another layer of objects, unless you use POCOs, in which case you run into namespace issues and what not.
Anyways, I don't think there is an industry standard. What I can tell you is that I have seen a few patterns emerge here and there leaning towards Anemic Domain Models and it's not hard to see why. In disconnected environments (e.g. web, API), complex objects don't work very well, hence the affluence of services.
Since you have layered your application nicely and do not wish to expose your domain model objects, I would suggest using Anemic Models in your service implementations. These would essentially function as DTO objects that can be reused and serialized if the need be, but can also implement basic logic that may even map back to functionality implemented in the services.
On a final note, there is no one-size-fits-all. Use the right tool for the job. Patterns are meant to be guidelines, not step-by-step instructions, so make sure you feel free to tweak them in order to fit your particular needs while retaining the general idea.
You can read more about Anemic Domain Models here:
https://en.wikipedia.org/wiki/Anemic_domain_model
Make sure to check out Martin Fowler's objections to Anemic Domain Models as well:
http://www.martinfowler.com/bliki/AnemicDomainModel.html
I'm currently working on a project that consists of an ASP.NET MVC web application with a back-end wrapped in WCF services. I've used MVC and WCF on past projects but I've never been responsible for designing the architecture from scratch. I'm hoping for some feedback on my current design to make sure that I'm employing good design practices from a high level architectural view.
Here is the dependency diagram to give an idea of how things are structured:
A few things to note:
Common MyApp.Utilities project is for any functionality which needs to be shared across layers. Currently it only contains extension methods.
Service contracts and data contracts are in a common project which is shared between both layers.
EntityFramework is being used for data access.
Mapping goes Entity <=> DTO (data contract) <=> ViewModel
Still working on this, using AutoMapper and not entirely sure as to how I should "rehydrate" the DTOs when they are passed back from the presentation layer.
ServiceImplementation is simply a wrapper for business logic which is contained in a separate assembly.
The presentation and service layers are to be deployed to separate physical servers
Packages are all contained in a single folder in the solution's root folder and are checked into version control
Does any of this stand out as bad practice?
• Service contracts and data contracts are in a common project which is shared between both layers.
I would avoid this. It may seem like extra work but I would break these out into separate namespaces and classes, even if it leads to duplication. I normally shy away from planning for the unforeseen, however, I have never had a project in which all my data contracts aligned with all my service contracts. The hacks to accommodate the differences tend to lead to confusing anti-patterns.
The majority of these classes will have identical properties and they can easily be mapped using an auto mapper.
The architecture that you proposed above is pretty similar that I've used in my projects.
Some comments:
Data contracts (Entity Framework) are not in a common project;
We are using currently AutoMapper to map between entity framework model and service model (simple and complex types) and between
service model and view model.
We have interfaces implementation in DAC, Service layer and Presentation layers, to use dependency injection (we use Ninject), to
make layers more "testable", so we also have contracts in all these
layers.
Presentation is basically Web Api with restful methods.
It works great and I don't see any issues in your archtecture.
I’m trying to reevaluate our n-layer architecture and would love to get some suggestions based on your experiences. Here is our typical .NET n-layer (sometimes n-tier) design.
Project.UI
Project.Services
Project.Business
Project.Model
Project.DataAccess
DataAccess typically consists of Entity Framework 4 and Repository classes. I attempt to follow the Aggregate Root concept in order to avoid having a repository for table, easier said than done in my experience. I tend to have ~70% match between Repositories and Tables.
Model usually consists of my Entity Framework 4 entities, I've been using Self-Tracking EF entities with success.
Business is what I struggle with the most. I typically have a Manager class for every Repository. This class will contain methods like .Add() which will perform business validation before forwarding down to repository.Add().
Services, typically I will only implement this if in fact I am looking to create a web service based solution. This layer will be tasked with marshaling requests/responses between DTOs and entities. And most importantly provide the more coarse grained interface. For example a TradingService.SubmitTrade(), which is really a facade for a business transaction which might include AccountManager.ValidateCash(), OrderManager.SubmitOrder(), etc.
Concerns
My business layer is very entity centric, really it's just the glue between the entities and the repository, with validation in between. I've seen many designs where the Service Layer is what holds a reference to the repositories (in essence skipping the "business layer"). In essence it serves the same purpose as my Business layer, it does the validation, however its' responsibility (and naming) is a higher level, more coarse grained business transaction. Using the example above the TradingService.submitTrade() will not delegate to any business manager classes, it would itself query the necessary repositories, perform all the validation etc.
I like my design in a sense that I can reuse a business layer method in multiple service calls, however I hate the fact that for every repository I have a matching business layer manager, creating tons of extra work. Maybe the solution is a different type of grouping at the Business Layer level? For example combine individual Manager classes like PhoneManager and EmailManager (note I have Phone entities and Email entities) into a logical Manager class such as ContactsManager (note I don't have a "Contact" entity type). With methods such as ContactManager.GetPhones() and ContactManager.GetEmail(), etc.
I guess more than anything I am wondering how others organize and delegate responsibilities, whether they have the Service layer, Business layer, both, etc. What holds the ORM context reference, etc.
I tend to do what you outlined near the end of your concerns, and at the business layer group things into managers that make more logical sense from a business point of view.
Using Contacts for example, I certainly wouldn't have a PhoneManager or EmailManager. "ContactsManager" is a more useful grouping to me, accomplishing pretty much the same thing only with a lot fewer managers to deal with. From a business point of view, phone numbers and emails are just small pieces of a Contact anyway. Just because they have their own tables and entities doesn't mean they need their own manager. That doesn't mean that you can't reuse them. If you have a need to do work with email addresses in several places, ContactsManager can have the relevant methods.
What we tend to have in our environment is a database/entity layer, then a business layer that sits on the server and handles business rules and business logic. That business layer is exposed as a service via WCF to the client (or at least, stuff relevant to clients is).
It sounds like you already know what you want to do, so I'd suggest doing a bit of prototyping work on it and see how it works for you. :)
As described above I'm implementing a multi-tier architecture to work with WCF and Entity Framework 4 (with poco). Since I'm already have persistence ignorance with POCO I do need implement DTO or I can use WCF in its pure way?
The main quote is - I do need DTO to pass a lightweight object on the network or I can use my POCO entities.
What you guys recommend?
Its hard to answer unless you define what the "pure way" is. Are we talking SOA pure or WCF pure?
WCF proxies already are DTOs in a way because they do not bring along any business logic across your service contract. Creating another layer of DTOs on top of the proxy classes generated by WCF seems redundant.
The biggest question you want to answer is "how SOA is this solution?". You cannot share your POCO entities across service boundaries if you want to be SOA compliant. SOA is all about disparate contracts.
If you go all SOA based than you lose a lot of functionality because the classes your web tier will be working with most of the time will be stupid proxies. You'll have to repeat a lot of logic and you lost a lot of the "meta data, convention over configuration" functionality that MVC 2 provides.
If you throw the SOA buzzword into the shredder, which you should do ( http://soafacts.com/ ), then you'll have a much easier time sharing business logic and meta data information across tiers. If the only consumer of your web service is yourself than this method is probably your best choice.
This is where you could use DTOs to send across the wire instead of your POCO entities. The only downside is again, repeating logic, and lots of boiler plate ceremonial code that does nothing. Really depends on the size of your project. If its small, forget about DTOs, but if you have 20 developers working with 200,000 LoC than DTOs are probably worth creating.
As jfar said it depends on whether you are going to the be only one consuming the service, or whether the presentation tier is going to be you only.
If you are doing the later and it's only going to be you using your service then you can serialise you POCOs across the wcf service boundaries. This is something I have done recently and wrote this blog post about getting it to work. This will allow you to use the same entities in the app tier as well as the presentation tier.
Hope it helps.
The strongest reason to recommend a DTO when using WCF with EF is that EF database-first classes drag implementation-dependencies into your proxy classes. If you are using code-first with POCO classes, then there should be no implementation dependencies.
Try returning just your POCO classes, but then take a close look at the generated proxy classes. Make sure that there is nothing in those classes that is part of the EF infrastructure. If the proxy classes are clean, then you should be all set.
Is it good practice to reference my web applications domain layer class library to WCF service application.
Doing that gives me easy access to the already existing classes on my domain model so that I will not need to re-define similar classes to be used by the WCF service
On the other hand, I don't like the coupling that it creates between the application and service and i am curious if it could create difficulties for me on the long run.
I also think having dedicated classes for my WCF app would be more efficient since those classes will only contain the members that will be used by the service and nothing else. If I use the classes from my domain layer there will be many fields in the classes that will not be used by the service and it will cause unnecessary data transfer.
I will appreciate if you can give me your thoughts from your experience
No it's not. Entities are all about behaviour. data contract is all about... data. Plus as you mentioned you wouldn't want to couple them together, because it will cripple you ability to react to change very soon.
For those still coming across this post, like I....
Checkout this site. Its a good explanation on the topic.
Conclusion: Go through the effort of keeping the boundaries of your architecture clear and clean. You will get some credit for it some day ;)
I personally frown on directly passing domain objects directly through WCF. As Krzysztof said, it's about a data contract not a contract about the behavior of the the thing you are passing over the wire.
I typically do this:
Define the data contracts in their own assembly
The service has a reference to both the data contracts assembly and the business entity assemblies.
Create extension methods in the service namespace that map the entities to their corresponding data contracts and vice versa.
Putting the conceptual purity of what a "Data Contract" is aside, If you begin to pass entities around you are setting up your shared entity to pulled in different design directions by each side of the WCF boundary. Inevitably you'll end up with behaviors that only belong to one side, or even worse - have to expose methods that conceptually do the same thing but in a different way for each side of the WCF boundary. It can potentially get very messy over the long term.