1

I'm developing some test web-project for my self to learn DDD and good architectural practice at all. So application, basically, is a simple photo manager.

I'm developing 3-tier architecture and for now I have:

  • DAL:
    • EF database first
    • UserRepository
    • PhotoRespoitory
    • UnitOfWork
  • BLL

    • UserService: user registration, authentication, registration
    • PhotoService: photo retrieving, uploading, updating
    • DTO Models: User, Photo, Album
    • Automapper: mapping DAO from EF to DTO model
  • Asp.Net MVC Client

Here are examples of DTO models:

public abstract class ModelBase
{
    public virtual long Id { get; protected set; }
}

public class User : ModelBase
{
    public string Name { get; set; }
    public string Email { get; set; }
    public UserRole UserRole { get; set; }
    public DateTime RegistrationDate { get; set; }

    public override string ToString()
    {
        return $"{Name} {Email} {UserRole} {RegistrationDate}";
    }
}


public class Photo : ModelBase
{
    public string Name { get; set; }
    public DateTime DateTaken { get; set; }
    public string Place { get; set; }
    public string CameraModel { get; set; }
    public string FocalLength { get; set; }
    public string Diaphragm { get; set; }
    public string ShutterSpeed { get; set; }
    public string ISO { get; set; }
    public bool? FlashMode { get; set; }
    public long OwnerId { get; set; }
    public string OwnerName { get; set; }
    public long AlbumId { get; set; }
    public string AlbumName { get; set; }
}

So my questions are:

  1. Does it make sense to create domain models with some logic, as model manipulation logic was delegated to service?

  2. Is BLL the right place for DTO models?

  3. Do I need to create an additional ApplicationService that will contain PhotoService and PhotoService and finds user that uploads picture and then pass the UserDto with PhotoDto to PhotoService?

1

1) Does it make sense to create domain models with some logic, as model manipulation logic was delegated to service?

You haven't really specified what you mean by "domain model". This definition is important as some developers consider their database entities as their domain model, whereas others keep a separate domain project which contains the interfaces and base classes that are inherited/implemented by actual DAL/BLL layers.

  • If you refer to the DTO classes, you can add logic to them.
  • If you refer to the database entities, you shouldn't add logic to them. At best, you can make a compromise and allow e.g. a simple property conversion (public string FullName => FirstName + LastName;) but no actual logic.
  • If you refer to the interfaces/base classes for DAL/BLL objects, then it can be meaningful to add some base logic, though you need to ensure that is it is dependency-agnostic. More often than not, the logic you intend to add won't be dependency-agnostic.

This question is a bit too open-ended for a direct answer. Some developers maintain an anemic model where data classes and logic classes are strictly separate. Other developers argue that this is against OOP principles.

I'm not making a decision here pro/anti anemic. Either approach has its benefist. And, if we're being honest, the majority of developers are expected to follow their tech lead/senior's preferred approach anyway.

2) Is BLL the right place for DTO models?

Technically, every layer needs its own DTOs. But I think most people agree that the effort to do so does not outweigh the benefits.

If you only have one DTO layer, the business layer is the place to put them. Essentially, the rule of thumb is that your database entities do not leak outside of your BLL.

3) Do I need to create an additional ApplicationService, that will contain PhotoService and PhotoService and finds user that uploads picture and then pass the UserDto with PhotoDto to PhotoService?

I wouldn't call it ApplicationService. But it can be meaningful to have a service named after a function rather than an entity.

For example, the UserService handles user CRUD, the RoleService handles role CRUD, but the AuthorizationService handles the combination of the two: logins, resolving permissions, ... And it reuses logic from UserService/RoleService where relevant.

It would make little sense to put the login/permission logic in either the UserService or RoleService since it so heavily depends on both. Developers would disagree with its location or, even worse, start mixing them.

I think the shortest direct answer to your question is that services don't need to point to a particular database entity.

-1

Since you've tagged your question with object-oriented:

  1. Yes, adding logic to "model" objects makes sense. It is actually the whole point of object-orientation. Every piece of logic which has to directly work with the data has to be in the object in fact. It is actually a worst-practice in object-orientation to expose data (some exceptions apply).

  2. "DTOs" should actually not exist in the first place, it doesn't really matter where they are.

  3. "Service" and "DTO" objects should not exist. Having "Service" "objects" implies that some business logic has not found its place in a real business-object somewhere. It can also imply a missing abstraction. Also note, that "Service" and "DTO" objects are not part of the Domain. They are technical, and can not be discussed with business-people.

The architecture you are thinking of, is the "traditional", strongly coupled, procedural, technically layered "enterprise design". It's not considered wrong to use it (you can use it if you want), but it has almost nothing to do with object-orientation.

  • Every piece of logic which has to directly work with the data has to be in the object in fact. That is a very dangerous overstatement. While the underlying idea you're trying to sell may be correct, I suggest at least reconsidering the phrasing, as the current phrasing can be constructed by less-than-expert developers that it is good practice to make monolithic classes. – Flater Aug 1 '18 at 15:06
  • "DTOs" should actually not exist in the first place, it doesn't really matter where they are. So how do you intend to separate your data repository entities from your UI models? How do you enforce any layer separation? – Flater Aug 1 '18 at 15:06
  • @Flater Remark about phrasing acknowledged. About DTOs and layers: You are thinking about the "usual" technical layers. That is, having at least 3 layers, which also means having at least 2 data-only boundaries which create strong coupling (with that I mean changing data in any layer changes all layers above with high probability). I have strong objections to these kinds of architectures. – Robert Bräutigam Aug 1 '18 at 15:17
  • Given an enterprise level application, it's nigh impossible to avoid these layers from forming. I actually use your proposed simplified setup for personal (often WPF) projects, but they are far from enterprise level. On top of improving testability, layering allows you to segregate developers into layers based on skill level. Low-skill developers can do no real harm (to other developers' work) in the frontend layers, but they can in the backend. Thus, seniors naturally gravitate towards the backend and juniors gravitate towards the frontend. – Flater Aug 1 '18 at 15:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.