SHARE
TWEET

Untitled

a guest Jun 20th, 2019 57 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. * By designing the Customer as an Aggregate Root and including a reference all of the
  3. * movies that it rented, we can place the validation logic for renting movies
  4. * directly on the customer entity.
  5. *
  6. * Advantages: More declarative-reading code. The operation is a lot closer to the
  7. * entity itself, which improves the discoverability and understanding what a customer
  8. * can do.
  9. *
  10. * Disadvantages: Additional overhead. Having to pull the ids of rented movie everytime we
  11. * retrieve a customer might become cumbersome + slow down performance depending on the use cases.
  12. */
  13.  
  14. interface ICustomerProps {
  15.   name: string;
  16.   rentedMovies: MovieId[]; // one way reference to movie ids
  17. }
  18.  
  19. class Customer extends AggregateRoot<ICustomerProps> {
  20.   private constructor (props: ICustomerProps, id?: UniqueEntityId) {
  21.    super(props, id)
  22.   }
  23.  
  24.   public static create (props: ICustomerProps, id?: UniqueEntityId): Result<Customer> {
  25.    // make all invariants are satisfied
  26.   }
  27.  
  28.   public rentMovie (movie: Movie): Result<Customer> {
  29.     // if this.rentedMovies is larger than the max amount of movies, then
  30.     // this operation should fail
  31.   }
  32. }
  33.  
  34. /*
  35. * Another design: using Domain Services / Use Cases
  36. *
  37. * Advantages: Probably a better design if performance becomes a problem. Domain Services are a good
  38. * place to put domain logic that doesn't belong to one particular entity.
  39. *
  40. * Disadvantages:
  41. */
  42.  
  43. class RentMovieUseCase {
  44.   private rentalRepo: IrentalRepo;
  45.    
  46.   constructor (rentalRepo: IrentalRepo) {
  47.     this.rentalRepo = rentalRepo;
  48.   }
  49.  
  50.   public async exec (customer: Customer, movie: Movie): Result<Rental> {
  51.     const { movieRepo } = this;
  52.     const rentedMovies: Rental[] = await rentalRepo.getRentalsByCustomerId(customer.id);
  53.     if (rentedMovies.length > MAX_NUM_MOVIES_TO_RENT) {
  54.       return Result.fail<Rental>('Customer rented the max amount of movies')
  55.     } else {
  56.       return Rental.create({ customerId: customer.id, movieId: movie.id });
  57.     }
  58.   }
  59. }
  60.  
  61. // Using the domain service, the controller might look more like
  62.  
  63. class MovieController extends BaseController {
  64.   private movieRepo: IMovieRepo;
  65.   private customerRepo: ICustomerRepo;
  66.   private rentalRepo: IRentalRepo;
  67.  
  68.   constructor (movieRepo: IMovieRepo, customerRepo: ICustomerRepo, rentalRepo: IRentalRepo) {
  69.     super();
  70.     this.movieRepo = movieRepo;
  71.     this.customerRepo = customerRepo;
  72.     this.rentalRepo = rentalRepo;
  73.   }
  74.  
  75.   public async rentMovie () {
  76.     const { req, movieRepo, customerRepo, rentalRepo } = this;
  77.     const { movieId } = req.params['movie'];
  78.     const { customerId } = req.params['customer'];
  79.  
  80.     const movie: Movie = await movieRepo.findById(movieId);
  81.     const customer: Customer = await customerRepo.findById(customerId);
  82.  
  83.     if (!!movie === false) {
  84.       return this.fail('Movie not found')
  85.     }
  86.  
  87.     if (!!customer === false) {
  88.       return this.fail('Customer not found')
  89.     }
  90.  
  91.     const rentMovieResult: Result<Rental> =  new RentMovieUseCase(this.rentalRepo).exec(customer, movie)
  92.  
  93.     if (rentMovieResult.isFailure) {
  94.       return this.fail(rentMovieResult.error)
  95.     } else {
  96.       const rental = rentMovieResult.getValue();
  97.         await rentalRepo.save(rental);
  98.       return this.ok();
  99.     }
  100.   }
  101. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top