24 ms·
Object-Oriented Programming is Bad (2016) [video]
- specialist 8y agoGood grief. The reason that OO, FP, functional decomposition, entity relation diagrams, methodology de jure sucks is because modeling is hard. -- These rules apply to all programming paradigms: Favor composition over inheritance. Try to not share state. Favor dumb objects over active objects. Favor shorter call stacks, less indirection. Try to bunch like things together. Try to DRY.
- holdenc 8y agoA 44 minute powerpoint on why OOP is bad? Please refactor into separate self-contained and neatly presented topics each with their own methods for breaking down this argument.
- tyingq 8y agoHere's the medium post from the same author that goes with the video: https://medium.com/@brianwill/object-oriented-programming-a-personal-disaster-1b044c2383ab https://medium.com/@brianwill/object-oriented-programming-a-...
- astazangasta 8y agoThis is someone who is confronting basic limits of representation and information flow and blaming OOP. There is no one best way to organize code just like there is no one best sentence to describe a rose.
- api 8y ago"There is no one best way" summarizes what I think is a major unheralded realization in software engineering in the past 10 years. Before that it was the search for the One Way. OOP and functional programming were probably the two biggest opposing schools during that era, but now the trend is languages that easily allow both plus plain vanilla procedural programming. It's the programmer's job to pick a paradigm for the problem being solved.
- slavik81 8y ago"there is no single development, in either technology or management technique, which by itself promises even one order of magnitude improvement within a decade in productivity, in reliability, in simplicity" ~ Fred Brooks, No Silver Bullet (1986)
- tyingq 8y agoThe explosion of variety has actually pushed the other way. It was expensive, but MVS shops could push out highly available apps with a consistent UI very quickly. It seems we've really only made progress on unit cost and ubiquity. I think this is roughly why cloud is popular. It's not cheap, but if you're using their standard pieces (RDS, lambda, ECS, ELB, CloudWatch etc), you're working in a defined box with fewer choices.
- tyingq 8y agoI'm curious if this is the way older and more established engineering progressed. I would be interested in how, for example, designing and building a bridge to suit a specific use case has evolved over time.
- 0x445442 8y agoSoftware not being bound by physical constraints like other engineering disciplines is a huge distinction. So much so that I think software development is closer to writing a novel or movie script than it is to building a bridge. However, I would say the closer the software is to bare metal the closer it is to "real" engineering.
- astazangasta 8y agoThere are two major concerns in software, performance and legibility. These concerns are somewhat orthogonal but neither can be abandoned, and the challenge is balancing them. By contrast in bridge-building (etc.) the two main concerns (performance and aesthetics) have been largely separated by discipline, into engineering and architecture, the former a purely mechanical discipline, the latter almost entirely artistic. The main result of Modernism has been the subservience of the latter to the former, and in general the almost wholescale abandonment of aesthetic concerns. This is starting to come apart a little bit as people realize that this separation is unhealthy, and maybe we shouldn't build brutal, ugly flyovers through our cities because they have measurable effects on happiness, and thus property values, etc. (i.e., aesthetic concerns have functional consequences). Similarly I think many software "engineers" take a long time to realize that one of their main functions is writing code that others can read; this is an aesthetic, artistic discipline that I think many developers reject as outside their domain. This, too, is starting to come apart as we slowly figure out that code's maintainability is a key determinant of its long-term success - that is, aesthetic concerns have functional consequences.
- yxhuvud 8y agoFrom the post; "The problem, however, is that, while organizing program state into a hierarchy is easy, OOP demands that we then organize program state manipulation into the same hierarchy, which is extremely difficult when we have a non-trivial amount of state. Anytime we have a cross-cutting concern, an operation that involves multiple objects that aren't immediately related, that operation should reside in the common ancestor of those objects" No, OO does not make any demands like that. You are totally free to make objects and classes out of processes and algoithms, and that is a good tool to do the kind of cross cutting concerns the article talks about.
- karmakaze 8y agoSo OP somehow inferred that OOP requires operations to only be carried out by 'ancestor' objects and fails miserably. What they call 'ancestor' objects also have nothing to do with OOP in hierarchy as it is not an is-a relationship by rather ownership/has-a that is common in many styles including composition over inheritance. Basically they don't know what they're talking about.
- randomsearch 8y agos/bad/unfashionable
- nathanaldensr 8y agoExcept it's not unfashionable. It's used by millions of programmers who just want to get stuff done. It's used by thousands of companies who don't really care how the native instructions are eventually generated. It's used by individuals and teams, application developers and library authors. This premise of this video is flawed from the beginning and the whole thing is basically a gigantic straw man.
- mrkeen 8y agoHe has reduced OOP to polymorphism/encapsulation/inheritance. Is that what you mean by the straw man?
- 0x445442 8y agoNot sure if nathanaldensr means that but that's what I would say is the straw man. Also, it's been my experience a lot of developers have a lot to learn about OOP principles. The most common OOP idea that's seemed to have been lost is asking an object to reason about its current state. If I had a nickel for every time I see code like below... String fooJson = new Gson().toJson(foo, Foo.class); or Double totalTax = TaxHelper.totalTax(orderItem.getCityTax(), orderItem.getCountyTax(), orderItem.getStateTax());
- peteradio 8y agoHe specifically says inheritance and polymorphism are irrelevant in the video. His problem is with poor encapsulation which is not specific to OOP.
- block_dagger 8y agoIt seems the author has not learned how to use OOP appropriately. His main argument can be summed up as “it’s hard to name things and hard to compose things” and that seems to apply to all programming.
- mrkeen 8y agoCan you please elaborate? What is his inappropriate use of OOP and how would he use it more appropriately?
- Wilduck 8y agoI don't think you understood his points. When he talks about the "kingdom of nouns" he's not complaining that the problem with "Manager" classes is that they're hard to name. Instead, the argument is that these manager classes are hard to name because you've reached a point in encapsulation where the association between behavior and state in inherently unclear and overly abstracted. I think the author would agree that all programing deals with the difficult problem of composition, however, the argument in this case is that OOP introduces unrealistic constraints on composition. The argument in this video is that encapsulation and the single responsibility principle requires you to choose between a difficult to maintain tree-based object hierarchy, or to abandon encapsulation, and that both of these are sub-optimal choices. Finally, I think the author would agree that he "has not learned how to use OOP appropriately" but would go one step further and say that "it's impossible to 'use OOP appropriately.'"
- ineedasername 8y agoThis seems like just another "bad" == "I prefer a different type of tool."
- api 8y agoOOP is a way of thinking about and structuring your program that works well for some problem domains and not for others. Like other paradigms it can become dogmatic and be overused. Also like other paradigms it became a huge fad for a while and now there is a backlash.
- j_m_b 8y agoThe problem for me in regards to OOP is the complexity related to the management of state. OOP encourages mutability and understanding the state of an object as its methods are called can be confusing when additional internal (and often times, private) methods are called. In functional programming, state is something acted upon by functions. It is as simple as f(x) = y. Reasoning in functional programming is much closer to the mathematics I've been trained in since grade school. In functional programming languages, mutability of an object is an explicit operation. It's easy to tell when state is being mutated visually from syntax. Mental overhead is greatly reduced when you can assume that your data structures are immutable.
- mjburgess 8y agoYes, but I/O is impure and sequentially dependent, unlike mathematics. Maybe the "impedance mismatch" between pure-fp and I/O is too great, with the IO monad being the "leaky abstraction" of the FP world. Then OO is not a bad solution to an irrelevant problem, but a pretty-good solution to a bad relevant problem. EDIT: To clarify: The "problem" is change. Imperative programming relates sequential device-change over time, to sequential programming lines. OO programming is a structured imperative programming. Pure FP langs model sequential change with (roughly,) lists of actions to-be-performed that are snaked through your program. (Also: maybe OO's failure has more to do with its limited static analysis, type systems, than its model of change?)
- rcdmd 8y agoYou can make any number of arguments why X, Y or Z is bad (or, "considered harmful"). The truth is, if you want to get stuff done, objects often fit the domain well enough and put state in predictable places. A bandaid here or there, "friend" classes and so on may be required. But, you'll get stuff done even if it's not in some perfect stateless beauty.
- hevi_jos 8y agoIt is quite obvious to me that the author is ignorant on the history of computing. The reason of the popularity of OOP is way longer than java, Xerox invented the graphical desktop and ALSO OOP. When Steve Jobs was ousted from Apple he created NEXT because he believed OOP was the next big thing. It was, and it became the foundation of MacOS X. Microsoft copied Steve Jobs in Windows with MFC. Java copied all of them. In the words of Steve Jobs, developing in OOP is not faster than not using it. The big difference was once it had been created, it can be reused easily. That was essential for complex systems. It became obvious for companies. There is this religion today of functional programing, people come to me and say, look how great this is, without state parallel programming is so easy, now you can use 32 processors at the same time. Great!!, until we measure performance and the thing goes 50 times slower. So now you can use 32 processors for what used to take one. Don't get me wrong, we use functional programming when it is the best tool for the job(it removes lots of bugs), but it is not panacea.
- adamnemecek 8y agoFunctional programming has little impact on performance.
- zaphirplane 8y agoProbably talking about Java’s implementation which takes a while to warm up
- pjmlp 8y agoOnly when proper use of memory isn't part of performance.
- goalieca 8y agoOop is slower than functional in many cases. The highly optimized java stack isn’t that fast and still uses oodles of memory. And then there’s languages like ruby which are practically slower than writing shell scripts.
- pjmlp 8y ago
- vikingcaffiene 8y agoI've seen this posted here before. I take issue with anyone who gets onto a soapbox and announces "this might be the most important video you've ever watched" and then proceeds to espouse their opinion about something. It's egotistical and it immediately sets up any dissenting opinions as Obviously Wrong. I call BS on all of it. OOP can be written well. I've done it. I've seen it done by others. When you need a strong domain layer and strong data integrity it can really pay off dividends. I think what people are really trying to avoid when they say "OOP is bad" is poor design and entangled concerns. In general favor composition over inheritance, strongly defined data contracts, and a clean separation of concerns (business logic from presentation for instance) and you will find yourself with more maintainable and easier to read code. But thats just like, my opinion man. :)
- mistrial9 8y ago> poor design and entangled concerns good on you to call BS a bit, but others have mentioned management of state specifically.. so "nouns" are ABCs, "verbs" defined, but after runtime for a while, and getting hammered or other difficult conditions, what is state like ? good OOP can be really useful, without being a religion.. personally I would build general-purpose objects here and there to save some tedious decomposition..and the resulting seperation of code and concerns was fine .. specific things get specific code, while one or two item constructs somewhere off the beaten path might get lumped into a collection of "util" or similar.. its ok - it takes some practice and thinking ..
- 0815test 8y ago> "this might be the most important video you've ever watched" This is standard practice on YouTube, for better or for worse - same with the usual appeal "hey, you can help me by liking, commenting and subscribing!" at the end. (I have not clicked on this video, so I have no idea if anything like that is in there too.) Gotta drive those "engagement" numbers!
- mrkeen 8y agoThis advice/reflection could apply equally to any style of programming, except for one particular snippet. You haven't made or refuted any OOP-specific claims. Separation of concerns? Egotistical soapbox speaker? Strong domain layer? What do they have to do with OOP, as opposed to just P? Except for this: > favor composition over inheritence Yes! Inheritance is OOP-specific, and I agree that you should avoid it.
- viach 8y agoWhat else people can do - videos, articles - just to avoid learning a little bit of Java? Stop that laziness and learn OOP properly, you'll find a good use for it!
- chriswarbo 8y ago> Stop that laziness and learn OOP properly, you'll find a good use for it! This is my biggest problem with OOP: proponents keep shifting the goalposts to avoid criticisms. If someone follows OOP practice, and it doesn't work out perfectly, then they must not have been doing it "properly". Hence "OOP" becomes a nebulous term, encompassing a whole bunch of approaches (encapsulation, inheritance, subtype polymorphism, dynamic dispatch, SOLID, MVC, etc.) but if any of those don't work in some situation then they mysteriously don't count as 'proper OOP' in that case. I used to be very deep down the OOP rabbit hole (oh the joys meta-object protocols!), but these days I tend to stick to functional programming. I wouldn't claim it's the best way to program, and there are different tools for different jobs, etc. but one thing I've taken to heart is that we should try to make the easy thing be the correct thing. An example of this is static type systems: it's possible to write correct code without types, but it's much easier to get things wrong. Type checking rules out a lot of those wrong things, which makes it more likely we'll do the correct thing (note: I'm not saying static types make things easier, I'm saying that the easiest thing to do in the presence of static types is usually more correct than the easiest thing to do when there are no types). Automated testing is another example, as is purity, effect systems, capability models, etc. Even the fact that Java forces us to write a class in a correctly-named file just for "hello world" is an example of making the path of least resistance more "correct" (although I disagree with Java's notion of what's "correct"). Even if we concede that these complainers aren't doing OOP "properly", that just means OOP is fraught with gotchas, misaligned incentives and lacks objectively checkable criteria. I wouldn't want to pursue any practice where earnest, researched attempts to follow it not only lead to the very problems that it claimed to avoid, but is met with advice to follow the practice "properly". Just look at how much of softwareengineering.stackexchange.com is bogged down in philosophical pontificating about the nature of OOP! As for your specific claim, after doing OOP in several languages for many years, professionally, academically and recreationally, I count Java among the worst (PHP is slightly worse). I could say that if you want to do OOP "properly" you should try Smalltalk, but that would be yet more philosophical snobbery (you should instead try Smalltalk because it's a great language ;) )
- ravenstine 8y agoIn my experience, the thing that's wrong about object-oriented programming is not the object-orientation itself, but the over-application of it. - Sometimes more "procedural" programming provides better clarity. At other times, object-orientation is a cleaner approach. Neither should be a replacement for the other at all times. - The idea that objects should reflect how we think of real objects in the physical world probably needs to die, or at least not be treated as a standard for object orientation, since objects in reality often do not fit into neat categories and hierarchies. Because reality is dirty, as is virtual reality, unanticipated exceptions to the rules end up causing OO zealots to create hack solutions that end up being rigid and less obvious to other programmers. The simplest example I can think of off the top of my head is the Fat Model Skinny Controller paradigm in MVC programming; since a model is often looked at as a representation of real-world objects, a programmer thinking in OO is likely to stick every conceivable property and behavior around the imaginary object into the model code, which sometimes results in files thousands of lines long with code that doesn't need to have anything to do with database abstraction. In such cases, a lot of code related to the concept behind a model would be better handled by helper functions or other classes.
- pacala 8y agoWell duh. We’ve been sold object oriented platforms for decades with the insistence that everything is an object, hiding its internals from the world. There was tepid support for representing plain data. At the heyday of the madness people were busy building object-over-network abominations like CORBA. Even today, the most popular enterprise platform, Java, does not support value types. In the free world, the widely used Python platform has added dataclasses only as recent as 3.7, the current version. No wonder OO style is widely overused.
- contextfree 8y agoisn't "object over network" basically microservices?
- pacala 8y ago
- deleted 8y ago[deleted]
- wowJavaScript 8y agoAnd watch, I bet the fix is to use JavaScript instead, because it's better.
- kyberias 8y agoCan't agree with his suggestion on long functions and comments.
- jelling 8y agoWhere does Domain Driven Design fall? DDD typically has service class that operates on multiple business objects in a pipe-line like fashion. Being business programming, there is always side-effects but usually handle via repository or db manager classes. I.e. no active record.
- ryanmarsh 8y agoIt is perfectly sensible, easier even, to apply DDD concepts to small functional services. Define a bounded context and aggregates. Under the hood (inside the context) there are a number of strategies for handling side effects, data structures, and state transitions. I'm finding DDD + functional languages + serverless architectures work quite well together, so far.
- ryanmarsh 8y agoBrian's video is one of the most influential bits of wisdom I've received in my career. Up until this video I did not have a language for explaining the problems I ran into trying to build OO systems. It also helped me understand why writing procedural-functional code felt so natural and easy. I was a die hard OO/UML guy. I even contributed to various open source software projects for a model-driven-architecture framework, a UML editor, and integrations with Rational Rose. I was an evangelist for good OO practices, SOLID, etc... As a development coach I was quite fervent. Looking back on that I feel like a fool. When I read the code refactoring examples from Uncle Bob and others I see all the problems Brian talks about in his video (and more). OO was a nice idea but we got the granularity and implementation wrong.
- bunderbunder 8y agoI really liked the first half - he provides some insightful thoughts on both why OOP doesn't quite deliver on the promise, and why it continues to be popular anyway. I am also becoming increasingly enamored of procedural programming as a default approach. Functional is also good - it's one of my first loves - but I find that it can be similarly prone to encouraging premature abstraction. Like OOP, that problem isn't going to become so apparent until you start using it in a large, long-lived business system with ever-shifting business requirements. That said, I think that I've got to part ways with the video around about the part where it switches to talking about how the speaker thinks good code should be structured. Especially the bit about not keeping functions small - the problem with that is, it makes it way too easy for spaghetti code to sneak in. In the same way that, in the heat of the moment, a developer in an OO language is going to start tangling together the connections among objects a bit too liberally, a developer working in a 300-line procedural function is going to start fiddling with any variable that happens to be in scope a bit too liberally. Factoring out your functions does mean you have to name all those functions (which, I realize takes effort, but I also can't agree that it's a waste of effort), but it also serves as a way of making sure everyone stays honest about shared mutable state. Maybe it wouldn't be so bad in a language that has that "nested functions that aren't closures" feature, but, like he says, such a language does not currently exist.
- polarcuke 8y agoRuby and Swift (and other languages I'm pretty sure) allow you to have named functions nested in functions
- bunderbunder 8y agoWhat the video specifically suggested was not any old nested function, it was nested functions that do not capture upvalues from their context.
- totony 8y agoPHP has those (e.g. function() use ($var) { })
- type0 8y agoActually - Object-Oriented Programming is Good* https://www.youtube.com/watch?v=0iyB0_qPvWk https://www.youtube.com/watch?v=0iyB0_qPvWk
- platz 8y agoNamedrops golang again.. seeing a pattern here. The claim that primitive types are better than interfaces (inside modules) reveals that he is comfortable with golang style. But this point misses that you can do _more_ things when you know the full concrete type of something, than when you program generically, only depending on the minimal requirements of what you need, which in turn opens up flexibility for the caller (constraints liberate). Of course, one doesn't think too hard about this in golang, lacking generics
- anonytrary 8y agoNot shipping a working product before your deadline is bad. How you get there is up to you. OO isn't necessary but it can get you there. In a perfect world where deadlines didn't exist and everyone writing code was doing so for academic purposes, maybe OO wouldn't be necessary.
- vitriol83 8y agoone issue with OOP in practice that I've seen is the entanglement of the domain representation (member variables of a class) and the varied operations on that data (methods). Classic OOP encourages you to manipulate objects by methods rather than free functions, which combines potentially unrelated functionality in the same object. my rule of thumb with objects is to keep the methods to a minimum, to the extent all classes are either interfaces, implementations of interfaces or pure data classes. obviously this approach will be natural to ML programmers.
- nfrankel 8y agoCould we please stop this kind of useless statements? Aren't we developers supposed to be scientific-minded? There is not such thing as "bad" or "good" in absolute. There are paradigmes that work better in certain contexts - and I use the word "context" in very general way here - and some that work worse. If my consulting experience has taught me something, is that "it depends" is a valid comment most of the time. By the way, I also learned that if you stopped at this comment, you're not a good consultant.
- platz 8y agoThis conversation would be improved by responding or refuting to the specific points made in the video instead of generalized comments
- pjmlp 8y agoThe irony of the anti-OOP bashers is that all successful GUI frameworks are OOP based, even those written in non-OOP languages like C. Likewise all the functional programming languages that get used as example, are also not pure FP, rather multi-paradigm, also supporting concepts from OOP. "FP vs OOP: Choose Two by Brian Goetz" https://www.youtube.com/watch?v=HSk5fdKbd3o https://www.youtube.com/watch?v=HSk5fdKbd3o
- willtim 8y agoGUI frameworks have always been OOP-based because everybody was copying Xerox Parc. But even the most successful were not always easy to use (composition and control-flow/concurrency being particularly awkward). Modern GUIs are all based on HTML/CSS these days anyway and certainly not always OOP, as demonstrated by frameworks such as react.
- discreteevent 8y agoI think that is a bit like saying Xerox parc guis were all pixels which certainly isn't oop. Modern guis are mostly OO code that targets the Dom or generates HTML on the server
- pjmlp 8y agoThose modern GUI based on HTML/CSS don't work at all without JavaScript. Prototype inheritance is also OOP.
- namelosw 8y agoThere are a lot of mention on functional programming and OOP comparison in this thread. There's my 2 cents on the topic: 1. OOP is not necessarily bad. 2. The original OOP should be Smalltalk-like languages (messaging), but the term OOP we refer today basically related to Simula-like languages (inheritance, polymorphism). 3. OOP and FP are not exclusive. Language like Scala you can have a 'case class Stack[A]' with a method 'def push[A](a: A): Stack' returns new stack. First, it's a class and be able to have methods, inheritance etc. Second it's an ADT (Algebraic Data Type) and without any function with size effect. So both OOP and FP still makes perfect sense. 4. Main stream OOP languages design are mostly terrible. (Basically the 'Blub language' according to Paul Graham, I'll call those language Objective-Blubs because I want it to be a mainstream OO language without hurting someone). 5. There are a lot of arguments against Objective-Blub or OOP itself are related to state, side-effect etc. These are partially true. But I can't say stateless and pure is totally better than other approaches, I just feel better when I'm tackling complex domain so code does not affect each other in a crazy way. However if the whole program is pretty easy to make sense for you. For FP approach there is no obvious advantage over Objective-Blub. In this case choose the one with higher velocity. 6. The core problem that Objective-Blub to me is not simple state or side effects. It's the wrong/implicit modeling, if you are not modeling a problem, 9/10 you cannot address the problem. It's would bite you again and again. For small application these are fine, for large application these omitted modeling could be a real problem. But there are so few people mention this explicitly, please allow me to list some of them here: a. Quick example - NullPointerException: Not modeling nullable concept makes you handle null everywhere. By explicit modeling Optional/Maybe/Some it could be resolved. b. In Objective-Blub objects are reference type by default: Which means it's assume you only use the object in this specific machine and thread. Objective-Blub programmers always complain about object-relational impedance mismatch, and then they blame SQL. But the real problem is Objective-Blub itself. For Objective-Blub you have to throw away all the methods and references. Not only SQL, JSON or other serialization is also a big deal. If you use FP languages you just map tables to an ADT which is not a big deal. There's no assumption on identity on FP language at all, if you want an entity, just give it an id field. That also explained why FP languages is more concurrent friendly, because same data on different machines are still same data. c. Sub-type polymorphism does not let programmer do the correct modeling easily: ADT have sum and product type. That's how you describe domain types, it's so straight-forwarded. Done. While languages like Objective-Blub have class and enums respectively, but no parametric enums. You have to write less obvious code to model simple concept like 'Payment = CreditCard(no, cvv) | Cash(amount) | FreeCoupon' d. Sub-type polymorphism means strong assumption: This is so called inheritance, which encourage you do strong assumption like a Person extends a Head, which works but implicitly indicates a Person is a Head. This is ridiculous but if you convert Person and Head to some business type and services you can find too many code bases having this problem. e. Sub-type polymorphism is under-powered than other polymorphisms: Less powerful is good when it's enough. But it's a huge problem when it's under-powered, which means you have to hack all the way round - like with old day Java, if you loop through an array, you have to cast type to every element. This is insane for a verbose statically typed language. Language should focus on simplify parametric polymorphism like OCaml or Haskell does to guide programmer choose a better way by default. Statically typed FP languages usually model effect with parametric/ad-hoc polymorphism, which could be a huge deal of separating dirty world concerns - like in Scala you can have your domain service accept F[_] as effect type parameter without knowing what this effect would be, it could be database IO or random generator or totally different abstract things. f. Methods are everywhere: In Objective-Blub you have to write all methods in same class. So if a class having 100 methods is considered a code smell. And someone refactored them, move some of them to other classes and extract some of them to a new class. That's typically one reason why large code base are so hard to read, because typically in FP languages it's no big deal when you have hundreds of function operates on the same type, you just split them in several files if you want. For those extracted class and moved methods, they largely blurred how domain type and logic should be, because you have to create a new concepts, or move concepts to other places just because the old concept is too big. g. Less expressive also blurred things: For the first time I was looking at a code base with design patterns everywhere I was so confused. Most patterns are the problem that language is so constraint that it cannot express simple idea, like TypeScript allow Partial<T> in constructor it would eliminate most of the builders. Like singleton and static properties could be addressed with Scala object. When a code base is filled with BarFactoryBuilder etc, that means the language itself does not modeling these common patterns at all. This make people(both reader and writer) fighting with languages instead of just expressing domain business.
- shmooth 8y agoi love any kind of 'hate' article, and this guy is hilarious, so +1
- shmooth 8y agoyeah, that was pretty good. i guess OOP is not the end-all be all. prob would have been more useful if this was produced 10 years ago instead of 3 years ago. is anyone still using OOP?