Few words about Object Oriented Programming

May 5, 2019 ☼ BeginnerOOPKotlin

When you start learning how to program you often hear or read that duplicating code is very, very bad. You should always strive to reuse logic and functionality. The DRY principle.

Code should be clean, maintainable, easy to read and easily extendable.

Easier said than done right?

What’s the real problem?

Complexity.

We deal with it every day. We need a set of tools and mental models that will help us tame the ever growing complexity of our program. If we want to be able to write clean, maintainable code that actually runs on machines we need some guiding principles”.

Enter OOP (Object Oriented Programming)

OOP helps handling complexity. It helps organizing your program but also your thinking.

As in real life where each one of us have roles, knowledge and can do various work, in OOP we have entities or Objects that store the knowledge, data, state and ways of doing work (methods).

I believe that programming is about breaking down a bigger problem into its fundamental pieces. As humans we do this every day without even thinking. We model the inputs we receive from the outside world and we provide adequate responses.

When we receive a specific input we know already how to respond because we have a set of abstractions or models with a clear defined set of responsibilities and knowledge about how to react.

When we model software we constantly try to encapsulate behavior based on some common patterns or shared responsibilities. Things that belong together are put together. At the same time we hide some parts because we don’t want other entities to be able to modify or access them.

This is a powerful concept that has been shaping our industry for long time and it’s still much applied these days.

OOP has 4 guiding principles:

1. Encapsulation

Encapsulation implies wrapping data and methods within classes while hiding implementation details (through access control).

Objects basically can hide certain parts of themselves from other Objects. Knowledge of how a specific Object works is not necessary for its use.

Whatever changes, encapsulate it

class Worker() {
    private val title = "Developer"
    private val name = "Nicola"

    fun whoAreYou(): String {
        return "My name is $name nad I am a $title"
    }
}

val nicola = Worker()
println(nicola.whoAreYou()) // My name is Nicola and I am a Developer

// You can't access or set title: nicola.title

2. Abstraction

In computer science, abstraction is the process by which data and programs are defined with a representation similar in form to its meaning (semantics) while hiding away the implementation details. Source

There are quite a few different definitions for this term in the wild but I like to think the abstraction helps defining what an Object does or can do instead of how it does it.

abstract class Worker(var name: String) {
    fun doWork(): String {
        // handle some complex logic
        return "Click, click, click"
    }
    abstract fun displayJob(description: String)
}

class Developer(name: String) : Worker(name) {
    override fun displayJob(description: String) {
        println(description)
    }
}

val nicola = Developer("Nicola")
println(nicola.doWork()) //Click, click, clics

3. Inheritance

Inheritance allows code reusability. Simple as that. Inheritance is when an Object is based on another Object. Same thing can be said for a Class.

There are several types: single, multiple, multi-level, hierarchical, hybrid. Some languages support some of them where others don’t.

For example JavaScript and Kotlin don’t support Multiple Inheritance.

See the Diamond Problem”

It’s essentially creating a parent-child relationship between classes.

Some of the advantages are:

There are of course disadvantages as well. Inheritance can bring maintenance and extensibility issues.

Inheritance is one of the most mis-used feature of OOPs by beginner programmers.

More on this topic: https://www.thoughtworks.com/insights/blog/composition-vs-inheritance-how-choose

// In Kotlin, if we want a class to have children, we have to declare it explicitly
open class Person(val name: String) {
    open fun printMyName() {
        println("My name is $name.")
    }
}

class Boy(name: String): Person(name) {
    override fun printMyName() {
        println("My name is ${name.toUpperCase()}.")
    }
}

val nicola = Boy("Nicola")
println(nicola.printMyName()) // My name is NICOLA.

4. Polymorphism

Polymorphism is the ability by which, we can assign a different meaning or behavior to something (objects and functions for example) in different contexts.

import java.math.BigDecimal
import java.math.RoundingMode
import java.text.NumberFormat
import java.util.*

interface Tax {
    val taxRate: Double
}

class EuropeTax: Tax {
    override val taxRate: Double = 0.25
}

class AsiaTax: Tax {
    override val taxRate: Double = 0.35
}

class RowTax: Tax {
    override val taxRate: Double = 0.15
}

class Order(private val tax: Tax, private val items: List<Item>) {
    fun grandTotal(): BigDecimal {
        val total = items.map{it.total()}.reduce{acc, curr -> acc + curr};
        return BigDecimal(total + (tax.taxRate * total)).setScale(2, RoundingMode.UP)
    }
    fun printTotal(): Unit {
        val form = NumberFormat.getCurrencyInstance(Locale("de", "DE"))
        println("Amount: ${form.format(this.grandTotal())}")
    }

}

val itemsIntheCart = listOf(
        Item("Book", 1, 10.12),
        Item("Apple", 3, 1.11),
        Item("Egg", 1, 0.50)
    )

val order = Order(RowTax(), itemsIntheCart)
order.printTotal() // Amount: 16,05 €

I hope this intro on OOP will help you familiarize with these concepts and provide some tools to help you manage complexity in your day to day work.

Being able to have a better grasp on these concepts will allow you to spot their limitations and trade-offs. It’s essential to be able to pick the right tool for the job.

Every other day a new blog post comes out where the author brings up legitimate issues with OOP and declares that it is a thing of the past.

Let’s do Functional Programming instead!

In the end it really doesn’t matter what you use. We should be aware of the pros and cons of the programming paradigm that we intend to apply.

It’s our responsibility to choose the right tool. We should do it wisely.


If you have any suggestions, questions, corrections or if you want to add anything please DM or tweet me: @zanonnicola