Most programmers fall into one of two categories in terms of how they think about program structure. Either

1) They think the fundamental elements of code are classes and methods on classes, or

2) They think the fundamental elements of code are functions.

Sometimes either of these also know there's something called a module or package, but the idea is loosely understood.

I was one of these people. If you're happy to stay that way, stop reading my comment now.

Ada is extremely well designed. One of the reasons is that the language design cleanly separates concepts normally bunched together into ideas like "everything is a class".

In many languages, if you want implementation hiding you get a whole bunch of other things with it. You can't use just implementation hiding without automatically opting into all parts of class-based programming, like inheritance, subclassing, etc.

Then you go "wait, what? Isn't inheritance and subclassing sort of the same thing?"

Yeah, no. Not fundamentally. It's only the same thing in popular programming languages because everything is the same thing in popular languages. Everything is a class and if you need anything you get the whole class concept, whether or not you wanted it.

This is problematic especially for beginner programmers because they learn implementation hiding is good. So they use that. But that opens up a huge toolbox of additional tools, not all of which are appropriate. But beginners are like beginners are, and when they see all those tools they simply use them -- sometimes out of desperation. This leads to messy code.

Ada is different. In Ada, you can pull out just the concepts you need, and it won't automatically opt you in to everything else.

A beginner that uses implementation hiding in Ada won't suddenly have an open toolbox full of subclassing. Their toolbox still contains just implementation hiding and whatever else they intentionally put in it. That leads to better code.

Just for that experience, Ada is worth learning, in my opinion.

Here are some quotes from TFA that alludes to this.

> Packages are namespaces for functions and types, unlike other languages where types can “contain” functions and types.

Organising code into subcomponents with implementation hiding is separated in Ada from class-based programming. You can do both, but you can also choose to do only one of them.

> Function overloading acts as a key design element

You can have polymorphism without opting into inheritance. (Further, you can have inheritance without opting into class-based programming.)

> Everything in a package is related, there’s no syntactical split between “free function”, “class function”, or “member function” (method).

You can have methods on types without opting into class-based programming.

> What most C-family languages call “functions”, Ada calls “subprograms”. Ada distinguishes between those which return a value and are truly “functions” and those which do not return a value, and are “procedures.”

A procedure is fundamentally different from a function from a reasoning-about-the-code perspective. You can have either without automatically opting into the other (as is the case when everything is a method.)

> Examples are “accesses” (sort of like pointers), “accesibility” (similar to a scope for borrowing), “tagged types” (classes), “derived types” (unrelated to OOP), and “subprogram”.

Using different words for different concepts -- instead of bundling them into the same generic idea -- increases the richness of your mental vocabulary which also increases the nuance your thoughts are able to express.

----

If you read my comment all the way down here, you might be interested in the Rust beginner's tutorial adapted to Ada, one of my more popular articles (which tells you something about my popularity...) https://two-wrongs.com/guessing-game-ada-style.html