7 ms·
No, that's not why OO sucks
- sodelate 14y agoOO,really matters
- pfraze 14y agoNot sure where I sit on the issue, but I wanted to add this: By putting the functions in the class definition, they become locked into that class. Other data structures could potentially make use of the function, but now they don't own it. I would say the alternative is a namespace, which you don't instantiate. Armstrong's grief is the idea that the functionality for classes can then only come from direct lineage. As I understand it, though, the OO-heavy languages (Java, C#, probably others) lean much more heavily on interfaces now to mix in behavior, which gets away from that specific problem. [EDIT] I forgot that interfaces don't give implementation, so the mixing is pretty limited. Not sure what I think of the state issue, though. Too green on the functional stuff to say how else it should work. I would point out, though, that programs hide state from each other; couldn't objects just be the same thing on a smaller scale? (That is, an opaque interface with a few access points.) It really comes down to how well it's made in both cases.
- anonymoushn 14y agoJava doesn't have multiple inheritance, so if you want to avoid writing the same behavior twice you instead get to write several interfaces describing the ability to do the behaviors and write several functions in each class that implements such an interface (but does not contain the implementation) calling the functions defined in the interface on its pet InterfaceImpl. This is probably a worthwhile tradeoff, but checking in hundreds of lines of code that do literally nothing is still a bad place to be.
- pfraze 14y agoAh, that's right-- interfaces don't give implementation. So yeah, Armstrong's criticism stands.
- UnFleshedOne 14y agoIn C++ they do. In C++ anything goes. <insane laughter>
- dclowd9901 14y agoThis was running through my head as well, and means that your software design is bad. If you have such a useful function that you can translate it among classes, it should sit in some sort of static Util class. Think of it as the Swiss Army Knife you carry in your regular toolbox, a go-to tool, when you know you don't need anything specialized.
- weavejester 14y agoYou can, but the better your standard library, the less you need specialized functions. For instance, instead of something like: response.setHeader("X-Foo", "Bar"); In a functional language we'd change the data structure directly: (assoc-in response [:headers "X-Foo"] "Bar") If, for instance, 90% of your application can be factored out into static methods, OOP starts to look like the wrong paradigm.
- wonderzombie 14y agoA lot of static methods on a Util object strikes me as a smell in the context of this discussion. In OO-land it's not a smell per se because often you have no alternative. But functionally your class is a glorified namespace.
- weavejester 14y agoWhat do you mean? I don't believe anyone is suggesting that if you have many static methods or functions, they should all be put in one namespace.
- Ralith 14y agoI think that's exactly what dclowd9901 was suggesting, though he may not have fully considered it.
- dclowd9901 14y agoNot necessarily. Of course defining classes is tricky, and there's no such thing as a rule of thumb, and that's more what I was trying to relay with my comment. And I agree with others who are saying that a piece of software where objects are crammed with tons of static classes is bad OOP.
- shimsham 14y agoWhich is what makes PHP so good, as you're not forced to use any particular style of programming. Or C.
- conradfr 14y agoAnd if you need a function in several objects, there is now Traits.
- flyinRyan 14y agoAnd, dutifully, most PHP programmers don't bother using any particular style of recognizable programming. When in Rome...
- tikhonj 14y agoNeither C nor PHP support functional programming well. They don't even acknowledge logic programming. But hey, you can use any style you want. As long as it's imperative. I think the most multi-paradigm languages are certain lisps. As long as you only care about different declarative styles (basically the opposite of C), Haskell is surprisingly good: point-free programming is like stack-based programming and you can easily embed non-deterministic code as well. And you can write imperative code about as easily as writing functional code in PHP or C.
- blahbap 14y agoThe title suggests that the aurhor will provide reasons for why OO actually is bad, but he doesn't. Why is it so fashionable to bash OO anyway? It's just a tool, it can be used wisely, but often it is not, which gives no reason to blame OO.
- aero142 14y agoOO is not "just a tool", because it's often coupled with a language. A wrench is "just a tool" because I can always reach over for my socket set if that seems to fit better. Once I'm in Java, I am locked into a whole ecosystem and Java work hard to make sure you write OO code. I can't just reach for a lisp halfway through if I think that tool would work better.
- fauldsh 14y agoAre you saying no project can consist of multiple languages working together?
- aero142 14y agoNo, but I am saying that switching between them is not as easy as grabbing a different tool. The easiest place to switch languages is between abstraction layers or between functional components/processes. These language separations do not often coincide with the types of code that benefit from either OO style structure vs functional data processing.
- Ralith 14y agoI think he's recognizing that doing so is not usually practical.
- readymade 14y agoIMHO, The biggest problem with the oft-repeated meme "just a tool" is the word "just". It dismisses out of hand the powerful ways in which tools (e.g. media) nudge us in certain directions and shape the way we work. Any time you hear someone say "just a tool", you are talking to someone who considers themselves cognitively separate from the tools they use, whereas in reality there is something much more fluid happening. Let us not forget that tools themselves are designed, and some designs can be downright pathological. A kettle is a tool for making tea, but (in deference to Donald Norman) there is a reason we don't make kettles with the spout on the same side as the handle. Just because someone designed a tool to solve a particular problem does not mean that it's the best way to solve that problem. We can and should be critical of our tools without emotional attachment to them.
- fusiongyro 14y agoAs time goes on, my bafflement at our collective need to swear allegiance to our tools is turning into bewilderment. Our tools have objective, technical merits and flaws, but our love and hate for them is subjective and mostly useless. Cargo cult behavior is the real problem, and the endless bickering and correcting that articles like Joe's and this one contain only serve to perpetuate it.
- cdmckay 14y agoI don't think the author was loving or hating OO, he was just pointing out the Joe Armstrong's points weren't very well argued. It's not bickering, it's discussion, and it helps people to understand the paradigms better.
- pfraze 14y agoThis isn't pointless. If you have good points, I want to hear them, at least so I know the reasons to look at other approaches.
- zzzeek 14y agoif you've ever had a job where your manager insisted that you must use technology XYZ, or that you were not allowed to use technology QPR, that's why people defend/attack approaches. nobody wants the industry to shift to a technology they find personally distasteful, lest you now have to base your career around it.
- rsaarelm 14y ago
- greghinch 14y agoI've noticed a pattern with people who rally against OO, that when you get down to the core of their argument and what irks them, they really just don't like Java, with all its superfluous-feeling ceremony code. Maybe try a lighter OO implementation first before you decry an entire methodology.
- MichaelGG 14y agoCertainly that clouds it. I feel Java and the like also cloud people's judgement of static typing as well. Who wouldn't hate static typing when you have to write out these massive types all. over. the. place.
- wonderzombie 14y agoI'm sympathetic to this line of reasoning, for sure. I also see value in critiquing a methodology as it is expressed in practice. Java is one of the most popular languages. I mean, you could critique C++, but at this point that seems kind of cruel. :)
- ww520 14y agoWhy do Java invoke such a strong negative emotion from people? It is not like a gun put on the head to make them use it.
- jmduke 14y ago" It is not like a gun put on the head to make them use it." From what I understand, a lot of universities do force students to use Java for many introductory courses, mine included (though we're migrating to Python.)
- ww520 14y agoUniversity's job is to expose students to variety of subjects even if they don't like it. It's part of the education.
- 14y ago
- aidenn0 14y agoA better "functions should be separate from objects" is for the fairly common case where there is a function that takes arguments of two (or more) different classes as arguments; which class should that belong to? It gets even worse when the function is commutative.
- MichaelSalib 14y agoIsn't that what multimethods are for? Multimethod systems (like CLOS in Common Lisp) allow you to specialize methods based on the types of more than the first argument.
- aidenn0 14y agoYep, but in CLOS, methods don't belong to a class, which is different from what most people mean when they say object oriented.
- MichaelSalib 14y agoOnce you have multimethods, you don't need to couple the method definitions to the class body. But you're still doing object oriented programming; CLOS is an object system. The fact that people assume that OOP==Java is unfortunate, but doesn't change the fact that CLOS is also OOP. Beyond that, I think you're conflating how method bodies are placed in a file with "belonging to a class". I can define C++ methods outside of the class definition, but surely no one would say that such methods don't belong to a class.
- aidenn0 14y agoWell if 95% of the population use a term to mean one thing, then arguing that no it really means something else doesn't get you anywhere. And no, I'm not conflating those. In C++ and Java, classes are, among other things, namespaces. When you declare a method in a class, it ends up in that namespace. Where it is defined is unimportant.
- glassx 14y agoI really don't know why people seem to think that post is the final position of Joe Armstrong about OOP. It's a very old post, without any context, and since then he has gone on record praising Smalltalk and Alan Kay's take on objects many times: http://infoq.com/interviews/johnson-armstrong-oop/ http://infoq.com/interviews/johnson-armstrong-oop/ http://erlang.org/pipermail/erlang-questions/2010-August/052836.html http://erlang.org/pipermail/erlang-questions/2010-August/052...
- shin_lao 14y agoObjection 1: The OP should take a look at the STL. Coupling N algorithms and M structures may lead to M * N implementations where you really want only N + M implementations. Additionally, decoupling algorithms and structures will probably make you write better interfaces for your structures.
- Fargren 14y agoBut that's just because of bad programming, not because of OOP, I think. I mean, of course you can use OOP to make really crappy designs, but polymorphism should make you able to have N+M implementations and not M*N.
- evincarofautumn 14y ago(Static) polymorphism is the very thing behind the STL. In order to decouple algorithms from data structures, you need a standard interface between them. In the case of the STL, that interface is iterators; other interfaces (such as stacks or ranges) are also possible, and in my experience much nicer to work with. But none of it requires OOP.
- Fargren 14y agoWell, of course OOP isn't required for a good design. What I'm saying is that, as far as not redefining functionality for different types, it doesn't work against it. At least not if we allow for static polymorphism, and I'm pretty sure that's considered an integral part of object orientation; at least I remember Kay talking about it.
- evincarofautumn 14y agoStatic polymorphism wasn’t part of OO originally; in Smalltalk, everything was late-bound. And you can of course write things generically even in the “classes and methods” kind of OO, but I think the culture around that paradigm encourages coding non-generically. You might say OO itself works toward genericity, but some OO-branded languages work against it.
- joelthelion 14y agoOO doesn't suck, it's just a tool among others in the toolbox. What sucks is making a religion of it.
- MichaelGG 14y agoThis is a rather lazy argument I often see levied. It provides no real insight, and defends against everything equally. "Gotos are just a tool; On Error Resume Next is just a tool; null pointers are just a tool; etc." That said, I think Joe's original article against OO was ill-informed (which is surprising, given his status), and this article rightly points out that Joe's arguments are bogus. I don't think anyone disagrees that religious battles are stupid. But to sweep all discussion about tools under the "hey man, different tools for different jobs" just avoids critical thinking. If you don't want to participate in these discussions, don't. It's like a discussion on Windows Phone 7 UI, and someone comes along and says "lol, doesn't matter, Windows Phone 7 will never take off".
- tikhonj 14y agoJust because it's one tool of many does not mean it's good. The whole tool thing is a bit of a non sequitur. After all Basic and Intercal are also just "a tool among others in the toolbox". This doesn't mean they are good tools! I really do not understand why this tool argument comes up. Do you never evaluate the quality of your tools? I was planning to come up with a good analogy to some carpenter's tool that is objectively bad and not used any more, but then it turns out I know effectively nothing about carpentry.
- malero 14y agoOOP is just another tool in my toolbox. It makes a lot of sense for some problems, and none at all for all of the rest.
- sbmassey 14y agoOO is a good fit for programming a lot of important types of software, such as GUI's or 3D graphics, where it is convenient to model the program data as consisting of widely different types of data structure, having a common interface, and which are easy to add new types to without having to change existing code. Other than that, most use of OO is really just applying the language's OO structures to software idioms that exist outside OO, such as modules, or data hiding, or closures, and so forth. The only times OO actively sucks is when you're trying to do non-OO stuff in a highly-OO language, such as trying to do algorithmic code in Java.
- pjmlp 14y agoI think that most people that bash OO fail to understand how to use it properly. From my experience many are also pretty bad at doing ADTs in module based languages. OO has quite a few powerful concepts, and not all languages that are OO based explore the same set of concepts. This is why the best languages to work with, are the ones which offer multi-paradigms, allowing the developers to pick the best abstractions for each scenario.
- Ralith 14y agoWhat is a "module based" language?
- pjmlp 14y agoAny language that offers modules/packages as a way to organize code, regardless of which paradigms it supports. This is why Modula-2 was named like that. The original idea of ADT (Abstract Data Types) with modules, is that the module exports the public operations of your type along with its visible definition. Then all operations on the ADT are done via the public operations. This was the way of modular programming before OO became mainstream.
- it 14y agoI bash it not because I don't know how to use it but because I see if being used so often for jobs that would be better done using other techniques.
- pjmlp 14y agoWhy blame the technology, when the real problem was the person that made the decision to use it?
- guelo 14y agoI think in practice most OO programs end up with two general kinds of classes. Some are more for data structures, e.g. User or Address classes, and others are more for functions like IOWriter or DAOs. But there aren't strict dividing lines between these two types, you end up mixing and matching functions and data as you see fit to help organize things. So you might put state into your function classes, such as the DB connection in a DAO: db = DBGetter.get("serverAddress;dbName;username;password;") userDao = new UserDao(db) User user = userDao.getUserById(123) You might also end up putting functions in your data classes, but you might not. As an example, to calculate the distance between two addresses you could put the function in the Address class: float miles = address1.distanceTo(address2) Or you could create a DistanceCalculator class that mostly just holds functions: float miles = distanceCalculator.distanceBetween(address1, address2) There are pros and cons to either design, personally I would go with the second one, but the point is that you have a choice. OO provides a flexible framework and there are many ways to design your classes. That's why there are a bunch of books on OO patterns and best practices, to help design the structure of classes. You can even work in a very functional/stateless style if you want to. What OO gives you are tools for organizing your code but you can organize in many ways, some ways that help and some that hinder. As others have said, it's just a tool.
- klawed 14y agoThe use of ORMs should/does eliminate the need to write any of the data structure classes. They still exist but they're automatically generated and updated. And the use of your second implementation allows you to separate your state from your business logic.
- MatthewPhillips 14y ago> The basic idea of OO is that data and functions are bundled together, which is an idea that Armstrong seems to hold a grudge against (objection 1). But he gives no arguments as to why this is a bad idea. Code reuse. Functions that are tied to a data type are less likely to be reused, and if you find that you want to reuse one it will, a lot of the time, require major refactoring (perhaps you have to move the function to a parent class, or create an entirely new class that represents the thing that is common between this data type's use and other data types' use of the function). Whereas if your data and function are never coupled you actually wind up writing more generic functions that don't care about the type they are operating on.
- ww520 14y agoOO doesn't prevent the use of pure function class. You can group all your common util functions together into the util classes. OO really isn't dogmatic in forcing one style or the other.
- MatthewPhillips 14y agoUtility classes are code smell (paradigm smell, even). They exist where the OO model breaks down and you want to get-shit-done rather than spend an hour thinking about where you can stick function X so that it's useable by class Y and Z. Same goes for verb classes; you know, those does-the-thing classes that you create which are just objects wrapped around a single function called execute(), run(), create(), etc. etc.
- ww520 14y agoUtility classes serve merely as organization purpose. It has nothing to do with OO. It's like putting related files in a directory, or putting related Python functions in a module. I don't get how "stick function X so that it's useable by class Y and Z" is relevant for consideration. As the name suggested, utility classes are function libraries that can be used by all.
- 14y ago
- AndrewO 14y agoI think the author and Armstrong have significantly different ideas of what a "type" is. That's not a huge surprise—depending on background, you'll often get several definitions from different people. One way to see types are things with fundamentally different access pattern: individual entities, sequentially retrieved ones (e.g. lists), fixed-length ordered lists whose elements are accessed positionally (e.g. tuples/vectors, fixed-length maps whose keys are known at compile-time/records/objects can also be viewed this way), unordered collections of distinct entities (sets), etc. I'd argue Armstrong's view is similar to this based on what he put in Erlang. I can't tell what the author's view is, aside from "a class is a data type". This suggests that he equates a type with the set of functions that can be called on something and not have the compiler or runtime blow up (or perhaps, the set of functions that the programmer, by putting them in the same file, has explicitly said won't blow-up, whether or not that set is correct or complete). This throws fundamentally different things like lists, tuples, sets onto the same level as Person, Account, and PayrollRecord—which are often just short-hand names for tuples with different arities or names for their elements' positions. If one has the later view, confusion over the point 3 is understandable: creating a new type for time is easy, just do class Time and define a bunch of properties and methods. In Armstrong's example, time is just a 6-tuple (or 3-tuple if all you want is hms). If you wanted to store it or send it over the wire, anything that could handle a tuple of integers would already know how to use it. If one function calls the last member "sec" and another "second", they're local names, so it doesn't matter as long as they're both accessing the same member. One can object that it's easy to write serializers or that a compiler or library could figure it out, or that having different names for the same data elements indicates inconsistency in code that should be caught earlier. De gustibus non est disputandum. But, don't throw up your hands and say "this makes no sense!" without considering another perspective first.
- artsrc 14y agoI propose that making the position of hour, minute and seconds the canonical definition is worse than using their names. So this: { type: "hms", hour : 10, minute : 45, second : 16 } is better than this: ["hms", 10, 25, 16 ] Either go across the wire fine. The names are not just local names, they describe the meaning of the data. In the JavaScript world we would call the map an object.
- halayli 14y agoI find it funny that programmers are debating why we should hate OO. It's like we know we should hate it but we are still in progress of figuring out why.
- zwieback 14y agoAnyone participating in these types of discussions should start with a disclaimer whether they are talking about static typing, where types are largely equated with classes (aka "class-based" programming), or message passing, where types are largely orthogonal to classes. The latter concept is what Alan Kay had in mind when he "invented" OO although arguably C++ and Java have really popularized OO as class-based programming.
- Ralith 14y agoStatic typing is orthogonal to, although not generally paird with, message passing. You can have dynamically typed Java-style OO easily.
- ww520 14y agoI don't get how state being evil. Pure functional program also has state. Its state are the arguments passed around between functions. What people talk about the evilness of state really is the scope of the state. In a typical program, there could be global state in global variable, local state in function local variable, and the state passed around in function parameter. OO adds the instance level scope state for instance variables. All these different levels of scoping are tools for programmers to manage the complexity in a program. If you don't like global scope, don't use it. If you don't like instance level scope, don't use it. Pure functional code are NOT appropriate 100% of the time. A global variable can be simpler and cleaner to get the job done. There are times for different tricks in a toolset. Use the right tool for the right problem. edit: added the NOT. Bad omission completely changed the meaning.
- rbanffy 14y agoI like to joke that, if your program executes without any side effects, how can you prove it did? ;-)
- sbmassey 14y agoYou can look at it's return code.
- wonderzombie 14y agoState isn't so much evil as it introduces complexity. I think we can agree that complexity, or at least unnecessary complexity, is evil. :) The goal isn't so much to make people stop using state, but to make people think about it and question whether the complexity of state is, in fact, necessary. Maybe the answer is yes! But you should think about it, at least. To expand on that wrt OO: OO tells you to encapsulate state in objects, generally, and then ignore it b/c abstraction, implementation detail, etc. But state makes it harder to reason about your program because now (ostensibly) the same function gives different answers depending on when you call it, not just how you call it. It couples your program that much more tightly to the order of operations. It introduces a bunch of assumptions dispersed implicitly throughout your code, as everything else now has to ensure that it does the right thing when the order of operations and/or input is correct vs not. That leads to bugs. The counter-narrative is along the lines of what you suggest, which is to reduce state to a very small and limited scope, and put up a bunch of red flags around it. You say "these answers can change and this is the place to handle all the possibilities." You handle it in as few places as possible, and not laterally, everywhere else a method call chain or where there is state which depends on other state. Haskell is an example of this idea taken to the Nth degree. But "the right tool for the right problem" isn't that helpful, although I think it's a worthwhile sentiment. The goal is to get people to think about the complexity they add to their programs, not to lambaste them for their choices or take away those choices in the first place.
- ajuc 14y agoAd 4 I don't see how you can do OO without state.