Code Monkeyism

Programming is hard by Stephan Schmidt

Functional design patterns and cargo cult blogging

Again, I’ve found someone. I considered stopping last time. But this one is too good. I will only pick some parts of the post, there is not enough time to fight all stupidity there is in the world - I need to choose my battles. As the last two posts, I’ve again chosen someone who rants and has an aggressive and insulting tone without any knowledge of the matter the writes about.

Let’s start. Don’t get fooled by the beginning of his post:

“At the same time, I actually think I’m a fairly good programmer. I also think I have a fairly good understanding of what most of these buzzwords actually mean [...]“

As well see shortly, contrary to his introduction he has absolutely no clue what he’s writing about. The first subject of his lengthy rant are design patterns:


“What is so wonderful about design patterns? Some of them are known to be goddamn awful constructs that will only pollute your codebase. What a design pattern really is, is a makeshift solution to a shortcoming in your language. A proper language would make every single design pattern redundant.”

He’s glorifying functional programming later. Do only I find it funny that people ranting against design pattern (the OO ones) don’t see that currying and monads are FP design patterns? Design patterns are best practices for designing software solutions and have nothing to do with OO.

Design patterns in OO languages and Java in particular, are not part of the language. They form a solution to common problems on top of the language. The state monad, the monte carlo monad, backtracking monads, maybe and either monads. All solve problems outside the functional domain of the language. (One could argue currying is not a design pattern but an implementation pattern. Go read the Beck book.)

Simple minded people everywhere. Who can’t see the wood for the trees. This seems prevalent in the functional community - at least the people who blog. If you want to read something about functional programming that is insightful read something from apocalisp. And use OCaml or Scala, or sneak good ideas into your Java code with functional Java.


“What is a design pattern? Code duplication? It’s a recipe for writing the same code over and over. And we all know that this is bad. You shouldn’t have duplicate code.”

The poster has no clue what a design pattern is. He quotes the Visitor pattern himself. The Visitor pattern is a clever way to use handlers with double dispatch and polymorphism. There is no duplication:

public void visit(Customer customer) {
  // do something with customer
}

And though other languages don’t need the visitor pattern - Nice with multimethods for example - they essentially do the same thing:

handle(Customer customer)
{
  // do something with customer
}

The solution is the same. Those languages have internalized the constructs and have syntactic sugar for less boilerplate. They don’t have new concepts. The concepts are the same.

This is how he describes a Factory


“An object that wraps a function that you can tailor to construct and return an object so you don’t have to construct it completely from scratch when you need it.”


Thats more of a Prototype or Singleton pattern. Factory is a different solution to a different problem.

This makes me sound like a design pattern evangelist. But though I’ve learned a lot about programming from design patterns, I rarely use them. Mostly not because they are bad, but there are myriads of other problems to solve - which can’t be solved by common Design Patterns (yet?).

That said, some should be used more often, NullObject especially. And some are bad - Singletons! No, Singletons are excellent as a pattern. Only the implentation in Java is not very useful with a static method. Inflexible and often hard to test. As most creational patterns, Singletons have been replaced with IoC/DI containers. Those offer more options, creating Singletons -as a concept - being one of them.

Reflection?


“And while it doesn’t have the same buzzword appeal, reflection as a language feature may be worth mentioning too. That too is just a workaround to compensate for missing language features. Great, so it lets you inspect a class to see what methods it has? That should never be necessary. If it has a method, I should be able to call it without going behind the code with introspection.”

Never used Reflection I suppose. Or any meta programming. Read The Art of the Metaobject Protocol. It’s about CLOS! Yes I know, Java has a very weak MOP and CGLIB only goes so far.

He goes on ranting about agile development.


“What does it mean? Anticipating that changes will happen? Testing every part of your code? Working as a team, with other programmers? Get the customer involved? Let them see regularly what you’re up to?”

Nope. It means “Individuals and interactions over processes and tools [...]” which a little googling would have turned up. But of course ranting without any knowledge is easier. Knowledge hinders one ranting.

