"It Depends" vs. "Fact With Exceptions"
Posted August 18, 2008 at 1:27 PM by Ben Nadel
While learning object oriented programming, I've come up against the phrase, "It Depends" quite a bit. Actually, with almost every question, it seems that someone offers "It Depends" as the answer. For someone learning a completely new topic, answers like this can be very frustrating because it seems that not only do you need to find information, you also need to, simultaneously, develop some sort of litmus test to check for validity.
My question is, is "It Depends" really accurate? When you hear the phrase, It Depends, you might think, "Equal." You might think 50/50. You might think, it could go either way. You might think, "evenly distributed." You might think that several options are almost all relevant. But is that what is meant to be implied by such a response?
If I asked you, Is it OK to hit a woman? You could very well say, It depends. NO if under normal circumstances. But, YES if she's attacking you with a deadly weapon. So here, we have a scenario that could go either way, but for most people, it doesn't really "depend." So in reality, it's more like a "fact" that happens to have some exceptions.
Now, I'm not trying to say that the response, "It Depends" is not valid. Sometimes it most certainly is. I guess, I'm just wondering if it is sometimes used too often or offered as a default response.
While these mean essentially the same thing, their "intent" as a teaching explanation is quite different.
>> My question is, is "It Depends" really accurate?
Well, sometimes yes; othertimes no - it depends...
Ben - Well said. In my OO journey I have heard the same thing sooooo many times it gets frustration. Sometimes I begin to wonder if it matters whihc methodology you choose for a particular task. In some cases maybe it doesn't.
Lately I have been trying to ask the question differently. Instead of asking "How should I handle form validation...?", where I would likely get the answer "It Depends" from 9 out of 10 Developers, I try to ask "How do YOU handle form validation...?" and hopefully get something clearer.
I agree with your assessment of the phrase, "it depends". It's too generic, has the connotation you described as well as the connotation that the writer doesn't really know the likelihood that the result will occur or not. I little bit phrase would be "usually", or "in most cases, yes".
But even would be when there was some statistical data (not always feasible, of course) to back up a claim - something like, "80% of the time X happens, 19% Y happens, and 1% Z happens".
PS - to play devil's advocate to your not-meant-to-be-entirely-accurate analogue: keep in mind that some Buddhists, as well as probably in a few other belief systems, it is never "okay" to be violent towards any other sentient being for any reason (even to protect one's own life). So, "it depends" on which belief system one aligns oneself with, and whether one will truly act according to those beliefs when confronted with the reality of the moment. (sorry, I have no stats at the moment to back up these statements). Peace. :-)
As someone who has become somewhat infamous for saying "It Depends", let me jump in and defend that annoying habit... :)
So, yes, part of the problem is what Jason hints at - asking a generic question. If you just ask "How should I do X?" with no background information, you're going to get an unhelpful generic answer.
Part of the problem is that with OO there is no "One True Way" and in my experience when trying to teach OO, a lot of people have a tendency to latch onto one way to do something without really understanding it and then they run into problems and have no idea why (when they should be using a different approach). This is especially true of people coming from a procedural background because in OO they no longer have their regular frame of reference for solving a given problem.
If you think about how you write procedural code, you make design decisions and trade offs all the time, based on your experience. Once you get really comfortable with OO, you'll find yourself doing the same thing. A lot of people who are prone to saying "It Depends" have been badly bitten by offering some off-the-cuff advice and then getting nailed because that advice doesn't apply to the situation (which the questioner failed to describe properly).
The bottom line is that OO design is much more fluid than procedural design because the trade offs can be much larger between different approaches. A bad OO design can really hurt you. Sometimes, you can't get to a good OO design without a lot of experience (i.e., making mistakes and learning from them) and it's not always easy to explain enough of the trade offs to help a novice in a way that doesn't completely overwhelm them :(
That's partly why OO can seem so hard to learn - there are a lot of gray areas.
To be fair (to me), when I say "It Depends", I usually follow up by asking a bunch of questions about the problem space and offering multiple solutions with some explanation of the trade offs. I want people to realize that there *are* multiple solutions to most problems and that there *are* trade offs - pros *and* cons - to every solution.
If you look at Design Patterns, one of the most important aspects - and the one most commonly glossed over in almost every design patterns talk I've seen given by CFers - is that each pattern has trade offs and that the pattern description itself explains when a pattern is applicable and what the pros and cons are for given situations.
Sometimes (like with your form validation problem) I say It Depends because there are good reasons for doing it in several ways, but the one I would go with depends on all the elements in the equasion.
For example, in your dilemma about putting save on the 'smart bean' vs the service, I might be perfectly happy with it on the object, unless I had to deal with saving the object in several states, each in turn with differing cascading objects. This happens a lot and is better put somewhere else.
You could put the save in the object and delegate to the service. Thereby putting the transaction logic and the cascading stuff into the service. This would make DI easier since we all know that ColdSpring isn't too excited about gen'ing instance objects.... but then again, you aren't using ColdSpring and don't have to worry about that. You also don't have to worry too much about cascading objects in this case either.
Blah blah blah...
There are many right answers, each with their own sets of tradeoffs. Each of which has numerous refactors. You seem to be learning much more by thinking this out than by having people tell you what the right answer is...
To be clear here, Object Oriented Programming and Design Patterns are two distinct things, even though DP is a "subset" of OOP. You can write OOP without following any Design Patterns. It's probably best to think of OOP as writing well structured sentences and paragraphs and Design Patterns are a specialized style of writing like poetry, screenplays, song writing, etc. Another analogy is the basics of writing and reading sheet music vs knowing jazz scales, classical scales, diatonic, pentatonic, etc.
There is no "it depends" when it comes to OOP. OOP is a foundation and the rules of OOP are clear and defined. Without that foundation, though, you can't successfully engage in specialized styles.
"It depends" relates to Design Patterns. The way most people learn Design Patterns is they learn one and then try to apply it to everything. By doing this, they learn the limits of that pattern first hand and then are driven to look into other patterns. It's pretty much universal that the first few patterns you learn you will use in that way. It isn't until you get a few under your belt that you start to understand a pattern upon reading its description, and differentiate between when a pattern is appropriate.
In other words, "It depends" is the only applicable terminology, and if you don't understand why "it depends", then you need more experience and the only way to get that experience is to walk the path.
I personally think the two most important patterns to learn first are Observer (Event/Listener), followed by MVC (I think the book "Agile Web Development with Ruby on Rails" is the best way to learn proper MVC concepts, even though it isn't Flash, it's leaps and bounds above any Actionscript-specific MVC texts or lessons I've ever read). If you can throw DRY in the process (an important auxiliary style that applies to OOP in general), all the better.
Once you have Observer and MVC down, you've got a solid foundation to move on to Factory, Singleton, Composition, and Strategy, in that order. Once you get those six patterns down, you will understand why "it depends" in any new pattern you learn.
On the other side of the coin, I find myself often looking at a situation where I've been working on some piece of code that deviates from what I've suggested as a good general practice and wondering "when am I going to have to defend this code because somebody thinks I'm being hipocritical here?" ...
The reality is of course that no matter how emphatically you state that X is either good or bad general practice, there are always exceptional cases like the woman who's attacking you with a deadly weapon. But when I'm writing articles where I'm commenting about things like for example why the semantics of Spry actually create more work (rather than making things easier like they're supposed to), I generally don't offer "it depends" as a justification for the way those things are written, I just say "x ain't good form if you want to accomplish y". Where y is usually productivity and x is usually the way most software is written.
Yes I believe most software practices -- the ones that are most widely used anyway -- are counterproductive. :) The day that I walk onto a new job or contract and am given a task and am able to achieve results in the hour that it takes me to do things my way, vs. the 5 hrs it takes to do the same thing someone else's way and the resultant code is both equally flexible (right now it's less flexible, i.e. Spry + lack of ORM) and no less error prone, then I'll be a convert.
I should probably have tried harder not to sound so conceited... :)
hey ben... sounds like you came to the same conclusion/observation that i did when doing the OO thing... being "right" is subjective :)
as sean points out above, one of the most frustrating things (that i've found, at least) in moving from procedural to OO is that we're looking for that recipe... that one "right" way to do it. we want to hear "if this, then do that.. else, do this". but that doesn't exist.
while it can be frustrating to hear that there is no "right" way, it can be awfully empowering to think of it as there is no "wrong" way. at the end of the day... does the code run? congrats. you've done it. it's "right" :)
now, that isn't to say there is not a "better" way and a "not so good" way... but it's subjective. it'll never be as clear-cut black-and-white as right or wrong.
look at the debates that rage on various mailing lists and forums. among people that i look up to as being experts in all things OO (sean c, joe rinehart, brian kotek, peter bell, etc), debates that border on all out holy-war still go on. is it because one knows what's "right" and the others are wrong? no. it's because they're all right. their ways work for them. different means to a similar end. is one method "better" than the other? depends who you ask :)
i still struggle to a degree with accepting that there's no strict formula to which i can adhere and start writing "good" OO code. i've accepted the fact that i'm going to write what seems to work for me. in a month or three, or maybe even a year i'll probably look back on it and go, "charlie wtf were you thinking?". but you know what? i do that today with my procedural code :)
focus on understanding things from a conceptual level, rather than the concrete implementation. i don't know that there's a specific "a-ha" moment when the light bulb turns on... for me, it's been kind of a dimmer switch. it's still sorta dark, but i can see that it's getting brighter little by little.
the whole OO thing really is a journey. it's not about crossing a finish line. it's about staying on the track.
Any askable question depends on some other piece of information to some degree. So it is very rarely worth saying. If follow-up questions need to be asked, just ask them.
A lot of the permutations can be ruled out from observing the question and some knowledge about the asker. If an OO newbie asks an unsophisticated question, it is very unlikely that they are concerned with the ramifications that your solution will have to sticky sessions in a cloud environment, for example.
It is only worthwhile to say so when then options are truly equal, given all that you know about the asker, the question and basic follow-up questions. Otherwise, to me at least, it is typical condescending IT snobbery to start every answer with "it depends".
q: "Should I separate my SQL into a DAO?".
a: "Well it depends, is there someone pointing a gun at you and threatening to shoot if you use DAOs?"
a: "Well then it depends, are you looking to die or live?"
a: "Well then it depends, do you want to hear a loud noise right before you die?"
The problem here is that people really, really want a hard-and-fast recipe for how to solve OO problems. And there isn't one.
Well, there is, actually, but it is so general as to be nearly useless to newcomers. The rules "favor composition over inheritance", "design to interfaces not to implementation", "encapsulate by convention reveal by need", "tell don't ask", etc. are what end up dictating virtually every solution. But that doesn't really help because the rules apply at such a high level.
As Sean mentioned, software problems are rarely black and white. The best solution in one context may very well not be the best solution in another. So much depends on what the person actually needs to do, the constraints, and the knowledge of the person solving the problem, that to offer a blanket solution often will make things worse.
Look at what happened way back when Sean put out his Coding Guidelines. He showed off the use of the Memento, DAO, and Gateway patterns. And what happened? Everyone who read it ran off and added Memento, DAO and Gateway objects all over their applications, with no actual understanding of what factors went into their use. I know this, because I did it myself! It is reasons like this that people are leery of trying to provide sweeping answers to questions, because the answer truly is, it depends...on a wide range of things.
The core issue here is that really internalizing the theory behind OOP and the elements that go into making design decisions cannot be supplied by cookie-cutter answers. Believe me, I wish it could be, it would have saved me years of effort and pain. ;-)
All one can do is try to grok the fundamental rules, and try things out. Ask for advice where you can, but know that the advice you get is provided with a very generalized idea of what problem you might be solving. The process never stops, no matter how far along you think you are. I can look at code I wrote last MONTH and something will jump out that makes me go "why the hell did I do that when THIS would have been sooo much easier?".
Anyway, this may not be a great answer to your question because it isn't much of an answer at all. But hopefully it helps a bit anyway. :-)
Sorry for posting this and then to responding to any of it - work got busy this afternoon and I didn't have time to jump in.
Obviously, this post stems from my frustration (but very fun) journey of learning object oriented programming in ColdFusion. However, there is nothing OOP-specific about the post, per say. I was merely trying to question whether "It Depends" was given too freely.
I guess my frustration with "It Depends" simply highlights my extreme newness to OOP. This is especially frustrating when compared to procedural code. In procedural code, you could also say that "It Depends" on so many things.... however, when someone asks me "How Do I Do XYZ", I rarely ever say, "It depends" - I say, "Oh, just do ABC."
Now, they might come back and say, that makes no sense and after explaining themselves more, I might come back with a different solution more catered to their needs.
But, what I find is that I have default solutions for many things that I consider the "right" way to do something. I have developed these defaults because of years of repetition and slowly figuring out which solutions work the best for which problems. I suppose that this is possible do to the more finite nature of procedural code?
So, the frustration comes when, to me, so much seems defaulted in procedural code and yet so much seems totally up in the air when it comes to OOP.
Again, this is just to show my newness and ignorance; but, if I had to guess, I would assume that eventually, I will find a style that becomes "Default". I always do XYZ with business objects, or I always do ABC with service objects, or I always do my database table interaction with DAOs or Gateways, etc.... except when it is not convenient. But just because some cases are not convenient, I still have to assume that in most cases, I will opt for a methodology of choice.
Maybe I am way off here. Maybe after years of attacking this problem space, I will truly find no "Default" methodology for solving problems. Maybe after years of OOP-based research and projects, I will still find that there is no common theme to my solutions.
I guess what I am slowly trying to come to grips with is that "It Depends" is frustrating to me because my world is so small and I am trying to make it much bigger. In a small world, repetition exists and is easy to spot. In a big world, repetition is rarer (perhaps) and much harder to qualify.
It is a most excellent journey that I am having and I think you all so much for all of the wonderful feedback. I hope that some day, I can also say, "It depends" :D
It is a good answer. I am beginning to get it.... slowly.
I think what I have to realize also is that I have like 8 years of procedural experience... and only like a month of quasi-OOP learning. Clearly, a huge discrepancy. So, as much as patterns clearly emerged in my procedural code in such time, it is silly perhaps to expect patterns to emerge in just a month of completely new theory :)
Give me 8 years of OOP experience and maybe, just maybe, I can start to answer in more black and white terms what I am asking ;) Or maybe in 8 years, I will finally accept that that simply isn't possible.