Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In the past few years, the languages I like to use are becoming more and more "functional". I now use languages that are a sort of "hybrid": C#, F#, Scala. I like to design my application using classes that correspond to the domain objects, and use functional features where this makes coding easier, more coincise and safer (especially when operating on collections or when passing functions).

However the two worlds "clash" when coming to design patterns. The specific example I faced recently is the Observer pattern. I want a producer to notify some other code (the "consumers/observers", say a DB storage, a logger, and so on) when an item is created or changed.

I initially did it "functionally" like this:

producer.foo(item => { updateItemInDb(item); insertLog(item) })
// calls the function passed as argument as an item is processed

But I'm now wondering if I should use a more "OO" approach:

interface IItemObserver {
  onNotify(Item)
}
class DBObserver : IItemObserver ...
class LogObserver: IItemObserver ...

producer.addObserver(new DBObserver)
producer.addObserver(new LogObserver)
producer.foo() //calls observer in a loop

Which are the pro and con of the two approach? I once heard a FP guru say that design patterns are there only because of the limitations of the language, and that's why there are so few in functional languages. Maybe this could be an example of it?

EDIT: In my particular scenario I don't need it, but.. how would you implement removal and addition of "observers" in the functional way? (I.e. how would you implement all the functionalities in the pattern?) Just passing a new function, for example?

share|improve this question
    
What about Actors? –  sschaef Mar 29 '12 at 8:42
    
Forget about the classes and all that OOPish useless stuff. You'd better think in terms of modules instead (see SML and OCaml languages for an inspiration). –  SK-logic Mar 29 '12 at 9:14
    
@Antoras If you could a comparison with an approach based on Actors, it would be more then welcome :) –  Lorenzo Dematté Mar 29 '12 at 9:22
    
@SK-logic I love functional programming, especially OCaml. But I am more interested in multi-paradigm languages, and in a comparison of approaches (when do you use a paradigm?). Basides, I do not work alone, so while I can use F# or Scala and still have happy co-workers using C# and Java, I cannot dump classes ;) –  Lorenzo Dematté Mar 29 '12 at 9:25
1  
@dema80, OCaml is perfectly multi-paradigm. Modules are not related to functional programming at all. There is an advanced module system in a purely imperative Ada, for example. And all the fame OOP gained should actually go to modules - all the good in OOP is just various forms of simulating the modules functionality. You can forget totally all that classes and use their syntax for expressing modules instead, thinking in terms of modules, not OOP. Btw., that's exactly what Microsoft did with their mscorlib - not much OOP there, just modules and namespaces. –  SK-logic Mar 29 '12 at 10:12

4 Answers 4

up vote 1 down vote accepted

That's a good example of two different approaches that carry the notion of performing a task outside the boundary of concern for the calling object.

While it's clear in this example that you should go for the functional approach, in general it will really depend on how complex the behavior the called object has to exhibit is. If it really is a matter of complex behavior, where you'll find yourself reapplying similar logic often, and function generators cannot be used to clearly express it, then you'll probably want to go for class composition or inheritance, where you'll have a bit more freedom to reuse and extend existing behavior on an ad-hoc basis.

One pattern I did observe, though, is that usually developers go for the functional approach initially and only once the demand for more granular behavior arises they decide to go for a class-based approach. I know, for instance, Django went from function-based views, template loaders and test runners to class-based ones once the benefits and requirements became obvious, but not before that.

share|improve this answer
    
I think this answer is a little bit misguided. Functional programming is not programming (only with) functions. Functional programming uses abstractions as well, so there's no dichotomy here. –  Doval Feb 5 at 12:29

The functional version is much shorter, easier to maintain, easier to read, and generally, vastly superior in just about every respect imaginable.

Many- although, far from all- patterns are to make up for the lack of features in OOP, such as Observers. Those are far better modelled functionally.

share|improve this answer
    
I agree and have the same feeling. –  Lorenzo Dematté Mar 29 '12 at 9:39
    
I agree and have the same feeling.But I was sort of "cheating" with my functional code: in my case is all what I need, but what if I need to add and remove "observers"? I edited my question –  Lorenzo Dematté Mar 29 '12 at 9:41

Your "FP guru" is partially right; many OO patterns are hacks to do functional things. (His claim that this is the reason there's few FP languages seems dubious at best.) The Observer and Strategy patterns are trying to emulate first-class functions. The Visitor Pattern is a hack to simulate pattern matching. Your IItemObserver is just a function in disguise. Pretending it's different from any other function that takes an item doesn't buy you anything.

Objects are just one kind of data abstraction. This paper will help shed some light on that topic. Objects can be useful, but it's important to recognize they're not appropriate for everything. There is no dichotomy; simply a matter of choosing the right tool for the right job, and functional programming in no way requires that you give up objects. That aside, functional programming is more than just using functions. It's also about minimizing side effects and mutation.

share|improve this answer

I can't really answer the question because I'm not good at functional languages; but I think you should be less concerned about approach as long as what you have works. From what I understand , as long as you are not adding more listeners in the future or not changing the listeners during execution, you can very well skip the Observer pattern here.

I disagree that design patterns make up for "limitations" in OO languages. They are there to make good use of OOP features. Polymorphism and inheritance are features, not limitations. Design patterns make use of these features to promote flexible design. You can make an absolutely non-OO program in an OO. You can, with a lot of care, write an entire program containing objects which have no state, mimicking FP.

share|improve this answer
1  
"You can, with a lot of care, write an entire program containing objects which have no state, mimicking FP.", of course, and through discipline you can do the same in imperative languages too. :) In general, I do not think at design patters as something to make up for limitations, but consider the case of the Visitor pattern.. –  Lorenzo Dematté Mar 29 '12 at 9:06
    
Also, I am not concerned with the code: however, I would like to confront with fellow programmers on the approach (to my understanding, this is what programmers.se is for, otherwise I would have posted my Q on SO) –  Lorenzo Dematté Mar 29 '12 at 9:07
    
Every time you're spotting a repeating pattern, it is nothing but an indication of a severe limitation of your language and modelling framework. There shall be no patterns at all in an ideal world. –  SK-logic Mar 29 '12 at 9:13
    
@SK-logic: Unfortunately the world isn't ideal, and the real world has patterns. Which is why OO languages have inheritance , to implement repeateable code without having to rewrite them all over again.Real world object have a state, thats why there is a State pattern –  DPD Mar 29 '12 at 9:23
1  
@SK-logic: I'm well aware that some languages are programmable, and some permit the enforcing of effects from the type system too. My point is that, like "OOP", "pattern" is a sadly misunderstood term. A pattern is something that keeps reappearing in similar but different forms, that does not admit a uniform solution. Sometimes you can make those quasirepetitions disappear - multimethods make Visitor/double dispatch redundant. That does not imply "all patterns are signs of a deficiency", because that means the real world is deficient. Patterns originated in architecture, not software. –  Frank Shearar Mar 29 '12 at 11:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.