OOP: Private/Public or Protected? Why does it matter?

I’ve found in lots of places i’ve worked for, developers don’t quite understand the need for private/protected methods. Why not have all of it public? Why bother thinking about it. I’ve decided to write a short article on the matter, hopefully this will clear things up a bit.

One of the reasons object oriented programming exists is to deliver the intent behind code to other developers using that code. We are not always around to explain what we’ve done, and we cannot document endlessly to explain things. So object oriented programming gives us these tools to deliver our intent/impose restrictions on certain functionality with an intention in mind.

Here is a real world example:

There is a worker in a packaging warehouse. He is asked to package up different items based on their size. There are 3 belts:

  • Large parcels – red packaging
  • Medium parcels – green packaging
  • Small parcels – yellow packaging

Being a human being he does the job seamlessly. But how about’s would you code this worker up?

So imagine a worker class with a package method

class Worker
{
    public function packageUp() {...}
}

The packageUp() method is public because that is what the external world sees him perform. You can ask him to package as he has set that this is one of the things he can do. So we know the public can use it, hence its public.

Now how the worker packages them up is entirely up to him as long as he can deliver the desired outcome. So he can do the following:

class Worker
{
    public function package() {
        $packages = $this->getPackages();
        foreach ($packages as $package) {
            $wrapping = $this->getWrappingBasedOnSize($package);
            $this->wrap($wrapping, $package);
            $this->labelUp($package);
        }
    }

    private function getPackages() {...}

    private function getWrappingBasedOnSize($package) {...}

    private function wrap(Wrapping, $package) {...}

    private function labelUp($package) {...}
}

At the end of this method, we should expect all of the packages to be wrapped up. In this case he has 4 private methods to finally produce the packaging. These are based on his skill and experience of working. He could also do this

class Worker
{
    public function package() {
        $sizes = [
          'small' => $this->getWrapping('small'),
          'medium' => $this->getWrapping('medium),
          'large' => $this->getWrapping('large')
        ];

        foreach ($sizes as $size => $wrapping) {
            $packages = $this->getPackagesBasedOnSize($size);
            $this->wrapAllPackages($packages, $wrapping);
            $this->labelUp($packages);
        }
    }

    private function getPackagesBasedOnSize($size) {...}

    private function getWrapping($size) {...}

    private function wrapAllPackages($wrapping, $package) {...}

    private function labelUp(array $packages) {...}
}

The output of this public method will be the same as the first one, but internally the worker has re-arranged himself to try out a different approach. And that is it! A private method specifies an approach. It could be anything – good/bad but its not meant for the world to use, just the public method as long as it delivers. A private method not only delivers the intent of the internal working of a class but enforces it. Once the worker is happy that he can provide labelUp($packages) as a service – he may choose to expose that as a public method to the world. But only when he has decided that, not before. Because once he decides that, other clients will start using it, and changing this midway would require the clients to change as well which is not a pleasant process.

Now what about protected? Imagine he brings his friend at the prospect of having him apply for a job there. The friend asks him to give it a go once. Worker says he will help him out where you need it. Consider the following classes now:

class Worker
{
...
}

class PotentialWorker extends Worker
{
}

The Worker shows him how to do it. Once the PotentialWorker sees what he does, he chooses to do them on his own.

class PotentialWorker extends Worker
{
    public function package()
    {
        ...
    }
}

The PotentialWorker can ask the Worker to handle the label up process (because he thinks its boring). For this to work, Worker makes that method protected. This isn’t a service he is prepared to offer to the public, but for his friend he is happy to provide it.

class Worker
{
    ...

    protected function labelUp($package) {...}
}

class PotentialWorker extends Worker
{
    public function package()
    {
        $package = $this->getOnePackage();
        $this->wrapPackage($package);
        $this->labelUp($package);
    }

    private function getOnePackage() {...}

    private function wrapPackage($package) {...}
}

This also begs the question of why create private methods at all? In the above example, it is very clear that if you want to expose any functionality later, be it public or protected, you need to have methods for those. Its best to create small methods that perform the task in isolation so you can choose to expose them later without much effort. Its also very clear that private methods provide excellent visibility of the internal workings of a class and its capabilities, so don’t shy away from them. Visibility often if not always, trumps performance.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *