DEV Community

loading...
Cover image for What´s wrong with the gorilla?

What´s wrong with the gorilla?

Eckehard
Inventor. Always interested in new experiences
・5 min read

Joe Armstrong, the principal inventor of Erlang, is quoted as saying: "The problem with object-oriented languages is they've got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.".

So, what´s wrong with the gorilla? Or the banana? Or the concept of OO?

Hopefully nothing. Let me show you a different view on the concept to see, how you could benefit from Objects and classes.

...my first object was a burden

If you are a web developer, maybe the first time you needed to use objects was in react like this:

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
Enter fullscreen mode Exit fullscreen mode

React uses inheritance like water. Now they invented React Hooks to get rid of all sorcerer's apprentice they have called.

But, why in hell do we need classes to say hello?

Well, maybe because in react you do not get a banana without a gorilla (does he not even look a bit like Mark Zuckerberg?). But this is not a fault of OO, it is more a result of over-use of a concept, that does not apply very well to the task.

Do not use concepts, that do not help...

The concept of OO was introduced with simula in 1962 and reused and extended by other languages like smalltalk (1972). There have been different ideas about OO programming concepts, but I will refer to the class concept we use in C++, Delphi or Javascript today.

One important rule is: Do not use any programming concept, that does not help to solve your problem. So, If you want a banana, do not buy a Jungle. Buy a banana. print("Hello World");

As long as you write small programs with some hundred lines of code you will probably be fine to write some useful functions. print() is a function provided by the operation system, but you may which to add your own functions. Calculate something that is not existing as a function? Add new functionallity? You will add more and more functions and procedures and variables and will easily get lost in your self grown jungle of spaghetti code. Today, we call this approach "procedural programming", as the name "functional programming" is already occupied.

When your program grows, is gets harder and harder to pick up all the loose ends, but the real hell starts, if you try to change something general. Finally your code gets unmaintainable and it is easier to write it from new. Object Orientation is just about solving this situation. It is a way to organize your code.

Encapsulation

The first approach to prevent unwanted results is to keep the context small. Objects are a world in it´s own, they have their private variables and procedures nobody else can change. Objects help you to protect your code against you! Classes typically implement only a hand full of functions (or methods if you like) and it is eays to keep an overview.

Inheritance

Inheritance is probably the most misunderstood concept of Object Orientation. Systems like the Windows GDI are often designed as deep class hierarchies. If you digg into one of the GDI-Objects, it implements tousands of functions inherited from the whole class tree. But - is this a burden?

Technically, inheritance is elegant. A class implements just a small number of new methods, but can access all the methods of their parents. It is just a pointer to the class definition of the parent. So, inheritance gives you access to an ecosystem without the need to implement anything new. This makes inherited objects not heavy, but very lightweight.

There is a second situation where you may benefit from inheritance. Maybe you have a group of objects, that need a very similar ability. Let say, they need to store their state. You may write a global function, but then you need to deal with all the different properties. If all your objects are childres of one parent class, you can implement the persistence there and let all your objects inherit this ability.

Often enough, a parent class will be created for this special purpose. It is possible, that the parent itself just defines a general algorithm and some useless methods that have to be filled by the children. This parent would be called an "abstract class", as it is not instantiated at all.

In some languages like C++, a class can inherit from multiple parent. If you think about inheritance als "giving access to", this makes absolutely sense, as you might want to have different abilitites at the same time. Inheritance is not a way to access an object, it is a way to share the abilities of it´s class.

Abstraction

There is an important difference between a class and an object. A class defines all the properties and methods of an object, but is not a living thing. Classes are more like "templates". So, a class is more a fictional version of the objects, that are instantiated from a class. This is one level ob abstraction.

In OO, another level of abstraction exists. You may implement am algorithm on abstract properties, hence properties you do not know. You can implement a function add(), but let the child classes decide, which data type add can use.

If we talk about abstraction, usually the second definition in used.

Polymorphism

Usually, Polymorphism is the ability of a function to handle different data types. In OO, it can also be the ability to have the same method name in different levels of inheritans with different abilities. Both ways can be useful, but not generic vor the concept of OO

Summary

I hope, you might see, that there are situations, where OO can be a real life saver. But it does not apply in any situation. Sometimes, functional concepts may be more useful.

OO methods are most powerful on large applications with many tousand lines of code. The concept forces you to think about the way to organize your code and it gives you the tools, to make it better. In most cases it is a really hard work to find a good and future proof class hierarchie. This shoud bring you a quick return of investment in form of a better maintainable code. In moste cases you will just see, that things get much easier, if your decision was right.

Object Oriented Programming can be very powerful. But there is absolute no sense in using concepts, that do not make your life easier.

Discussion (13)

Collapse
efpage profile image
Eckehard Author

Every paradigm comes at it´s price. So, it should be clear that OO is not a tool for any problem. Usually it is more work to solve a problem based on classes and we have to decide, if this really pays back.

You can write multithreaded code based on classes. Think of a life game, where every cell is an object. But, you have to be very carefull to avoid typical multithreading problems. I suppose, this would be easier using pure functions.

Sure, every concept has it´s drawbacks, but we should talk more about how people can benefit most of a concept.

Collapse
peerreynders profile image
peerreynders • Edited

So, it should be clear that OO is not a tool for any problem.

The issue is that the mainstream often does not even consider exploring other, perhaps less complex options besides class-based object orientation - Java presented a world view where "class" is the atom that every software product is based on.

In JavaScript things are a bit different:

  • Plain functions
  • Plain object literals
  • Compose functions and object literals to get objects with "methods"
  • Assemble objects with a constructor function.
  • … then add a prototype object for sharing of behaviour implementation (inheritance; classes start here) without explicit composition.

So I guess if classes are atoms, functions and object literals are quanta.

Function-oriented

You don't need classes

Think of a life game, where every cell is an object. But, you have to be very careful to avoid typical multithreading problems.

Thinking like an Erlanger - Game of Life

but we should talk more about how people can benefit most of a concept.

A balanced view requires an honest review of all the trade offs.

These days class-based OOP is often practiced without scrutiny because its practitioners don't explore other approaches or the tooling that shapes their workflow masks the downsides until it's too late.

Before OO became more widely adopted, "structured programming" was practiced just as mindlessly.

Meanwhile Go has down-leveled OO back to the days of C Interfaces and Implementations (1996) and Rust has adopted a largely expression based (i.e. value oriented) syntax (Implementing an Object-Oriented Design Pattern).

And James O. Coplien feels that Data, Context, Interaction (DCI) is the right way to go "full OO".

Collapse
efpage profile image
Eckehard Author • Edited

Nice to hear that somebody knows "the right way", this usually is more the attitude of a missionar than of an engineer. As long as we do not talk about a certain problem to solve, I think there is no right way at all...

For me, OO was one concept to build maintainable logical segments of code. As long as you keep the interface small and well defined, a class can be developed relatively independently by a separate team.

A second reason to use classes was the ability to keep the namespace tidy. Each class has it´s own namespace and it is easy to avoid any conflicts.

Both things apply to larger projects rather to small applications.

I really wonder, how people solve these issues with pure functional programming?

Thread Thread
peerreynders profile image
peerreynders • Edited

Nice to hear that somebody knows "the right way", this usually is more the attitude of a missionar than of an engineer.

Sure but his rants are always fun to watch especially as there usually is a grain of truth to them. And evangelist or not - he does touch on some downsides of the classic approach that most practitioners wouldn't even think of.

For me, OO was one concept to build maintainable logical segments of code.

Correct when contrasted to structured programming as it was practiced at the time - however that doesn't change that class-based OO is essentially managing complexity with complexity rather than simplifying the overall approach.

Aside: Kevlin Henney: The Forgotten Art of Structured Programming

A second reason to use classes was the ability to keep the namespace tidy

And in JavasScript ECMASCript modules work much better for that purpose. They were introduced with ES2015 (i.e. when class became available) and even before that function closures and object literals were used to emulate them.

Another issue is hat OOPLs use classes as a surrogate for a proper type system. "Types" don't conflate data with behaviour the way classes do.

I really wonder, how people solve these issues with pure functional programming?

Scott Wlaschin:

Thread Thread
efpage profile image
Eckehard Author • Edited

By the way, the concept of CSS should give any functional programmer a heart attack. Never heard one of the evangelists complain about that?

Thread Thread
peerreynders profile image
peerreynders • Edited

CSS has nothing to do with functional programming. You are correct that neither an OO or functional mindset is helpful - but that doesn't mean that CSS isn't "fit for purpose".

Martin Fowler Bliki: RulesEngine:

A rules engine is all about providing an alternative computational model. Instead of the usual imperative model, which consists of commands in sequence with conditionals and loops ... rules, each of which has a condition and an action - simplistically you can think of it as a bunch of if-then statements.

i.e.:

  • Selector lists act as conditions.
  • Property lists act as actions.
  • Specificity and source order govern rule priority.

So in writing CSS you are composing rules for a domain specific rules engine (the layout engine) which drives the visual design of the page.

To understand CSS better I'd look into the Inverted Triangle CSS architecture. It makes clear that CSS works from the top down specifying rules that specify the global look and feel - then adding more rules where necessary to override the global settings for more local requirements (Google's web.dev uses it).

CSS Is Certainly Global And That’s Exactly The Point

The entire CSS-in-JS and styled-components movement fails to account for the fact that layout, visual styling and CSS works top-down - not bottom-up.

Keith J. Grant:

The problem is that people are familiar and comfortable with component approaches even when they are a "square peg in a round hole".

It seems a bit the power of OO was forgotten when the Web was created…

No - it's just that many people don't want to but in the effort to

  • understand why the web is the way it is
  • understand how to work to the strengths of the platform

and rather preserve at all costs the ways which they are already comfortable working with.

Front end and back end

Static page performance is the gold standard

Thread Thread
efpage profile image
Eckehard Author

From what I can see, people do far more with CSS today than styling the corners of a button. If you where true, why did they invent the shadow dom then?

The more people start to create applications on the web, they will need state dependent styling. Yes, you are right, CSS features a top down approach that does not fit to this task.
.

Thread Thread
peerreynders profile image
peerreynders • Edited

If you where true, why did they invent the shadow dom then?

About Web Components - Why Shadow DOM?:

While the theory was good on paper, the practice is that only ads and ads providers somehow benefit from this technology


they will need state dependent styling. Yes, you are right, CSS features a top down approach that does not fit to this task.

On the simplest level that is accomplished by adding and removing CSS classes but even techniques like quantity queries are available. So the "component" has control of the class names on the DOM elements to reflect visual state but the top-down styles get to actually act on it - because layout and visual design has to be orchestrated as a whole.


Thread Thread
efpage profile image
Eckehard Author

"We all love the Web, but in stories like this one, it feels like the Web doesn’t really love us back … or not as much"

Thread Thread
peerreynders profile image
peerreynders

And Andrea Giammarchi has been at it (the web) since before 2006 - and he will keep at it for the foreseeable future. Got to admire that but if that's what it takes …

Collapse
peerreynders profile image
peerreynders

Do not use any programming concept, that does not help to solve your problem.

So don't use "class-based object orientation" unless there is a clear indicator that it will help to solve your problem. It should not be the default approach.

However there is the mainstream attitude that OO is the best tool for any problem simply because it was declared to be better than structured programming in the late 1980's to early 1990's.

Meanwhile technology has moved on and made some of OO's trade offs into liabilities.