For some real insight into agile, read about Agile vs. Lean. Lots of people like agile because it helps with lean development.

The post is titled “Cargo-cult programming”, what he mainly attributes to Java developers. Cargo cult programming? His post is more like cargo cult ranting. Like lots of bloggers - see the two I’ve written about before - who only parrot what others say about design patterns, functional programming, Java or agile development. Count yourself one more cargo cult blogger.

I hope you’ve read the original post. It’s fun from a certain point of view as you see in this post.

Thanks for listening.

PS: When wanting to comment on his post, his blog told me “Sorry, but it seems you are a Spambot.” That says a lot about the blogger, keeping to oneself and not listening to others helps staying without knowledge and helps with more ranting. I hope none of my commentators see a spam bot message ;-)

About the author: Stephan Schmidt is currently a team manager at ImmobilienScout24 in Berlin. Stephan has been working as a head of development and CTO. He has used a lot of different technologies in the last 20 years including Java, Rails and Python. Stephans main field of interest is maintainablity and productivity in software development. Want to know more? All views are only his own.

If you did like this article but you don't want to subscribe to new articles with your reader, you can follow me on Twitter or subscribe to new posts with your email:

Comments

Jalf

First, sorry about the spambot thing. It’s some automated response from a wordpress plugin I installed, still trying to figure out if it’s worth using. I’ll unblock your comment now, of course.

Second, I think you’ve missed my point a bit. :)

The entire point in a design pattern is “when you encounter a problem like this, write the following code”. If that is not code duplication, I don’t know what it is. Which doesn’t mean we shouldn’t use design patterns. It just means that we’re working in imperfect languages. And that certainly shouldn’t be news to anyone.
And I’m not ranting against design patterns per se. I’m ranting against blindly applying them in the belief that they’re somehow magic, and will confer some of this magicness to your code.

And yes, I have used reflection (in C#, primarly. So yes, it’s possible I’m that I’m missing some vital aspect of how reflection could be a lifesaver in other languages). And again, reflection is neat. It allows you to solve problems that you can’t otherwise solve within the language constraints. But another way to look at that is that the language is too constraining. You have to jump “outside the language” to get this task done. (And in the above, I’m not counting something like Lisp which could be said to be *all* reflection.)

Of course, I overstated a lot of points in that post. Where’s the fun in blogging if you can’t be a bit provocative? ;)

“Nope. It means “Individuals and interactions over processes and tools […]”
Yes, and (from the same page)
Working software over comprehensive documentation
Customer collaboration over contract negotiation - (I said “Get the customer involved? Let them see regularly what you’re up to?”)
Responding to change over following a plan - (I said “Anticipating that changes will happen”)
And of course, “Working as a team, with other programmers”, which I (and I wrote it ;)) would interpret as “Individuals and interactions over processes and tools […]”.

No, I don’t see any big differences between your description of Agile and mine.

And once again, I’m not ranting *against* agile as such. It’s a very sensible ideology. I’m ranting against people who don’t stop and think about why *each* aspect of agile works, and how it applies to their situation, before blindly copying it.

Anyway, thanks for reading, even if you think I’m a moron. ;)

matthew

Your “this one” link is screwed up. You’ve got a “br” tag inside of your href.

stephan

Ah, the glory of Wordpress and stupid me.

Thanks, fixed.

stephan

@Jalf: “The entire point in a design pattern is “when you encounter a problem like this, write the following code”. If that is not code duplication, [...].”

So: Whenever you need to make a decision on variable (problem), use an if (solution), you call this code duplication? Then my definition of code duplication (using ifs) is quite different from yours. Or using objects is code dupliction?

Observer documentsObserver = new Observer(this);

Code duplication?

“[…]” <= you know what that symbol means?

For the fact that your’re not ranting you’re ranting a lot in your post. Just my 2c.

“You have to jump “outside the language” to get this task done.”

