A
A
asslicker20182018-12-26 15:02:19
Software design
asslicker2018, 2018-12-26 15:02:19

What layer does the Repository belong to and how to return the Business object?

The language is not important. For example, I have a database with a User table.
My program has a Data Access Layer (DAL) and a Business Logic Layer (BLL).
In the DAL for the User table, I have written the UserEntity {username, secondname, age ...} entity class, which, accordingly, reflects the data of a separate table field.
In my BLL I have a User{fullname, age} object which is obtained by turning UserEntity -> User i.e. mapping occurs.
I also have a UserRepository that encapsulates the work with the repository and returns data. This is where I have questions:
1) What should UserRepository return: UserEntity or User?
2) In which layer should the UserRepository DAL or BLL be located
Logically, the DLL should not know about the BLL at all, especially about its objects. But it turns out that if I want
the repository to return User, then it turns out that the DLL is tied to the BLL. That is, if the repository is in the DAL, then it should not return BLL objects in any way. But in many articles I saw that they write the opposite - the repository returns Business objects.
How to solve these problems?

Answer the question

In order to leave comments, you need to log in

4 answer(s)
E
Evgeny, 2018-12-26
Maltsev @maltsever

Hey! Much depends on the details and the number of abstractions. I will try to answer how it should look in the most general case. UserRepository uses direct access to the database (it can be raw sql, some kind of ORM, it doesn't matter). Therefore, it is logical that it be in the Data Access Layer. That's why it's called that, because in practice there can be several of them: SqlDataAccessLayer, MongoDbDataAccessLayer, etc. Also, if we are talking about OOP, then the IUserRepository interface should be stored exactly where it is planned to be used. In our case, this is BLL, aka Domain Layer. It is not always possible to adhere to this rule with the interface, but this should be strived for.
Regarding what the UserRepository should return: it doesn't really matter. Depending on the situation, we can either return just a container with the necessary data (DTO), or a full-fledged User'a. If we talk about dependencies, then the main thing to understand is that in the general case, our Domain Layer should not have dependencies on any other layers. But the rest of our project (for example, DAL) can use the Domain Layer.

D
dmitriy, 2018-12-26
@dmitriylanets

As a rule, Repository is an infrastructure level and not a domain level, they are connected with the domain by interfaces.
for example, a domain entity (essentially a BLL):
Domains/User/User
Domains/UserCollection
Domains/User/RepositoryInterface (returns User, UserCollection)
Infrastructure:
Infrastructure/User/Repository (implements RepositoryInterface, works with the database, uses DAL, mapping)
well and Application
controllers, GUI , views

S
Stanislav Silin, 2018-12-28
@byme

I usually do it like this.
There is a Domain project which describes common interfaces for BLL and View (REST, SOAP, CLI, Desktop, etc.). There is some IUserService interface that works with User.
There is a project with all the business logic that implements IUserService in UserService. This UserService goes to the DAL, from where it gets the UserEntity and converts it to User. In addition, validation takes place here, notifications are sent, i.e. everything business logic needs. Separately, there is a DAL project that already goes to the database and returns UserEntity through UserRepository.
At the same time, View only knows about the existence of the Domain project, and all implementations are forwarded through IoC.
I described an abstract example, it can vary from platform and application size

A
AlexHell, 2019-01-05
@AlexHell

class User {Id, Name, Age}

class UserRepository
{
 User GetUserById(long Id)
  {
  string[] data = {select from Users where id = Id}
  return new User() {Id = Id, Name = data[0], Age = data[1] };
  }

  void PutUser(User)
  {
    {insert into Users}
  }
}

Why do you need UserEntity? If you have a domain object User - pass it everywhere, and Repo must also rotate it when reading from the database and accept it in order to save it in the database.
If the question is in EntityFramework (and others like them ORM) with mandatory inheritance from the base Entity class - well, do the mapping again inside UserRepo and never give UserEntity outside at all, I mean as a private class, for example, purely for namespace / package

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question