Hacker News new | ask | show | jobs
by evdev 2229 days ago
It seems like there's something deficient in the way we tell the story of the history of software architecture (to the extent we tell a story at all) in terms of the name-brand techniques and technologies involved, rather than in the actual layout and organization of actual codebases.

For a while I've assumed that OOP as in C++/Java essentially formalized modular programming in C. In other words, that people were already writing programs whose state was divided into functional areas, with some functions serving as the interfaces between the modules. With a class-based system you can rigidly formalize this; and then OOP as we use the term essentially just reinterprets this formalization as actually creating the architectural paradigm that had already evolved as programs grew.

(This is NOT meant as the one way to sum up the whole world of things identified as or related to "object-oriented programming".)

But I wasn't around at the time...

3 comments

This is my thinking too. It's really silly to have wars around programming paradigms. There are only a few principles around which we're all arguing:

* How do we make programs that are easy for the machine to execute efficiently? * How do we make programs that are easy for humans to read and understand? * How do we ensure, given the maintenance requirements of our programs, that another human who doesn't have the benefit of our experience can safely make changes to our programs without unitended consequences?

Discussions around OO versus Functional versus Procedural miss the point. You can write perfectly maintainable procedural, functional, or object-oriented code. If you're authoring something brand new you have to approach it with a complete understanding of all the moving parts. If you're not there, make a prototype, wait a few days, then go through and re-read it. Anything you don't understand is something nobody else will the first time they approach your code base. Come up with ways to be explicit and to communicate clearly what the intent is. Try to anticipate what things people will be changing often and make those easy things to change. Remember that it's about conveying a representation, not a deep understanding. You want to represent your understanding of the problem space to someone who doesn't have the same level of understanding as you.

> It's really silly to have wars around programming paradigms. There are only a few principles

Well, you say we're having wars around the programming paradigms, I say we're having "spirited debate" around the principles :). I've been working mostly in Java for the past 20 years or so, and I can't help but observe that most people, when they try to put together a Java application, default to a sort of design that looks an awful lot like old Cobol programs did: they have a "datatype" generator (usually automated from XML schemas) and a slew of "utility" classes with mostly static functions that have mostly static data that operate on these datatypes, and as little class instantiation as they can possibly get away with. I've seen this same basic architecture repeated many times across four different employers in two decades. It's always a lurching, monolithic, untestable behemoth that never works reliably and resists any attempt to change. In talking with the original designers, it's clear that there were no principles behind the design besides "it still doesn't work, how do I get this thing to work". If there were clear and adhered to principles like automated testability, you'd end up naturally with an OO (or even better, FP) type design.

Interesting. I guess I've been more fortunate. Most of the Java code I've worked with has involved reasonably well thought out classes. For me that mostly means I can read and understand parts of the codebase in isolation. There are usually a few piles of sometimes ugly utility classes and the occasional mess of deeply nested inheritance that nobody wants to touch. When the latter becomes painful enough, someone usually decides to refactor it, which is often not as hard to do as everyone fears.

It seems to be improving in the last 5-10 years, as most practitioners have found that both of these eyesores can be reduced. DI (sometimes messy itself, but it can be done cleanly) tends to make people rethink those utility classes, and shallow inheritance is now favored, with a focus more on interfaces and composition.

Sort of.. But the way this was done in C is still done and was evolving long after C++ split.

IMO classes as false separation is the reason we kept C++ and Java out of Oses. ABI compatibility, dynamic loading, etc are all from the duck philosophy. It is no one's business if your duck thinks it is a duck.

When I learned C, it was drilled into us that the proper way to implement all the data structures and things was with abstract data types.

https://www.edn.com/5-simple-steps-to-create-an-abstract-dat...

And then you have nicely "namespaced" functions that operate on those abstract pointers and your code is isolated from the implementation and you don't accidentally depend on some implementation detail you shouldn't.

But ultimately this is all just informal OOP. Objects/classes are just a natural way to organize programs.