Inheritance results Coupling

Inheritance, Initiator of coupling



It all start with resolving the code duplication issue. The concept was pretty straightforward. Write the code once and use that code everywhere when needed. Why not! Who wants to write the same code multiple times. After all the duplicate code is a nightmare for code maintenance. So Inheritance was introduced.

Introduction

So we were given a new concept of Inheritance. On initial state it seems very awesome to write down the code on Inheritance patterns, but after some times when the code base grows that Inheritance code start to shape like a Spaghetti code. If one portion is modified the others portion falls. Overall it becomes very tough to understand the code base and to debug the falling part of the code base. Now again it is a nightmare for code maintenance, but this time a more complex one. Did it really help us? Or the Inheritance just put us on a more difficult situation?

If we try to avoid the Inheritance patterns, then what options do we have here on Swift? Well, there is one cool solution and that is the Protocol. On protocol oriented programming we will be using composition patterns for handling the duplicate code. The composition patterns is not something new, but it is not yet that much popular as Inheritance is. But day by day we are getting more closer to composition than the Inheritance.

The concept Protocol is also not new to iOS development, but now on Swift the protocol has some real cool features which facilitate the developer to achieve the composition, dumping the inheritance.

The Swift Protocol Hub contains all the related post with protocol. Be sure to check that out.

The dilemma

Does that mean we will not use the Inheritance at all. No at all. We have to use Inheritance also, it has its benefit. And we have to know the ins and outs of Inheritance and Composition.

There is no silver bullet to this problem. What we have to achieve is the balance, probably a bit more lean to Composition rather than the Inheritance. Let us use this talk on this topic. This will be the very first blog post of six blog post series to teach ourself about Composition over Inheritance and when to choose which one.

Background

What is Inheritance

On Inheritance patterns we will have a base class. And that base class will hold all the common property. And then the derived class will inherent the properties from the base class, plus they will add their’s own property.

Anything that is common will move to base class, so that all the derived class get that property from base class, this will remove the duplicate functionality from the code base. Let us have an example.

We need to use class whenever we want to establish some Inheritance on our code base. Value type like enum and struct can not establish an Inheritance as class can. We will talk about this topic on the next blog post.

This time we will derived some superheroes from DC comics. Lets build Justice league 😉. So our base class will be SuperHero and from the SuperHero we will start building the other derived class, like Batman, WonderWomen etc.

class SuperHero{
    let name: String
    let originalName: String
    let capeColor: String
    
    init(name: String, originalName: String, capeColor: String) {
        self.name = name
        self.originalName = originalName
        self.capeColor = capeColor
    }
    
    func speciality() -> String{
        return ""
    }
    
    var profile: String?{
        return "Known as: \(name) \n Original Name: \(originalName) \n Wears a \(capeColor) colored Cape.\n Speciality is: \n\(speciality())"
    }
}

So here is our SuperHero class. We have some common property like name, originalName and capeColor listed here. We have a method named speciality which currently returns an empty String as the derived class will override this method according to their needs. Because each of the derived super hero will have their own speciality. Finally we have a computed property named profile which will print all the details of the specific super hero.

As we know the very first founding member of Justice League was Batman and WonderWoman. So let us build that two class from the base class SuperHero.

class Batman: SuperHero{
    init() {
        super.init(name: "Batman", originalName: "Bruce Wayne", capeColor: "Black")
    }
    
    override func speciality() -> String {
        return "Very techie and extremely cool 😎"
    }
}

class WonderWoman: SuperHero{
    init() {
        super.init(name: "Wonder Woman", originalName: "Diana", capeColor: "Red")
    }
    
    override func speciality() -> String {
        return "Come on, she is a Demigoddess"
    }
}

On the above two derived class, Batman and WonderWoman, we defined the properties like name, originalName and capeColor on the respective init(). Also we override the speciality() method to provide the corresponding power description.

As a result by using the Inheritance we were able to override the property/function, speciality(), that was different for different derived class. Also we pushed the profile var up to base class, SuperHero, to remove the code duplicity.

Benefit of Inheritance

  • Common code on base class, reduction of duplicate code
  • Reusability, as derived class just inherent all the property and methods from the base class.

This benefits seems very ok on the first look. But those benefits will bite us on the long run.

As we all know Software need to be updatable/ modifiable. So there should be changes upcoming.
In that respect, we need to build our software in such a manner so that we can deliver the latest requirements by doing minimal changes to your code base. This means less coupling of our code. Does Inheritance help us anyway on this purpose or does it make our code base more coupled.

Drawback of Inheritance

As we know after Batman and WonderWoman, The Flash joined the Justice league. So let us make a new derived class TheFlash.
But immediately we find out that TheFlash does not have any cape, so there is no capeColor for TheFlash. Hmmm…

Inheritance already bite us. The structured code of Base class, SuperHero, makes a tight coupling with capeColor. We can not modify this the capeColor to nil without modifying the structure of the base class, SuperHero. And already we have two derived class dependent on this base class. On production it cloud be some very significant number of derived class. Updating all of them can easily lead us to some serious bugs.

When we initiate the Inheritance for our code base, we though Inheritance will save our development time by reducing the duplicate code. And on initial stage it does. But things are getting messy when we have some new requirements. Now we need to change the base class and all the derived classes, which cloud easily lead to a 100 classes or even more. This will cause us some serious development time.

Let us have a summary of the problem we face for using Inheritance of the very first hand.

  • Coupling
  • Development time
  • Potential bugs

Now what measurement we should have taken for not leading us to this situation? The answer is Composition. We will talk more about composition on our next talk. And achieving composition through protocol on the future talks. Al always the corresponding code is pushed to GitHub.

Happy Talk.

5 thoughts on “Inheritance, Initiator of coupling

Leave a Reply

Notifications for mobidevtalk! Cool ;) :( not cool