I am planning on building a single page application(SPA) using RavenDB as my data store.
I would like to start with the ASP.NET Hot Towel template for the SPA piece.
I will remove the EntityFramework/WebApi/Breeze components and replace with RavenDB for storage and ServiceStack for building the backend API.
Most current opinions seems to frown upon using any sort of repository or additional abstraction on top of RavenDB and call for using the RavenDB API directly inside of controllers(in an MVC app)
I am assuming I should follow the same wisdom when using Raven with ServiceStack and make calls against IDocumentSession directly inside of my service implementations.
My concern lies with the fact that it seems my service implementation will become rather bloated by following this path. It also seems that I will often need to write the same code multiple times, for example, if I need to update a User document within several different web service endpoints.
It also seems likely that I will need to access Raven from other (future) pieces of my application. For example, I may need to add a console application that processes jobs from a queue in the future, and this piece of the app may need to access data within Raven...but from the start, my only path to Raven will be through the web service API. Would I just plan to call the web api from this theoretical console app? Seem inefficient if they are potentially running on the same hardware.
Can anyone offer any advice on how to utilize Raven effectively within my webservices and elsewhere while still following best practices when using this document store? It would seem practical to create a middle business logic tier that handles calls against raven directly...allowing my webservices to call methods within this tier. Does this make sense?
EDIT
Can anyone provide any recent samples of similar architecture?
FWIW, we're currently working on an app using ServiceStack and RavenDB. We're using a DDD approach and have our business logic in a rich Domain Layer. The architecture is:
Web App. Hosts the web client code (SPA) and the service layer.
Service Layer. Web services using ServiceStack with clean/fairly flat DTOs that are completely decoupled from the Domain objects. The Web Services are responsible for managing transactions and all RavenDB interaction. Most 'Command-ish' service operations consist of: a) Load domain object(s) (document(s)) identified by request, b) Invoke business logic, c) Transform results to response DTOs. We've augmented ServiceStack so that many Command-ish operations use an automatic handler that does all the above without any code required. The 'Query-ish' service operations generally consist of: a) Executing query(ies) against RavenDB, b) Transforming the query results to response DTOs (in practice this is often done as part of a), using RavenDB during query processing/indices/transformers). Business logic is always pushed down to the Domain Layer.
Domain Layer. Documents, which correspond to 'root aggregates' in DDD-speak, are completely database agnostic. They know nothing of how they are loaded/saved etc. Domain objects expose public GETTERs only and private SETTERs. The only way to modify state on domain objects is by calling methods. Domain objects expose public methods that are intended to be utilised by the Service Layer, or protected/internal methods for use within the domain layer. The domain layer references the Messages assembly, primarily to allow methods on our domain objects to accept complex request objects and avoid methods with painfully long parameter lists.
Messages assembly. Standalone assembly to support other native .Net clients such as unit-tests and integration tests.
As for other clients, we have two options. We can reference ServiceStack.Common and the Messages assembly and call the web services. Alternatively, if the need is substantially different and we wish to bypass the web services, we could create a new client app, reference the Domain Layer assembly and the Raven client and work directly that way.
In my view the repository pattern is an unnecessary and leaky abstraction. We're still developing but the above seems to be working well so far.
EDIT
A greatly simplified domain object might look something like this.
public class Order
{
public string Id { get; private set; }
public DateTime Raised { get; private set; }
public Money TotalValue { get; private set; }
public Money TotalTax { get; private set; }
public List<OrderItem> Items { get; private set; }
// Available to the service layer.
public Order(Messages.CreateOrder request, IOrderNumberGenerator numberGenerator, ITaxCalculator taxCalculator)
{
Raised = DateTime.UtcNow;
Id = numberGenerator.Generate();
Items = new List<OrderItem>();
foreach(var item in request.InitialItems)
AddOrderItem(item);
UpdateTotals(taxCalculator);
}
private void AddOrderItemCore(Messages.AddOrderItem request)
{
Items.Add(new OrderItem(this, request));
}
// Available to the service layer.
public void AddOrderItem(Messages.AddOrderItem request, ITaxCalculator taxCalculator)
{
AddOrderItemCore(request);
UpdateTotals(taxCalculator);
}
private void UpdateTotals(ITaxCalculator taxCalculator)
{
TotalTax = Items.Sum(x => taxCalculator.Calculate(this, x));
TotalValue = Items.Sum(x => x.Value);
}
}
There's two main parts to consider here.
Firstly, as you have already noted, if you go by the word of the more fanatical RavenDB fans it is some mythical beast which is exempt from the otherwise commonly accepted laws of good application design and should be allowed to permeate throughout your application at will.
It depends on the situation of course but to put it simply, if you would structure your application a certain way with something like SQL Server, do the same with RavenDB. If you would have a DAL layer, ORM, repository pattern or whatever with a SQL Server back-end, do the same with RavenDB. If you don't mind leaky abstractions, or the project is small enough to not warrant abstracting your data access at all, code accordingly.
The main difference with RavenDB is that you're getting a few things like unit of work and the ORM for 'free', but the overall solution architecture shouldn't be that different.
Second, connecting other clients. Why would a console app - or any other client for that matter - access your RavenDB server instance any differently to your web site? Even if you run the server embedded mode in your ASP.NET application, you can still connect other clients to it with the same RavenDB.Client code. You shouldn't need to touch the web service API directly.
Related
I am having trouble connecting the dots from many posts I have read (and coming to realize I probably need to buy Eric Evans book instead of relying on loads of internet material) I am trying to adhere to domain driven design, but I am having trouble on the best method to communication from the presentation layer to my domain before saving my data back to the database. To keep it simple, right now I have a user class that can have a list of jobs. When a user opens the application their active directory information is queried and this class is populated with their data as long as they have the app open. Then, the user can edit an existing job if they own it or create a new one. I started creating a service class that uses my UnitOfWork class thinking this would act as my communication, but that is where I am stuck.
Current Setup:
DAL - EF 6 generated POCOs and DbContext, Repository, Unit of Work
Domain - Entities, Repository & Unit of Work interface, domain interface services I refer to in this post?
Presentation - MVC (intranet), concrete service?
Questions:
Is the service class the best class to implement for this type of communication (and for creating new instances of my domain classes (e.g. a method to create a new job)? I realize I could use a factory pattern, but I did not want to get too complicated yet)? Would the service reside in the domain layer or do I create a separate project for an application layer? Then would the interface go in the domain layer and the concrete implementation go into the application layer? I feel like that could be over complicating the app. Also, is the service WCF or can I just create my own classes?
How do I map the ViewModel in my MVC layer back to the domain using this service (if that is the best way) without the presentation layer leaking in to the service? I've read up on DTOs, but then is that overkill in the service layer? Or is it okay to expose my domain entities as the ViewModel? I must be thinking about this incorrectly. I cannot picture how this interaction would look in a controller without some leakage. Sorry for all the questions, and thanks.
public class User
{
public int Id{ get; set; }
public string WindowsId{ get; private set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get { return FirstName + " " + LastName; } }
public string Email { get; set; }
public string WorkPhone { get; set; }
public List<Job> Jobs { get; private set; }
public void AddJob(Job job)
{
if(job == null)
throw new Exception("Job is null");
var newJob = new Job(this) //tell the job that this user is creating the job
{
Description = job.Description,
DueDate = job.DueDate,
Name = job.Name,
Reason = job.Reason
};
Jobs.Add(newJob);
}
}
UPDATE: My Solution
I ended up taking a little bit from everybody's answers.
#granadaCoder - I used my EF POCOs as the classes to pass around as DTOs because most of the time that is the data I was displaying to the user in my ViewModel. So it allowed me to use the DTOs as the ViewModels
#ChrisPratt - you are correct. Doing this prevented a lot of extra work. All I did was create a service that had all the queries I needed. And if I ever had to change the EF it would still not bother my other layers. All I would have to do is create the repository and UOW
#MilivojMilani - I did have repeating logic in the controller so the service layer kept me aligned with the DRY principal
#Yorro - I used your points and references to reinforce the design since I was still unsure about the service layer setup. Since this is a smaller project, I setup another folder with my service and interface that I created, no WCF
Stay away from the Repository/Unit of Work pattern if you're using Entity Framework. EF is itself an implementation of this pattern. If you want to abstract Entity Framework, then implement a service pattern that returns fully-baked data exactly how you need it. It's best illustrated with an example:
With EF/Repository
IQueryable<Post> posts = db.Posts.Where(m => m.BlogId == blog.Id && m.Status == PostStatuses.Published && m.PublishDate <= DateTime.Now).OrderBy(m => m.PublishDate);
With Service
List<Post> posts = service.GetPublishedPostsForBlog(blog);
The two key differences here are:
You're returning data already pulled from the database with the service; a repository/EF will return a queryable that may or may not have been executed against the database yet.
All your logic goes into the service method with a service. Whereas, with a repository/EF you build your query in place.
That said, don't get so hung up on the layers of your application. It's not about how many layers you have and what you call them, but rather about abstracting logic away from pieces of your application that shouldn't need to know how to construct that logic. A controller action to return a list of published blog posts, for example, shouldn't need to know what qualifies a post as being "published". That's domain logic that should go somewhere else (like the service method that returns this dataset). The idea is simply to follow the single-responsibility principle: a class/method/etc. should do one thing and do it well. Your controller action should only concern itself with returning the view (and doing the bare minimal amount of work to fetch what that view needs).
As far as mapping goes, the term explains exactly what you do, so I'm not sure of the confusion here. If you want to map Post to PostViewModel for example:
var model = new PostViewModel
{
Title = post.Title,
Content = post.Content,
...
}
Or with a list of objects, you can employ LINQ:
var model = posts.Select(m => new PostViewModel
{
Title = m.Title,
Content = m.Content,
...
}
If you question is simply: how do I do this easier? Then, you can look into a third-party mapping library like AutoMapper.
The Service Layer
The service layer serves as the application's boundery, it encapsulates your domain entities, in other words, it protects your domain. All communication to the domain must go through the service layer. But the Domain Model (at its purest form) should not have any reference to the Service Layer or any other infrastructure layers (DAL/Presentation).
http://martinfowler.com/eaaCatalog/serviceLayer.html
Would the service reside in the domain layer or do I create a separate project for an application layer? Then would the interface go in the domain layer and the concrete implementation go into the application layer?
If you are already segregating your layers into their own projects, then the service layer should have its own project.
Is the service WCF or can I just create my own classes?
The simplest service is just a class, see an example of a service layer straight from Microsoft Tutorials:
http://www.asp.net/mvc/tutorials/older-versions/models-(data)/validating-with-a-service-layer-cs
Here is another example on how to refactor an MVC using a service layer
http://www.arrangeactassert.com/asp-net-mvc-controller-best-practices-%E2%80%93-skinny-controllers/
How do I map the ViewModel in my MVC layer back to the domain using this service (if that is the best way) without the presentation layer leaking in to the service? I've read up on DTOs, but then is that overkill in the service layer? Or is it okay to expose my domain entities as the ViewModel? I must be thinking about this incorrectly. I cannot picture how this interaction would look in a controller without some leakage.
This question is another topic altogether. DTO is a good way for the service layer to communicate with outside layers.
Your questions are very good, and in fact it is the most frequently asked.
Is it overkill to use DTO in the Service Layer?
Is it okay to expose the guts(domain) of my application to outside layers?
How would the service layer interact with outside layers without leakages?
Where should the DTO reside?
I've answered the same questions here: https://stackoverflow.com/a/21569720/1027250
This image provides overhead view on how a service layer fits into a multi-layer architecture. Note that this is not absolute or perfect for every project, you should approach a pattern depending on the need of the project. Additional layers adds complexity, it is a long term investment on a long term project with a large team.
1.If you're using MVC you may or may not have a service layer. Ask yourself a following question - do you use this functionality on more than one place? If the answer is yes - use the application service (not domain service). If no, put it in the MVC controller itself.
Don't put any hydration logic in the domain layer. Domain layer in DDD shouldn't know anything about persistence. Controller/Application service should fetch the data using repository interfaces and save the data using same interfaces. In your case, you should be fetching and saving only the User class, while Job should be below it as aggregate root child. Using UnitOfWork and Repository is perfectly fine. Here is a good article on it =>
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
2.It is perfectly normal to, in some cases, use domain object as ViewModel class. In other more complex cases, you will have to map properties manually. Mapping is usually best done as extension method on ViewModel class. Some use AutoMapper though I'm against using it when mapping presentation classes to domain. All this mapping work should NOT be done in domain layer. You might have a lot of viewmodel classes and it would bloat the domain layer with presentation layer logic.
Hope it helped.
I currently have a UI Layer/ DomainService layer (domain logic and services reside here) and Repo Layer for persistance, I use Ninject to help decouple things.
I have kept my UI Layer very simple - which delegate tasks to the service layer, however I have a very complex application that depends on the loggedonuser, therefore my CRUD can get quite complex.
My problem though is: I have a service for almost everything and that then connects onto a GenericRepository.
For example
IOrder which communicates with the IDBRepo to get order info depending on what client accesses the order, then I have IShipping - which also connects to IDBRepoand retireves info... it gets complicated when 1 service needs to call another service, they are both connected to the IDBRepo.
I have managed to pull out the IUserSession and can give this to each service - but this all seems too complicated to me...
When setting up my test I have to do something like:
var db = new DBRepo();
var s1 = new OrderService(db);
var s2 = new ShippingService(s1,db);
Then to extend some/most of my services I have to add an ILoggingService and INotificationService - they both need access to the database too...
NOTE: I am not looking for a pure DDD, I am trying to take the best of things and make it work I guess that has been my problem...
Bob Cravens truck trackr is a good series of posts to read to get you thinking about it:
http://blog.bobcravens.com/2011/05/a-net-generic-repository-pattern-with-implementations/
In general I don't think it's a great idea to have interdependent services if you can avoid it. If you have to have it like that then consider using a dependency injection framework such as unity or spring.net or ninject.
Struggling with this one today.
Rewriting a web-based application; I would like to do this in such a way that:
All transactions go through a web services API (something like http://api.myapplication.com) so that customers can work with their data the same way that we do / everything they can do through our provided web interface they can also do programmatically
A class library serves as a data layer (SQL + Entity Framework), for a couple of design reasons not related to this question
Problem is, if I choose not to expose the Entity Framework objects through the web service, it's a lot of work to re-create "API" versions of the Entity Framework objects and then write all the "proxy" code to copy properties back and forth.
What's the best practice here? Suck it up and create an API model class for each object, or just use the Entity Framework versions?
Any shortcuts here from those of you who have been down this road and dealt with versioning / backwards compatibility, other headaches?
Edit: After feedback, what makes more sense may be:
Data/Service Layer - DLL used by public web interface directly as well as the Web Services API
Web Services API - almost an exact replica of the Service Layer methods / objects, with API-specific objects and proxy code
I would NOT have the website post data through the web services interface for the API. That way leads to potential performance issues of your main website. Never mind that as soon as you deploy a breaking API change you have to redeploy the main website at the same time. There are reasons why you wouldn't want to be forced to do this.
Instead, your website AND web services should both communicate directly to the underlying business/data layer(s).
Next, don't expose the EF objects themselves. The web service interface should be cleaner than this. In other words it should try and simplify the act of working with your backend as much as possible. Will this require a fair amount of effort on your part? yes. However, it will pay dividends when you have to change the model slightly without impacting currently connected clients.
It depends on project complexity and how long you expect it to live. For small, short living projects you can share domain objects across all layer's. But if it's big project, and you expect it to exist, work well, and update for next 5 years....
In my current project (which is big), I first started with shared entities across all layers, then i discovered that I need separate entities for Presentation, and now (6 month's passed) I'm using separate classes for each layer (persistence, service, domain, presentation) and that's not because i'm paranoid or was following some rules, just I couldn't make all work with single set of classes across layers... Make you conclusions..
P.S. There are tools that can help you convert your objects, like Automapper and Value Injecter.
I would just buck up and create an API specifically aimed at the needs of the application. It doesn't make much sense to what amounts to exposing the whole DB layer. Just expose what needs to be exposed in order to make the app work, and nothing else.
Several "parts" (a WinForms app for exmaple) of my project use a DAL that I coded based on L2SQL.
I'd like to throw in several WebApps into the mix, but the issue is that the DAL "offers" much more data than the WebApps need. Way more.
Would it be OK if I wrapped the data that the websites need within a web-service, and instead of the website connecting directly to the DAL it would go through the web-service which in turn would access the DAL?
I feel like that would add a lot of overhead, but on the other hand, I definitely don't like the feeling of knowing that the WebApps have the "capabilities" of accessing much more data than they actually need.
Any input would be greatly appreciated.
Thank you very much for the help.
You can either create web services, or add a repository layer that presents only the data that your applications require. A repository has the additional benefit of being a decoupling layer, making it easier to unit test your application (by providing a mock repository).
If you plan on eventually creating different frontends (say, a web UI and a WPF or Silverlight UI), then web services make a lot of sense, since they provide a common data foundation to build on, and can be accessed across tiers.
If your data access layer were pulling all data as IQueryable, then you would be able to query your DAL and drill down your db calls with more precision.
See the very brief blog entry I wrote on Repository and Service layers using Linq to SQL. My article is built around MVC but the concept of Repository and Service layers would work just fine with WebForms, WinForms, Web Services, etc.
Again, the key here is to have your Repository or your Dal return an object AsQueryable whereby you wait until the last possible moment to actually commit to requesting data.
Your structure would look something like this
Domain Layer
Repository Layer (IQueryable)
Service layer for Web App
Website
Service layer for Desktop App
Desktop App
Service layer for Web Services
Web Service
Inside your Service layer is where you customize the specific calls based on the application your developing for. This allows for greater security and configuration on a per-app basis while maintaining a complete repository that doesn't need to be modified until you swap out your ORM (if you ever decide you need to swap out your ORM)
There is nothing inherently wrong with having more than you need in this case. The entire .NET 4 Client Profile contains over 50MB of assemblies, classes, etc. I might use 5% of it in my entire career. That doesn't mean I don't appreciate having all of it available in case I need it.
If you plan to provide the DAL to developers that should not have access to portions of the data, write a wrapper or derive a new DAL. I would avoid the services route unless you're confident you can accommodate for the overhead.
Sounds like you are on the right track. If many applications are going to use the this data you gain a few advantages by having services with DTOs.
If the domain model changes, just the mapping to the DTO needs to change. You can isolate the consuming application from these changes.
Less data over the wire
You can isolate you applications from the implementation of the DAL.
You can expose different services (maybe different DTOs) for different applications if it is necessary to restrict what parts of the object model should be exposed.
What is considered the appropriate development for .asmx or wcf service classes regarding how many files, lines of code, responsibilities, etc? Do most people publish separate .asmx service files for the different crud methods for every class?
Generally speaking, a service should encapsulate a set of common operations. Regardless of whether you use ASMX or WCF, you shouldn't be creating one "service" for each operation. The general idea behind service-oriented architecture (SOA) is to model real-world business behavior. To give you a dumb, but hopefully effective, example...think of a waitress at a restaurant. The waitress provides a service to customers in the form of taking orders, serving those orders, providing drink refills, providing condiments, and finally handling payment. The service the waitress offers is not a single operation, its an aggregation of related operations.
However, it doesn't stop there. The true nature of SOA is that any given service is likely to rely on other services. The waitress can not do her job without relying on the services of the cook, to provide meals, the person serving the counter, where she can get instances of condiments and drink, and the services provided by the restaurant building itself. There are also some fundamental differences between the kind of service provided by a waitress, and that provided by a cook. To bring it down to technical programming terms...a Waitress is a task service, but a Cook is an entity (or CRUD) service. The waitress handles higher level operations that provide useful functionality to clients, while the cook handles lower level operations that provide fine-grained and complex functionality only to other employees of the restaurant.
I can't really give you a specific answer to your question, other than to say just organize your services however they logically fit. Its probably not a good practice to have one operation per service...however, it is not unheard of for a service to have just one operation. Task services often have just one operation. Entity services often have many operations, usually CRUD based, but sometimes additional services. There are also Utility services that provide lowest level, infrastructural operations (back to the restaurant, utility services would be like stoves, grills, the register, etc.) If you model your services after actual business concepts, then the operations they expose and their dependencies on each other should eventually become clear.
For some GREAT information on SOA, check out the SOA series by Thomas Erl (Prentice Hall), as they are the definitive resource for implementing a service-oriented enterprise.
First of all, the best practice for new development is to use WCF. See Microsoft: ASMX Web Services are a “Legacy Technology”.
Second, in SOA, one tries to create services with coarsly-grained operations. For instance, you would want an OrderProduct operation, rather than StartOrder, AddLineItem, AddOption, FinishOrder operations. The OrderProduct operation might accept an OrderDTO as follows:
public class OrderDTO {
public CustomerInfo Customer {get;set;}
public DateTime OrderTime {get;set}
public DateTime ShipTime {get;set;}
public List<LineItemDTO> LineItems {get; private set;}
}
public class LineItemDTO {
public int LineItemNumber {get;set;}
public string ProductName {get;set;}
public int Quantity {get;set}
public Decimal Amount {get;set}
public Decimal ExtendedAmount {get;set;}
}
Rather than a StartOrder method that just creates an empty order, followed by AddLineItem calls to add individual line items (as you might do from a desktop application), I'm recommending a single OrderProduct method that accepts an OrderDTO, which will have a collection of LineItemDTO. You'll send the entire order all at once, add all the pieces in a transaction, and be done.
Finally, I'd say that you should still separate into business and data layers. The service layer should be concerned only with the services side of things, and will call on your business logic layer in order to get things done.
Grab this book from wherever you can:
Service Oriented Architecture (SOA): Concepts, Technology, and Design
Answers each of your questions and many many more you're bound to run into during your implementation.