eugenedrvnk
eugenedrvnk

Reputation: 493

Separation of concerns in business layer (usecases, services)

Let's say at the beginning I had a requirement where by sending a post request to my /posts API endpoint - post had to be created.

To implement this I created a PostsUsecases thinking about it as a class that provides implementation for business scenarios and implemented the createPost method there.

Then, in addition to the /posts endpoint, I got a new requirement to implement a user creation flow (POST /users). In scope of it, user should be created and default post should be generated for user.

To achieve this, I create UsersUsecases, create createUser method and at this point I don't understand which option to use:

  1. reuse PostsUsecases.createPost method in scope of my UsersUsecases.createUser method?
  2. create a separate PostService class (will it be infrastructure layer or still business?), implement createPost behaviour there and then use it in both places, in UsersUsecases and PostsUsecases.

Upvotes: 0

Views: 52

Answers (4)

Fouad HAMDI
Fouad HAMDI

Reputation: 491

Your context is not 100% clear to me (a users & posts example might be too simple to capture it) but what about using a domain event approach?

A basic workflow could be:

  • a UserCreated event is emitted in your users bounded context every time a user is created
  • your posts BC is configured to listen to such events
  • when one is received, the default post is created (by the posts BC).

This approach would keep your contexts loosely coupled.

You'd probably have to consider if you want to use asynchronous or synchronous notification in case eventual consistency is an issue in your context.

Since it appears that you have all your code in a monolith, you could use the Observer pattern to implement this in a simple way.

Upvotes: 0

Shameel
Shameel

Reputation: 802

Since a Post entity can exist independently on its own or as part of the User entity, I suggest you compose the Post entity within the User entity, and reuse its methods. There is no need to create a separate domain or business object and it does not provide any additional benefits and actually complicates the design.

class Post {
   
   void create(...) {
      
   }
}

class User {
       
   private Posts posts;

   void create(...) {
      
   }
   
   void AddPost(Post post) {
      Posts.create(post)
   }
}

Upvotes: 0

nik0x1
nik0x1

Reputation: 1461

I would recommend you to create interfaces and their implementations at the domain level (pseudocode):

interface Posts {
   void add(...);
}

interface Users {
   void add(...);
}

And two classes of use cases:

class CreatePostUseCase {
   
   private Posts posts;

   void createPost(...) {
      posts.add(...);
   }
}

class CreateUserUseCase {

   private Users users;
   private Posts posts;

   void createUser(...) {
      users.add(...);
      posts.add(...);
   }
}

With this design, your dependencies will be directed to domain entities and you will not have cross dependencies at the use case level.

P.S. Your API level will use the use case level. Because in general you can have several API types (for example, REST and gRPC) and in this case, use cases can be reused.

Upvotes: 0

Davinder Singh
Davinder Singh

Reputation: 1

Ideally you should create two different services for different use cases to achieve separation of concerns in future you might get some other requirements for updating or validating the users considering these points you should create in a business class and utilize DI for both the classes.

Hopefully this can help you. Thanks

Upvotes: 0

Related Questions