DEV Community

Discussion on: How you can reduce usage of getter methods in your code

Collapse
 
aleksikauppila profile image
Aleksi Kauppila

Sorting, if you choose to sort by only one criteria (which is not often the case), you do not put it in a compareTo!

You can design compareTo() any way you like. With a callback for instance. Here, i'm concerned about business logic and there's generally quite limited amount of ways certain entities need to be ordered. I don't want to mix presentation concerns to this issue.

You do not make decisions for the users of your Class, let them make sort by ANY field by providing getters.

What? This makes absolutely no sense. Who else makes the decisions?

belongsTo() is another big mistake.

Consider this:

class Customer
{
    private $shifts;
    // ...
    public function addShift(Shift $shift): void
    {
        if (!$shift->belongsTo($this)) {
            throw new Exception("Shift doesn't belong to customer");
        }
        $this->shifts->add($shift);
    }
}

class Shift
{
    private $customer;
    //...
    public function belongsTo(Customer $customer): bool
    {
        return $this->customer->equals($customer);
    }
}

// application code
$customer = $customerRepository->findByName("Big Corp");
$shift = new Shift($customer, new DateTime("2018-01-01 12:00"));

Shift doesn't have any reason to exist without a customer who orders an employee to do some work. Customer is an aggregate for a Shift. We deal with all persistance issues through Customer and that is why we add Shifts to Customer's collection. We also have to make sure that we don't add "Small Corp's" Shifts to "Big Corp's" collection and use belongsTo() to make sure that doesn't happen.

We decide to put focus on Customers in this application. Shifts and Customers are not equals in terms of importance. We also don't access Shifts directly from the database. This happens through Customers.

Maybe the focus shifts at some point and then we change the model but for now belongsTo() serves this use case well.

The big picture here is that we shouldn't have to know the internals of objects. We need to limit the public API as much as it makes sense. Otherwise further development becomes harder and slower as time goes by.

Collapse
 
bgadrian profile image
Adrian B.G.

The big picture here is that we shouldn't have to know the internals of objects. We need to limit the public API as much as it makes sense. Otherwise further development becomes harder and slower as time goes by.

Exactly, but you are also limiting your classes usages.
Without access to the $company you cannot do: group by company, sort by company, are in the same company, show the company in a table, change the company, should I continue?

If it is a property and it is not used, maybe it should not exists.

Thread Thread
 
aleksikauppila profile image
Aleksi Kauppila

I'd prefer calling this design. I design what interactions are appropriate for objects.

Employee has to know $company because when we save it to database (or anywhere) this information is important. To be fair i didn't communicate this that clearly.

Accessing the company of an Employee must come from a use case. Until we have use case we avoid exposing this information. When we have use cases these things may be able to catch a certain more natural meaning. So instead of just doing data processing based on employee attributes we could have named reports or something.

This discussion is very difficult when the model is as crude as my code example here.

Thread Thread
 
bgadrian profile image
Adrian B.G.

Maybe you even forgot to mention that you control your entire app (monolith), and is easy to refactor the classes AND maybe it is even a small app (and you can refactor ALL the usages of a class in a matter of minutes.

my problems with this article will happen when you do not have access to the source code of the classes and you are just an User. This includes libraries, APIs,RPCs, frameworks. Also this could happen when the code has millions of LOC.

Probably some of the readers will build these kind of classes too, and you cannot and should not think of all use cases when you are building an API/expose your classes. If you try to do that it will bloat your classes, give the users flexibility, let them decide how to use it, of course in limited reason.

Thread Thread
 
aleksikauppila profile image
Aleksi Kauppila

As implied in code examples, this is business layer code. Yes, i expect people working with applications to be able to change their code

When you're working with libraries, you usually don't have to worry about them containing entities such as Company or Employee. But defensive practices work well when designing a library too. If there's only one way to use a class, it's virtually impossible to break the code.