lundi 14 novembre 2016

No getter/setter on model with many instance vars

I have been reading a lot of material on how to become better in OOP, DDD etc. While reading Object calisthenics and Getters/Setters. Evil. Period. I got confused. Let me explain it by example.

I have this organization class, representing the information about organization, the classic entity:

class Organization
{
    private $name;

    private $city;

    private $street;

    private $phone;

    private $email;

    public function __construct($name, $city, $street, $phone, $email)
    {
        $this->name = $name;
        $this->city = $city;
        $this->street = $street;
        $this->phone = $phone;
        $this->email = $email;
    }

    public function getName()
    {
        ....
    }

    public function getCity()
    {
        ....
    }

    public function setCity($newCity)
    {
        ....
    }

    public function getStreet()
    {
        ....
    }

    public function setStreet($newStreet)
    {
        ....
    }

    public function getPhone()
    {
        ....
    }

    public function getEmail()
    {
        ....
    }

    public function setPhone($newPhoneNumber)
    {
        ....
    }
}

The organization name, city, street, phone and email may change, so the setters looks kind a logical. Getters are used to to display the properties of organization in table. How can I remove the boilerplate code and break trough from this anemic model? Maybe this is the case where the getter/setter is unavoidable?

Also object initialization using __construct. Is it a good practice to pass so many instance variables to constructor?

I gave it a try, according to what I read. Created some ValueObject to store information and do validation (don't know if the ValueObject should do a validation on its data):

class Phone
{
    private $phone;

    public function __construct($phone)
    {
        if (!$this->validate($phone)) {
            throw new InvalidPhoneNumberException();
        }

        $this->phone = $phone;
    }

    public function getPhone()
    {
        return $this->phone;
    }

    private function validate($phone)
    {
        // validate the phone number
    }
}

class Email
{
    private $email;

    public function __construct($email)
    {
        if (!$this->validate($email)) {
            throw new InvalidEmailAddressException();
        }

        $this->email = $email;
    }

    public function getEmail()
    {
        return $this->email;
    }

    private function validate($email)
    {
        // validate email
    }
}


class Address
{
    private $city;

    private $street;

    public function __construct($city, $street)
    {
        $this->city= $city;
        $this->street = $street;
    }

    public function getCity()
    {
        return $this->city;
    }

    public function getStreet()
    {
        return $this->street;
    }
}

Then passed these objects instead of string representations of data to my Organization and did some renaming on methods:

class Organization
{
    private $name;

    private $address;

    private $phone;

    private $email;

    public function __construct($name, Address $address, Phone $phone, Email $email)
    {
        $this->name = $name;
        $this->address = $address;
        $this->phone = $phone;
        $this->email = $email;
    }

    public function getName()
    {
        return $this->name;
    }

    public function getAddress()
    {
        return $this->address;
    }

    public function getPhone()
    {
        return $this->phone;
    }

    public function getEmail()
    {
        return $this->email;
    }

    public function changeAddress(Address $newAddress)
    {
        $this->address = $newAddress;
    }

    public function changePhoneNumber(Phone $newPhoneNumber)
    {
        $this->phone = $newPhoneNumber;
    }
}

Does this code smells less and looks more mature from the perspective of OOP?

Aucun commentaire:

Enregistrer un commentaire