Techlogs
Published in

Techlogs

Learning Go — Hello Interface

By a Developer who does not know Go for other Developers

This is part 2 of the Learning Go Series

Part 1 https://medium.com/techlogs/learning-go-hello-world-fde2e29c5eb1

EPISODE 2: WHAT’S WITH INTERFACES.

What is the big deal with Interfaces? If you are a Python developer you may wonder. If you are a new programmer you may wonder more. Not that it is not there in Python ( abc from 2.7), but rarely used compared to C++ (Abstract Class) or Java (Interfaces ). ( I use/used python a lot and strangely have not used ABC’s), though I will kick myself if I don’t use this in other languages. Maybe it depends on the nature of the SW created with Python or the dynamic nature of Python.

Anyway, let us stick with Go, and Interfaces are a big deal in Go.

Why does Go have no Inheritance- Implementation Inheritance

Actually, it is the only deal if you are thinking of the Animal — Dog — Cat — Man speak (bark/meow/ Grunt) Object Oriented example that you have been taught in school.

While in Java you may use like

abstarct class Animal {       astract public void speak();}
class Dog extends Animal {
@overrrides
public void speak(){
System.out.println("bark bark");
}
class Cat extends Animal {
@overrrides
public void speak(){
System.out.println("meow meow");
}

This is fine for this example. However, very few SW projects model these kinds of textbook scenarios, and when people take concepts out of textbooks and apply it to the real world SW projects, that is when they get scared and new posts appear on the internet at regular intervals till the horror is well known.

That Extends is Evil — https://www.javaworld.com/article/2073649/why-extends-is-evil.html

Or the Fragile Base Class problem: The fragile base class problem is a fundamental architectural problem of object-oriented programming systems where base classes (superclasses) are considered “fragile” because seemingly safe modifications to a base class, when inherited by the derived classes, may cause the derived classes to malfunction. The programmer cannot determine whether a base class change is safe simply by examining in isolation the methods of the base class.” https://en.wikipedia.org/wiki/Fragile_base_class

Or even the Java expert Joshua Bloch in his wildly famous Effective Java bok tells one not to use it/or use it very carefully — “Design and document for inheritance or else prohibit it”. (many links also SO )

I could go on and on, but enough said. Or here is one more from the creator of the Java Language

Bill Venners: When asked what you might do differently if you could recreate Java, you’ve said you’ve wondered what it would be like to have a language that just does delegation.

James Gosling: Yes.

Bill Venners: And we think you mean maybe throwing out class inheritance, just having interface inheritance and composition. Is that what you mean?

James Gosling: In some sense I don’t know what I mean because if I knew what I meant, I would do it. There are various places where people have completed delegation-like things. Plenty of books talk about style and say delegation can be a much healthier way to do things. But specific mechanisms for how you would implement that tend to be problematic. Maybe if I was in the right mood, I’d blow away a year and just try to figure out the answer.

Bill Venners: But by delegation, you do mean this object delegating to that object without it being a subclass?

James Gosling: Yes — without an inheritance hierarchy. Rather than subclassing, just use pure interfaces. It’s not so much that class inheritance is particularly bad. It just has problems.

https://www.artima.com/intv/gosling3P.html

The Go designers ( Robert Grismer, Rob Pike, and none other than Ken Thompson -creator of B language -the predecessor to C language) knew well of these and Go has no support for implementation inheritance (extends in Java) and interface inheritance.

Go takes an unusual approach to object-oriented programming, allowing methods on any type, not just classes, but without any form of type-based inheritance like subclassing. This means there is no type hierarchy. This was an intentional design choice. Although type hierarchies have been used to build much successful software, it is our opinion that the model has been overused and that it is worth taking a step back — https://talks.golang.org/2012/splash.article

Nuff said about something that is not there in Go in the first place to worry about — don’t you think.

But that liberation, that freedom for those who have felt the mad subclassing orgy about a decade back will like this choice.

this is no joke — this picture is a representation of a real piece of code (obfuscated). You needed to dream within dreams to understand what was happening.

Why are Interfaces so Important

The reason is Interfaces are a big deal in creating a well-designed software. The vast majority of programmers are actually Procedural Programmers. They do not understand what SW Design is and why Design is needed. Somehow this is hard to explain as it is not easy to design, but the skill of a good programmer is trying to extract the patterns in the code structure and model the code structure to align with the Open Closed Principle.

If you are a programmer and the above paragraph goes over your head, please stop and research this more and think. This is the only way to be a better programmer and create brittle monoliths.

Let’s pause a bit and see why Interfaces are so important even internally and why it is so less used.

Interfaces are the tool that helps you create decoupled code — Code that can be extended with time and features, code that needs less modification after it has been released. It is hard to explain with a Toy Example, as the worst examples to give are misleading examples and Object Oriented Programming textbooks are full of it. So let’s skip Animal -Cat and Dog and take a harmless example -Let us create a Command Pattern and try to illustrate how it has to be used. Read more about it here — https://en.wikipedia.org/wiki/Command_pattern

Here is a good link to get you up to speed with the syntax of interfaces — http://www.golangprograms.com/go-language/interface.html

Let us create a folder internal_interface (since we want to play with packages a bit ) and create interface.go

package  internal_interfacetype CommandInterface interface {
Execute () int
}

Pretty simple right.Let us see how to implement concrete types of these in Go

Let us try to use this package in another package so that we are also more familiar. You can read more about packages here — https://medium.com/rungo/everything-you-need-to-know-about-packages-in-go-b8bac62b74cc

Let us create a folder called command_pattern and in it create a file command_pattern.go

We create three types SkipCommand, JumpCommand and a FakeCommand

type SkipCommand struct {
//Go exports a variable if a variable name starts with Uppercase.
}
func (cmd SkipCommand) Execute() int {
fmt.Println("SKIP Command Executed")
return 0
}
type JumpCommand struct {
}
func (cmd JumpCommand) Execute() int {
fmt.Println("JUMP Command Executed")
return 0
}
type FakeCommand struct {
}

Note that the Execute method in the interface is implemented by SkipCommand and JumpCommand and not by FakeCommand. Go compiler automatically now infers that SkipCommand and JumpCommand implements the CommandInterface as all methods of CommandInterace is implemented by both.

Let’s test it out. Let us create another folder /package called pattern_examples and add a file main.go (note the package main declaration — Go compiler uses this to create an entry point for the application)

package main
import (
"fmt"
)
import(
"command_pattern"
"internal_interface"
)

Now before we add the main loop, lets add the million dollar function

// A great rule of thumb for Go is accept interfaces, return structsfunc run(cmd internal_interface.CommandInterface)() {       cmd.Execute()}

If you were frustrated where the CommandInterface type that you actually defined in internal_interface folder is used it is used here.

If your business logic can work with Interfaces and not actual types, then you are on the path of OCP.

Let is finish the rest of the code

func main() {skip := command_pattern.SkipCommand{}
jump := command_pattern.JumpCommand{}

run(skip)
run(jump)
}

Compile and run this. You will see the statement SKIP and RUN printed. We have used a dummy interface properly. We can keep on extending different types of Commands and assuming our business logic is just selecting and executing a particular command based on a particular event, then all is well and none of the old has to change to accommodate the new.

go_learn# go install pattern_examples
go_learn# ./bin/pattern_examples
SKIP Command Executed
JUMP Command Executed

Now let’s do one more test; Let’s really check if Go compiler can catch our FakeCommand

func main() {fake := command_pattern.FakeCommand{}

run(fake)
}

Compile this and you get the error; Go is a statically typed language and this ensures that the type correctness is checked at compile time. This is pretty good as it the first test of program correctness done automatically by the compiler and one reason why it is used in commercial SW development.

go install pattern_examples
# pattern_examples
src/pattern_examples/main.go:32:5: cannot use fake (type command_pattern.FakeCommand) as type internal_interface.CommandInterface in argument to run:
command_pattern.FakeCommand does not implement internal_interface.CommandInterface (missing Execute method)

That’s all for this Episode.

More extra reading here

Robert C Martin — Open Closed Principle via Interface Inheritance (Abstract base classes) link + History how Martin redefined the tern https://stackify.com/solid-design-open-closed-principle/

https://www.calhoun.io/how-do-interfaces-work-in-go/

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store