So i am reorganizing a winforms C# solution to help decouple and make it cleaner and more organized. The solution tracks a small business orders,etc . .
I have broken out the projects so far into
App.View - all GUI Related Code
App.Data - just data structures and interfaces. No other implementation code
App.BusinessLogic - all business logic code that has no GUI references
I have some classes that i can't figure out where they belong. Please let me know your thoughts which project each class should go or if there is another project that should get created for this.
A Class that retrieves user preferences from a database
A Class that retrieves static data from our static data server and returns sets of data results.
A Class that brings down user entitlements
A model class that stores a hashtable of orders
A class that emails out messages on a user action
Actually, I think you have things a little off from a traditional layered architecture. Normally, the models of your data that your application works on would be kept in a business layer, along with the code to operate on them. Your data layer would have both the data models of your persistence framework and the code to interact with that framework. I think this might be the source of the confusion between the suggested locations of your classes and your reaction to it based on your comments.
From that perspective anything that retrieves or brings would necessarily be located in your data layer -- it's accessing data in persistent storage. What it retrieves are eventually converted into business layer objects that your business logic operates on. Things are are conceptual models -- like a table of orders -- or business actions belong in the business layer. I would agree with #Adron with, perhaps, the same confusion about where (3) goes depending on what it actually is.
More specifically:
User Preferences are business
objects, the thing that retrieves
them is a data layer object.
The static data maps on to a business
object (table or view or something),
the thing that accesses the external
server is a data layer object.
The user entitlement is a business object, the thing that retrieves it is data layer object.
A table of Orders is a business object
Emailing is a business activity, so the thing that mails people is a business object
[EDIT] My generalized 3-Tier Architecture for (simple) web apps
DataAccessLayer
This would include my TableAdapters and strongly typed DataTables and Factories that turn rows of my DataTables into business objects in pre-LINQ projects. Using LINQ this would include my DataContext and designer generated LINQ entities.
BusinessLayer
This would include any business logic, including validation and security. In pre-LINQ these would be my business objects and any other classes that implement the logic of the application. Using LINQ these are the partial class implementations of my LINQ entities to implement security and validation along with any other classes to implement business logic.
Presentation
These are my web forms -- basically the UI of the app. I do include some of the validation logic in the forms as an optimization, although these are also validated in the BL. This would also include any user controls.
Note: This is the logical structure. The project structure generally mirrors this, but there are some cases, like connections to web services, that may be directly included in the web project even though logically the components are really in the BL/DAL.
Note: I'll probably be moving to MVC over 3-Tier once ASP.NET MVC is in production. I've done some personal projects in Ruby/Rails and I really like the MVC paradigm for web apps.
You have specified that App.Data should contain only data structures and interfaces, no implementation code, which is fine if you want to do that, but that leaves you with nowhere to put your database access code except in your App.BusinessLogic assembly.
Perhaps you really need to rename App.Data to App.Model (or something similar), and have a new App.DataAccess assembly that talks to the database (perhaps implementing a Repository pattern). Having done that, I would split things up like this:
App.DataAccess
App.DataAccess
App.DataAccess
App.Model
App.BusinessLogic
I would probably go with
Data
Data
Data, although I'm not entirely sure what the class is doing
Data
BusinessLogic
-> App.Data
-> App.Data
-> App.BusinessLogic or App.Data - not sure exactly what this means.
-> App.BusinessLogic
-> App.BusinessLogic
Related
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).
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 created a solution in Visual Studio to attempt to implement a basic 3-Tier C# Application. I've researched this concept and now I am trying to put it together using different projects for each Tier i.e I have projects for DataAccess, BusinessRules and BusinessObjects.
Should the BusinessRules project contain references to the DataAccess and BusinessObject projects? (And DataAccess and BusinessObjects should not reference BusinessRules?)
After setting this up, I realised although I understand what each layer is responsible for, I didn't know if you should populate a Business Object(s) with data in the DataAccess layer, or whether the DataAccess Layer should pass the requested data to the BusinessRules and then populate the objects - what is the recommended way of doing this?
While it probably doesn't help with your question, the answer will always be "It depends." There is no "one ring to rule them all" when it comes to this. If there were, architects wouldn't be needed.
That being said, in my particular case I like to:
Have the Data Access layer operate on business objects. This assumes the DAL is all in code and not split between code and stored procs in a database.
Have the Business Rules layer operate on business objects. Again assumes all code rather than stored procs.
The Business Rules to Data Access is a tricky question. It depends heavily on the type of app and the rules. If you need your business rules to update the store, I'd probably extract interfaces from the DAL so that the business rules could depend only on the interfaces.
Again, those items work in my case. They could be completely wrong for you. Also, you didn't mention a user interface layer, a service layer, a blah blah layer, etc. There can be a lot of pieces and parts.
There aren't any hard rules that you must follow to be correct. You have to look at your needs, your requirements, and what constraints you have.
Good luck.
I Am creating a web application and first use Entity Framework. I created Entity Data Model and now I am not sure, how to proceed now.
Premise: My database is really simple (Rating, WebPage, Visitor) and database tables corresponds to the business objects.
My suggestion is 3tier architecture but how to make it?
It is good idea create partial classes with the same name as Entity Framework objects (Rating, Visitor) and declare here new methods (GetAverageRating()...)? Or is better create some VisitorProvider, RatingProvider and place logic here?
It is better use EF objects in BLL and Presentation Layer or I should create my own BO objects on my BLL layer and transform EF object to BO?
I'm think, it is more practical use static methods on my DAL than instantiate classes on BLL. Do you agree?
Can you recommend me some best practices? I have many ideas how to create it, but I do not know what is the right.
3 layer architecture is quite popular but what it really means?
Presentation layer
Application layer
Database layer
If you ask what each layer means you can be pretty sure you will get several different answers. You can further divide each layer into sublayer and build layered hell like:
Client side presentation layer
Server side view layer
Controller layer
Service facade layer
Service layer
Domain objects layer
Repository + Factory layer
ORM layer
Stored procedure layer
Database view layer
Database table layer
WTF? That is just example that application can be easily over architected. It can go even worse if you insist that only neighbours can exchange data and if you decide to add special type of objects to be exchanged between layers instead of flowing sing set of objects through multiple layers.
Add layers which you need to make you more comfortable with developing the application and which will do reasonable separation of concerns and maintainability needed for the scale of your application. You can simply do the most simplest application which will be used just few weeks and must be developed as fast as possible. In such case you can do that within few days simply by using ASP.NET web forms and data source controls (or ASP.NET dynamic data). It can be badly extensible but in such situation it is exactly what you need to implement application quickly. Writing layers and doing all the stuff around maintainability and extensibility is reasonable if you need it. Another quick prototyping technique is ASP.NET MVC Scaffolding which can create quick multilayered skeleton of the application which can be further modified.
Both approaches are correct and it only depends on the approach you like. The first is called active record pattern but it is not used very often with entity framework. The second approach is more popular. You can either use EF directly in some middle class which you called Provider (common name is also Service). This class will do both data access logic and business logic. In more complex applications developers like to somehow wrap EF to separate class following repository pattern and call the repository either from service or directly from web app. code behind or controller (depending on amount of business logic). Try to do it without repository first. My personal opinion is that people should start to use repository only once they understand EF itself.
Again both approaches are correct. In a simple application it is fully acceptable to create EF model with POCO classes (EFv4.x) and use them in all layers. If you are using ASP.NET MVC you can find that you need special classes as view models to fully represent needs of your individual views. In a more complex application you can have separate objects exposed from a business layer - this is especially used if the business layer is exposed as a remote service (WCF).
It depends how you write these DAL methods - it is absolutely necessary to not share the EF context among requests! It also depends if you want to write some test or not. Layer defined by static methods is something which goes directly against testable architecture where you want unit test just single layer (unit testing with EF can be hard). It also depends if you want to use dependency injection which is based on instances.
Solution setup:
DAL (class library)
BLL (class library)
Common (class library (some common functionality - enums, logging, exceptions,...))
Application1 (Windows Application)
Application2 (Windows Application)
WebApp (Web application)
...
Let's say I have a Customer entity, which is:
a table in SQL server
a CustomerDataTable in DAL
a Customer class in BLL
a BLL.Customer class in all the applications
What kind of objects should BLL and DAL use for communication - DataTable or List<Customer> (for example)? In first case, BLL logic should transform Customer object to DataTable and send it to DAL. In secod case, DAL layer should be aware of Customer class, which is in BLL layer. But originaly DLL references DAL and not opposite...
Should I put all classes into seperate assembly, which is referenced by all others (Common, BusinessObjects, ...)? In this case I could use Customer class in all my projects.
Should I even bother to seperate DAL and BLL when I know, that only one BLL will use my DAL. In this case I could merge them together into one project.
PS - I am reading about DataTables and a lot of people say that we shouldn't use them at all. What are better options? Maybe it is time for me to learn some ORM mapping tools :)
In my opinion you should have another Layer (seperate dll). Like "domain", where would you keep all entities like Customer.
Then simply include in all higher levels(DAL, BLL, UI and others) in hierarchy this assembly.
Sample architecture can look like this:
(Database) <-> DAL <-> BL <-> UI
and on all levels you will have access to "domain" layer.
DAL should return List not a DataTable. On some stage your development process you may want to use in DAL some OMR like NHibernate with would also return a List, probably.
it's hard to answer this general question without knowing the application domain well enough.
I would start with thinking about where future changes are most likely and try to figure out from that where flexibility is required.
my following thought are just a suggestion. feel free to consider them and change/ignore what you feel is irrelevant.
separating the DAL from the BLL is almost always a good idea. the data scheme is one thing that should be encapsulated and hidden from the rest of the application, so leave your DataTables, DataSets, ORMs or any other solution hidden in the DAL. the BLL (and layers above it) should use simple data types (meaning simple classes). I think it would be a good idea to put those classes in a Model class library that has no references and can be used everywhere.
it feels like you have a bit too much layering...do you really need a Customer class in the BLL and another one in the Application layer? could be, but I would make sure and think it twice over.
from my experience in one of my recent project (a weather web site with 200K unique visitors daily), we used link2sql for data access (mostly read only data), and simple data classes all over our ASP.Net MVC application (of course as part of models/view models). it worked quite smoothly, and we could easily change the data scheme without breaking down other layers.
as for your last question about DataTables, these objects, should you decide to use them (I would vote against), belong solely in your DAL. they should not be exposed to other layers as that would create coupling to that specific class. what if tomorrow MS invents a much better class? would you switch over now that you have a gazillion references all over your projects to the DataTables, its method and properties? would be nicer to just change your DAL to work with the NewAwsomeDataTable class and the rest of your app is blissfully ignorant.
hope that helped :)
I would use the following pattern as it allows you to upgrade to a different persistence strategy later.
UI/Consumer <--- (view models) --> BLL <--- Models ----> DAL/Persistence
Here the View models are consumed outside the BLL and models are communicated across the BLL/DAL layers.
In your case the model can be anything the DAL uses - DataTables for example or later perhaps ORM entities. The BLL is responsible to mapping between the model and view model.
As to keeping types in their own assemblies - yes for view models and in order to maintain a consistency, yes for the models as well.
Keeping the models and view models separate stops leakage of the persistence strategies outside of the BLL and thus permits future design changes to the persistence.
One advantage of this separation is that that different view model consumers can have differing view models for the same persistence model/entity. Some could be small and have few attributes and others large and rich in functionality. It also permits you to introduce offline/disconnectedness capability as the view models could be returned at differing times allowing you decide data merging strategies. This also allows you're persistence entities (e.g. tables to grow and change shape). Since this looks like a .net implementation things like AutoMapper will provide a lot of functionality out of the box
Of course this may be way overkill for your app - however I'd still maintain a BLL mapping that only talks view models to all BLL consumers. This should give you enough decoupling.
Pushing the domain entities into the dal is an option that would remove the crcular dependency, but may not match your intent. This isn't unheard of, though; for example LINQ-to-SQL gnerated entities would live in the DAL.
Other options:
put them into a common lower assembly (but that may leave your BL rather empty)
use IOC to remove / reverse the reference between BL/DAL
There are no single right answers here.
Re DataTable; personally I agree - I'm not a fan ;) However, they can be used successfully and reasonably. But if I had to use them, I'd be keeping them in the DAL as an implementation detail - and not exposing them above that.