There is a fundamental point here that really bears thinking about.<p>Software design has as a fundamental problem being able to express yourself in a way that is clear and remains clear as things change. Basic principles of good software design, like reducing cohesion, remain good principles no matter what "paradigm" you think you're using. When you change paradigms, be aware that the basic principles remain the same no matter what label you give them. And since design is all about tradeoffs, if you are going to have to violate a principle, you might as well do it in the clearest and most straightforward way possible.<p>Let me give an example. A singleton is bad for all of the reasons that a global variable is bad. If you need one, I prefer to make it a global variable simply because that is honest about what design principle has been broken. (Unless I want to make it lazy - then it is easier to write with a singleton!)<p>So learn the principles. Figure out what they look like and are called in your paradigm. Get on with life and solve real problems.<p>Let me give a concrete example. I learned more about good OO design from the first edition of <i>Code Complete</i> than any other book that I ever read. Even though it was entirely about procedural programming. Because the principles that it discussed, from how to name functions to the value of abstract data types to information hiding, all apply directly to OO. And to functional programming. And to aspect oriented programming. They are truly universal. Learn the principles, they are more important than the labels.
I really like Hadi's criticism of OO, and in fact I would like to hijack it and take it a few steps further, to paint what in my mind is a more realistic picture. Functional programming is only <i>an alternative choice of paradigm</i>. Expert programmers will use the best tool for the job and eschew the pointless search for the <i>absolute best</i>.<p>Why OO? Classes exist to decouple behaviors from data. In fact, their purpose is to think in terms of cohesive sets of behaviors instead of data-driven functions.<p>Does this apply to any possible case? No, it's a leaky abstraction.<p>Why FP? Functions exist to decouple behavior from other behavior. In fact, their purpose is to think in terms of completely decoupled sets of behaviors instead of cohesive functions.<p>Does this apply to any possible case? No, it's a leaky abstraction.<p>Why AOP? Aspects exist to decouple behaviors that apply across classes. In fact, their purpose is to think in terms of orthogonal sets of behaviors instead of hierarchical sets of behaviors.<p>Does this apply to any possible case? No, it's a leaky abstraction.<p>Why Procedural Programming? To separate the functionality of the application in separate behaviors. In fact, the purpose of procedures is to think in terms of behaviors instead of sequences of operations.<p>Does this apply to any possible case? No, it's a leaky abstraction.<p>Why Declarative Programming? To express solutions in terms of goals instead of behaviors. In fact, its purpose is to think in terms of desired state, not sequences or compositions of behaviors.<p>Does this apply to any possible case? No, it's a leaky abstraction.<p>Why Logic Programming? To explore the logical consequences of given facts, instead of focusing on behaviors or desired outcomes. In fact, its purpose is to find new truths starting from given truths.<p>Does this apply to any possible case? No, it's a leaky abstraction.<p>Why spaghetti code? Wait, no that's just crap ;-)
I think that the article uses a bad example. OO is actually really bad in db apps (DTO apps). OO shines when you are in one big continuous memory space, and don't have to worry about the data behind the objects. I see OO as a good way of abstracting the data away from the logic of your program.<p>This abstraction works well with classical desktop apps (lots of code, one big heap, pointers are always valid), but breaks down badly when your program is about communicating data and you start to cross memory address barriers.<p>A lot of modern apps are about data. You see a lot of networked apps, db apps and layered apps with different technologies in every layer, communicating with each other only through shared data formats. Such an app is primarily concerned with shuffling data around, and oo breaks down into a horrible mess. Each transition to a data representation requires a complete serialization of the object graph to a reasonable data representation and back again at the other side. This means that you essentially have twice the amount of work than if you would operate on the data directly as you would do with FP.<p>Once the amount of "internal juggling" with the data exceeds a certain limit, OO might be beneficial. But for data-centric apps, forget it.
If you think of classes as namespaces and not objects (which is what they are half the time), it becomes a bit saner. Pragmatism makes the world work.<p>You can still write functional code in OO. Heck if it makes you feel better, you can just make a macro to rename 'namespace' to 'class' and then you can write code like<p><pre><code> namespace Utils {
function thingy() {...}
}
</code></pre>
Namespaces are generally an improvement over globally defined functions as it lets you mix and match libraries without having to worry that you included the right header files, etc. Again, pragmatism.
I think of learning OOP much like learning Chess. In Chess it's very easy to learn how the pieces move and start playing, but becoming a master is incredibly difficult, requiring years and years of deliberate practice. When I see people complaining about OOP, it makes me think of two beginners playing Chess, thinking victory is a random outcome.<p>The dialogue of the article is entirely about coupling, and in OOP figuring out how to make a loosely coupled system is what separates the grand masters from the beginners. Designing a loosely coupled system is incredibly hard and requires years of deliberate practice to master. So when someone who's a beginner or not very good at OO design claims OO isn't a valuable paradigm, I don't listen. Bad OO can be less valuable than no OO, just like anything else, and just like anything else, that doesn't make the whole paradigm bad.<p>I've explored functional programming in a couple of college courses now, and find it very intriguing. When it's time to go a make a system, however, I find it difficult to boil down functional principles into the system I want. This is a complaint in the same vein as the OO complaints. Functional programming is incredibly impressive when designing a behavior, but what separates the masters from the beginners seems to be when it's time to model an entire system. This is the current separation in my mind: OO is designed and really good for modeling a complex system that involves lots of mutation, and functional programming is really good for modeling and separating behavior within a system.<p>I don't think we have grounds to say one is better than the other yet. Both OO and Functional have their niches where they're amazingly effective, and both have a giant gray area where it's difficult to mold the pure paradigm onto a solution.<p>I think the best solution so far is a mixture of the two, such as we see in Scala. Though, a mixture too has its own set of drawbacks. Mainly what seems to be an explosion of language complexity and a giant need for design conventions and limitations when there are so many possible routes to a solution.<p>The best of the current climate is a mixture of the two, with a framework that clearly defines and separates where and when to use one paradigm over the other, so you aren't bogged down with the additional complexity.
Not to get into the oo vs functional debate, but generic advice about how big a class should be and how it should relate to other classes is guaranteed to be inappropriate some of the time.<p>Classes are a tool you can use to design a solution to your particular programming problem. Sometimes the problem with call for a few large classes. Sometimes it will call for an evenly balanced network of small classes. Sometimes there will be a lot of DTOs, and sometime none. Sometimes large classes will cause maintenance problems because there is a lot of complexity confusingly jammed in one place, and other times they will be a boon because you don't have to look in lots of confusingly named files to discover what you are looking for.<p>Criticizing a design by how well it conforms to abstract rules, rather than criticizing its fit to the actual problem will often lead to confusion.<p>These rules of thumb are useful, but only as a way to question whether your design is a good fit - I.e. "Would it be better if this class had more behavior or less behavior? Would it be better to split this class into smaller components, or should this group of similar classes be coalesced into a single entity?"
This is a nice narrative. Some people have misconceptions about what OO gives you in comparison to other paradigms. OO provides specific abstractions, which may be useful in many cases, but also may be too much. In some cases, simpler abstractions may be preferable. Less complected (baked together and inseparable) abstractions can often be found in other paradigms. For example, in Java, a person might use a class even though all they need is a namespace. In many functional languages, you can just create a namespace without the other trappings of OO. Sometimes that is just what you want.<p>I've seen some nice slides from Clojure talks that talk about how many OO abstractions are complected (combined) versions of simpler abstractions. If anyone has seen the slides I'm talking about, please share. For example, a class is combination of a namespace and ___. Possible answers include mutable state, shared data, and so on.
> <i>Why Class?</i><p>To enforce an invariant but of course. Just ask Bjarne.<p>[1] <a href="http://www.artima.com/intv/goldilocks3.html" rel="nofollow">http://www.artima.com/intv/goldilocks3.html</a>
I've found the most critical difference between OO and FP to be state. Objects are stateful from the moment they are created until they are destroyed. FP is remarkable for its general lack of side-effects - i.e. computations do not normally affect shared state.<p>I believe this distinction is a critical one because an application with a lot of shared state is more difficult to scale than one without. As another poster pointed out, in a shared addressed space such as a desktop app, this isn't a concern. But if you want to scale an application across multiple address spaces, communicating and synchronizing the state of objects between these spaces tends to be difficult.<p>So, my tendency is:<p>Small and shared address space? Tend to use OO patterns and implementations.<p>Big and distributed address space? Tend to use FP patterns and implementations.<p>Note, I don't consider OO vs. FP a language choice – I consider it a programming paradigm choice.
I think OO and FP can coexist peacefully. You just need to pick out their good parts and discard the rest, and use a programming language that allows this.<p>Do put your object in classes, but don't put behaviors there. Use classes to allow static type checking so that functions taking them can guarantee certain field exist.<p>Separate behaviors out into its own module. I'd avoid calling them classes here because there will be confusion. Interactions between objects can be implemented in FP style. This is where you get to use map and reduce.<p>I've been learning about DCI (data context interaction) recently. I can't say I've fully grasped it yet, but it did opened my mind on how to do design differently.
This is a great piece and probably mirrors the process that a lot of us have gone through over the years. I know it definitely rang true for me.<p>I would hazard to guess that functional programming or any other solution will go through the same type of evolution and we will be looking back in 10 years at how immaturely we used the technology. Then we will circle back to yet some other technology that was previously used and went out of style, with some new insights added.<p>It seems to me that we go in a great big circle over and over again, picking up a little bit of new info each time around.
Use a better OO meta object system, ie. Moose.<p>And then you can build a class like LEGO, literally.<p>Because, it has Class and Roles, a class can extend another class. And a Role can be built with multiple roles. And a class can be built with multiples Roles.<p>Your OO is outdated if it doesnt implement classes, roles, types and at least method modifiers.<p>And your language should allow first function class to allow functional programming if you desire.<p>Perl has all that and comes installed in any unix/linux/mac.. try in your terminal: $ perl -v<p>Every linux/unix/mac system runs perl. So your company is probably using perl and they dont even know.
I do agree the "noun" vs "verb" analogy when classes are taught are horrible..actually the way classes are taught in general are just confusing.<p>Ultimately, classes are about code organization and reuse. Done properly, it leads to a well maintained program. Functional programming...it still needs to be organized somehow, whether you put them in classes or namespaces, the last thing you want is spaghetti code. Now depending in the type of programming, you may need to preserve state, which can be quite challenging in a purely functional environment.
I can somewhat relate to the conversations in the article. While I admit that I don't think I used OOP correctly, since I started using more functions instead of classes (in Python, my primary language), I observed that it has been more convenient to reuse and refactor existing code.<p>Another observation is that it's far easier to read someone else's code if there is no mutation. For eg. I have enrolled for the proglang course[1] on coursera and only yesterday I completed this weeks homework which involves enhancing an already written game of Tetris in Ruby. Major part of the assignment was about reading and understanding the provided code that uses OOP and makes heavy use of mutation. It was quite difficult to understand what one method does without having a picture of the current state of the object, specially with side effecting methods that call other side effecting methods. A few times I had to add print statements here and there to actually understand which one is being when and how many times. While I could score full marks in the end, I am still not confident about completely understanding the code and have a feeling that if I ever need to work with it again, the amount of time it will take to load up everything again into my mind's memory will be equal to what it took for the first time.<p>Of course, one could only make a true comparison by studying an implementation of Tetris written in FP style. But from my experience with reading and writing code in Erlang (for production) and Racket, Clojure (as hobby) I find it relatively easier to study functional code written by others.<p>[1]: <a href="https://www.coursera.org/course/proglang" rel="nofollow">https://www.coursera.org/course/proglang</a>
It's not like one paradigm is perfect for everything. But there's one thing that the author wrote that stood out for me: writing a "utils" class for stuff he doesn't "know where it really belongs."<p>That's one of the benefits of OOP: it forces you to think harder about where things belong, and this really helps as codebases grow. A "utils" class is often a sign that things could be better organized.
Will someone give me a few concrete, practical examples of using functional programming in JavaScript?<p>I'm interested in this concept, but I'm not sure how to go about applying it to my own work as a front-end web developer. Most of the resources online are theoretical.
:D. Why is anyone even considering FP vs OO programming a choice? I've used functional patterns within OO before and I'm sure the opposite is possible.<p>Both have merit depending on the skill-set and staff available to you, scale of project and existing infrastructure.<p>I was however very disappointed when the author bundled interfaces into the mix as if it was the same as the rest of it. The interface enables you to support many different types of behaviour and enables you to structure your libraries in different ways. It's a different aspect from just classes themselves.<p>Genuinely I don't think shit like this is healthy. Smacks of religion.
I might be a little late, but does anyone have any examples of simple CRUD web applications written in a functional language? There seems to be a lot of meta discussion about the suitability of functional programming for the web, but not very many concrete examples. Thanks!
'Don’t be silly Jake. Where else are you going to put functions if you don’t have classes?'<p>The core argument is more of philosophical in nature in terms of paradigms, because from functional programming view a function just acts on a data transforming it to other form. But in pure OO world (like Java) one can not dare to think beyond objects so for them it has to be in a object.
In one of the initial posts of the series, OP mentions that functional programming doesn't have app state. Can anyone point out more details on this?<p>I don't know if I am understanding it correctly but one of the reasons I absolutely loved Backbone.js was that it kept state of our DOM. Is this relevant to above discussion? because state surely looks pretty beneficial.
Ever since I started playing around with Java (or even earlier with C++) having data co-mingled with functions has never felt right to me. It just never seemed very extensible to me, especially in a language like Java. Even in C# where you have extension methods, they are second class citizens.<p>But also the old question of where to put a method seems like unecessary mental overhead for solving a problem. Use modules and just pass things in. You could probably even put some syntactic sugar in the language so that you could use the "object".method notation on the first argument passed in if you really wanted to.<p>So someone give me clojure with optional typing, a Python-like syntax, and get off my lawn!
IMO, most critics of FP or OOP do so because they lack a full understanding of one or the other. Either paradigm can be applied incorrectly and cause plenty of problems. Both have their merits and strong points. Each fits a different type of project better than the other. Also different people tend to grasp or appreciate one or the other better naturally depending on how their brains are wired. More logical, abstract thinkers tend toward OOP while more right brained people tend toward FP. There is nothing wrong with this. There is also nothing wrong with learning the benefits of the "other side". If fact it is quite beneficial.<p>some language designers see and fully appreciate the benefits of both. They start putting class synonymous structures in FP languages or FP functionality in OOP languages. This is the future of the mainstream (Ex: EcmaScript 6 has classes/types, C# has Linq, closures, lambdas ETC).