I can see the negatives of public properties over setters: Public properties are dangerous even in PHP because you could potentially override a dependency with something unexpected. At least setters can enforce integrity by checking what the variable is being set to. That said, the number of times I use setters rather than constructor injection is so minimal this shouldn't be much of a consideration.
Getters, however, request object state. Any method in a class which returns a value beyond a success/failure condition is essentially a getter. If objects can't request the state of their dependencies
I can entirely understand the advantages of removing getters and even moreso setters, but I've yet to see a viable alternative. The visitor pattern I posted above creates separation of concerns issue and adds complexity.
I am totally open to having my opinion changed on this if someone can provide a sensible answer.
Let's take a very simplistic case. In a lot of cases accessors are used to transfer data from the model layer to the view layer:
PHP Code:
class User {
public $name;
public $email;
public function __construct($name, $email) {
$this->name = $name;
$this->email = $email;
}
}
class UserFormatter {
public function output(User $user) {
return 'Name: ' . $user->name . ' Email: ' . $user->email;
}
}
$user = new User('Tom', 'foo');
$userFormatter = new UserFormatter;
echo $userFromatter->output($user);
Here we've enforced separation of concerns. The user object has a state an exposes that state. Which apparently is bad. Whether we use getters or public properties here is irrelevant.
So what's the solution? One would be to combine both the classes but that's even worse as it hugely limits flexility and reusability. Using inheritance to fix that causes more problems than it solves. So the visitor pattern solution which retains the separation of concerns and avoids getters looks like this:
PHP Code:
interface UserDetails {
public function writeInfo($name, $email);
}
class User {
public $name;
public $email;
public function __construct($name, $email) {
$this->name = $name;
$this->email = $email;
}
public function requestDetails(UserDetails $info) {
$info->writeInfo($this->name, $this->email);
}
}
class UserFormatter implements UserDetails {
protected $output;
public function output(User $user) {
$user->requestInfo($this);
return $this->output;
}
public function writeInfo($name, $email) {
$this->output = 'Name: ' . $name . ' Email' . $email;
}
}
However, is this really an option? This has vastly increased the complexity, maintainability has become a nightmare. I want to add a surname field so now need to modify 3 times as many lines of code.
Beyond that, the User object needs to know what other objects need to know about it. This has removed any idea of separation of concerns. Why should the user object need to have any idea about how it would ever possibly need to be used?
Again, perhaps I am totally misunderstanding but... yes getters and setters cause problems but I can't see a solution that avoids them and doesn't cause more problems than it solves. Again, I'm totally open to being proved wrong!
Let's keep in mind that a common PHP script will take a request, query a database and, format the result in some way and return it to the user. Most of the processing here is transferring that data between the layers. That data needs to be transferred and formatted somehow.
Bookmarks