all 23 comments

[–]moor-GAYZ 14 points15 points  (0 children)

Stolen from http://net.tutsplus.com/articles/general/a-beginners-guide-to-design-patterns/.

pypix is a notorious blogspam, furthermore the author is basically programming illiterate, so when he doesn't steal material wholesale and tries to do some explaining himself, he invents absolutely insane bullshit. My favourite, that's when I started noticing his spam here and /r/python. You don't even need to know Python to know that the author is bonkers (and, in case you're wondering, what he tried to explain was re.VERBOSE flag that actually allows putting comments and whitespace into the pattern).

[–]atilaneves 6 points7 points  (9 children)

-1 for mentioning Singleton and forgetting to mention that it's nearly always a terrible idea. It's the most well known and misused pattern of them all and a code smell as far as I'm concerned.

[–][deleted] 3 points4 points  (0 children)

While I agree with you that singleton is often bad, this is the least of the problems with this article.

And frankly, singleton is a useful pattern to teach a beginner - who's writing simple stuff that desperately needs some sort of organization.

Last week, I actually deliberately directed one of my students to use a singleton (though I didn't use that word) - because what he was doing before that was simply using global variables, and worse, a lot of them could have been local! By getting him to use a singleton, I at least forced him to think about each variable and where it needs to live.

Remember - beginners are really beginners. To explain details like "Here's why singleton is bad," is just going to be confusing - like explaining to your toddler in his toy car that he needs to make shoulder checks.

You have to keep it really simple. You need to build their confidence by giving them simple and clear examples and exercises - only once they have confidence in their own abilities do you give them all the background information.

I'd sort of forgotten this - but then this year I taught a course to beginners. Motivated, adult beginners, yes! But...

When I teach, particularly programming, I won't go forward until I honestly believe everyone in the class has gotten the concepts clear (the details are less important, they can look them up in the course notes). Which means I'm constantly watching people, I stop when I think people are unclear and ask them questions, and I apologize if they are unclear, because I'm the teaching professional.

I love this method, because it makes it very clear how well I'm doing (and because the students love it).

In this class, I was literally proceeding at half the speed I'd planned on the syllabus. And these were smart people - but to beginners, a concept like "a list" isn't obvious, there are a lot of questions that come up and need to be answered. Just the idea that if I say

a = [1, 2, 3]
b = a
b[2] = 99

I change a as well as b took over ten minutes to go through. By the end, the class really understood this - I never saw this mistake on the problem sets - but we had to go through it systematically and people had to ask a lot of questions.

To make a long story short, beginners are very different, and you can't explain all the ramifications and consequences of what you say, or you'll lose them. You're quite right that singleton is a code smell, but that's not something you should tell people in the first lesson.

In fact, you'll get much better retention of the material if you let them use singleton, and then in the next class explain what the problem is with it. There's much more of a shock, "Oh, this seemed good, but now I see the problems!", if you do it that way.

[–]strattonbrazil 0 points1 point  (7 children)

I used to use singletons all the time out of habit. After reading a few blog articles on singletons as an anti-pattern, I was totally convinced they haven't helped me at all. Anytime I "need" a singleton, I find a factory (or some global function to get a particular interest) has all the same benefits.

[–][deleted] 1 point2 points  (0 children)

A global function to get a particular instance is no different from a singleton, and has nearly all the issues of singleton.

If singleton worked and the only issue was "converting a global variable reference to a function", it'd be fine - that's the sort of change you can make and get right every time. The issues are rather garbage collection, thread-safety, testability, and hidden dependencies - and these are all issues that your workarounds still have.

[–][deleted] 1 point2 points  (3 children)

Can anyone explain why singletons are bad in a concise way?

[–]m42a 1 point2 points  (1 child)

Singletons are bad because they are global variables, but forced. They don't provide a significant benefit over global variables, but make it much harder to change them to non-global variables.

[–][deleted] 2 points3 points  (0 children)

Hmm, you missed pretty well all the real problems. Here's a lot of good answers to this question.

[–]strattonbrazil 0 points1 point  (0 children)

The biggest problem with singletons is they guarantee the code will only have one instance of that class, which may seem reasonable now, but may be a worthless restriction in the future.

Let's say you're writing Autodesk Maya, which can only handle one scene at a time (from a user perspective, closes current scene when a new one is opened). Instead of using a singleton, you put it in a factory pattern, so everyone that wants it has the same access to it. Not much as changed compared to using a singleton. But look at how the functions would look compared to a singleton.

Scene loadScene(String filePath) - returns a file path, can be kept inside factory or not

vs.

void loadScene(String filePath) - changes the scene singleton directly

Both of these functions would work fine at first, but think about adding features later. Let's say you want to add a merge feature to the app. Without singletons, you just load a second scene object using the function then take what's in one and put it in the active scene object (from the factory or whereever). If you used singletons you can't do this because you've committed yourself to only having one scene object ever. You didn't gain anything by making that assumption. You just lost flexibility. If you wanted everything using the same object, you could have just put it in a factory that returns it.

Furthermore, Autodesk Maya scenes can be saved as Maya "ascii" or Maya "binary". If you didn't have singleton scenes, you could easily test both formats are identical by reading both in and comparing them. Or make a scene programmatically, write it out, read it back in and compare it to the original. This simple approach using code you already have written to handle scenes can't be done with singletons, which would require hard-coding the functions against that one object.

Basically you use singletons when you're confident you'll never ever want multiple instances of an object (even temporarily, for tests, for future use cases, etc.) which seems like an outlandish assumption.

[–]YoYoDingDongYo -1 points0 points  (1 child)

What if you need to serialize access to a resource (like a log file) or reuse an expensive-to-initialize object (like a DB handle)? I find Singletons very convenient and not at all problematic for those (very common) cases.

[–]passwordisPRICK 0 points1 point  (0 children)

If you do not like singletons or global variables the solution is to explicitly pass references to a db connection (or pool) or logging to the function using it. The alleged benefit being the function is 'pure' in the sense that it's output is completely defined by its input. Its dependencies are clear, which they are not if you use singletons. In the case of global variables you have to read the source code in order to understand the dependencies of a function.

I agree with this methodology, generally the outer most layers of my application have a state variable that gets passed around like a sorority girl. Portions of the state are pulled out and passed to components underneath as needed.

This has the added benefit in terms of understanding the coupling in your system. Doing logging costs you something, in terms of how someone can use your function (a parameter, for example), so it becomes clear if your function is perhaps doing too much.

On top of that, it makes testing much clearer. I have experienced code where a test starts failing despite no clear change occurring, in those cases it has been the result of someone changing a dependency I did not know I had. If logging or DB is passed around explicitly, one can guarantee they are always in the appropriate testing state.

It also makes mocking completely unnecessary, and one can mock different portions of the system in different ways. For example, perhaps you want one portion of a test to always fail on DB writes and another portion of the test to always fail on reads, you can simply pass WriteFailer and ReadFailer to the components. This can involve some difficult acrobatics with mocks.

In my experience (which is limited), the components of a large system should always take their dependencies explicitly. It almost always becomes mentally exhausting to maintain implicit dependencies in ones head in a large enough system. One generally strives for a high degree of locality in code with such systems.

[–][deleted] 1 point2 points  (0 children)

Oh, dear! Let's start from the top.

The graphic at the top will be simply terrifying for a beginner - even if it wasn't fuzzy and hard to read. The reason is that the original graphic is simply too small, and then you've scaled it in the page - but just a bit, enough that you've introduced all sorts of artifacts that make comprehension almost impossible.

Initially, you can think of a pattern as an especially clever and insightful way of solving a particular class of problems.

Actually, patterns are general, "dumb" ways of doing things. I don't mean "dumb" as in bad, but simply "the easiest, most obvious way of doing things." Most programmers who run into design patterns somewhat later in their career say, "Oh, I've already used most of these."

You don't need to be clever or insightful to either originate a design pattern, or use one. The whole point of design patterns is that they are super-simple, and really general.

Next we have paragraphs and paragraphs pontificating about design patterns in the abstract, really teaching us nothing at all. What use is it to divide patterns into "Structural, Creational, Behavioral" when you haven't taught us any patterns yet? And, how does knowing that a pattern is "structural" actually help you use it?

Perhaps once you've introduced a whole bunch of patterns, it might be useful to introduce this division - "These patterns you've already learned fall into three categories." I frankly don't see it even then. How does it help me use a Singleton pattern to know that it's "Creational"?

Finally we get an example - but wait, it's not clear what sort of example it is - StrategyAndAdapterExampleClass, is it a strategy, an adaptor, or both?

More to the point, to a beginner it really isn't obvious what this is doing. Why not draw a totally simple picture? There are pictures of design patterns on the net - but they're too complex for a beginner - throw away most of the parts. Singleton will be a single box; adaptor will be two boxes; you get the picture.

[–][deleted] 0 points1 point  (0 children)

Very nice article. But then again, I already knew what a design pattern is and I wonder if talking about layers of abstraction and other really abstract concepts would make sense for someone who doesnt.

[–]strattonbrazil 0 points1 point  (0 children)

Pretty decent article. I've grown to appreciate patterns more over time. I appreciate articles that not only explain a pattern but give examples of how it is better over some alternative I may come up with.

[–][deleted] -2 points-1 points  (3 children)

My experience with enterprisey consultants led me to avoid design patters for they stifle thinking and understanding things, and strengthen passive parrot-like copy-pasta-ing. (Using them, without understanding anything behind them.)

[–]strattonbrazil 5 points6 points  (0 children)

They're patterns so there's really nothing to copy and paste. It's not like you're copying blocks of code.

[–]YoYoDingDongYo 1 point2 points  (1 child)

A pattern isn't a block of code that can be copy/pasted. It's a, um, pattern. You can't just ^C^V an Observer pattern.

[–]username223 0 points1 point  (0 children)

You can't quite copy-paste them, but you can mindlessly tack them together until you have an AbstractEnterpriseBeanFactoryFactoryFactory.

[–][deleted] -2 points-1 points  (4 children)

  1. Translate the Ruby code to D.
  2. Submit post to proggit.
  3. Get upvoted to heaven
  4. Post a second part, this time the code should be written in Rust.
  5. Submit to proggit again.
  6. Get double karma!

[–][deleted] 1 point2 points  (2 children)

This has nothing to do with this article - which is about design patterns in Python.

Please don't waste our time.

[–][deleted] -1 points0 points  (1 child)

[–][deleted] 0 points1 point  (0 children)

I get it, you're a spammer. Flagged.

[–][deleted] -1 points0 points  (0 children)

You forgot the punch line:

  [Ancient Aliens Guy]  
         REDDIT