> An object is both code and data, but also neither. This means people can talk about objects and yet not have to talk about either data or code.
These two sentences jumped out at me. I really like this analysis, because it would explain why object-oriented thinking especially seems to be prevalent in hierarchical organizations. It allows any number of minds to contribute to the design of a system without any knowledge of the technical details of that system.
Object orientation works because it worked for windows (and other UI toolkits, even today) when computers were switching to graphical user interface toolkits. And frankly, object-oriented UI toolkits work a lot better than webdev even today.
But OO doesn't work because webbrowsers have detonated a hydrogen bomb of "historic reasons for this API" over the worst UI toolkit ever, and abstractions, whether OO or ..., simply don't work well over this. They make it extremely hard to find where the OO toolkit is incompatible with vendor X's browser version 82.2.1.3.3.883.1.3.4, and harder yet to fix the problem.
It seems like 2014 was the year of having programmers rant against every form of abstraction because they can be misused and because they "hide complexity". Well of course they hide complexity. That's the point. That's what allows us to raise the abstraction level of what we're doing and working on.
A simple shared networked database (also known as CRUD, or to some extent MVP) was a solved problem on NextSTEP before I left kindergarten but in 2014 we all insist on rewriting the whole thing from scratch (can't even use an actual database anymore "it doesn't scale").
When I was a 12 year old discovering dBase writing a networked CRUD application was something you'd do in roughly an hour. Today, a week is not that bad, apparently. When I turned 14, and worked with dBase for windows, putting rich text fields (with working copy-paste from office documents) was less work and finished faster, by a factor of 100. First I wrote them in things like dBase, then Delphi. Then I started writing them in PHP + SQL. This was tedious, but at least it was vaguely manageable. Today, I write them in Bash (for deployment) + Go + SQL + Python + Javascript + JSON, not counting the various configuration languages I need to know. They don't work nearly as well as the things I made in dBase for windows, without a doubt they are less functional than the tools I wrote in Delphi, and they can do vastly less on computers thousands times faster (my first Delphi was installed with 66mhz, 16M RAM and 500M drive) without weeks of work they don't look nearly as good, and they are utterly and completely incompatible with everything else on the planet.
This is why we had OO (the very first book I had on the subject started with how to make OO work for an extensive text editor). That's what's good about it, and why we're not doing it anymore ... I don't really know.
Today we are locked into the web. Any end user has no control whatsoever over their files, over what programs his computer runs (my "standard" text editor is in javascript and gets it's code downloaded from an internet provider that could change it at any time. I, of course, cannot change it), over who can read their files/mail, governments, MPAA, RIAA, and so on get people's mail clients blocked and their mail made inaccessible on a regular basis, ...
("AnonymousField" is the name they give to it. But it's inheritance. Badly executed and doesn't fit well in the type system, but that's par for the course for Go)
I don't get where these statements keep coming from. Well, I do, to an extent : the Go authors keep claiming these sorts of things, but I don't understand why. They're not true. There is no complex language feature that Go does not have. Go has inheritance, Go has generics (simply inaccessible for everyone except the language authors, like in modula-2), Go has polymorphism (simply inaccessible for "mere" users). Go has return-value polymorphism. Go has type parameters, both in types and functions (again, inaccessible for users of the language, but it's there).
Everything is simply built as custom compiler code that's inconsistent and riddled with unexpected edge cases, none of it worked into the type system itself. This is the real reason for resistance against these language features : working them into the type system would be a necessity, and isn't possible without breakage because they're not consistent.
I think Java-style OO was successful because it made code organization obvious, more so than any other programming language I've seen. The key insight is that source files are the natural unit of writing code. Each source file has an explicit public API and private internal state, and a dedicated namespace that always reflects the file's name and location in the source tree. That makes it easy to see the big picture by just looking at the directory structure and the imports.
But what you describe are basically namespaces. All the rest of OO is overkill. Recipe for success: take a simple language with only functions (like Lisp or C) and add namespaces. Result: this language can do 90 % of what OO languages are useful for, with only 10 % of the features.
OO is simply a layer of human-readability on top of functions and data. As far as the CPU is concerned, both object and method arguments are just data to operate on. So `steve.drink(water)` in another context is just `drink(steve, water)`, which is a little more difficult (at least in English) to reason about.
OO principles are for the limitations of people, not computers.
I should hope it'd be obvious to most people that you don't actually need all of OO just to get that little bit of syntactic sugar. I'd also like to point out another obvious fact: this idiom completely breaks down when the subject happens to be more than one person, i.e: steve_and_irene.drink(water) whereas it works fine in the procedural case (thanks to varargs): drink(water,steve,irene,...).
And you don't need syntactic sugar to do OOP, as you have just demonstrated with your examples. And also, multi methods exist, but you probably want one subject/dispatch variation per sentence anyways for complexity reasons.
This is correct. OO codifies the pattern of having a struct and a set of functions that operate on it. The syntax does help humans reason about that pattern. But my understanding is that the goal is more about the human limitations of managing large code bases than the human limitations of language.
OO is all about encapsulation. We tend to decompose a program into chunks for different teams and individuals to work on. Software development is a distributed task. Encapsulation means when you code against components written by other people, you only have to understand the public API that they provided. You are supposed to be guaranteed that that API will continue to work even as the code behind it is updated. As component users we can focus on our own task and not worry so much about the details of the component. As the author of a component, we can hide state from the users. That can't be done with structs. we can make updates and switch out implementations without (as much) fear of breaking the code that depends on it.
It's really all about being able to modify code more safely on bigger teams.
In my mind the issues that OO introduces are:
* Encapsulation results in more verbosity for the same functionality.
* Inheritance takes more thought.
* OO as a whole is more complicated and has a bigger learning curve.
* OO used incorrectly will magnify the first two points greatly. Given the learning curve I imagine a lot of people don't use it fully correctly.
Which is great until you have to OO-ify `playWith(steve, bob, ball)`. OO dictates that one of steve, bob, or the ball, knows how these three interact, and that it not vary with respect to the other two.
Or `steve' is given to you from a 3rd-party library, and you want to imbue him with the ability also to eat. Well, you can't define `steve.eat(salad)', unless you subclass his class and make a proxy of the object from the library.
To properly solve either of these, you are forced to resort to the second-class citizen of a static class, which is exactly just functions in a namespace.
The one actual "benefit" OO gives you is run-time dispatch; the ability for the program to defer until run-time the decision which implementation of `steve' actually handles `.drink()'. Outside of OO's poster child of GUIs, I have rarely seen a need for this capability in 20+ years of programming. (Mere compile-time dispatch, as captured precisely by OCaml's module functors, is much more common.) Centering a paradigm around this rarity is quite bizarre.
Isn't also limiting the potentially boundless array of (mostly irrelevant) functions to relevant data types also relevant? I'd venture to say it is.
Ooooh... that's a Point object - no way the AddAccount function does anything relevant with it! In OO you don't even actually need to think that since Point has a limited set of methods.
I'd be willing to bet that the Point object in any given language is going to have more methods that take it as an argument than methods the class itself has.
True. But I still go looking for the "Point" class first. Then I start looking for things which accept "Point" parameters. Big difference from procedural programming languages.
This applies to any language with static types. Or that allows code to be separated in multiple files, for that matter.
In Haskell, I can literally ask the editor to list me all functions that operate on type X. Even in C written with a modicum of coding discipline, 90% of the functions relevant to type X will be defined in X.h, wherein 100% of the functions in X.h are relevant to type X. (And the 10% of functions relevant to type X that aren't in X.h? Well, in Java, they also wouldn't be part of class X anyway.)
IMO apart from namespaces, the other biggest convenience provided by OO is inheritance. In some problem domains, there are naturally emerging inheritance hierarchies. And when you need it, manually coding virtual dispatch in non-OO languages is going to be hairy.
> I think Java-style OO was successful because it made code organization obvious
I can't agree with this opinion. I often find it an annoying restriction that I must put all my functions in a class. Let's look at a trivial example of multiplying a matrix by a vector. You can write
matrix.multiplyBy(vector);
// OR
vector.multiplyBy(matrix);
It is possible to multiply from the left or from the right (as long as the matrix and vector dimensions match). This makes it even more annoying. What I'd really like to do is:
multiply(matrix, vector); // vector is a column
// OR
multiply(vector, matrix); // vector is a row
Perhaps it's the kind of problems I work with (and the non-OO languages I am used to), but I am regularly faced with this problem if I have to use a language like Java where you have to put all your functions inside classes.
To further elaborate why I don't really like OOP (except in a minority of cases where inheritance, etc makes intuitive sense), I think the biggest issue is that classes/objects are the method to do almost everything.
Namespaces, visibility, inheritance, dynamic dispatch, etc are all somewhat orthogonal features. Having a "class" to be the unit that uses all of these features is, in my opinion, a restriction.
Lists (or arrays), tuples (or structs) and Maps (or dicts) are what I want 99% of the time. When programming with Java or similar languages, I feel like the primary means of abstraction and composition in the language is catering to a 1% problem.
I learned programming in the late 90s, early 2000s, during the height of the craziest OOP craze (when "object oriented" was synonymous with "good"), so it took me a while to un-learn all of the OOP methods but I feel like I did turn into a better programmer when I stopped thinking in terms of objects.
OOP is a neat paradigm for some cases, but I find those cases very rare.
Honestly, I think something like Ocaml's module system would be better for large teams than objects, and I think it's also just a better way to organize code.
I think it's a worthwhile tradeoff to make source files serve as the unit of namespacing and encapsulation. You lose some flexibility, but large programs become easier to read, and new programmers have fewer random conventions to learn.
I agree that object orientation is a psychological success, but I think it's more for linguistic reasons than anything else. Our speech and thinking are organized into things, attributes, and actions.
"The stove heats the water." An object performing an action on another object (a direct object, in parts of speech), changing the state of the direct object.
So when we code this, it makes sense naturally to write something that is readable in human terms:
stove.heat(water);
This makes code easier to reason about and easier to go back to later. Hopefully, our code reads like the computer- and human-readable literature it is.
I don't think there is a particular reason why OO became popular here. There are several ways to do it, the choice between them is fairly close to arbitrary, and one of them became popular.
While I'm no fan of OO as a dogmatic solution to every problem, the differences between it and any other reasonable approach are small for most problems, compared to the complexity of solving the problem itself.
The difference between OO and most other approaches is that OO very strongly encourages you to raise the abstraction level of your code.
Hackers hate this, because small segments of code that look near-identical can do vastly different or complex things and lots can go wrong in there. Also, the higher you go in abstraction, the more subtle the code becomes, the more important differences in meaning originate from very small differences in source code. Take a haskell monad chain and try to explain the sequence of 2 statements ... it takes 2 minutes of thought to figure it out. But of course those 2 statements do much more than 100 lines of C can do.
And of course bad programmers hate this, because you have to learn abstractions.
It depends on what you're doing. If you're writing a big application, something to be supported over the long term that isn't trivial, then OO is most definitely the way to go. If you're hacking something together that won't last the week, raising abstraction level will only stand in your way. If you're planning to rewrite the core of the application on a monthly basis, OO, and any other kind of abstraction, will make life very hard on you.
I think this is why Elixir's pipe syntax spoke to me while hacking on it yesterday. It puts the subject first, which has that human-readable bit to it. I've been writing code in myriad languages for 15+ years, but that doesn't make me impervious to what seems "obvious" or intuitively "proper" to my brain, organization-wise.
This organization of language in this fashion is English-specific though. I wonder what feels intuitive to non-English (or non-Romantic) speakers - is it OO as well, or something else?
What (from a code organization perspective) might work better in practice is:
water.heat(stove);
because it's the water that's being changed and change should be encapsulated. On the other hand, the stove may also change in the process. In fact, the water and the stove do things to each other. Then what makes either of the two options more appropriate? Similar issues arise with a method called sendMessage; is the object having this method now supposed to send a message or to receive a message?
What we actually need is to be able to use different heating algorithms dynamically. To achieve this we will use the strategy pattern, so you end up with:
What methods is this heating strategy going to call on water and stove? Consider for example that the stove builds up rust. Therefore it needs to know the properties of what's inside. Is the heating strategy going to tell it that?
In 1963 (SketchPad)? Or 1967 (Simula)? So when OOP was created in 1967, I'm not sure modules and interfaces were in wide spread use, considering that they didn't really even appear until the 70s (definitely not in Algo 68).
OO is successful because at the time (when software engineering was really growing into a proper engineering discipline) large engineering efforts needed something anything that would improve the management and development of large-scale software efforts with millions of lines of code and hundreds or thousands of developers working in different time zones all contributing to the solution. OO has always been a solution of management science for software engineering, not Computer Science.
One of the things that's very hard to understand is how much large efforts rely on our ability and understanding to manage and coordinate the effort of all these people providing work input -- yet management science is still remarkably poorly understood.
OO is nice because objects define work-units which are easy to measure and track through a management structure and the development of which kind of map to a work breakdown structure in much the same way assemblies and sub-assemblies go into a bridge or a car in traditional engineering:
Phase 1:
Part A: develop all the classes and methods on each class.
Part B: test and certify components.
Phase 2:
Part A: integrate 1A components.
Part B: test and certify integration.
Phase 3: repeat phases 1 and 2 until you have finished software
"oh team X is working on component (class) A2? when does A2 move to testing? okay, I'll schedule that. You know component B6? Yeah, it failed testing and needs to be reworked, but it shouldn't hold up phase 2: integration."
Lots of people give Java and Java shops lots of flak because the work is unglamorous, but they've semi-succeeded in mapping software engineering to the management science practices that were formulated during the Industrial Revolution...meaning they've turned software development into assembly line work.
This is why good software developers hate working in these places. It would be like a fine watch craftsman going to work on the Timex digital watch assembly line at Foxconn.
The Management Practices that informed OO and drive it are the dominant way to "make stuff on schedule" that humans have managed to come up with. Like it or not, it's why cars get made, t-shirts end up in stores for $10, and your state DMV has an on-line renewal site.
It's interesting to study large software projects that failed as well. SAIC has a couple of well known ones: Virtual Case File [1] and CityTime [2], Healthcare.gov [3] was another good example. It's even more enlightening to compare these failures to big traditional engineering failures: Seattle Tunnel [4], Space Shuttle failures, etc.
One thing to keep in mind. Large software projects are often more complex on raw unit count than even the most complex engineering efforts in history. For example, the Space Shuttle is considered one of the most complex pieces of engineering ever, and it only had 2.5 million parts. [5] OS X 10.4 by comparison has almost 100 million lines of code. [6] It's not a perfect comparison of course, but it does help cement in the magnitude of modern software efforts.
If OO has a failing it's that humans haven't managed to come up with a better way to break complex work down or to define software methodologies that map well to how we know how to manage and coordinate complex tasks. OO works very well when considered in this context, it does more or less what it's supposed to. It's not intended to provide a methodology for elegant or creative software crafted by a single person or small team of experts.
We've learned a lot in the decades since OO has become the dominant force in software organization. And Management Science has improved a couple tick marks as well. The next paradigm shift is likely close. But make no mistake it'll probably be a streamlined OO-like system of trackable, schedulable work components. But it won't happen quickly, literally trillions of dollars in work effort have been put into OO from the s...
Why couldn't we have achieved this assembly-line production system with procedural programming? Just separate the project into files, assign each programmer to a file, say, "Write a function called X, that takes input A, and returns output B," the manager writes the main() function that pulls them together, and there's your assembly line. It may be a dumb question, but I'm honestly asking.
In a sense you do. Most OO languages like Java are procedural languages as well. But OO offers the "advantages" of bundling everything in a given work-unit together. While something like C may leak state or names all over the place and you end up with similar/same methods being improperly used and that all needs to be tracked or disambiguated somehow.
Lots of people consider namespacing and packaging up your source well as a way to do this. I think that works up to a point, but once you start hitting really big projects, I think the way that Java enforces and cleans up some of this optional stuff and makes these things as part of the language makes it a little more natural. Instead of having to be careful about your work (meaning if you aren't something will go wrong), you simply have to do the best practice to make progress. On smaller projects, where the manager can review every commit, every line of code, every way that work was done, and can enforce a cohesive and singular idea about how it should be done, it can work. But once the scope expands beyond what one management drone can handle it starts to become something that falls into the next layer of Management Science abstraction.
tl;dr Making things that are optional in some languages into requirements (or the code won't work) seems to have been a good optimization.
Because most real applications don't model very well as a dataflow system at all. If you're thinking of linux utilities, I'm sure you see everything "works fine" as a dataflow system.
Now imagine writing a complex application like Excel, or Photoshop procedurally. It's not impossible. During the Windows 3 series that was actually done.
Read through it. Ideally install Borland C++ in a windows 3.1 in Dosbox and make it work. Then you will fully understand why people switched to OO.
But the more general reason is this : procedural programming doesn't allow you to raise the abstraction level of your code more than a bit. OO allows for more "distant" abstractions. Algorithms that are far further removed from the actual datatype being operated on. Since we've seen a regression in program complexity due to web browsers being the main application delivery method, OO is falling out of favor.
On the other hand, maybe mobile development is simply the pendulum already swinging back. Both android and ios apps are OO apps, by necessity. And as everybody (hopefully) agrees, they beat the pants of websites.
Not necessarily. For apps that don't have rich UIs (i.e. apps that could practically be websites), WebViews can reduce cost by allowing you to use the same HTML for both iOS and Android apps. So I think it's really more of a grey area depending on the situation.
But yeah, I wouldn't want to write Excel in procedural C.
Nice response, and I agree with a lot of it. Particularly, I think this is key: "This is why good software developers hate working in these places. It would be like a fine watch craftsman going to work on the Timex digital watch assembly line at Foxconn." For an individual developer, OO can be restrictive and prevent them from writing their best code. This tends to make us argue against OO on various (legitimate) technical bases but for an organization the (perceived) weight of the pros will tend to be for OO and the cons are not seen to make for enough of an actual bottleneck on peoples abilities.
Yes. This would also explain why Ruby became popular in corporate America. It gives the appearance of being an OO language, so it can be sold to management as such, but it really is more of a Lisp in disguise. So in practice it's OO language with a hidden escape hatch. Just if only it wasn't so dang slow...
For learning programming concepts and everything I started out with java (OO language).
(I still love java I just don't feel like OO is the only languages to get things done)
Java(2.5 years experience) is fairly easy and it has great IDE support etc.
And the template thing in OO with a house has a floor and a roof and 4 walls etc. is fine.
But can't you do the same in C (which I have recently started to learn quite intensely)? I know you have to do a little more code but it isn't that much really and C gives you great control over anything really, you can also have it organized into files and such in C just as fine at you would have done in java.
That is correct, in the abstract. There can be programs written in both C and Java that do the same thing. The question is then: if people are writing programs in Java, what is the cause, what is making that happen?
Presumably the cause is that their boss told them to use Java.
Now why did their boss tell them that ... Often these decisions have all sorts of legacy issues involved which don't make the real reasons all that clear cut - and if one were to really dig back the initial answer is likely "because that's what people say we're supposed to use"
I went the opposite path, from C to OO languages, including Java.
Yes, you can do the same in C, in fact a lot of people did it intuitively before OO became mainstream. Many of the techinques that make OO design work so nice (encapsulation, loose coupling, strong cohesion) were called simply "modularization" back then.
The advantage of modern OO languages of today is that the techniques are explicit, clear on the language design, they don't depend only on the programmers discipline. Also, they bring a lot of other features hard to implement in C: garbage collection, reflection that provides sleek frameworks and tools for refactoring, etc.
I think OO is successful because people by our very nature love to name and categorize things. The way most people see OO, it is ALL about naming/categorizing and inheritance. Things belong to other things and are related to other things and so on and so forth.
Academia especially loves naming things and creating structure and hierarchy. OO makes programming sound scientific, like physics or biology or something.
The business world loves the idea that you could have these reusable objects that would let you just fit a program together like legos. Given the huge technology investments, it sounded like a great idea, but it hasn't really worked out that way for the most part.
It sounds silly to think that OO really took off because it feeds on the psychological need to name things, but I think that's a big part of it. Even the Bible says that Adam's first and primary job was to name all the animals of the earth. Even if you aren't a believer, a book written thousands of years ago and handed down from generation to generation where it explains that the first man's job was to name things I think speaks a great deal about how humans are obsessed with names and naming things and have been for a very long time.
In that way, it wouldn't at all be surprising that OO would be successful. If anything, things that take away the ability to name and organize things in a way that people enjoy would be something that fewer people take up unless there is some other psychological benefit that is larger than the benefit of naming and organizing things.
I think the key to the success of Java's flavor of OO is providing an efficient implementation of dynamic function dispatch. This is the core feature, without it, OO would be useless.
The same feature can easily be achieved in functional languages (including javascript), but its performance doesn't scale well at all.
This is the case even in javascript: attaching dynamic functions to object instances performs significantly worse than relying on a prototype chain.
When a function is defined in the prototype chain, it's defined once and shared across all instances.
In Java, when you have a reference to an abstract class, and you call `object.method(args..)`, you don't know which function is being called. It's somewhat like if you have a function pointer/reference and called `method(object, args...)`.
Java lets you do this without losing all the benefits of static type checking.
I have been arguing against OOP with my peers for years. The last resort argument is very similar: "OOP is a form of communication between humans and a mental concept".
I think the answer lies in the late '80s computing zeitgeist.
During the preceding decades, the object-oriented paradigm had been shown to be highly useful in simulation (Simula) and graphical UIs (Smalltalk), but these use cases were still far removed from the majority of real-world apps.
A lot of people looked at OO's phenomenal success in these fields and extrapolated that all software would soon look like that. "GUIs are going to be the future. Also, all of our software works with real-world stuff. Money exists in the real world, right? Therefore it's an object."
Java certainly didn't start the OO hype. By the time Java hit, the hype had already been in full force for at least 5 years... Borland's CEO announced sometime around 1992 that they would defeat Microsoft by adopting a "full OO" development workflow. At the same time, Microsoft was hyping its own OO concepts and frameworks like MFC.
But Java definitely hit the sweet spot of multiple hype cycles at once with its combination of OO everywhere, web-oriented applet deployment and platform-independent VM.
Machine learning is the next OO.
Where you write code that can learn and adapt to changing conditions.
I think code will be more of a poem than a recipe.
I think it has a much simpler reasoning. Most experience programming GUIs were in object oriented languages with the original Macintosh showing the problems of not using one. It fit because it grew up with the concepts. The 1990's was the era of the new UI (e.g. Windows). If Microsoft had said that functional programming was the way to go, then OO would not have taken off. Instead C++ and Java with Sun's amazing marketing won.
Recently I was showing my coworkers how the type class pattern works in Scala, and was arguing that this was very OO, just not OO the way someone from the Java/C++ branch family tree would think of it - but rather more along the lines of what you see in CLOS, Dylan, R's S4, etc. They weren't buying what I was selling, but I'm still selling it.
First, most languages aren't doing OO the way it was described by Alan Kay who coined the term.
What we have are data structures with procedures that invoke other procedures in data structures.
That's a long way from independent units sending messages to each other. REST on the web these days may be closer to that initial intent.
Not that it means anything special, but I've been busy with this "Object" thing since 1990, trying to figure out what it meant exactly.
C++ (Symantec C++, MS Visual C++ with COM/ATL, Delphi, Tcl with Xotcl, Java with the dreaded EJBs shipwreck, Smalltalk, R, C (including Tuxedo services), Assembly, Javascript, and other languages like Clipper/xBase have been used to deliver client solutions.
A couple of the are not OO at all. Still they worked too.
For the record, I've also given OO related trainings to more than 2000 people over the years (language side, analysis side, system design side) and seen people "getting it" or not. I've been involved in UML (and OMT/Booch/... before that).
At this point in time, a lot of that boils down to being able to partition a system properly based on responsibilities and the team that is available to build the system.
Fred Brook was right, there is no silver bullet.
"OO" designs were quite apt to adjust to changes that were quite probable. But some changes just made them break.
For some systems, the OO approach was really good for remembering what was done. I remember being called to fix an issue in a system that had been running in production for, like 13 years (it was C++). It was easy to figure out how things were laid out, as the pieces were still identifiable.
One lesson is that objects shouldn't be too fine grained. Too many objects and you get the "ravioli" effect.
Good architecture and good coverage of key concerns is what matters. Once this is done, technology can be bent to do one's will.
I do have a personal affinity to objects but with functions and closures, one can get other ways of thinking.
But there is something that has been all wrong for years, namely the fact that a lot of OO languages required to have hierarchies for polyphormism to work. And that's just wrong, and that's why I like Smalltalk for example with the messaging at the core. That's what made Tuxedo apps successful for transaction processing. Messaging, async, ability to decouple. That is more key than structures. And that's been lost for a long time.
Javascript gives more in that regard, despite it being quite a kludge of a language. But it is flexible and has closures, more than a lot of "OO" languages.
I don't thing OO is what made Java successful as OO designs in Java are quite poor and over complicated. Spring gave some sanity back but the core thing is that Java has libraries for a lot of things. Not that it is OO.
My take is that OO is going to be less of the dominant way, and we are entering the age of the polyglot programmer.
All the details of OO aside, it for a first gave a way of managing the complexity for large projects. It allowed for large number of people to come together to write one piece of software and a way for putting it all together, testing, debugging.
Managing complexity, large projects, large teams and all that were just fine with C. And neither Java nor OOP were able to improve on that. If anything, they only made it worse. So, I don't think popularity of OOP is a success. Certainly not for software engineering.
To the extent that anything is "wrong" with OOP, it is encapsulated (!) well by the Reactive Manifesto [1].
The global computing paradigm is outgrowing the domains where OOP is useful. And I'm pretty sure that if you look closely enough, there will be OOP under the hood of a great many systems for a long time to come.
Something forgotten: Visual Basic. Plus some smaller but still know players like Visual FoxPro, Delphi.
And the MS evangelism of OO and "flavor of the year arch that also is OO" that was central to their conferences.
So: The most popular language, and the others, and java, all OO.
Outside university, that was the landscape. And inside the university? All tech there give a bad taste, and the impression of be bad, ugly, slow, bad, ugly, slow. Instead, Delphi, Fox, Visual Basic: DELIVER. And them were OO, so OO is the thing.
75 comments
[ 3.4 ms ] story [ 130 ms ] threadThese two sentences jumped out at me. I really like this analysis, because it would explain why object-oriented thinking especially seems to be prevalent in hierarchical organizations. It allows any number of minds to contribute to the design of a system without any knowledge of the technical details of that system.
But OO doesn't work because webbrowsers have detonated a hydrogen bomb of "historic reasons for this API" over the worst UI toolkit ever, and abstractions, whether OO or ..., simply don't work well over this. They make it extremely hard to find where the OO toolkit is incompatible with vendor X's browser version 82.2.1.3.3.883.1.3.4, and harder yet to fix the problem.
It seems like 2014 was the year of having programmers rant against every form of abstraction because they can be misused and because they "hide complexity". Well of course they hide complexity. That's the point. That's what allows us to raise the abstraction level of what we're doing and working on.
A simple shared networked database (also known as CRUD, or to some extent MVP) was a solved problem on NextSTEP before I left kindergarten but in 2014 we all insist on rewriting the whole thing from scratch (can't even use an actual database anymore "it doesn't scale").
When I was a 12 year old discovering dBase writing a networked CRUD application was something you'd do in roughly an hour. Today, a week is not that bad, apparently. When I turned 14, and worked with dBase for windows, putting rich text fields (with working copy-paste from office documents) was less work and finished faster, by a factor of 100. First I wrote them in things like dBase, then Delphi. Then I started writing them in PHP + SQL. This was tedious, but at least it was vaguely manageable. Today, I write them in Bash (for deployment) + Go + SQL + Python + Javascript + JSON, not counting the various configuration languages I need to know. They don't work nearly as well as the things I made in dBase for windows, without a doubt they are less functional than the tools I wrote in Delphi, and they can do vastly less on computers thousands times faster (my first Delphi was installed with 66mhz, 16M RAM and 500M drive) without weeks of work they don't look nearly as good, and they are utterly and completely incompatible with everything else on the planet.
This is why we had OO (the very first book I had on the subject started with how to make OO work for an extensive text editor). That's what's good about it, and why we're not doing it anymore ... I don't really know.
Today we are locked into the web. Any end user has no control whatsoever over their files, over what programs his computer runs (my "standard" text editor is in javascript and gets it's code downloaded from an internet provider that could change it at any time. I, of course, cannot change it), over who can read their files/mail, governments, MPAA, RIAA, and so on get people's mail clients blocked and their mail made inaccessible on a regular basis, ...
http://en.wikipedia.org/wiki/Worse_is_better
Just wondering, but why Go? I ask because Go doesn't have objects, so why not use a regular OO language like C#?
http://golang.org/ref/spec#Struct_types
("AnonymousField" is the name they give to it. But it's inheritance. Badly executed and doesn't fit well in the type system, but that's par for the course for Go)
I don't get where these statements keep coming from. Well, I do, to an extent : the Go authors keep claiming these sorts of things, but I don't understand why. They're not true. There is no complex language feature that Go does not have. Go has inheritance, Go has generics (simply inaccessible for everyone except the language authors, like in modula-2), Go has polymorphism (simply inaccessible for "mere" users). Go has return-value polymorphism. Go has type parameters, both in types and functions (again, inaccessible for users of the language, but it's there).
Everything is simply built as custom compiler code that's inconsistent and riddled with unexpected edge cases, none of it worked into the type system itself. This is the real reason for resistance against these language features : working them into the type system would be a necessity, and isn't possible without breakage because they're not consistent.
OO principles are for the limitations of people, not computers.
people.find('thirsty').drink('water')
Not about plain language reading, but instead writing code the way people think about actions and things.
Procedural is just as valid, but you use the right tool for the right job.
OO is all about encapsulation. We tend to decompose a program into chunks for different teams and individuals to work on. Software development is a distributed task. Encapsulation means when you code against components written by other people, you only have to understand the public API that they provided. You are supposed to be guaranteed that that API will continue to work even as the code behind it is updated. As component users we can focus on our own task and not worry so much about the details of the component. As the author of a component, we can hide state from the users. That can't be done with structs. we can make updates and switch out implementations without (as much) fear of breaking the code that depends on it.
It's really all about being able to modify code more safely on bigger teams.
In my mind the issues that OO introduces are: * Encapsulation results in more verbosity for the same functionality. * Inheritance takes more thought. * OO as a whole is more complicated and has a bigger learning curve. * OO used incorrectly will magnify the first two points greatly. Given the learning curve I imagine a lot of people don't use it fully correctly.
Or `steve' is given to you from a 3rd-party library, and you want to imbue him with the ability also to eat. Well, you can't define `steve.eat(salad)', unless you subclass his class and make a proxy of the object from the library.
To properly solve either of these, you are forced to resort to the second-class citizen of a static class, which is exactly just functions in a namespace.
The one actual "benefit" OO gives you is run-time dispatch; the ability for the program to defer until run-time the decision which implementation of `steve' actually handles `.drink()'. Outside of OO's poster child of GUIs, I have rarely seen a need for this capability in 20+ years of programming. (Mere compile-time dispatch, as captured precisely by OCaml's module functors, is much more common.) Centering a paradigm around this rarity is quite bizarre.
Ooooh... that's a Point object - no way the AddAccount function does anything relevant with it! In OO you don't even actually need to think that since Point has a limited set of methods.
The latter shouldn't typically access internal state of the Point object.
This separation can help immensely while analyzing a code base.
In Haskell, I can literally ask the editor to list me all functions that operate on type X. Even in C written with a modicum of coding discipline, 90% of the functions relevant to type X will be defined in X.h, wherein 100% of the functions in X.h are relevant to type X. (And the 10% of functions relevant to type X that aren't in X.h? Well, in Java, they also wouldn't be part of class X anyway.)
I can't agree with this opinion. I often find it an annoying restriction that I must put all my functions in a class. Let's look at a trivial example of multiplying a matrix by a vector. You can write
It is possible to multiply from the left or from the right (as long as the matrix and vector dimensions match). This makes it even more annoying. What I'd really like to do is: Perhaps it's the kind of problems I work with (and the non-OO languages I am used to), but I am regularly faced with this problem if I have to use a language like Java where you have to put all your functions inside classes.To further elaborate why I don't really like OOP (except in a minority of cases where inheritance, etc makes intuitive sense), I think the biggest issue is that classes/objects are the method to do almost everything.
Namespaces, visibility, inheritance, dynamic dispatch, etc are all somewhat orthogonal features. Having a "class" to be the unit that uses all of these features is, in my opinion, a restriction.
Lists (or arrays), tuples (or structs) and Maps (or dicts) are what I want 99% of the time. When programming with Java or similar languages, I feel like the primary means of abstraction and composition in the language is catering to a 1% problem.
I learned programming in the late 90s, early 2000s, during the height of the craziest OOP craze (when "object oriented" was synonymous with "good"), so it took me a while to un-learn all of the OOP methods but I feel like I did turn into a better programmer when I stopped thinking in terms of objects.
OOP is a neat paradigm for some cases, but I find those cases very rare.
"The stove heats the water." An object performing an action on another object (a direct object, in parts of speech), changing the state of the direct object.
So when we code this, it makes sense naturally to write something that is readable in human terms:
This makes code easier to reason about and easier to go back to later. Hopefully, our code reads like the computer- and human-readable literature it is.While I'm no fan of OO as a dogmatic solution to every problem, the differences between it and any other reasonable approach are small for most problems, compared to the complexity of solving the problem itself.
Hackers hate this, because small segments of code that look near-identical can do vastly different or complex things and lots can go wrong in there. Also, the higher you go in abstraction, the more subtle the code becomes, the more important differences in meaning originate from very small differences in source code. Take a haskell monad chain and try to explain the sequence of 2 statements ... it takes 2 minutes of thought to figure it out. But of course those 2 statements do much more than 100 lines of C can do.
And of course bad programmers hate this, because you have to learn abstractions.
It depends on what you're doing. If you're writing a big application, something to be supported over the long term that isn't trivial, then OO is most definitely the way to go. If you're hacking something together that won't last the week, raising abstraction level will only stand in your way. If you're planning to rewrite the core of the application on a monthly basis, OO, and any other kind of abstraction, will make life very hard on you.
This organization of language in this fashion is English-specific though. I wonder what feels intuitive to non-English (or non-Romantic) speakers - is it OO as well, or something else?
"The table is red."
and
"Red is the color of the table."
Edit: https://en.wikipedia.org/wiki/Verb%E2%80%93subject%E2%80%93o... Cool.
heatingStrategy.heat(water, stove);
One of the things that's very hard to understand is how much large efforts rely on our ability and understanding to manage and coordinate the effort of all these people providing work input -- yet management science is still remarkably poorly understood.
OO is nice because objects define work-units which are easy to measure and track through a management structure and the development of which kind of map to a work breakdown structure in much the same way assemblies and sub-assemblies go into a bridge or a car in traditional engineering:
Phase 1:
Part A: develop all the classes and methods on each class.
Part B: test and certify components.
Phase 2:
Part A: integrate 1A components.
Part B: test and certify integration.
Phase 3: repeat phases 1 and 2 until you have finished software
"oh team X is working on component (class) A2? when does A2 move to testing? okay, I'll schedule that. You know component B6? Yeah, it failed testing and needs to be reworked, but it shouldn't hold up phase 2: integration."
Lots of people give Java and Java shops lots of flak because the work is unglamorous, but they've semi-succeeded in mapping software engineering to the management science practices that were formulated during the Industrial Revolution...meaning they've turned software development into assembly line work.
This is why good software developers hate working in these places. It would be like a fine watch craftsman going to work on the Timex digital watch assembly line at Foxconn.
The Management Practices that informed OO and drive it are the dominant way to "make stuff on schedule" that humans have managed to come up with. Like it or not, it's why cars get made, t-shirts end up in stores for $10, and your state DMV has an on-line renewal site.
It's interesting to study large software projects that failed as well. SAIC has a couple of well known ones: Virtual Case File [1] and CityTime [2], Healthcare.gov [3] was another good example. It's even more enlightening to compare these failures to big traditional engineering failures: Seattle Tunnel [4], Space Shuttle failures, etc.
One thing to keep in mind. Large software projects are often more complex on raw unit count than even the most complex engineering efforts in history. For example, the Space Shuttle is considered one of the most complex pieces of engineering ever, and it only had 2.5 million parts. [5] OS X 10.4 by comparison has almost 100 million lines of code. [6] It's not a perfect comparison of course, but it does help cement in the magnitude of modern software efforts.
If OO has a failing it's that humans haven't managed to come up with a better way to break complex work down or to define software methodologies that map well to how we know how to manage and coordinate complex tasks. OO works very well when considered in this context, it does more or less what it's supposed to. It's not intended to provide a methodology for elegant or creative software crafted by a single person or small team of experts.
We've learned a lot in the decades since OO has become the dominant force in software organization. And Management Science has improved a couple tick marks as well. The next paradigm shift is likely close. But make no mistake it'll probably be a streamlined OO-like system of trackable, schedulable work components. But it won't happen quickly, literally trillions of dollars in work effort have been put into OO from the s...
Lots of people consider namespacing and packaging up your source well as a way to do this. I think that works up to a point, but once you start hitting really big projects, I think the way that Java enforces and cleans up some of this optional stuff and makes these things as part of the language makes it a little more natural. Instead of having to be careful about your work (meaning if you aren't something will go wrong), you simply have to do the best practice to make progress. On smaller projects, where the manager can review every commit, every line of code, every way that work was done, and can enforce a cohesive and singular idea about how it should be done, it can work. But once the scope expands beyond what one management drone can handle it starts to become something that falls into the next layer of Management Science abstraction.
tl;dr Making things that are optional in some languages into requirements (or the code won't work) seems to have been a good optimization.
Now imagine writing a complex application like Excel, or Photoshop procedurally. It's not impossible. During the Windows 3 series that was actually done.
Here's how it looks :
http://www.transmissionzero.co.uk/computing/win16-apps-in-c/
Read through it. Ideally install Borland C++ in a windows 3.1 in Dosbox and make it work. Then you will fully understand why people switched to OO.
But the more general reason is this : procedural programming doesn't allow you to raise the abstraction level of your code more than a bit. OO allows for more "distant" abstractions. Algorithms that are far further removed from the actual datatype being operated on. Since we've seen a regression in program complexity due to web browsers being the main application delivery method, OO is falling out of favor.
On the other hand, maybe mobile development is simply the pendulum already swinging back. Both android and ios apps are OO apps, by necessity. And as everybody (hopefully) agrees, they beat the pants of websites.
But yeah, I wouldn't want to write Excel in procedural C.
(I still love java I just don't feel like OO is the only languages to get things done)
Java(2.5 years experience) is fairly easy and it has great IDE support etc. And the template thing in OO with a house has a floor and a roof and 4 walls etc. is fine.
But can't you do the same in C (which I have recently started to learn quite intensely)? I know you have to do a little more code but it isn't that much really and C gives you great control over anything really, you can also have it organized into files and such in C just as fine at you would have done in java.
- If I'm complete off please tell me
Now why did their boss tell them that ... Often these decisions have all sorts of legacy issues involved which don't make the real reasons all that clear cut - and if one were to really dig back the initial answer is likely "because that's what people say we're supposed to use"
Yes, you can do the same in C, in fact a lot of people did it intuitively before OO became mainstream. Many of the techinques that make OO design work so nice (encapsulation, loose coupling, strong cohesion) were called simply "modularization" back then.
The advantage of modern OO languages of today is that the techniques are explicit, clear on the language design, they don't depend only on the programmers discipline. Also, they bring a lot of other features hard to implement in C: garbage collection, reflection that provides sleek frameworks and tools for refactoring, etc.
Academia especially loves naming things and creating structure and hierarchy. OO makes programming sound scientific, like physics or biology or something.
The business world loves the idea that you could have these reusable objects that would let you just fit a program together like legos. Given the huge technology investments, it sounded like a great idea, but it hasn't really worked out that way for the most part.
It sounds silly to think that OO really took off because it feeds on the psychological need to name things, but I think that's a big part of it. Even the Bible says that Adam's first and primary job was to name all the animals of the earth. Even if you aren't a believer, a book written thousands of years ago and handed down from generation to generation where it explains that the first man's job was to name things I think speaks a great deal about how humans are obsessed with names and naming things and have been for a very long time.
In that way, it wouldn't at all be surprising that OO would be successful. If anything, things that take away the ability to name and organize things in a way that people enjoy would be something that fewer people take up unless there is some other psychological benefit that is larger than the benefit of naming and organizing things.
And inheritance is problematic.
[ADT is Abstract Data Type; i.e. values that support operations, and are not tied to a specific concrete implementation]
The same feature can easily be achieved in functional languages (including javascript), but its performance doesn't scale well at all.
This is the case even in javascript: attaching dynamic functions to object instances performs significantly worse than relying on a prototype chain.
When a function is defined in the prototype chain, it's defined once and shared across all instances.
In Java, when you have a reference to an abstract class, and you call `object.method(args..)`, you don't know which function is being called. It's somewhat like if you have a function pointer/reference and called `method(object, args...)`.
Java lets you do this without losing all the benefits of static type checking.
Maybe we should delete OOP and just talk UML?
During the preceding decades, the object-oriented paradigm had been shown to be highly useful in simulation (Simula) and graphical UIs (Smalltalk), but these use cases were still far removed from the majority of real-world apps.
A lot of people looked at OO's phenomenal success in these fields and extrapolated that all software would soon look like that. "GUIs are going to be the future. Also, all of our software works with real-world stuff. Money exists in the real world, right? Therefore it's an object."
Java certainly didn't start the OO hype. By the time Java hit, the hype had already been in full force for at least 5 years... Borland's CEO announced sometime around 1992 that they would defeat Microsoft by adopting a "full OO" development workflow. At the same time, Microsoft was hyping its own OO concepts and frameworks like MFC.
But Java definitely hit the sweet spot of multiple hype cycles at once with its combination of OO everywhere, web-oriented applet deployment and platform-independent VM.
Obligatory ref: http://www.paulgraham.com/reesoo.html
Recently I was showing my coworkers how the type class pattern works in Scala, and was arguing that this was very OO, just not OO the way someone from the Java/C++ branch family tree would think of it - but rather more along the lines of what you see in CLOS, Dylan, R's S4, etc. They weren't buying what I was selling, but I'm still selling it.
First, most languages aren't doing OO the way it was described by Alan Kay who coined the term.
What we have are data structures with procedures that invoke other procedures in data structures.
That's a long way from independent units sending messages to each other. REST on the web these days may be closer to that initial intent.
Not that it means anything special, but I've been busy with this "Object" thing since 1990, trying to figure out what it meant exactly.
C++ (Symantec C++, MS Visual C++ with COM/ATL, Delphi, Tcl with Xotcl, Java with the dreaded EJBs shipwreck, Smalltalk, R, C (including Tuxedo services), Assembly, Javascript, and other languages like Clipper/xBase have been used to deliver client solutions.
A couple of the are not OO at all. Still they worked too.
For the record, I've also given OO related trainings to more than 2000 people over the years (language side, analysis side, system design side) and seen people "getting it" or not. I've been involved in UML (and OMT/Booch/... before that).
At this point in time, a lot of that boils down to being able to partition a system properly based on responsibilities and the team that is available to build the system.
Fred Brook was right, there is no silver bullet.
"OO" designs were quite apt to adjust to changes that were quite probable. But some changes just made them break.
For some systems, the OO approach was really good for remembering what was done. I remember being called to fix an issue in a system that had been running in production for, like 13 years (it was C++). It was easy to figure out how things were laid out, as the pieces were still identifiable.
One lesson is that objects shouldn't be too fine grained. Too many objects and you get the "ravioli" effect.
Good architecture and good coverage of key concerns is what matters. Once this is done, technology can be bent to do one's will.
I do have a personal affinity to objects but with functions and closures, one can get other ways of thinking.
But there is something that has been all wrong for years, namely the fact that a lot of OO languages required to have hierarchies for polyphormism to work. And that's just wrong, and that's why I like Smalltalk for example with the messaging at the core. That's what made Tuxedo apps successful for transaction processing. Messaging, async, ability to decouple. That is more key than structures. And that's been lost for a long time.
Javascript gives more in that regard, despite it being quite a kludge of a language. But it is flexible and has closures, more than a lot of "OO" languages.
I don't thing OO is what made Java successful as OO designs in Java are quite poor and over complicated. Spring gave some sanity back but the core thing is that Java has libraries for a lot of things. Not that it is OO.
My take is that OO is going to be less of the dominant way, and we are entering the age of the polyglot programmer.
The global computing paradigm is outgrowing the domains where OOP is useful. And I'm pretty sure that if you look closely enough, there will be OOP under the hood of a great many systems for a long time to come.
[1] http://www.reactivemanifesto.org/
And the MS evangelism of OO and "flavor of the year arch that also is OO" that was central to their conferences.
So: The most popular language, and the others, and java, all OO.
Outside university, that was the landscape. And inside the university? All tech there give a bad taste, and the impression of be bad, ugly, slow, bad, ugly, slow. Instead, Delphi, Fox, Visual Basic: DELIVER. And them were OO, so OO is the thing.