Good practices for class that grows a lot

Asked

Viewed 164 times

2

Supplementing a question I posted here some time ago, about a system for user registration using concepts of the SOLID standard, one of the problems I faced was the question of the User class being very large and can be very variable, since a user can have several characteristics, follows a "script" of situation:

  • Each attribute has its Setter/getter in the User class.
  • Each attribute has its validation rule in the userValidator class.
  • Each attribute has its "definition" in a class associative array userCrud.

Let’s say that in another situation a user can have attributes like: colorOS, colorDoCabelo and etc, I would have to always be changing the classes above, which would be a good solution for this?

Structure of the User class:

class User {

private $attributes;

function __construct() {
    $this->userValidator = new userValidator;
}

function setName ($param) {

    if($this->userValidator->validateName($param))
        $this->attributes['name'] = $param;
}

function getAttributes () {
    return $this->attributes;
}

function getAttribute ($attr) {

    if(isset($attributes[$attr]))
        return $this->attributes[$name];
    else throw new Exception("Attribute '{$attr}' does not exist");

}

}

  • 1

    Whenever you add a new attribute you have to change the Uservalidator class. This is a violation of the O principle of SOLID. Have a validator class by attribute. Your Usercrud class I didn’t quite understand, it would be nice to post an example.

  • I get it, thank you. on the userCRUD is simply a class that interacts with the database, takes the User object and transforms it into array and inserts, for example

1 answer

2


The validation

To validate each attribute it will be better to have a validator for each value. With this in mind, if a new attribute arises it is not necessary to modify the class.

Basically, the validators will be passed to a main validator:

class UserValidator
{

   private $validators = [];

   public function setValidator($attribute, $validator)
   {

      $this->validator[$attribute] = $validator;

   }

   public function validate(User $user)
   {

       $messages = [];

       foreach($user->getData() as $attribute => $value){

           // Verificando se um validador para o atributo existe
           if(isset($this->validators[$attribute])){
               $message = $this->validators[$attribute]->validate($value);

               // Caso contenha a mensagem de validação, ela será armazenada em um array
               if($message){
                  $messages[$attribute] = $message;
               }

           }

       }

       // Retornando as mensagens de validação para serem utilizadas
       return $messages;

   }

 }

Using the Uservalidator

To use the class you will need to pass the validators to it. As you can notice, to add a new validation just configure the class with the setValidator method.

$userValidator = new UserValidador;
$userValidator->serValidator('name', new NameValidator);
$userValidator->setValidator('age', new AgeValidator);
$userValidator->setValidator('corDosOlhos', new CorDosOlhosValidator);
// Basta continuar configurando para cada novo atributo necessário.

The User entity

Finally, the User entity would work with an array to avoid getting a huge amount of methods. If a new attribute is added, the class is intact. Follow the implementation:

class User
{

   private $attributes;

   public function __construct(array $attributes){

       $this->attributes = $attributes;

   }

   public function getData()
   {

      return $this->attributes;

   }

   // Exemplo de método que pode ser utilizado em outros contextos
   public function getUserAttribute($attribute){

       if(isset($this->attributes[$attribute])){
           return $this->attributes[$attribute];
       }

       throw new Exception('Attribute not found');

   }

}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.