Anyone else think this was codified common sense when you first read it? Seems to be the case with a lot of software engineering stuff I read. I have trouble thinking of anything truly insightful my exposure to software engineering has taught me.
I'll have to think about others still (or turn around and look ;), but "Mastering Regular Expressions" (O'Reilly) really helped me many moons ago. I just bought the latest edition recently to see what's new, and to finally have a copy for my shelf.
One point it unfortunately doesn't cover is the large percentage of Go4 patterns that are just plain bad ideas. Singleton, for example, should just never be used: it's like relying too much on global variables, but worse.
I agree that the book is way too overused. I was immediately turned off when I would interview people who started talking in design patterns (not to mention people who would say the wrong ones).
However, I think there are completely valid uses of the "Singleton" concept. It can be an elegant solution to a lot of problems.
But some of the very things you need to live will kill you if you consume too much of them.
The problem is people often use the Design Patterns book as a design manual but that's not what it really is - it's an attempt to catagorize ideas. The very fact that you used the term Singleton means that now you and I can argue the merits of using that pattern in different situations. Would you rather us attempt to do that without common terminology?
There's nothing wrong with having common terminology. But when people are being taught about bad ideas without any cautionary comments, that's a problem.
By the same token, there's nothing wrong with knowing what a goto statement is. But I'm glad we don't have a popular book that implicitly advocates its use, or college classes that teach it to students as if it's the state of the art in control flow.
Usually when I see Singleton used, what the author really wants is either a value that is cached after the first time it's created (so the correct pattern is "cache"), or more often just a global variable.
What I find offensive about Singleton is the idea that that the author knows there is no context in which you might want more than one of some object. This is especially bad in libraries, where having objects enforce their own uniqueness breaks the ability for me to use two FooManagers where the author only envisioned using one. Designs are generally improved by accounting for the possibility of more than one instance, even if it isn't immediately necessary.
I must admit I can't remember when I have last seen it. I guess the usual case is the ConnectionPool for the database, which for most Java Web projects is being handled by the container (not sure how Rails does it). But in that case it does not seem the end of the world to have two connection pools. Somehow you have to still manage the whole picture, though... Maybe two are OK, but what if suddenly you have 1000 connection pools? Maybe then suddenly you start wishing you had restricted them to 1 from the start.
How is a global variable different from a singleton, anyway? Seems to me, in distributed and multithreaded environments the singleton problem is still a hard problem.
ConnectionPool is an excellent example of a bad case for Singleton: what if you have two databases? What if you want to use different pools for different types of queries?
A global variable is different from a Singleton because if you write a Singleton class in some module that I want to use, I have to fork your module if I want to make it possible to use two of them. If you use a global variable, I can always make a second global variable.
OK, I am not even sure anymore what the singleton pattern is _(it's been a while). If it is the class constructor that makes sure you can only ever create one instance, it might be bad. I thought any mechanism for ensuring singleness would qualify for the pattern. Then you examples wouldn't invalidate the connection pool, you could just have to different pools, one for each database. I agree that with the "class instantiation implementation" you could probably not do that.
I think Singletons are ok when the core language's runtime promises to take care of them. They are also ok for things like the abstract state objects in a state machine and for special immutable Sentinal objects (e.g. Lisp nil, Python None, ...).
Good point: things like states, true, false, and nil make sense. I think the commonality there is that those are all immutable values whose only purpose is to have a fast object identity comparison. In a way, they're similar to global variables which are all members of the same class, except that it's nice for them to have separate types.
In fact, you could think of Python's None as being a singleton, but True and False being the two allowed instances of a, uh, doubleton? And similarly, states might be implemented as a limited set of allowed values of a single class. This reminds me of Haskell's algebraic types.
This maybe isn't quite "Singleton", but it is at least a useful case for limiting the number of allowed values of a class.
Using design patterns really helped me in a large project I did in C# two years ago - although I must admit I used the friendlier Head First Design Patterns as my reference rather than the original Design Patterns book.
I honestly think I would not have been able to do the project without the aid of design patterns. The project's architect was living too high in the clouds to grasp why his architectures were unimplementable, yet tried to micromanage the implementation as well. He continually specified implementation details which violated basic constraints of the language syntax and the static type system (like asking for multiple inheritance in C#). So I would use design patterns to get around a language limitation to do something close to what he wanted. Since he didn't understand design patterns, he found my explanation of how the design pattern accomplished the trick impenetrable enough to just leave it alone.
It backfired on me when he learned the Singleton pattern (which he kept mistakenly referring to as the "Simpleton" pattern), and started insisting that every object should be a "Simpleton".
Anyhow so the reason I didn't downmod you, is that I do think design patterns are useful, but they fix a problem which is partly that the language is broken, and partly a people problem.
To the weak of mind, perhaps. I believe that patterns are useful and beneficial in moderation. This requires a degree of understanding that some do not have, leading to pattern hell.
Admittedly, I haven't read the texts on design patterns, and have only a cursory knowledge of what they're about. So, I'm about to commit the cardinal sin of talking on a subject that I don't know intimately.
Near as I can tell, design patterns are just ways of vaguely describing common solutions to common problems. They say, "You might try to solve problem X in some language by creating an object that does Y."
In lieu of actually understanding the specific problem they're facing, the inexperienced or less skilled programmer then looks through their dictionary of design patterns, finds something that sounds like it fits, and then proceeds to throw some very generic code at their problem until it goes away.
This strikes me as very similar to the problem Feynman discussed in "Surely You're Joking", when he worked as a professor in Brazil and came to realize that, on a national basis, the students had all been taught to memorize entire books of facts, but hadn't done experiments and didn't understand the concepts behind the things they were taught.
I recommend reading a text on design patterns. The Brazil example falls short, because people having no understandings of concepts doesn't invalidate the concepts themselves.
Design patterns are on my reading list, but these days that list is much larger than my available free time.
I agree with you, actually. My point wasn't that the design patterns themselves are wrong, or necessarily bad, it was that (I think) they'll tend to get used in situations where the programmer doesn't understand the immediate problem or solution well enough to deal with it directly.
Anecdotally, this came up somewhat recently when the question of whether or not it's "OK" to return early from a function got briefly passed around the net. I noticed a lot of instances where people were coming up with some pretty absurd reasoning to justify always doing it one particular way, the 'textbook' way if you will.
Myself, I think it's _sometimes_ OK to return early from a function. It depends on what you're doing. You have to understand the situation you're looking at, and all of the various circumstances around it.
So, the idea of "never return early from a function" isn't necessarily wrong, but it does indicate that the programmer probably doesn't really understand what they're doing.
It's been a while that I read it, but I thought the original "Design Patterns" book was pretty good. You won't find something like the "return early from function" in it. I think it is best to read the original design patterns book, not the language specific clones (ie not "Design Patterns for Java" etc).
Most patterns in the book are not that trivial, so I don't think you can apply them without understanding them (in general).
I don't want to go into details, because things would quickly get biographical, but the real danger is that the book is written with faux-scientific verbiage, and uses that to trick weak-minded people into thinking that they are reading a scientific text. This is an old trick of conmen and cultists and when it works it isn't pretty.
You say you don't want to go into the details but you really should in order to strengthen your argument. At the moment you're just using DH2 (Responding to Tone), DH1 (Ad Hominem) and perhaps a little DH0 (Name calling). If you really think the GoF are aiding conmen in tricking the weak-minded, then please substanciate that.
I don't have the book to quote it. But roughly, here is how it works:
What is an "Iterator"? It's an object that contains functionality to retrieve objects from a container. Period. The end.
Now, what is an "Iterator Pattern"? (Again, I don't have the book, so...) I think it is about 10-15 pages of how to define, describe, document, specify, graph, implement, re-use, contextualize and otherwise belabour the Iterator object.
But, at the end of the day, an "Iterator" is simply the next-next-next functionality moved from the linked list to another place. That's all it ever is, in practice. The book makes things worse by using PhD-dissertation levels of vocabulary and grammatical structures to describe simple, simple concepts. This gives confusion to people who don't see through the bull, and when they say "Aha! I understand Iterators!", they believe they've unriddled a mystery, and so become "educators" and "advocates" on behalf of others.
I speak from experience, and have no statistics on this.
But most people who start out with "The C Programming Language" and never read "Design Patterns" will only ever use for loops and never think about iterators. How do you want to transmit certain concepts without giving them names?
I also had situations where "Design Patterns" helped me find a solution. Of course I also experienced the IT Manager who wanted to see Design Patterns everywhere, no matter if they were useful or not. But that is not the fault of the book.
What the Portland Pattern Repository has to offer here: http://c2.com/cgi-bin/wiki?IteratorPattern would probably suffice for all but beginning programmers. Much of the additional verbiage comes from their attempt to explain the relationships between the patterns they've identified (e.g. Iterator vs Visitor). Perhaps the book would probably be better if it did less of that, but I think that's more a matter of taste.
What about less code-specific books, like "Cathedral & the Bazaar"? I find my shelf ends up with a fair amount of these compared to code/code theory books.
I'm also reading "Programming Collective Intelligence" right now which is pretty awesome so far!
I actually like Code Complete, too. But my point is, I doubt anyone ever became a better hacker for reading it. Compare to the Dragon book, which, if you haven't read a book on compilers, is virtually guaranteed to make you better.
Structure and Interpretation of Computer Programs (SICP), Abelson & Sussman
The Little Schemer, Friedman
The C Programming Language (K&R), Kernighan & Ritchie
The Analysis of Algorithms, Purdom & Brown
The Elements of Statistical Learning, Hastie, Tibshirani, Friedman
Biological Sequence Analysis, Durbin et al.
Artificial Intelligence: A Modern Approach, Russell & Norvig
Introduction to the Theory of Computation, Sipser
Introduction to Linear Algebra, Strang
GEB is my 1/2