In which way is using Reflection in Java jumping out of the language? The nice thing with Reflection (and UML for that) is that you can _stay_ in the language but still switch to a meta level. That’s the beauty of it. The MOP in this case - as in Ruby and Groovy and others - is part of the language with the same constructs (method calls, objects, classes).

Peace
-stephan

“Do only I find it funny that people ranting against design pattern (the OO ones) don’t see that currying and monads are FP design patterns? Design patterns are best practices for designing software solutions and have nothing to do with OO.”

I’m sorry, but that’s not entirely correct. Currying and monads don’t have anything especially to do with FP. Currying is a mathematical property of functions, and monads are a specific class of mathematical objects. Both of these concepts apply to ALL programming and I would strongly object to the suggestion that there is any sort of divide between “functional” and “regular” programming.

Let’s take Currying. It’s simply the observation that “A and B, therefore C” is exactly equivalent to “A, therefore B, therefore C”: (A, B) -> C == A -> B -> C.

As for monads, ponder what this means: there is no programming without monads. It’s true. Let me state it again, just so it sinks in. You cannot write a program that doesn’t use monads. Not in Java, not in Ruby or any other language, whether you ever see the word “monad” or not. Do you still think it’s a “design pattern”?

Without having read Jalf’s article, I still tend to agree that “patterns” are cruft used to overcome inexpressiveness in a language. Indeed, Chris Alexander speaks of “pattern languages”. What that translates to in programming is not “when you encounter this kind of problem, use this kind of code”, but to logical induction, which is an expansion of our language so that we may speak of things according to their essential similarities, omitting their particular differences.

I’m reminded of a passage from The Structure and Interpretation of Computer Programs (paraphrasing): Programming is not so much about creating programs as it is about creating languages.

stephan

@Apocalisp: I didn’t mean they are special to FP. They are solutions to problems which FP developers use - and they are outside the language. One could argue concerning the “deficit” argument that the state monad solves the “deficit” of missing state in FP (I do not adhere to the deficit argument in neither case).

Currying - not on a mathematical but practical level - is about how to structure you’re functions. Either to allow or not to allow currying. And the decision to structure a function in a way to allow currying is - from my point of view - a pattern to follow. How to design your function. The same goes for monads.

Perhaps people use currying without needing to make that decision. Just because it’s “the way to do it.” But the same could be said for Iterators in Java. You just use Iterators (see google collections also) without every time thinking “what pattern could solve this problem”.

All in all, though the deficit argument is very popular in some circles, I’m very skeptical. What deficit does Chain of responsibility solve? Facade? Flyweight?

And I’m sure the idea that monads and currying are patterns - are a pattern language as you say - is repulsive to FP developers as design patterns aggregates all they despise in OO.

The idea that monads are a “pattern” of programming is as absurd as the idea that sound is a pattern of music. The concept of monad is fundamental to programming.

I think you will find, if you amputate the notion that there’s a useful distinction between FP and OO, that you didn’t need it after all. The same with the distinction between a mathematical and practical level. Math is practical.

stephan

“The concept of monad is fundamental to programming.”

Monads are fundamental to programming? So I cannot write code without them? No Lisp without monads? No Basic code? No Assembler code? Punchcards had the concepts of monads in them? Babbage?

Then perhaps I really don’t understand what monads are if programming without them is impossible.

10 print “Hello”
20 goto 10

Funny, I’ve never thought in the last 26 years that there are monads in these two lines of code.

Of course there’s a monad to be discovered in those two lines of BASIC. Let’s make it easier to spot:

10 input s
20 print s
run

The value of s in line 10 is being bound to a free variable s in line 20. How does that happen? A lot of work is done behind the scenes by the BASIC interpreter.

Let’s rewrite this in an invented notation that’s more verbose and makes things more explicit. A lot less done behind the scenes by the interpreter.

ten = input(s); return(s);
twenty s = a <- read s; print(a); return();
run(ten.bind(twenty));

