I'm trying to structure my WPF MVVM application according to best practises. I have to start with a lot of existing code so don't have the option of resolving all structural flaws straight away. I like the following solution structure.
http://www.paulspatterson.com/technology/dot-net-development/mvvm-and-wpf-for-vb-net-series-2-part-1-again/
This separates the solution into the following projects; BusinessLogic, BusinessObjects, Infrastructure (Common reusable utilities), WPF Shell and Modules (application components to be injected using an IOC container).
I understand that the business object represents the human world entity whereas the business logic is the implementation details as discussed in this question.
What are Business Objects and what is Business Logic?
Therefore using MVVM does the business object just become a dumb container that doesn't actually do anything other than wait to have its properties changed by external business logic? I don't see how you decouple the business object from the business logic to the point of being able to have them in separate assemblies.
Take the following hugely simplified code:
public class Chart
{
private SizeChart _activeChartSize = new SizeChart();
public void Draw() {
// Size the chart object
_activeChartSize.Size(this);
// Do other draw related things
}
}
public class SizeChart
{
public void Size(Chart chartToSize) {
// Manipulate the chart object size
}
}
In the context of the MVVM solution structure described above (to my mind at least) the SizeChart class would be business logic and the Chart class would be a business object but placing them in different projects would be a circular dependency. Is the SizeChart class business logic or a business object and where in the solution structure should the SizeChart class reside if I adopt this proposed MVVM solution structure?
Apologies if this is an incredibly obvious and simple question to some people but it's difficult when you can't start with a clean slate to know how to best start transitioning poorly structured code to well structured code.
http://en.wikipedia.org/wiki/Business_object
Business Object: A type of an intelligible entity being an actor inside the business layer in an n-layered architecture of object-oriented computer programs.
Whereas a program may implement classes, which typically end in objects managing or executing behaviors, a business object usually does nothing itself but holds a set of instance variables or properties, also known as attributes, and associations with other business objects, weaving a map of objects representing the business relationships.
http://en.wikipedia.org/wiki/Business_logic_layer
Business Logic Layer : A business logic layer (BLL), also known as the domain layer, is a software engineering practice of compartmentalizing.
Within a BLL objects can further be partitioned into business processes (business activities) and business entities. Business process objects typically implement the controller pattern, i.e. they contain no data elements but have methods that orchestrate interaction among business entities.
So basically a business object models an entity (usually a real world object such as Employee or Account) whereas business logic facilitates the interaction between business objects and between other application layers.
I think the most appropriate answer was given by Daniel Hilgarth. His answer was don't separate the business logic from its objects, because this leads to an anemic domain model.
While I think the following WPF MVVM solution structure proposed by Paul S Patterson is a good one I don't think it's appropriate for everyone.
http://www.paulspatterson.com/technology/dot-net-development/mvvm-and-wpf-for-vb-net-series-2-part-1-again/
The creation of distinct Business Logic and Business Object projects probably works best if your business objects are Data Transfer Objects (DTOs) e.g. Linq to SQL rather than a more complex object such as a composite that may have tighter coupling to the business logic.
Business object is a rather amorphous term - is it a DTO, a POCO, or a mix of that with some business logic thrown in?
To me, I would consider something different - Chart and SizeChart are both controls rather than "business objects" or "business logic". It's not the fact that they have UI sounding function names in them, but that they are actually doing UI or rendering related work (sizing and drawing). The collection of data that these work with would be separate and would be assigned to the controls before invoking Size or Draw.
Note that this answer is agnostic of MVVM as it is a bit of a red herring - your question is more closely related to general n-tier design in which you also incorporate MVVM.
I ran into something similar on a project recently.
We have a web app that allows an administrator to create groups. One of the rules that was required was that you couldn't create two groups of the same name. What we ended up doing was creating a very basic object, a Group, and then creating a service called GroupService. GroupService does the rule checking so that when a user calls GroupService.Save(Group), the service goes out and checks for prior groups with the name. If the name is found, an error is given back to the user and the save doesn't occur.
In our case, the hierarchy is Controller has Services, Services have Repositories, and Repositories finally commit to the database. Running throughout each of these abstractions is the model, Group. But our model isn't just a 'dumb' object. It does contain the validation logic on the data fields themselves and has aggregate properties to simplify databinding.
Expanding this to the MVVM conecept, I would think the View Model would have the service that contains the business logic and a model that was to be incorporated into the View. Obviously the View would be bound to the ViewModel, but the ViewModel would have some instance of the Model object to bind to.
Related
I've inherited a WinForms application which has significant issues surrounding separation of concerns between business logic and UI control. The two are so completely intertwined that UI modification/extension has become near impossible without introducing significant regressions.
One of the issues I'm facing as part of an MVP refactoring proposal is how best to define actions that affect our model. There are a lot of these actions (e.g, updating customer history) which are utilized in multiple areas of the application, so I don't want to code model interaction directly into the presenter.
A lot of actions that affect a given persistent object are already encapsulated within that object (albeit as static methods). Should I continue with this pattern, refactoring to make the methods instance-based, or split the methods off into a separate set of API-like classes?
EDIT:
What I'm really asking here is: is it okay to encapsulate methods affecting the model within the classes defining the model, or should I keep these POCO, and implement the methods in a separate set of classes which define an API to the model?
When you are using MVP architecture, business logic and UI should not be intertwined. Because there is presenter sitting between business logic and UI. Presenter knows only interface of View, and Presenter subscribed to events of View. That's all what is known. You are free to changed controls on your View - arrange them, replace, change color - any UI stuff. And those modifications do not affect Presenter. And, of course those modifications do not affect business logic.
Now about Presenter. It just translates UI events to calls to Model, and then updates UI through IView interfaces. What calls to Model mean? It depends. It could be call to some service like WCF where business logic sits. It could be call to application or domain service object, or to repositories (in terms of Domain-Driven Design). But there should not be business logic. Presenter is simple translator of UI events to Model calls. It can create some DTO objects to assign them to View, but no real business.
And Model. Model is all those classes, which are called by Presenter. Here business logic sits. And business logic is not duplicated. If you need to update customer history, then it could be CustomerRepository, or some service object like SalesService. And that object is called by every presenter, which needs to update customer history.
Advice - do not use static methods for business operations. It tightly couples your objects. It makes testing impossible with standard testing frameworks. Use instance methods. Implement interfaces. Mock them. Your system will become loosely coupled and testable. Thats where benefit of MVP pattern becomes visible.
My question is in regard to the first "M" in MVVM, the model. I see a ton of variations on how to implement the model. Some are just POCO's with no business logic and no persistence logic, and others contain one or both.
Right now, in our application, we have a decent separation between models, views, and view-models. This is our current solution structure (its a WPF prism application):
Infrastructure
Module A
ViewModels
Views
Module B
ViewModels
Views
Models (shared amongst modules, which is why its in its own class library)
Services
DataAccess (possibly utilizing dapper-dot-net)
Shell (main WPF project)
We now need to figure out how to perform our CRUD against the database and keep our models updated. I like the idea of keeping the models pretty bare-bones and having a "Services" class library that contains our business logic and performs a unit of work pattern against our data access classes. Are there any known issues with keeping the models dumb and ignorant of business logic / data access? Is this pretty uncommon to do in MVVM?
I wonder if I'm limiting myself or making things more complex than they need to be by not placing some logic in the models, for example, loading a model from within its ctor given an argument. As a note, this will be a large application.
Our application will have to persist models to multiple databases. We're using Unity as our dependency injection container for our services. How would you recommend I tell the service which data connection to use? Ctor, per function, etc?
Kinda looking for someone who built a similar structure, and what their experiences were / recommendations are.
In my view, MVVM models just 'represent' the data and should therefore not have any logic, CRUD or otherwise embedded. You already have the Data Access Layer so it is perfectly normal to write your CRUD code there and to use DI to access this CRUD code from your models.
The "beauty" of MVVM is that it is open to interpretation so I'm sure someone else would argue that model IS the data and it can containt CRUD logic...
I have all my CRUD operations in my DAL and am yet to see the downside of that approach...
Something on my mind about structuring a system at a high level.
Let's say you have a system with the following layers:
UI
Service Layer
Domain Model
Data Access
The service layer is used to populate a graph of objects in the domain model. In an attempt to avoid coupling, the domain model will be not be persistence aware and will not have any dependencies on any data access layer.
However, using this approach how would one object in the domain model be able to call other objects without being able to load them with persistence, thus coupling everything together - which I'd be trying to avoid.
e.g. an Order Object would need to check an Inventory object and would obviously need to tell the Inventory object to load in some way, or populate it somehow.
Any thoughts?
You could inject any dependencies from the service layer, including populated object graphs.
I would also add that a repository can be a dependency - if you have declared an interface for the repository, you can code to it without adding any coupling.
One way of doing this is to have a mapping layer between the Data Layer and the domain model.
Have a look at the mapping, repository and facade patterns.
The basic idea is that on one side you have data access objects and on the other you have domain objects.
To decouple you have to: "Program to an 'interface', not an 'implementation'." (Gang of Four 1995:18)
Here are some links on the subject:
Gamma interview on patterns
Random blog article
Googling for "Program to an interface, not an implementation" will yield many useful resources.
Have the domain model layer define interfaces for the methods you'll need to call, and POCOs for the objects that need to be returned by those methods. The data layer can then implement those interfaces by pulling data out of your data store and mapping it into the domain model POCOs.
Any domain-level class that requires a particular data-access service can just depend on the interface via constructor arguments. Then you can leverage a dependency-injection framework to build the dependency graph and provide the correct implementations of your interfaces wherever they are required.
Before writing tons of code in order to separate everything you might want to ask yourself a few questions:
Is the Domain Model truly separate from the DAL? And yes, I'm serious and you should think about this because it is exceedingly rare for an RDBMS to actually be swapped out in favor of a different one for an existing project. Quite frankly it is much more common for the language the app was written in to be replaced than the database itself.
What exactly is this separation buying you? And, just as important, what are you losing? Separation of Concerns (SoC) is a nice term that is thrown about quite a bit. However, most people rarely understand why they are Concerned with the Separation to begin with.
I bring these up because more often than not applications can benefit from a tighter coupling to the underlying data model. Never mind that most ORM's almost enforce a tight coupling due to the nature of code generation. I've seen lot's of supposedly SoC projects come to a crash during testing because someone added a field to a table and the DAL wasn't regenerated... This kind of defeats the purpose, IMHO...
Another factor is where should the business logic live? No doubt there are strong arguments in favor of putting large swaths of BL in the actual database itself. At the same time there are cases where the BL needs to live in or very near your domain classes. With BL spread in such a way, can you truly separate these two items anyway? Even those who hate the idea of putting BL in a database will fall back on using identity keys and letting the DB enforce referential integrity, which is also business logic..
Without knowing more, I would suggest you consider flattening the Data Access and Domain Model layers. You could move to a "provider" or "factory" type architecture in which the service layer itself doesn't care about the underlying access, but the factory handles it all. Just some radical food for thought.
You should take a look at Martin Fowler's Repository and UnitOfWork patterns to use interfaces in your system
Until now I have seen that application can be well layered into three layers: Presentation-->Logic-->Data--and Entities (or Bussines Object). In the Logic Layer case you can use some pattern such as Transaction Script or Domain Model I'm supposing you're using this last. The domain model can use a Data Mapper for interacting with the data layer and create business objects, but you can also use a Table Module pattern.
All this patterns are described in Marttin's Fowler Patterns of Enterprise Application Architecture book. Personally I use Transaction Script because it is simplest than Domanin Model.
One solution is to make your Data Access layer subclass your domain entities (using Castle DynamicProxy, for example) and inject itself into the derived instances that it returns.
That way, your domain entity classes remain persistence-ignorant while the instances your applications use can still hit databases to lazy-load secondary data.
Having said that, this approach typically requires you to make a few concessions to your ORM's architecture, like marking certain methods virtual, adding otherwise unnecessary default constructors, etc..
Moreover, it's often unnecessary - especially for line-of-business applications that don't have onerous performance requirements, you can consider eagerly loading all the relevant data: just bring the inventory items up with the order.
I felt this was different enough from my previous answer, so here's a new one.
Another approach is to leverage the concept of Inversion of Control (IoC). Build an Interface that your Data Access layer implements. Each of the DAL methods should take a list of parameters and return a Data Table.
The service layer would instantiate the DAL through the interface and pass that reference to your Domain Model. The domain model would then make it's own calls into the DAL, using the interface methods, and decide when it needs to load child objects or whatever.
Something like:
interface IDBModel {
DataTable LoadUser(Int32 userId);
}
class MyDbModel : IDBModel {
DataTable LoadUser(Int32 userId) {
// make the appropriate DB calls here, return a data table
}
}
class User {
public User(IDBModel dbModel, Int32 userId) {
DataTable data = dbModel.LoadUser(userId);
// assign properties.. load any additional data as necessary
}
// You can do cool things like call User.Save()
// and have the object validate and save itself to the passed in
// datamodel. Makes for simpler coding.
}
class MyServiceLayer {
public User GetUser(Int32 userId) {
IDBModel model = new MyDbModel();
return new User(model, userId);
}
}
With this mechanism, you can actually swap out your db models on demand. For example, if you decide to support multiple databases then you can have code that is specific to a particular database vendors way of doing things and just have the service layer pick which one to use.
The domain objects themselves are responsible for loading their own data and you can keep any necessary business logic within the domain model. Another point is that the Domain Model doesn't have a direct dependency on the data layer, which preserves your mocking ability for independent testing of business logic.
Further, the DAL has no knowledge of the domain objects, so you can swap those out as necessary or even just test the DAL independently.
Assuming a "standard" 3-tier application (UI - Domain - Data), should the Domain Layer show to the UI classes originally defined in the Data Layer?
I mean, assuming there's a Product class defined in the Data Layer, is it wrong to make some method from my Domain Layer have methods returning it (this is, making them visible to the UI)? Or should I define in the Domain Layer itself some class that wraps the Product from the Data Layer, so the UI now doesn't depend on the Data Layer?
Thanks
You usually have a Product interface and a ProductImpl. The UI only knows of the interface and is perfectly decoupled from the Data layer (which uses the implementation class).
This kind of implementation binds the UI classes to data classes which generally is harmful. A better practice in all known scenario is to keep them separate. This will not only decouple them from each other but also give you the freedom to insert custom logic (anytime in future) between UI classes and data classes. It also gives you freedom to do customizations to data object without affecting the UI classes directly.
It depends on your architecture. For example, if you're using the MVVM pattern (Model-View-ViewModel) you have to define UI model classes in the middle.
The answer on this question strongly depends on what the domain layer exactly does.
If you've got nearly no or no logic in the domain layer, in 90% of all cases, there is no need to use different objects then defined in the data layer.
If you have a simple product class, which only holds values for passing data between Data Layer and UI and so on, it should be pretty safe to use them. You have only to be careful if the domain layer does much additional processing and some parts of objects of the data layer should not be exposed to the UI.
One thing you should do is to define an Interface for your Data Layer and only work with this interface, so you can make the Data Layer independent and switch quickly between different data sources if needed.
In concept the attributes required by the UI are derived from those held in the Data layer, but they are not identical to them. We enrich the data, for example adding reference data or derived values or combining items from different classes or perhaps denormalising data to make it easier to present. So in the most general case the UI data model and the persistence data model are different.
In really simple cases, especailly the sort of things I do in demonstration code there is little or no difference between the two models and if you do create a new set of classes you just end up with complete duplication. I think in this case Andreas_D's point about creating an Interface defining what the UI needs, and which may well initially be directly implemented by the Data layer is a nice compromise. It very clearly demarks the UI's interests and the Data Layer's responsibilities.
Is a Product domain class? How do you get Product class in UI tier? Do you really mean 3-tier? A tier is physical boundary so 3-tier means that UI / BL / DB are three different processes.
If you use Product as domain class (= data + logic) you should not share it with UI and you should create new data transfer object (DTO) instead. DTO transfers only needed information between two tiers.
If you don't share assembly / package with Product domain class with UI and instead you are creating new class from WSDL you can use Product domain class in your exposed service - serialization will transfer only data not logic.
If you use Product as pure container for data, you have already created DTO and you can share assembly / package with this class among tiers.
I am using a repository design with web applications (repository (data layer) exposing model (objects) to the business layer which is then consumed to the data layer (ui). Objects or lists of objects are passed between the layers with this type of implementation.
I am finding my business layer is a becoming a series of manager type classes which all have common GetAll, GetById, Save, Delete type methods. This is very common with a number of very small simple objects. This is the area of concern or opportunity for improvement (the series of smaller business manager classes). I am looking for options to avoid the whole series of smaller business manager classes mapping to the smaller objects which only do get/save/delete object.
The bigger objects which are closer to the functionality to the application have a number of methods in addition to the get/save/delete type methods (these manager classes are ok).
I am thinking there is a design pattern or implementation which will allow me to have one manager class which resides in the business layer which would accept an object as a parameter of a particular object type and the get/save/delete methods respectively know the type of repository object to spin up and pass the object to it for its operation.
The benefit here would be that I can have one generic manager class to pass save/delete/get's for smaller type objects to the appropriate repository class thereby reducing the many smaller manager classes.
Ideas on how to accomplish this?
thx
I would not go that way. The business layer classes can be as simple as code that forwards to the data layer, and it is true that they can be annoying to write, but they exist for a couple of reasons: validation, security, taking some actions based on business rules.
If you try to make a generic business layer, it will hard to include all the various things that a business class could do. The generic business layer will become much more complex than the one you currently have. Testing will be much harder. Adding a new business rule will be hard, too.
Sorry, this is not what you wanted to read, but I have already gone the route of generic systems and have always had lots of regrets.
The idea behind a repository (or a dao), is to further abstract data access concerns away from the business layer in order to simplify that layers focus on the "business" of a given domain.
That said, there are many common plumbing type of concerns that are reuseable across different applications, some of which do lend themselves to a supertype in the business layer. Consider the cross cutting concern of being able to retrieve a given business entity by some Id from a database, and you might come to the conclusion that it is in fact useful to have an Id property in a business layer supertype. It might even be useful if entities considered that Id when determining equality. Etc..
Now I do believe that Timores is right in principal and trying to write one application that fits all domains is both incredibly painful and totally fruitless, but I also beleive the the art of the profession is knowing how to use a variety of tools and when to apply which one, and having some core infrastructure code should be in your tool belt.
For a good idea of a framework concept for a web app that has been road tested, take a look at SharpArch.
HTH,
Berryl