In my onion architecture I've my PresentationLayer who contains a class named LogRabbitMQFilters with differents properties to filter search.
I pass LogRabbitMQFilters in ApplicationLayer by mapper :
public RabbitMQController(IELKService iELKService, IMapper mapper)
{
_iELKService = iELKService;
_mapper = mapper;
}
public async Task<IActionResult> Index(int? id, LogRabbitMQFilters filters)
{
var filtersMapped = _mapper.Map<LogRabbitMQFilters>(filters);
var response = await _iELKService.GetLog(filtersMapped);
/*some code.....*/
}
In ApplicationLayer I map my logRabbitMQFilters to RabbitMQFilters which is declare in Persistance layer and I call my repository like this :
public ELKService(IELKRepository iELKRepository, IMapper mapper)
{
_iELKRepository = iELKRepository;
_mapper = mapper;
}
public async Task<LogResult> GetLog(LogRabbitMQFilters logRabbitMQFilters)
{
var filterMapped = _mapper.Map<RabbitMQFilters>(logRabbitMQFilters);
return await _iELKRepository.GetLogs(filterMapped);
}
It's best approch to do this ? Is there another way to pass my filters class to the repository ? I thought of specification pattern but I don't now if it's a good solution.
DDD and onion architecture share common principles (e.g. domain isolation), however they also draw some different aspects regarding development techniques. It should be pointed out that architectures and designs should serve our goals rather than be the goals themselves.
From your description it seems you have a CRUD-style system. I see no business rules, no domain concepts, no specifications. And that is, of course, not a bad thing.
Isolating domain from other layers (presentation, infrastructure) is beneficial in particular when sophisticated validations are to be applied and business rules are to be enforced within complex entity objects. In your case, however, you map plain object LogRabbitMQFilters (presentation layer) to "itself" (application layer) then to plain object RabbitMQFilters (infrastructure layer). Passing an object as is from presentation layer to application layer is OK in cases like yours (even from a DDD/onion perspective), however:
The second mapping should not exist, since infrastructure layer knows domain and therefore should receive your (presumably) domain entity LogRabbitMQFilters.
LogRabbitMQFilters is actually not a true domain entity since, as mentioned before, it does not apply any business rule.
Flatly mapping objects from one layer to another seems pointless.
I thought of specification pattern but I don't now if it's a good solution
Specification pattern is very useful when we want to pack expressions as business invariants, e.g. having a class named ShortMessage (business invariant) encapsulating an expression such as Message.Length < 42. But with your case I see no use for that, due to the CRUD nature of your application: you simply receive some user properties to function as operands in the context of an ORM object representing a database table, in order to do something like that:
myORMManager
.FetchAll<MyTableObject>()
.Filter(record =>
record.DateDebut == filter.DateDebut &&
record.DateFin == filter.DateFin &&
.
.
record.Message == filter.Message
.
.
.
);
Each of the predicates separated by 'and' operator can be considered as specification, however such specifications are just technical, as they do not convey any business invariant. The object filter can actually be a client request.
To conclude, it is acceptable to develop a single-layer application directly using client properties as operands for database filter expressions, as long as business invariants are out of picture (or at least with low complexity). If you would still like to have a DDD framework, i.e. having an application service (where you may apply simple validations such as DateFin > DateDebut) and a repository object together with the controller object, then I would recommend to have a single class "walking through" all three objects
In regards of complexity it always great to break up the application
according to its responsibilities or concerns.
Considering your code, it seems you are following the industry specified standard. For better clarity I am also adding here a sample code snippet of a standard project architecture.
Controller:
[Route("api/User")]
[ApiController]
public class UserController : ControllerBase
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
[HttpGet]
[Authorize]
[Route("users")]
public async Task<ActionResult> Users()
{
var users = await _userService.GetAllUsers();
return Ok(new ResponseViewModel { output = "success", msg = "request successful", returnvalue = users });
}
}
Service Interface:
public interface IUserService
{
Task<List<UserViewModel>> GetAllUsers();
}
Service Implementation:
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public async Task<List<UserViewModel>> GetAllUsers()
{
return await _userRepository.GetAllUsers();
}
}
Repository Interface:
public interface IUserRepository
{
Task<List<UserViewModel>> GetAllUsers();
}
Repository Implementation:
public class UserRepository : IUserRepository
{
private readonly AppDbContext _dbContext;
private readonly IMapper _mapper;
public UserRepository(AppDbContext dbContext, IMapper mapper)
{
_dbContext = dbContext;
_mapper = mapper;
}
public async Task<List<UserViewModel>> GetAllUsers()
{
var users = await _dbContext.Users.ToListAsync();
var userViewModel = _mapper.Map<List<UserViewModel>>(users);
return userViewModel;
}
}
Model:
public class UserViewModel
{
public long user_id { get; set; }
public string full_name { get; set; }
}
Note: Hope above steps guided you accordingly. Additionally, you could also have a look our official document for more information
regarding industry practices.
Related
I am working on an ASP Core 2 project using JWT authentication and the Dapper ORM.
Like all ASP projects, I have a lot of controllers, each instantiating its associated data objects. Each data object inherits from an abstract DbObject class that provides database access services. I also have an AuthenticatedUser object that abstracts the JWT to make it's properties easier to use.
What I want is to do is create the AuthenticatedUser object in the constructor of DbObject. Of course, one method is to create it in the controller and pass it to every concrete data object but this is messy as it would have to be passed hundreds of times (and it just feels wrong).
Is there a way to use the ASP Core middleware to get the token after authentication and make it available through dependency injection in the DbObject?
Edit
Hopefully, this clarifies my intentions. I would like the controller to create data objects and use their properties and methods without regard to implementation (i.e. DbObject). But queries executed by DbObject will be filtered by information in the token of the logged in user.
public class ManufacturerController : Controller {
[HttpGet]
public async Task<IActionResult> Get() {
var manufacturers = await new Manufacturer().SelectMany();
return Ok(manufacturers);
}
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id) {
var manufacturer = await new Manufacturer().SelectOne(id);
return Ok(manufacturer);
}...
public class Manufacturer : DbObject<Manufacturer> {
protected override string QrySelectOne => #"
Select *
From org.fn_Manufacturers ({0})
Where Id = {1}";
protected override string QrySelectMany => #"
Select *
From org.fn_Manufacturers ({0})";
public int Id { get; set; }
public string Name { get; set; }
public string Phone { get; set; }...
public abstract class DbObject<T> {
protected readonly AuthenticatedUser authenticatedUser;
public DbObject(IHttpContextAccessor contextAccessor) {
authenticatedUser = new
AuthenticatedUser(contextAccessor.HttpContext.User);
}
protected abstract string QrySelectOne { get; }
protected abstract string QrySelectMany { get; }
public async Task<T> SelectOne (int id) {...}
public async Task<T> SelectOne(params object[] ids) {...}
public async Task<IEnumerable<T>> SelectMany () {...}
public async Task<IEnumerable<T>> SelectMany (params object[] ids) {...}
I suppose one solution may be to create a static data object factory which has the IHttpContextAccessor injected??
ASP.NET Core provides IHttpContextAccessor interface for accessing HttpContext from non-controller objects.
The usage is fair simple. Inject IHttpContextAccessor into DbObject and access HttpContext by calling IHttpContextAccessor.HttpContext:
public abstract class DbObject
{
protected DbObject(IHttpContextAccessor contextAccessor)
{
var context = contextAccessor.HttpContext;
// Create instance of AuthenticatedUser based on context.User or other request data
}
}
EDIT
Your controllers instantiate data objects directly (with new operator), that's why you can't have IHttpContextAccessor injected out of the box. Here are possible solutions. I list them in order of my preference (from best to worst).
If each controller uses only one (or just several) types of data objects, the best options will be to avoid direct instantiation and move toward normal Dependency Injection.
So if ManufacturerController requires only Manufacturer like in your sample then, it's better to inject Manufacturer instance to controller, not to create it inside:
public class Manufacturer1Controller : Controller
{
private readonly Manufacturer manufacturer;
public Manufacturer1Controller(Manufacturer manufacturer)
{
this.manufacturer = manufacturer ?? throw new ArgumentNullException(nameof(manufacturer));
}
[HttpGet]
public async Task<IActionResult> Get()
{
var manufacturers = await manufacturer.SelectMany();
return Ok(manufacturers);
}
// ...
}
IHttpContextAccessor will be injected into Manufacturer and passed to base DbObject:
public class Manufacturer : DbObject<Manufacturer>
{
public Manufacturer(IHttpContextAccessor contextAccessor) : base(contextAccessor)
{
}
}
It's the cleanest solution in the list. You use DI in classic way and utilize all benefits DI provides.
If one controller could use dozens of different data objects, you could inject the factory object that creates instances of data objects. It could be simple implementation based on IServiceProvider:
public interface IDbObjectFactory
{
TDbObject Create<TDbObject>() where TDbObject : DbObject<TDbObject>;
}
public class DbObjectFactory : IDbObjectFactory
{
private readonly IServiceProvider serviceProvider;
public DbObjectFactory(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}
public TDbObject Create<TDbObject>() where TDbObject : DbObject<TDbObject>
{
return serviceProvider.GetRequiredService<TDbObject>();
}
}
public class Manufacturer2Controller : Controller
{
private readonly IDbObjectFactory dbObjectFactory;
public Manufacturer2Controller(IDbObjectFactory dbObjectFactory)
{
this.dbObjectFactory = dbObjectFactory ?? throw new ArgumentNullException(nameof(dbObjectFactory));
}
[HttpGet]
public async Task<IActionResult> Get()
{
var manufacturer = dbObjectFactory.Create<Manufacturer>();
var manufacturers = await manufacturer.SelectMany();
return Ok(manufacturers);
}
}
The code for Manufacturer and DbObject does not change comparing to the first option.
I don't see any reason not to use option #1 or #2. However just to complete the picture, I'll describe another two options.
Inject IHttpContextAccessor into conroller and pass this instance (or IHttpContextAccessor.HttpContext.User) to Data Object constructor invoked with operator new:
public class Manufacturer3Controller : Controller
{
private readonly IHttpContextAccessor contextAccessor;
public Manufacturer3Controller(IHttpContextAccessor contextAccessor)
{
this.contextAccessor = contextAccessor ?? throw new ArgumentNullException(nameof(contextAccessor));
}
[HttpGet]
public async Task<IActionResult> Get()
{
var manufacturer = await new Manufacturer(contextAccessor).SelectMany();
// or
// var manufacturer = await new Manufacturer(contextAccessor.HttpContext.User).SelectMany();
return Ok(manufacturer);
}
}
It's a bad solution, because you don't use Dependency Injection for Manufacturer here and loose many advantages that DI provides.
And the worst option would be using of static object factory with injected IHttpContextAccessor. With this approach you also loose benefits of DI. In addition you get ugly code somewhere in Startup that initializes static instance of IHttpContextAccessor. When you come to this approach, you'll discover that theere is no quite elegant way to do this.
My advice: use option #1 untill you have good reasons against it. Then use option #2.
Here is Sample Project on GitHub with samples for approaches ##1-3.
My Startup.cs contains 40 repositories:
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IXRepository, XRepository>();
... 40 more lines ...
I'm trying to find a way to have this mess in a single line, but I'm failing miserably to put my head around this, I have several methods that are not available in the interface. Can someone provide some help? I understand why it is not working, it does not have a concrete repository, but I'm no closer to making this work.
InvalidOperationException: Unable to resolve service for type...
// IRepository.cs
public interface IRepository
{
}
// IUserRepository.cs
public interface IUserRepository : IRepository
{
User ReadToken(string email, string password);
}
// BaseRepository.cs
public class BaseRepository : IDisposable
{
protected IDbConnection PostgreSQL;
public BaseRepository(IDbConnection postgreSQL)
{
PostgreSQL = postgreSQL;
}
public void Dispose()
{
}
}
// UserRepository.cs
public class UserRepository : BaseRepository, IUserRepository
{
public UserRepository(IDbConnection postgreSQL) : base(postgreSQL)
{
}
public User ReadToken(string email, string password)
{
object parameters;
string sql;
parameters = new
{
email,
password
};
sql =
#"
SELECT
user_id AS id,
token
FROM users
WHERE
email = #email AND
password = CRYPT(#password, password) AND
active = TRUE;
";
var user = base.PostgreSQL.Query<User>(sql, parameters).SingleOrDefault();
if (user == null)
throw new UnauthorizedException("User", "User not found.");
return user;
}
}
// UsersController.cs
public class UsersController : ControllerBase
{
protected IUserRepository UserRepository;
public UsersController(IUserRepository userRepository)
{
UserRepository = userRepository;
}
}
// Startup.cs
services.AddTransient<IRepository, BaseRepository>();
You can do that with Scrutor
It offers assembly scanning and decoration extensions for Microsoft.Extensions.DependencyInjection
All those repositories can be summed up to something like this:
services.Scan(x => x.FromAssemblyOf<IAnAssemblyRegistrationMarker>()
.AddClasses(filter => filter.AssignableTo(typeof(IRepository)))
.AsImplementedInterfaces()
.WithScopedLifetime());
IAnAssemblyRegistrationMarker is an empty interface to point at the assembly (project) you want to scan
AddClasses Adds all public, non-abstract classes from the selected assemblies that matches the requirements specified in the
AsImplementedInterfaces Registers each matching concrete type as all of its implemented interfaces
WithScopedLifetime Registers each matching concrete type with Scoped Lifetime (You also have WithSingletonLifetime and WithTransientLifetime)
The only requirement in the code example above is that the repositories implement IRepository in order for you to target only the necessary items.
Disclaimer: I am not associated with Scrutor in any way. I just like the thing.
What you are looking for is called convention based registration. This gives you ability register all types which for example ends with Repository as the interfaces they implement. However the built-in ASP.NET Core IOC is very lightweight and doesn't provide such functionality. So you can either wrap it up with your code which scans all referenced assemblies, look for types by a pattern and then add them to ServiceCollection or you can use different IOC implementation that provides this functionality and supports .Net Core e.g. Autofac, StructureMap etc.
How do you perform property injection with Simple Injector.
The with Ninject you do is as per bellow:
[Inject]
public IUnitOfWork UnitOfWork { get; set; }
How can I do the equivalent to this with Simple Injector. I tried finding a solution online but had no luck.
Why do I want to use Property Injection?
I want to use property injection to set up unit of work in my base controller so that it will create a new unit of work OnActionExecuting and commit the changes OnResultExecuted. It also means I don't have to pass in the UoW with each new controller I create through the constructor.
Another option is to use the RegisterInitializer method:
container.RegisterInitializer<BaseControllerType>(controller =>
{
controller.UnitOfWork = container.GetInstance<IUnitOfWork>();
}
It keeps all configuration in your composition root and does not pollute your code base with all kinds of attributes.
Update: (as promised)
While this is a direct answer to your question I have to provide you with a better option, because the usage of a base class for this is a IMO not the correct design, for multiple reasons.
Abstract classes can become real PITA classes as they tend to grow towards a god class which has all kinds of cross cutting concerns
An abstract class, especially when used with property injection, hides the needed dependencies.
With focus on point 2. When you want to unit test a controller which inherits from the base controller, you have no way of knowing that this controller is dependent on IUnitOfWork. This you could solve by using constructor injection instead of property injection:
protected abstract class BaseController : Controller
{
protected readonly IUnitOfWork uoW;
protected BaseController (IUnitOfWork uoW)
{
this.uoW = uoW;
}
}
public class SomeController : BaseController
{
public SomeController(IUnitOfWork uoW) : base(uoW) { }
}
While this solves point 2, point 1 is still lurking. The main reason you're wanting this, as you say, is because you do not want to commit your changes in every Action method. Changes must just be saved by the context when the request is done. And thinking about design in this way is a good thing, because Saving changes is, or can be seen as a cross cutting concern and the way you're implementing this is more or less known as AOP.
If it's comes to AOP, especially if you're working with atomic actions in the action methods of your controllers, there is a far better, more SOLID and more flexible design possible which deals with this very nicely.
I'm referring to the Command/Handler pattern which is described in great detail here (also read this for the query part of your application).
With this patterns you don't inject a generic IUnitOfWork abstraction, but inject the specific needed ICommandHandler<TCommand> abstractions.
The action methods would fire the responsible commandhandler for this specific action. All commandhandlers can simple be decorated by a single open-generic SaveChangesCommandHandlerDecorator, 'ValidationDecorator', 'CheckPermissionsDecorator', etc...
A quick example:
public class MoveCustomerCommand
{
public int CustomerId;
public Address NewAddress;
}
public class MoveCustomerCommandHandler : ICommandHandler<MoveCustomerCommand>
{
public void Handle(MoveCustomerCommand command)
{
// retrieve customer from database
// change address
}
}
public class SaveChangesCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand>
{
private readonly ICommandHandler<TCommand> decoratee;
private readonly DbContext db;
public SaveChangesCommandHandlerDecorator(
ICommandHandler<TCommand> decoratee, DbContext db)
{
this.decoratee = decoratee;
this.db = db;
}
public void Handle(TCommand command)
{
this.decoratee.Handle(command);
this.db.SaveChanges();
}
}
// Register as
container.Register(typeof(ICommandHandler<>), new []{Assembly.GetExecutingAssembly() });
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(SaveChangesCommandHandlerDecorator<>));
// And use in controller as
public ActionResult MoveCustomer(int customerId, Address address)
{
var command = new MoveCustomerCommand
{ CustomerId = customerId, Address = address };
this.commandHandler.Handle(command);
return View(new ResultModel());
}
This keeps your controllers clean and let it do what it must do, namely be the layer between the business logic (the commandhandler implementation in this case) and the view.
Need to create the following:
First create the attribute class
[System.AttributeUsage(System.AttributeTargets.Property]
public class Inject : Attribute
{
}
Then create a custom property behavior
class PropertySelectionBehavior<TAttribute> : IPropertySelectionBehavior
where TAttribute : Attribute
{
public bool SelectProperty(Type type, PropertyInfo prop)
{
return prop.GetCustomAttributes(typeof(TAttribute)).Any();
}
}
Finally tell the container to use custom behavior
container.Options.PropertySelectionBehavior = new PropertySelectionBehavior<Inject>();
All that is left to do is decorate the property with the attribute
[Inject]
public IUnitOfWork UnitOfWork { get; set; }
I'm building an N-Tier MVC 4 Application that implements the Repository and UnitOfWork patterns as well as Domain Driven Design using an abstracted CommandProcessor layer that validates and executes my CommandModels.
I'm beginning to learn Workflow Foundation now and have added a workflow project that handles user registration. At the end of the workflow if everything went through, the workflow will execute the ApproveMembership CodeActivity:
public sealed class ApproveMembership : CodeActivity
{
[RequiredArgument]
public InArgument<string> UserEmail { get; set; }
protected override void Execute(CodeActivityContext context)
{
IDatabaseFactory databaseFactory = new DatabaseFactory();
IUnitOfWork unitOfWork = new UnitOfWork(databaseFactory);
IUserRepository userRepository = new UserRepository(databaseFactory);
string userEmail = UserEmail.Get(context);
User user = userRepository.Get(u => u.Email == userEmail);
if (user != null)
{
user.Activated = true;
userRepository.Update(user);
unitOfWork.Commit();
}
}
}
There is also a similar RemoveMembership activity that deletes the user after a certain time if he never validates.
My question is, does it make sense to handle this right inside my workflow? Or is the better approach to use Dependency Injection in the workflow to get a CommandBus that will handle processing 2 new, almost identical command models that I will have to create, along with Validation and Submission handlers for them? This is how it's done in my MVC AccountController.
public class DeleteUserCommand : ICommand
{
public int UserId { get; set; }
}
public class ApproveUserCommand : ICommand
{
public int UserId { get; set; }
}
public sealed class RemoveMembership : CodeActivity
{
public InArgument<string> UserEmail { get; set; }
private readonly ICommandBus commandBus;
private readonly IUserRepository userRepository;
public RemoveMembership(ICommandBus commandBus, IUserRepository userRepository)
{
this.commandBus = commandBus;
this.userRepository = userRepository;
}
protected override void Execute(CodeActivityContext context)
{
string userEmail = UserEmail.Get(context);
User user = userRepository.Get(u => u.Email == userEmail);
if (user != null)
{
var command = new DeleteUserCommand
{
UserId = user.UserId
};
IEnumerable<ValidationResult> errors = commandBus.Validate(command);
if (!errors.Any())
{
commandBus.Submit(command);
}
}
}
}
Obviously it's a lot more code but is it good design?
I feel like I answered me own question writing this and I'm thinking the answer is YES. But would still like to hear a professional opinion.
My question is, does it make sense to handle this right inside my
workflow?
I would encapsulate the code that you have inside the CodeActivity into an application service and have the workflow reference that application service:
class UserApplicationService
{
public void ApproveMembership(string userEmail)
{
var user = userRepository.Get(u => u.Email == userEmail);
if (user != null)
{
user.Activated = true;
userRepository.Update(user);
}
}
}
public sealed class ApproveMembership : CodeActivity
{
[RequiredArgument]
public InArgument<string> UserEmail { get; set; }
protected override void Execute(CodeActivityContext context)
{
var userEmail = UserEmail.Get(context);
this.userService.ApproveMembership(userEmail);
}
}
The motivation for this is that WWF is an infrastructural component in your architecture and it serves well to decouple infrastructure from domain logic. WWF could be replaced by something like NServiceBus in which you'd reference the same application service. Some would say this is a case of YAGNI but I think that separating infrastructure for domain code is very beneficial both in terms of code quality and the ability to reason about the domain.
I would also recommend that you push the unit of work code into the infrastructure as much as possible, so that application services don't have to call Commit explicitly.
Or is the better approach to use Dependency Injection in the workflow
to get a CommandBus that will handle processing 2 new, almost
identical command models that I will have to create, along with
Validation and Submission handlers for them?
This seems more in line with my suggestion, however based on your code sample, I'd recommend going a step further and extracting most more of the logic inside the CodeActivity into an application service, or structure the application in such a way that you can dispatch a command without needed access to a repository.
I was looking at the differences between POCO and DTO (It appears that POCO's are dto's with behaviour (methods?))and came across this article by Martin Fowler on the anaemic domain model.
Through lack of understanding, I think I have created one of these anaemic domain models.
In one of my applications I have my business domain entities defined in a 'dto' dll. They have a lot of properties with getter's and setter's and not much else. My business logic code (populate, calculate) is in another 'bll' dll, and my data access code is in a 'dal' dll. 'Best practice' I thought.
So typically I create a dto like so:
dto.BusinessObject bo = new dto.BusinessObject(...)
and pass it to the bll layer like so:
bll.BusinessObject.Populate(bo);
which in turn, performs some logic and passes it to the dal layer like so:
dal.BusinessObject.Populate(bo);
From my understanding, to make my dto's into POCO's I need to make the business logic and behaviour (methods) part of the object. So instead of the code above it is more like:
poco.BusinessObject bo = new poco.BusinessObject(...)
bo.Populate();
ie. I am calling the method on the object rather than passing the object to the method.
My question is - how can I do this and still retain the 'best practice' layering of concerns (separate dll's etc...). Doesn't calling the method on the object mean that the method must be defined in the object?
Please help my confusion.
Typically, you don't want to introduce persistence into your domain objects, since it is not part of that business model (an airplane does not construct itself, it flies passengers/cargo from one location to another). You should use the repository pattern, an ORM framework, or some other data access pattern to manage the persistent storage and retreival of an object's state.
Where the anemic domain model comes in to play is when you're doing things like this:
IAirplaneService service = ...;
Airplane plane = ...;
service.FlyAirplaneToAirport(plane, "IAD");
In this case, the management of the airplane's state (whether it's flying, where it's at, what's the departure time/airport, what's the arrival time/airport, what's the flight plan, etc) is delegated to something external to the plane... the AirplaneService instance.
A POCO way of implementing this would be to design your interface this way:
Airplane plane = ...;
plane.FlyToAirport("IAD");
This is more discoverable, since developers know where to look to make an airplane fly (just tell the airplane to do it). It also allows you to ensure that state is only managed internally. You can then make things like current location read-only, and ensure that it's only changed in one place. With an anemic domain object, since state is set externally, discovering where state is changed becomes increasingly difficult as the scale of your domain increases.
I think the best way to clarify this is by definition:
DTO: Data Transfer Objects:
They only serve for data transportation typically between presentation layer and service layer. Nothing less or more. Generally it is implemented as class with gets and sets.
public class ClientDTO
{
public long Id {get;set;}
public string Name {get;set;}
}
BO: Business Objects:
Business objects represents the business elements and naturally the best practice says they should contain business logic also. As said by Michael Meadows, it is also good practice to isolate data access from this objects.
public class Client
{
private long _id;
public long Id
{
get { return _id; }
protected set { _id = value; }
}
protected Client() { }
public Client(string name)
{
this.Name = name;
}
private string _name;
public string Name
{
get { return _name; }
set
{ // Notice that there is business logic inside (name existence checking)
// Persistence is isolated through the IClientDAO interface and a factory
IClientDAO clientDAO = DAOFactory.Instance.Get<IClientDAO>();
if (clientDAO.ExistsClientByName(value))
{
throw new ApplicationException("Another client with same name exists.");
}
_name = value;
}
}
public void CheckIfCanBeRemoved()
{
// Check if there are sales associated to client
if ( DAOFactory.Instance.GetDAO<ISaleDAO>().ExistsSalesFor(this) )
{
string msg = "Client can not be removed, there are sales associated to him/her.";
throw new ApplicationException(msg);
}
}
}
Service or Application Class
These classes represent the interaction between User and the System and they will make use of both ClientDTO and Client.
public class ClientRegistration
{
public void Insert(ClientDTO dto)
{
Client client = new Client(dto.Id,dto.Name); /// <-- Business logic inside the constructor
DAOFactory.Instance.Save(client);
}
public void Modify(ClientDTO dto)
{
Client client = DAOFactory.Instance.Get<Client>(dto.Id);
client.Name = dto.Name; // <--- Business logic inside the Name property
DAOFactory.Instance.Save(client);
}
public void Remove(ClientDTO dto)
{
Client client = DAOFactory.Instance.Get<Client>(dto.Id);
client.CheckIfCanBeRemoved() // <--- Business logic here
DAOFactory.Instance.Remove(client);
}
public ClientDTO Retrieve(string name)
{
Client client = DAOFactory.Instance.Get<IClientDAO>().FindByName(name);
if (client == null) { throw new ApplicationException("Client not found."); }
ClientDTO dto = new ClientDTO()
{
Id = client.Id,
Name = client.Name
}
}
}
Personally I don't find those Anaemic Domain Models so bad; I really like the idea of having domain objects that represent only data, not behaviour. I think the major downside with this approach is discoverability of the code; you need to know which actions that are available to use them. One way to get around that and still keep the behaviour code decoupled from the model is to introduce interfaces for the behaviour:
interface ISomeDomainObjectBehaviour
{
SomeDomainObject Get(int Id);
void Save(SomeDomainObject data);
void Delete(int Id);
}
class SomeDomainObjectSqlBehaviour : ISomeDomainObjectBehaviour
{
SomeDomainObject ISomeDomainObjectBehaviour.Get(int Id)
{
// code to get object from database
}
void ISomeDomainObjectBehaviour.Save(SomeDomainObject data)
{
// code to store object in database
}
void ISomeDomainObjectBehaviour.Delete(int Id)
{
// code to remove object from database
}
}
class SomeDomainObject
{
private ISomeDomainObjectBehaviour _behaviour = null;
public SomeDomainObject(ISomeDomainObjectBehaviour behaviour)
{
}
public int Id { get; set; }
public string Name { get; set; }
public int Size { get; set; }
public void Save()
{
if (_behaviour != null)
{
_behaviour.Save(this);
}
}
// add methods for getting, deleting, ...
}
That way you can keep the behaviour implementation separated from the model. The use of interface implementations that are injected into the model also makes the code rather easy to test, since you can easily mock the behaviour.