c# - Proper way to enforce business rules in property setter -


let's application has employer object has been created user , program prompting user enter in property called employerid. in example application won't let user enter in invalid employeeid. have mocked following solution solve problem.

public int employerid         {             { return employerid; }             set             {                  employerid = setemployerid();             }         }          public int setemployerid()         {             int id = 0;             console.write("enter employer id: ");             id = convert.toint32(console.readline());             while (id < 5 || id > 10) //silly logic illustrative purposes             {                 console.write("invalid id, enter id: ");                 id = convert.toint32(console.readline());             }             return this.employerid = id;         } 

this keeps heavy lifting out of setter of property , delegates responsibility setemployerid method.

would acceptable solution in production setting? there way improved upon, or pitfalls might lead later down road when application isn't such contrived example? (besides fact user isn't aware of valid input is).

i think better question should outside class able modify employerid directly.

most times methods create mutation should exposed verbs changeemployer(employer newemployer) , on. doing way make more explicit , allows more raise domain events. in case set method private owning class can call it.

that said, change of employerid should verified in setter way logic in 1 place , not strewn multiple methods.

karl anderson's answer makes point, putting business logic in setter prevents returning non-exceptional error. true , should taken consideration before using property setters.

he makes point validation objects, aggregate entities may reference each other id such having separate business validation object validating ids may excellent choice. can reuse validator in multiple places @ end of day place matters inside entity, place must always consistent.

public class employee {      private employerid employerid;       public employee(employerid id /* other params such name etc */)      {          var employersetresult = this.setemployerid(id);          if(!result.success)             throw new argumentexception("id", "id invalid");      }       // separate method because need set employerid      // multiple locations , should ever call setemployerid       // internally      public result changeemployer(employerid id)      {           var result = this.setemployerid(id);           if(result.success)              domaineventpublisher.publish(                new employeeemployerchanged(id, this.id));           return result;      }       private result setemployerid(employer id)      {           var result = employeridvalidator.validate(id);           if(result.success)              this.employerid = id;           return result;      } }  public static class employeridvalidator {     public static result validate(employerid id)     {         if(id < 5)            return new result(success: false, new validationresult("id low"));         else if (id > 10)            return new result(success: false, new validationresult("id high"));         return new result(success:true);     } }  public class result {      public bool success {get {return this.success;}}      public ienumerable<validationresult> validationresults       {          get{ return this.validationresults; }      }  } 

Comments