That “bind” right there should be screaming “monad” at you.

Now, as for Currying, see here:
http://blog.tmorris.net/proving-the-existence-of-curry/

stephan

Interesting. Is there a monad, or did you introduce one?

I didn’t introduce anything. I just changed the notation. It’s a bit like your saying: ||||, and my responding: four! Is there a four there, or did I introduce it? What’s going on conceptually is exactly the same either way, I’ve just given it a handier name.

Sorry if the made-up notation is a bit off-the-cuff, but the point is to bring the “bind” operation into view. No matter what the notation, the first instruction creates an environment with a value in it and the second instruction reads from that environment (or runs inside of it, if you will).

Enjoy your weekend.

stephan

Curious, I thought there was more to monads than a bind function?

My suspicion is still, that because two things are equivalent or can be transformed into each other, they are not the same, and one thing is not inside the other.

There’s more to monads than a bind function, but only just. You need a bind function, a unit function, and a type constructor. Those then need to obey a couple of laws (left/right identity, and associativity). Anything that has those properties is a monad, in the same sense that any three points are a triangle.

James Hofmann

Both the design pattern discussion and the monad discussion seem to be a case of explicit vs. implicit terminology. This is the same debate that “structured programming” faced in the 1970s: goto did the job of for, while, and other flow-control keywords — but the difference was that goto required much more context, and errors could result from improperly setting up the context.

Ultimately, the people on the structured side won.

Same deal with the general concept of object-oriented design: OO allows more explicit formations for how to organize code and data together than the more general procedural style. And it won out in the end.

The Wikipedia definition “Monad (functional programming)” says:

In imperative programming the side effects are embedded in the semantics of the programming language; with monads, they are made explicit in the monad definition.

So monads are another way to attack implicit semantics, and my understanding of how they are implemented in Haskell et al. is to act at the type-system level, allowing a programmer to specify more and more precisely what the results of an action are, so that type-checking eliminates those bugs.

Design patterns also attack implict semantics, but the difference with design patterns, and the one that makes them different from the previous concepts, is that they are always framed as constructs of object relationships; this makes them feel like a data structure, even though they have executable code embedded in them as well.

Having design patterns implemented at language-level is an interesting problem: My experience with design patterns is that I will rediscover a pattern as the optimal solution for a particular class of problem, but with an implementation that is slightly different from the canonical one. That is, I cannot claim that my implementation of MVC in one particular case has the same semantics as other implementations of MVC. So then, if you are designing a new PL, how do you accommodate this variance when providing a syntax for a pattern?

Well, I’ve spent too much time on this comment already, so I’ll stop my musing here.

Greg M

Chain of Responsibility is a partial workaround for lack of higher-order functions.
Flyweight is for lack of automatic sharing of immutables.
Facade is… too simple and obvious to be a pattern like the others?

Iterators are a good example of a former design pattern that became a library/language feature. Surely you write less duplicate code now that you’ve got libraries that operate on iterator interfaces?

stephan

“Chain of Responsibility is a partial workaround for lack of higher-order functions.”

I think you need to explain that more to make some sense. In what way does a pattern which specifies a group of handlers, where each handler solves a problem if it can be solved by the handler, be a partial work around for higher order functions?

“Flyweight is for lack of automatic sharing of immutables.”

No, Flyweight is the idea to use immutables for small things. Not the other way round.

How is Iterator a language feature. It’s a class! It’s a plain implementation to the book of the pattern. What you say is, if a language uses the classes of a pattern, it becomes part of the language? Then you’ve lost me.

I think most people here mix the concept and ideas of a pattern with the specific Java implementation. Of course patterns (Observer?) would be implemented differently in other languages - FP ones for example. You mix semantics and syntax for sure.

stephan

@Greg: After some thought your argument sounds more like “everything is everything” with a lose enough definition of “is”. Which of course is perfectly legal, but diminishes any real insights because of vagueness.

