My project has 4 layers: Presentation, application, domain, infrastructure.
I am using ORM for the write side. Read side, sometimes I have cases that have a complex query. I process by using a native query.
I write it at the infrastructure layer. But, I see some projects such as "ESHOPONWEB" write a native query in application layers.
Which layer should contain the native query?
I wasn't familiar with ESHOPONWEB aka eShopOnWeb, a reference architecture & implementation that Microsoft put out, but I see it has an accompanying eBook which includes an "Architectural principles" section, another on "Common web application architectures", and at a glance other sections explain the architecture in more detail.
Using the book and code should give you a good way to learn the relevant concepts at your own pace.
Which layer should contain the native query?
I'm not 100% sure what you mean by "native query". I did a quick search through the eBook and didn't see any obvious references to that.
Typical best practice architecture (like what is in the eBook) says that queries in the Application / Business Logic layer should be agnostic - meaning they should not contain any code or dependencies that tightly-couples the Business Logic to a specific Data Access provider.
So, if you need to query a data base, the database specific query code (or reference to a Stored Procedure in the database or any other database specific concept) should be in the Data Access code, which is in the Data Access (Infrastructure) layer.
If something in your Business Logic layer wants to do a query, there's three approaches that come to mind:
It wants to query itself, which it is free to do, using agnostic code against objects it already has.
It wants to query data from the database, it gets the Data Access to do that. The query inputs and results need to be transported between these layers agnostically. E.g. query results might come back as a collection/array/list of Data Transfer Objects (DTO) or Plain Old CLR/Class Objects (POCO).
You take some section of data from your database / Data Access layer, pre-load that as a database agnostic data model in the Business Logic layer, which it can query just like #1.
I'm not sure, but your Domain layer might be what you can use to do #3?
Does that make sense, and answer your question?
Regarding Layers
As the eShopOnWeb book explains, you want to keep various "concerns" (like business logic, UI, and data access all separate. The separation is to make maintenance and change easier to manage, especially over a long time. E.g.:
Keeping the business logic layer/code separate from the UI layer/code means that you should be able to add new types of UI without having to re-write the application code.
Keeping the business logic layer/code separate from data access layer/code means that you should be able to add/swap data providers (e.g. different types of database), and the business logic should be less impacted by database changes.
In the two points, above I say "should" because it depends on how clean and effective your separation is.
To translate that to your layers, UI is obviously your Presenation layer, Business Logic sounds like your Application and Domain layers, Data Access is your Infrastructure layer.
In the eBook they give an example (fig 5-1, pg 16) where they logically have those four layers you use but in the one code-base / package (it will all get deployed together).
Related
I have read many posts concerning the issue of having several databases and how to design a DAL efficiently in this case. In many cases, the forum suggests to apply the repository pattern, which works fine in most cases.
However, I find myself in a different situation. I have 3 different databases: Oracle, OLE DB and SQLServer. Currently, there exists a unique DAL with many different classes sending SQL queries down to a layer below to be executed in the corresponding database. They way the system works is that two of the databases are only used to read information from them, and the other one is used to either store this same information or read it later on. I have to propose a better design to the current implementation, but it seems as if a common interface for all three databases is not plausible from an architectural point of view.
Is there any design pattern that solves this situation? Should I have three different DALs? Or perhaps it is possible (and advisable) to apply the repository pattern to this problem?
Answers to your question will probably be very subjective. These are some thoughts.
You could apply command-query separation. The query side integrates directly with your data layer, bypassing any business or domain layer, and the returning entities are optimized for read and project from your databases. This layer could also be responsible to merge results from different database calls.
The command side consists of command handlers, using domain or business entities, which are mapped from your R/W database.
By doing this, the interface that you expose will be more clear and business oriented.
I'm not sure that completely abstracting out the data access layer with custom units of work and repositories is really needed: do the advantages outweigh the disadvantages? They rarely do, because you will you ever change a database technology? And if you do, this probably means a rewrite anyway. Also, if you use entity framework code first, you already have unit of work and an abstraction on top of your database; and the flexibility of using LINQ.
Bottom line - try not to over-engineer/over-abstract things; or make things super-generic.
Your core/business code should never be dependent on any contract/interface/class that is placed in the DAL layer of the application.
Accessing data is something the business/core layer of your application needs to be able to do, and this it should be able to do without any dependency of SQL statements and without having any knowledge of the underlying data access technology.
I think you need to remove any "sql" statements from the core part of the application. SQL is vendor dependent and any dependency to a specific database engine needs to be clean out of you core, and moved to the DAL where it belongs. Then you need to create interfaces that resides outside of the DAL(s) which you then create implementation classes for in one or many DAL modules/classes. Your DAL can be dependent of your core, but not the other way around.
I don't see why the repository layer can't be used in this case. When I have a database which I can only read from, I usually let the name of the repository interface indicate this, like ICompanyRepositoryRead.
In a 1 tier application i.e Mvc, you get a folder called models and you build and store your classes in there, I'm aware when it comes to a three tier application from what I have read it seems correct to store the models inside the business layer (2nd tier), and from the UI (first tier) I would add a project reference to the 2nd tier which will allow me to use the models and make calls to methods.
From the second tiers perspective it would call the data layer (third tier) and perform crud operations against the database, but the data layer would require the models from the business layer so when I try to add a project reference from data layer to business layer i get the error
A Reference to "Business Layer" could not be added, adding this project as a reference would cause a circular dependency
Which I understand as a reference has already been made via business layer to data layer
How would I get around this? do I create additional models in the data layer and populate them with results from the database and pass that back to the business layer which then passes it back up to the UI? I'm slightly confused on this.
** Update **
From what I have read for the data layer to reference models inside the Business layer I would need to do model mapping, My model mapping will be quite large so I'm thinking of including a 4th tier which will be a shared library and that will consist of all the models that way the data layer and the business layer can access the models as and when is required.
A little off topic but ...
Depending on the size of your application, there may be no reason to introduce unnecessary complexities to try and follow pattern you may not necessarily understand. Doing so, will cause you extra headache.
That being said, if your project is of a large size and requires some good organizing, I would strongly suggest more research and maybe a few sample project in where you try out the architecture you came up with. No way you'll get it right the first time.
I would personally suggest looking into "onion architecture" instead of "n-tier", and of course you'll find many different views on it. You'll have to make your own decisions.
Here's a generic set-up I would start off with.
Core. It knows about no other project. This is where your classes with your "business" go. Such as Customer, Product, Order, etc.
Data. It knows about Core. It is responsible for taking in a Core object and storing it somewhere. That is all.
Service. It knows about Core AND Data. It's job is to expose methods such as "Create Customer", it will be responsible for creating a customer and storing it.
Web / Api / Mvc. This will know about Service. It's job is to expose your service to the user. (UI and such). (It may also know about Core / Data ... but that's a larger discussion.)
You're on the right track but I find it easier to think of the model layer as the data (third tier), the controller (business layer, second tier) manages the flow of the data between the ui (first tier) and the data layer.
If you modify your architecture this way, you should get rid of the circular references.
This also allows you to map your data layer objects to the appropriate less/more complex structures of the middle tier in a way which simplifies the interface shown to the UI and encapsulates the business logic there too.
I have been writing applications which are layered as:
DB<->DAL<->BL<->Service<->Presentation
And that's all that get's referenced. That is, The Presentation doesn't have a reference to the DAL.
We have a new app to write for a client, and the client is proposing something that is foreign to me. That is, the WRITE flow goes through the SL, but to READ data from the database, the want us to have a linq query in the presentation, direct to the DAL. That seems strange, but I am being told that my way is old fashioned and that my way, and their proposed way is essentially the same thing.
Also, my business logic usually resides in the BL, which is a separate project. But the client wants the business logic to be in the DTO object's themselves.
Is this normal? Is this basically Domain Driven Development or something? I find it strange that the linq calls to get the data for a form, is in the presentation layer, as opposed to my idea of a service layer method:
public MyPersonObject GetPersonByPersonId(int personId)
And then the same method in the Business, which might apply some rules to what is got, and then the same method in the DAL, which has the Linq.
Client is client, did you ever hear CQRS?
Your client might be affected by CQRS which is a new architecture fashion in domain driven design. In general, it separates command and query in different ways to database.
But in your client's proposed approach, it seems mixed up between traditional DDD and CQRS which does not use event sourcing inside. But it is still okay and normal, IMHO, query which provides data for presentation layer is trivial and it is not essentially complicated. It is like the report system which just queries data from database, you don't need to use ORM for this.
Also, my business logic usually resides in the BL, which is a separate project. But the client wants the business logic to be in the DTO object's themselves.
Business logic should be in domain entity, if not, seem you are violating Anemic Model anti pattern, it is also not in DTO. DTO is the concept of data transfer object between distribution layer with consumer.
What you describe is in no way DDD. While some DDD implementations do use a split architecture for queries and commands (CQRS approach), it doesn't remove the need for good layering of your application.
If writes go through a Service layer, it probably means that your software is at least of reasonable complexity and as such, should decouple presentation from persistence with a layer of abstraction in between. In CQRS, that layer often takes the form of Facades that accept queries and return DTO's containing the required data.
But the client wants the business logic to be in the DTO object's
themselves.
DTO stands for Data Transfer Object. DTO's don't contain any business logic and have no other purpose but to carry data.
I am creating a WPF application that uses a WCF service to interact with the data source. I use DI for both the client and the WCF server to ensure decoupled code, but I am unsure how to handle the data transfer from backend to user interface.
To keep the layers separate data is currently transferred from the database to the UI through several mapping steps. On the server side data entities are mapped to domain objects which again are mapped to service data contracts. On the client side WCF proxy classes are mapped to viewmodels.
Some developers at work claim that this "copying" of data between seemingly identical classes creates a maintenance problem because so many classes must be updated when a change is introduced. Instead they say you should use shared classes across the layers since we control both the client application and the WCF service. I too worry about the amount of work involved and see a potential performance penalty, but on the other hand using a shared class across the layers/abstractions might create tight coupling the way I see it. What is the best approach?
Using DTOs as business objects is not the best decision you can make.
From my experience I can say that usually when your objects are identical for all the layers then there is probably a problem with the architecture somewhere.
In a real business scenario it is quite unlikely that a business logic on a server and a business logic on a client have the same context and operate with the same objects. And if they have exactly the same structure with the database... hmmm... sounds like a data-driven application.
But if it is a data-driven application when clients access some data, modify it and save it back, then probably you don't really need this complicated layering? It sounds simple so let's keep it simple. If it is a data-driven application, why not just create a WCF DataServices context on top of your database and let it do all the dirty work for you when you just access your data over WCF without even thinking about DTOs, mappings, etc.
If it is not a data-driven application, then you probably have some complicated business logic on your server side, and this business logic usually operates with objects that make sense only its context. It just doesn't make sense to push these object all the way through to the UI.
Instead, the UI will probably send commands to the server in order to ask the system to do something. For example, it will send a "DisableAccount(id=123)" command instead of loading AccountDTO, changing its IsEnabled flag to false and pushing it back.
If there is a business logic, then it probably will be triggered by such command from the client who does not need to know how to disable accounts or how to do other things. It just knows and can command the system to do something.
So in this scenario client (the UI) just does not need the same object that server has. It may need some data to display to user, but it definitely will be in a format that make sense for the client's view, not for the business logic. It will probably contain some denormalized data, combined somehow.
Say, User for UI is not a DTO mapped to the Users table. It is another DTO, containing users data and statistics from different tables, processed somehow. Client does not need to know the internal structure of server's data storage so there is no need to expose it. Get the relevant data and send the appropriate commands, that's it.
Saying all this I should underline that it is NOT a binary choice you make. For simple features you may use a simple approach, for the features where having business logic make sense you may do the other things.
You do not have to choose one for everything. So you do not have to always create 3 similar objects just because it is "The Way" or always pass entities all the way through to the UI.
But what you will have to do is to clearly separate contexts and to define where which approach is going to be used.
In 80% you will probably end up with something simple (like WCF DataServices), and you don't need to do anything, and it is fine as in a lot of operations you just want to change the data.
But in other 20% (which is the "core" of your application) where the real business logic lives - here you may want this kind of separation not only for objects, but also for responsibilities between your layers.
All that mapping indeed creates a maintenance burden. Whether or not it's warranted depends on what you are building, and how complex the business logic is.
However, it's very important to realize that once you start sharing data structures across layers and tiers, the architecture is no longer decoupled. If you do that, you'd essentially be building a monolithic application. Don't get me wrong: there's nothing wrong with building a monolithic application if all you're doing is a glorified CRUD application, but it's essential to make that decision explicitly.
There's at least these alternatives:
Maintain strict layering. The mapping cost remains, but the code is decoupled.
Build a monolithic application. Collapse everything you can collapse. Keep it as simple as possible. It's going to be tightly coupled, but it just may become so simple that it doesn't matter.
Do something radically different, like building a CQRS application or a SOA mashup.
Personally, I prefer the third option these days.
I see nothing sacred about layers. Having layer-specific versions of each and every entity in the model would increase the number of classes a great deal. It's unnecessary, in my view. It violates the DRY principle: why keep repeating yourself?
What does layer purity buy you?
So I'd say the best approach is to pass those model entities around without fear.
I'm working on a small application from scratch and using it to try to teach myself architecture and design concepts. It's a .NET 3.5, WPF application, and I'm using Sql Compact Edition as my data store.
I'm working on the business logic layer, and have just now begun to write the DAL. I'm just using SqlCeComamnds to send over simple queries and SqlCeResultSet to get at the results. I'm starting to design my Insert and Update methods, and here's the issue - I don't know the best way to get the necessary data from the BLL into the DAL. Do I pass in a generic collection? Do I have a massive parameter list with all the data for the database? Do I simply pass in the actual business object (thus tying my DAL to the conrete stuff in the BLL?).
I thought about using interfaces - simply passing IBusinessObjectA into the DAL, which provides the simplicity I'm looking for without tying me TOO tightly to current implementations. What do you guys think?
I don't think there is a simple answer to your questions because there are many options depending on the circumstances. I have found it helpful to read the two books below to help me understand the problems you describe better.
MS .NET: Architecting Applications for the Enterprise (Esposito, Saltarello)
MS Application Architecture Guide, 2nd edition.
The second book is available online. Look here.
I think it is OK to pass the Business object to the Data Access Layer. I think the BLL's job is just to work with its objects, to check if all rules are being followed, about what can be saved, by whom, on what fields, time, etc.
Once it has done that it should pass it to the DAL, and I think it is IT'S job to figure out how to convert what it got into something that can be persisted, but it wont check what is being persisted or read or by whom, it will just do it. This could be straight foward, a la linq, but if your logic mdoels do not match your data model 1:1, then the DAL should do all the conversion.
About tying your DAL to the stuff in the BLL, I think you should worry about the other way around, tying your BLL to your DAL. I would use an interface to represent your DAL (as in IRepository) that way you can make your BLL call any kind of persistance mechanism just by changing the type of IRepository it is using (extra points if you use IoC :P). The concrete classes that implement the IRepository would be tied to the business objects, but they have to know what is it that they are saving don't they? while the BLL does NOT have to know what is doing the saving.
To pass business object in the DAL is the simpler and fastest method. It works in small projects, but have same disadvantages:
1) Business Objects are part of BLL layer, and if you pass objects in BLL then DAL becomes dependent of BLL. low layer knows about upper one - this contradicts the idea of layers at all.
2) Business Object are usially very complex to save it directly in BD. In this case it is better to introduce new "Mappers" intermediate layer.
To overcome all these issues I usially make interface to DAL independent of Business Objects. I use "Row" classes instead - representation of one record in the database or XML. In .NET 3.5 linqtosql autogenerated classes can be used for this purpose.
If I was in your position, I'd probably use LINQ to SQL to define my data access layer - it'll save you lots of work maintaining all that SqlCeFooBar stuff and give you a designer (of sorts) for maintaining your database that you would otherwise lack, using SQL CE.
So in that case, I'd probably couple the business logic layer pretty tightly to the entities exposed by the L2S layer. The justification being that the entities are the business objects, albeit devoid of any services.
I probably wouldn't let the entities get as far up the hierarchy as the UI though. At that level, it makes much more sense to use a model specifically for the view - especially given that you're using WPF.
Of course, all of this depends upon the size and complexity of your application. I'm assuming it's a fairly small scale application (single user?) given that you're using SQL CE.