Ways you are breaking encapsulation without knowing it

I have seen good developers, nay great developers break encapsulation and even more interestingly, they didn’t even know they we’re doing it! How is this even possible? On this piece we shall explore this phenomena.

First, lets look at what encapsulation is. Encapsulation is one of the four pillars of Object Oriented Programming commonly abbreviated as OOP. The others include inheritance, polymorphism and abstraction. The principle behind encapsulation is hiding of data and behavior of an object to prevent it from external corruption and reduce overall complexity.

In practice this is implemented in most OOP languages by use of certain keywords such as:

    - protected
    - private
    - public

The language specific implementation shall be left as an exercise to the reader. Please check your language documentation.

Today however we shall be looking at a particularly insidious way of breaking encapsulation that is exceedingly difficult to diagnose and correct . Today we look into the world of semantic encapsulation

Semantic encapsulation is broken when we depend not on the public interface offered by the object but on some prior knowledge of the implementation.

This concept is rather hard to grok, as such will give some few examples.

<?php

class A
{
        function initialize()
        {
                //Do some bootstrap work here
        }
        function performFirstOperation()
        {
                $this->initialize();
                //Now do other operations

        }
        
        
}

In normal use of this code we would simply call $a->performFirstOperation() safe in the knowledge that the requisite initialize() operation will be called.

Do you see the gotcha there?

To protect ourselves we would need to change the method type to either protected or private that would then ensure initialize can only be called from outside the function.

Lets look at another example

<?php

class User
{
        function retreiveById(Database $database)
        {
                if(!$database.isConnected()){
                        $database.connect();
                }
                return $database.runSql("select * from users where id=1");
        }

}

class Database
{
        function connect()
        {
                //Connection logic
        }
        function isConnected()
        {
                $status=false;
                //run logic to check connection status
                return $status;
        }
        function runSql($sql){
                //runs the sql query
        }


}

What about that one? Did you see anything of interest?

Well in this case the User class is very intimate with the Database class, knowing not just how to connect to the external service but also how to check if its connected to start with!

Now for our final example.

<?php

class A 
{
        static $b;
        function __construct()
        {
                $b= new B();
                $b->interesting_fact="Some interesting fact";
                static::$b=$b;
        }

}

class B
{
        public $interesting_fact;
}

//Earlier in code

$a= new A();

//later in different part of codebase

$bInitialized= A::$b;

In this case we initialize a Class B from Class A where we modify its behaviour or data in some way that is useful to our business rules. However since we already know that the Class B is already initialized we can now use it later on in our code safe in the knowledge that the class has the right data.

This again is a demonstration of how prior knowledge of implementation is used to break encapsulation.

I believe third time’s the charm and we now have an even better understanding of encapsulation.

Have you encountered the issues highlighted above in your code base? Talk to us in the comment section below.

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Published by

jchencha

API Engineer