I could be wrong, but intuitively it seems that “Chain of Responsibility” is just Kleisli composition on the Either monad. Higher-order functions are not enough to attain a generic interface for that that you can write once and re-use. You would need higher-kinded types as well.

“Flyweight” assumes that your language is strict and that it lacks memoisation.

Iterator is a workaround for the lack of higher-order functions and tail-call optimisation. The iterator is a mutable cursor that keeps track of the state of a fold (catamorphism) over a data structure. Folding is more general than iterating (i.e. there are more foldables than iterables, and all iterables are foldable). A generic Foldable interface can’t be written in a language that lacks higher kinds (unless, of course, it’s dynamically typed).

stepha

Apocalisp: Again you’re wrong. You mix a solution with the concept. Just because two solutions exists for the same problem, that doesn’t make the solutions identical. Repeating “Your solution to a problem is inferior to my solution” is a view point, but nothing more than name calling.

Memoisation is another solution to the problem of memory. But it’s a different solution. And after some thought, memoisation mainly solves performance problems while Flyweight solves memory problems. So perhaps you’re plain wrong with your idea and it popped just up to drop another FP concept to make OO look bad. The same as for Chain of Responsibility. The same with Iterator.

I’m certain that there exist solutions to problems in a functional way compared to design patterns, but that doesn’t make the solutions identical, design patterns inferior and it doesn’t make designpatterns “fix deficiencies” in OO languages.

The onthology game is nice (”A is just B”), I had a lot of it in my philosophy studies - Heidegger, the American pragmatists - where people drop names and quote other people just to look more intelligent. And people often say things like “No, A is B and B is equal to C”. But after several years I came to the conclusion that all this sounds nice but is essenceless. As is your name dropping in this comment. The goal seems to be to only to make you look clever- as lots of FP developers who only chose FP today to look cleverer than OO developers. Go look around the blogosphere.

So in the course of several days you went from someone I’ve linked to because he was clever and showed some insights in to FP (your Either and Future posts and several others) and I’ve respected a lot to someone who drops names to look better and isn’t interested in discourse.

The best part of this comment? I’ve used name calling and dropped my Philosophy studies to a.) look cleverer than I am b.) keep you out of the game by using concepts most commentators don’t know about. I like the self referenceness of the comment this way. Which in the end is another stupid way to make me look clever. Isn’t blogging nice?

“Again”? Are you being honest? I’ll grant you that I may very well be wrong. I’d rather be corrected than chided though. “Someone who drops names to look better and isn’t interested in discourse” is far from my intention. But I’m not interested in what you think about me at any rate. I think this last lashing out is a case of misunderstanding and evidence that blog comments are not a good venue for this kind of discussion. So I’ll treat it as if nothing had been said.

I’ll rather visit design patterns later, in an article, looking for hints at how they can be formalised or mapped into formal theory. In the meantime, this guy posted a bunch of links to that kind of material on one of his better days, most of which (the linked material) is good reading: http://www.codinghorror.com/blog/archives/000308.html

I don’t subscribe to the view that OO and FP are different or at odds. Sorry.

But I’ll gladly take sides with you against both Heidegger and pragmatism.

stephan

“I think this last lashing out is a case of misunderstanding and evidence that blog comments are not a good venue for this kind of discussion.”

Yes, that’s true. And I apologize if my comments or my post increased the misunderstanding.

Thanks for the link, I’ll take a look.

“But I’ll gladly take sides with you against both Heidegger and pragmatism.”

:-)

Nevertheless I’ve learned something about FP - I think.

“Nevertheless I’ve learned something about FP - I think.”

So have I. Thank you.

stephan

Thank you.

As a side comment, in the se-radio.net interview
(http://www.se-radio.net/podcast/2008-08/episode-108-simon-peyton-jones-functional-
programming-and-haskell), Simon Peyton Jones said “monads are almost like design patterns”.
Sure, design patterns aren’t formally defined as monads, but hey share common traits.

stephan

Nice catch, thanks.

Leave a Reply