Here is the mediator pattern, but Im not sure I understand it well.
It basically means, if many object want to talk to each other, then lets create a mediator and they will talk to that mediator: https://refactoring.guru/design-patterns/mediator/php/example
this kinda reminds me purely a "service locator" which still is a "bag" which has object put into it. And its an anti-pattern. Where is the justice?
EDIT: and to me, it also violates Demeter's law:
lets say I have table models injected:
class Test
{
Model users;
Model usersPasswords;
.
.
.
this.users.getAll();
}
lets refactor:
class ModelsMediator
{
Model users;
Model usersPasswords;
Model userEmails;
}
class Test
{
ModelDecorator models;
.
.
.
this.models.users.getAll();
}
there will be too many . . . dots.
Related
I've got an ASP.NET MVC application and am looking at ways to improve readability, testing, etc. Currently, much of the business logic is in the controller and I would like to move this to another location.
Here's one idea I have been looking at using: Entity framework creates entity classes for me (e.g. Product, Customer). Why not just create partial classes to store the business logic? Here is an example:
public partial class Product()
{
public static List<Product> GetGreenProducts()
{
using(MyEntities db = new MyEntities())
{
return db.Product.where(p => p.Color == "green").ToList();
}
}
}
Then, in the controller, I can do this:
public class ProductController : Controller
{
public ActionResult GreenProducts()
{
return View(Product.GetGreenProducts());
}
}
This approach seems 1) Very simple 2) Very clean 3) would allow for easy unit testing.
I think this is a relevant pattern. Can anyone identify any problems with this, or other thoughts?
There are two questions being asked here:
Why not extend EF classes with business log (as opposed to Controllers)?
Simple. Because business logic should not be coupled to EF anymore than it should be coupled to Controllers.
Essentially (and this is my interpretation of the OP's comment), why not put CRUD operations in EF as opposed to Controllers. Sample method given: UpdateLastModified does it belong in EF or a seperate Service?
UpdateLastModified is already far too coupled an example to begin with. You should not create a method to update a column on an entity. Do you also need UpdateCreatedBy, UpdateName, UpdateId? I sure hope not. EF gives you all the tools necessary to perform such trivial tasks.
The ProductService should be concerned with middle tier concerns, whatever they may be. Things like projecting the ProductEntity -> ProductDao and what have you. ProductService.UpdateLastModified should not exist.
I have problems in organizing my code when I want to update a non-simple domain object. The problem is to separate responsibilities for the controller and the service layer.
More explicitly, assume that we have a domain class Client that depends on other domain classes like Address and so on.
In the view there is a gsp for editing some of the Clients properties including some of the nested properties like street on the Address.
When I would like to update those fields I call the update method on a Controller (in this case the ClientController).
I like the feature coming from the errors of a domain class when validated. Like if I in the Controller write
Client client = Client.get(params.id)
client.properties = params
client.validate()
If the client now has errors it is very easy to display them in the edit view.
But, I thought that updating, saving and getting the client from the database (Client.get(theId)) should be handled by the service layer. In my case I have to update or create other domain objects (like the Address) before I update the Client.
So one of my questions are how should the API look like for the service layer?
public ... updateClient(…)
In the literature they have the trivial example of updating the age of a person. So, their API consists of the id of the person and the new age. But, in my case I have about ten params from the view and they are just a subset of all properties of a client and I don't know which one of these that have changed.
I would like to have a Client in the controller that I can validate and resend to the edit view if it has validation errors.
I would like to handle the database interactions and transactions from the service layer.
How can I combine these? What responsibilities should the different layers have regarding update? How should the API of the service layer look like regarding update?
If there is a good reference implementation somewhere I would be happy to study it. Many times the service layer is unfortunately totally or partially ignored.
The missing piece of this puzzle is command objects. These classes represent the contract for your API into your services and provide you the ability to have a concrete class for your views and for validation. Let's look at an example.
Given a domain class of Client which as an Address and several Phone instances your Service layer might look like this:
...
class ClientService {
def updateClient(ClientUpdateCommand cmd) {
..
}
}
...
While the ClientUpdateCommand looks something like this:
#grails.validation.Validateable
class ClientUpdateCommand {
Long id
String name
List<PhoneUpdateCommand> phoneNumbers = []
AddressUpdateCommand address = new AddressUpdateCommand()
...
static constraints {
id(nullable: false)
name(nullable: false, blank: false, size:1..50)
...
}
...
}
You will note that this command object is composed of other command objects, and has constraints for validation. It may seem like you are replicating your domain classes here, but I have found that the more complex your application then more differences will appear between the domain classes and your command objects.
Next up is the use of the command object within your controller and your views. A controller method may look something like this:
Class ClientController {
...
def clientService
...
def edit(ClientUpdateCommand cmd) {
...
cmd = clientService.load(cmd.id)
Map model = [client: cmd]
render(view: 'edit', model: model)
}
def update(ClientUpdateCommand cmd) {
Map model = [client: cmd]
if (cmd.hasErrors() {
render(view: 'edit', model: model]
return
} else {
clientService.update(cmd)
...
}
...
}
}
I have left a lot out of the controller as I didn't want to bore you with the details but rather show how a command object replaces the domain instance. In some ways it's a little bit more work but it moves you completely away from manipulating the domain classes and delegates that to the service you have created. You will also notice that the command object replaces the domain class instance for your model for your views. I won't bother giving you any examples of the GSPs since they really don't change much when using command objects like this.
I'm sure there could be entire chapters of books written on the subject, but hopefully this gives you some insight and you can see that the answer to your question(s) is: Command objects.
I can't really find a satisfying solution for that problem. I have a n-layers application :
UI
Presentation (Domain Model used as DTO, ViewModels are then presented)
Business Layer (Domain Model)
Repository and DAL (Data Model)
My problem is that I need to work with full objects in my business layer. However I can't figure out what is the best way to load them. The question may look stupid - and perhaps it is - but I'm very puzzled by it. I have the following classes (just to illustrate):
public class Library
{
int ID {get;set;}
string Name {get;set;}
Book[] Novels {get;set;}
Book[] TextBooks {get;set;}
}
public class Book
{
int ID {get;set;}
Library[] SalePoints {get;set;}
string Name {get;set;}
string Type {get;set;}
}
And I have two Service Methods LoadLibrary and LoadBook whose aim is to populate these respective models. My problem is that it looks like I will get into an infinite loop. I'll explain myself right now.
I have pre-loaded domain models coming from the Repositories (The repositories convert the Data Models into domain models using valueinjecter (unflatenning), so basically the simple fields (int, string, etc..), are populated in the resulting domain model but the IEnumerable properties are not. That's why I'm finishing to load them in the Service Layer. (There are also two reaons why I can't fully load them in my repositories : 1/ I'm using a generic repository and 2/ The loading logic relay on business rules)
Let us say that I do the following :
public class LibrairiesProcessor
{
public Library LoadLibrairyObject(int ID)
{
Library l = UnitOfWork.LibraryRepo.GetByID(ID); // Only retrieve "simple" properties, here it will get the Name and the ID properties;
l.Novels = UnitOfWork.BookRepo.Get(b=>b.LibrairyID==l.ID && b.Type="Novel");
l.TextBooks= UnitOfWork.BookRepo.Get(b=>b.LibrairyID==l.ID && b.Type="TextBook");
for(int i=0;i<l.Novels.Count();i++)
{
l.Novels[i] = BooksProcessor.LoadBookObject(l.Novels[i].ID);
}
}
}
and
public class BooksProcessor
{
public Book LoadBookObject(int ID)
{
Book b = UnitOfWork.LibraryRepo.GetByID(ID); // Only retrieve "simple" properties, here it will get the Name and the ID properties;
b.SalesPoint = // Get From repo using the Unit of work
for(int i=0;i<b.SalesPoint.Count();i++)
{
b.SalesPoint[i] = LibrairyProcessor.LoadLibraryObject(b.SalesPoint[i].ID);
}
}
}
Isn't there an infinite Loop ? LoadLibraryObject() calling LoadBookObject() and vice versa... And especially when you come to the book whose SalePoint is the librairy who triggered LoadBookObject()... at best the same work is done twice, but I really suspect that it will never end.
So I'm wondering if I'm doing the things right. My goal is to have fully loaded objects to avoid wondering if the object is enough loaded before using it, but I'm not sure of the solution I've came up with. How do you usually achieve that ?
It looks like a trivial issue but seriously I can't figure out how to load my stuff. I feel like I have a dilemma :
1/ Manually Populating all the properties and sub properties by using UnitOfWork.Repository, but I will have a lot of code and a lot of redundant code.
2/ Live with partially loaded domain models with some properties set to null, but I really don't want that. And since I'm not working with EF objects directly since my domain model is complex, I can't use their lazy loading stuff.
3/Call the Service LoadObject Methods from one LoadObjectMethod to an other, to avoid code redundancy, but it looks like I'm introducing a lot of recursivity.
How should I handle that ?
Thanks !
This is probably best suited for CodeReview, but here are a few thoughts that may save you some trouble :
Having a whole separate DAL object model might be overkill. Most modern ORMs will take care of the domain objects/DB mapping for you without polluting your domain model with persistence stuff. See Should I create in BLL project class the same like poco class in DAL project and return it to UI project if I want to display data from database?
Having a generic repository seems like a poor excuse for not being able to load lists of sub-entities. As for "the loading logic relies on business rules", if you're referring to the Novels/TextBooks distinction, there are other, less class-intensive ways of doing this.
"since I'm not working with EF objects directly since my domain model is complex, I can't use their lazy loading stuff" : how exactly is your model complex ? Technically speaking, why couldn't you use lazy loading ?
As a good practice, Aggregates shouldn't refer to one another with navigatable properties but with (lists of) ids. The object that got an Aggregate root from a Repository will call another Repository if it wants to load associated aggregate roots.
UnitOfWork.LibraryRepo looks awkward. The UoW should be injected or directly instantiated in the method, not made available as a singleton. Same is true for the Repository. Things will be more testable and loosely coupled if you pass an ILibraryRepo around to the method instead. Unit of Work and Repository are two separate concepts, they somehow converge in Entity Framework but from the outside, they shouldn't look as tightly tied togteher as that.
This is my first attempt, after reading a lot about DDD, TDD and Repository / UnitOfWork paterns, to make my own application.
I'm using Entity Framework, MVC 4 on .NET 4.0 (the server that will be running this application is a Windows 2003)
This is the basic simplified pattern logic (The original one uses a IRepository, IUnitOfWork, GenericRepository and extends the EF POCOs with a IEntity interface to give access to the common ID field. But this simplified example will be enough to ask my question)
View -> ViewModel -> Controller <- UnitOfWork <- Repository <- EntityFramework <- Database
View
Model.Employee.GetSeniority()
EmployeeDetailsViewModel
Employee e { get; set; }
Employee
DateTime dateHired { get; set; }
TimeSpan GetSeniority()
{
return DateTime.Today - dateHired;
}
Controller EmployeeDetails()
using(var unitOfWork = new UnitOfWork) {
return View(EmployeeDetailsViewModel model = new EmployeeDetailsViewModel {
e = unitOfWork.GetEmployeRepository().Find(o=>o.id == id)
});
}
UnitOfWork GetEmployeRepository()
return (_employeeRepository ?? _employeeRepository = new EmployeeRepository(this.dbContext));
Repository Find()
dbContext.Configuration.EnableProxyCreation = false;
Employee e = dbContext.Employees.Where(expression);
dbContext.Configuration.EnableProxyCreation = true;
return e;
Everything actually works properly. The problem is that I feel like something is terribly wrong here, and I'm not sure at which layer it should be fixed.
After getting suggested, by a lot of people (Hi Darin), to always pass ViewModels to views and no models, I started doing this. However, what I'm doing (I think) isn't much better. I'm simply encapsulating my model in a viewmodel. At first, it didn't sound that bad since my Find() method would turn proxy off before getting an object, which would result in a persistance-ignorant POCO. However, now that I want to add some logic in the POCOs, I feel like there is something wrong.
I think the problem resides in where my Business logic is and the fact that my Employee POCO should be mapped to a DTO object. However, where should I transfer the Employee POCO to a EmployeeDTO? Should that be the task of the Repository, the Controller or something else? I'm also unsure of where I should put my business logic (as simple as GetSeniority() displayed in the example). Should that be added to the EF POCO through partial classes or should that be in the DTOs? Or is there another missing step in the Employee -> EmployeeDTO transfer?
This is a great question. It looks like you are trying to find clean separation which is fantastic. I would break the problem up. You have Data Access and you have UI display and in between you have your business logic. If you want to use a Domain model approach here is how I would structure it.
Never expose EntityFramework Entity classes outside of Repository. You can choose to return Dto's (POCO') or Domain objects from your repository. If you want Dto's for more separation, that is fine you will just need another layer such as a service layer to convert the Dto's into Domain Objects.
Put your business logic in your Domain Objects. So Domain.Employee.GetSenority() would be on your domain object.
Any logic that does not fit in your Domain Objects can reside in your UnitOfWork or Service Layer.
Convert Domain objects to ViewModel in controller. At this point map Employee.GetSenority() to MyViewModel.Senority property. Basically your ViewModel is a Dto and only contains view specific logic which typically is not much.
Where do you call the repository. You could use the UnitOfWork pattern as you have it or simply create a Service Layer class. The key here is that these should be useable to other application types. For instance if you were to write a desktop or Windows 8 Style App, you would likely want to reuse either of these along with your Domain Entities.
I'm sure you are having fun with this. Good luck.
Wanna get views on a very basic structure as follows:
"Person lives inside town ABCTown. ( ABCTown consists of "Person" visually). And "Person" has information about town ABCTown", ie. he has knowledge about his town.
That's all .
A very basic approach would be making two classes Class_Person and Class_ABCTown . And exchanging references of each other.
public class Class_ABCTown
{
var person:Person ;
.....
.....
public function get personInfo()
{
return person.info() ;
}
}
public class Person
{
var abcTown:ABCTown ;
....
....
public function get townInfo()
{
return abcTown.info() ;
}
}
Now as a programmer, i want to extend the project more towords MVC design pattern. So what do you think, what classes can i add here, and how can i arrange them, to get a MVC design.
( For example Class_ABCTownView can be created to store the reference of PersonView, because visually, person is present inside the town )
Share your views.
Thanks
"Person lives inside town ABCTown. ( ABCTown consists of "Person" visually). And "Person" has information about town ABCTown", ie. he has knowledge about his town.
Based off of this I'd create a Person Class, a Town Class and have them consists of a One-Many relationships (one town can have many people). This is all that is needed for the model.
The Controller is sort of like a pointer that directs all user input to the correct action (so if you click the details button the controller will direct the application to go to the view page and display the model).
The view page essentially is used to display information and forms.
If you want an action to happen such as a person moving to a town, you can put in an Edit action for example in the Person Controller to edit information about a person such as which town they live in. This will cause the application to go to an edit view where users can make changes.
This is a well-known tutorial that teaches you what MVC is and how to use it: http://www.asp.net/mvc/tutorials/mvc-music-store
I think you are misunderstanding the MVC pattern. The code above represents the M part of MVC - the data Model. The V (View) would be the classes, JSPs, etc that present the information to the user, and the C (Controller) is the code that handles user interaction, retrieves the data model from persistence, updates the model, binds the model data to the View, etc.