domain driven design - Dealing with a user dependent application -


an application i'm writing heavily dependent on current logged in user, give concrete example lets have list of products.

now every user has 'rights' see products, particular details of product, , edit / remove fewer of those.

e.g.:

  • the user can see 3/5 products
  • the user can see details 2 out of 3 products
  • ...

as case of application's domain, have tendency pass around user in methods. becomes cumbersome time time. have pass in user in methods, pass down 1 needs it.

my gut tells me i'm missing something, i'm not sure how tackle problem.

i gave thoughts @ using class holds user, , inject class everywhere need it. or using static property.

now time time handy pass in user in method, guess override then:

public dosomething(user user = null) {     var u = user ?? this.authservice.user;     ... } 

are there other ways tackle kind of problem ?

your gut correct, keep listen it.

authorization checks should not mixed core domain checks. example, if checks user may update product details , if checks product details long enough should not contained in same class or same bounded context. if have monolith 2 checks should contained in separate namespaces/modules.

now tell how it. in latest monolithic project use cqrs lot, separation between commands , queries. give example of command validation can extended query validation , non-cqrs architectures.

for every command register 0 or more command validators check if command may sent aggregate. these validators eventual consistent. if command passes validators command sent aggregate further checked in strong consistent manner. so, talking 2 kinds of validation: validation outside aggregate , validation inside aggregate. checks belongs other bounded context can implemented using command validators outside aggregate, that's how it. , example source code, in php:

<?php namespace coredomain {     class productaggregate     {         public function handle(changeproductdetails $command):void //no return value         {             //this check strong consistent             //the method yields 0 or more events or exception in case of failure             if (strlen($command->getproductdetails()) < 10) {                 throw new \exception("product details must @ least 10 characters long");             }              yield new productdetailswerechanged($command->getproductid(), $command->getproductdetails());         }     } }  namespace authorization {     class usercanchangeproductdetailsvalidator     {         private $authenticationreaderservice;         private $productspermissionsservice;          public function validate(changeproductdetails $command): void //no return value, if no exception thrown         {             //this check eventual consistent             if (!$this->productspermissionsservice->canuserchangeproductdetails($this->authenticationreaderservice->getauthenticateduserid(), $command->getproductid())) {                 throw new \exception("user may not change product details");             }         }     } } 

this example uses style commands sent directly aggregates should apply pattern other styles too. brevity, details of command validators registering not included.


Comments

Popular posts from this blog

networking - Vagrant-provisioned VirtualBox VM is not reachable from Ubuntu host -

c# - ASP.NET Core - There is already an object named 'AspNetRoles' in the database -

ruby on rails - ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true -