Going through Arthur Riel's OOD heuristics (1996) it becomes clear that OO is an approach that manages complexity with complexity. Meanwhile encapsulation doesn't address one core problem:

Mindless mutability and side effects weren't an issue in single thread environments (Thinking Outside the Synchronisation Quadrant) but given that Moore's law is done, software increasingly has to distribute processing tasks across multiple threads, if not multiple cores.

Even many client side web applications running on mobile client devices today are constrained by the legacy single thread model (single core performance was how the web was built) adopted by current frameworks despite the fact that it is becoming more common for devices to feature multiple but lower power cores.

It isn't that functional programming is fundamentally better - however immutability does limit the possibility that something shared is going to unexpectedly change and it forces a style of processing that relies less on sharing values but more on creating new ones.

Value-oriented programming tends to be simpler than place-oriented programming (PLOP) even when PLOP seems initially easier.

The fundamental tenet seems to be:

  • Don't share what you mutate (i.e. local mutability is OK)
  • Don't mutate what you share.

The most amazing achievement of the computer software industry is its continuing cancellation of the steady and staggering gains made by the computer hardware industry. — Henry Petroski

PLOP still has its place but when performance actually counts OO is overhead.

Data-Oriented Design: Mapping the problem (2018):

Object-oriented development is good at providing a human oriented representation of the problem in the source code, but bad at providing a machine representation of the solution. It is bad at providing a framework for creating an optimal solution.

So more than a decade ago part of the game industry abandoned object-orientation as a design time representation and embraced a different approach - Entities, components and systems ECS - aligned with the "machine" rather than the problem domain.


Even in 1994 the "Gang of Four" design patterns book stated (p.20):

Favor object composition over class inheritance.


Classes are types but not all types are classes. Classes are not a substitute for types. Polymorphism is about types, not classes (The SOLID Design Principles Deconstructed). So to get polymorphism one does not need OO - just a good type system, preferably one with abstract data types.


Conclusion: Only adopt "class orientation" which is typically mislabelled as "object orientation" if there is a clear benefit to doing so.

"class-based object orientation" carries an inherent complexity which is only appropriate for limited types of problems. Given that this article has a JavaScript tag it needs to be understood that an awful lot of work can be accomplished with just functions, object literals and modules (in my opinion a far more important addition to ES2015 than class).

That said when working with custom elements one really doesn't have much choice because class MyElement extends HTMLElement is just how it works.

Collapse
peerreynders profile image
peerreynders

Joe Armstrong's Banana/Gorilla/Jungle criticism was his polite opinion. Why OO sucks dug a bit deeper into his position.

In an interview in 2010 he stated:

… but Erlang might be the only object oriented language because the 3 tenets of object oriented programming are that it's based on message passing, that you have isolation between objects and have polymorphism.

Finally in 2019 Alan Kay stated:

And, he might be right. Erlang is much closer to the original ideas I had about "objects" and how to use them.

So it seems that from Armstrong's perspective Simula 67-derived "class-based object-orientation" lead the industry down the garden path.

Collapse
peerreynders profile image
peerreynders

If you are interested in exploring functional programming for yourself then keep an eye on Introduction to Functional Programming in OCaml (twitter) just in case they start another session in September/October.

Why OCaml?

Who's using it? (example: Jane Street).

While it's unlikely that most people will ever earn money with OCaml it's a good basis for other dialects like F# (.NET; Scott Wlaschin: F# for Fun an Profit, Domain Modeling Made Functional) and ReScript (front end).

Personally I think learning functional programming with OCaml is a bit harder than with Erlang (twitter) but it comes at a good trade off because that additional difficulty comes from being statically typed (with a sound type system) and is mitigated by excellent type inference.

But OCaml is also more practical and therefore easier than Haskell (twitter) because functional purity is not dogmatically pursued (i.e. immutable by default but there are escape hatches), there is no laziness to deal with and monads and category theory don't come up at every turn.