views:

87

answers:

3

Was: Design by contract: predict methods needed, discipline yourself and deal with code that comes to mind

I like the idea of designing by contract a lot (at least, as far as I understand the principal). I believe it means you define intefaces first before you start implementing actual code, right?

However, from my limited experience (3 OOP years now) I usually can't resist the urge to start coding pretty early, for several reasons:

  1. because my limited experience has shown me I am unable to predict what methods I will be needing in the interface, so I might as well start coding right away.
  2. or because I am simply too impatient to write out the whole interfaces first.
  3. or when I do try it, I still wind up implementing bits of code already, because I fear I might forget this or that imporant bit of code, that springs to mind when I am designing the interfaces.

As you see, especially with the last two points, this leads to a very disorderly way of doing things. Tasks get mixed up. I should draw a clear line between designing interfaces and actual coding.

If you, unlike me, are a good/disciplined planner, as intended above, how do you:

  1. ...know the majority of methods you will be needing up front so well? Especially if it's components that implement stuff you are not familiar with yet.
  2. ...resist the urge to start coding right away?
  3. ...deal with code that comes to mind when you are designing the interfaces?

UPDATE:
Thank you for the answers so far. Valuable insights! And... I stand corrected; it seems I misinterpreted the idea of Design By Contract. For clarity, what I actually meant was: "coming up with interface methods before implementing the actual components".

An additional thing that came up in my mind is related to point 1):

  1. b) How do you know the majority of components you will be needing. How do you flesh out these things before you start actually coding?

For arguments sake, let's say I'm a novice with the MVC pattern, and I wanted to implement such a component/architecture. A naive approach would be to think of:

  • a front controller
  • some abstract action controller
  • some abstract view

... and be done with it, so to speak.

But, being more familiar with the MVC pattern, I know now that it makes sense to also have:

  • a request object
  • a router
  • a dispatcher
  • a response object
  • view helpers
  • etc..
  • etc..

If you map this idea to some completely new component you want to develop, with which you have no experience yet; how do you come up with these sort of additional components without actually coding the thing, and stuble upon the ideas that way? How would you know up front how fine grained some components should be? Is this a matter of disciplining yourself to think it out thoroughly? Or is it a matter of being good at thinking in abstractions?

+1  A: 

Hmmm...my idea of Design By Contract doesn't mesh well with yours. DbC is more about defining the "other" aspects of interaction beyond method signatures (which is all that most programming languages enforce). So, you define things like "invariants" (things that are always true, such as Stack.Count >= 0) or "pre-conditions" (things that must be true to execute a piece of code, such as Stack.Pop requires Stack.Count > 0), etc.

That being said - I'd advise you to look into Test (or Behavior) Driven Design (TDD or BDD). It suggests writing unit tests not only to test your code, but to drive your design. As such, it addresses your 3 points:

know the majority of methods you will be needing up front so well?

No need to. You don't write a method until you have a test (client code) that requires it.

keep yourself from resisting the urge to start coding right away?

No need to. Just start coding the specifications (as unit tests) instead of the actual code. Then fill out the actual code to fulfill the specs.

deal with code that comes to mind when you are designing the interfaces?

Write a unit test that shows the missing functionality. You can either make it pass now, or leave the actual code for later - the failing unit test will force you to write the code at some point.

I'm not an expert on TDD, nor do I even consider myself a practitioner. There are a lot of worthwhile ideas in it, however. You should research it, try it, and see if it helps you organize yourself.

Mark Brackett
+2  A: 

Design by Contract != Interface based design

There are differences although I will grant that the use of interfaces is commonly called a contract (of sorts) in software. That being said I think I understand where you are going with the question and have some thoughts on this. I'm about 2 weeks into a new project that I am designing and I have had some of these same thoughts recently with regard to interfaces.

unable to predict what methods I will be needing 

Accept the fact that you will (or almost) never get the interface completely right the first time. To be honest trying to design an interface to account for all cases without exercising it will probably fail. Instead define your interfaces to have a very specific purpose and only initially provide the most basic of methods necessary to meet that purpose. As an example you might have an interface define the object and another that defines a simple set of crude operations on the object. As the project matures you may add additional methods as they are identified to facilitate get/search operations. Keep in mind as the design is refined then you can add to the interface; this is (generally) fine for development purposes since an interface typically isn't versioned until it's in production.

urge to start coding right away

You will probably be well served by implementing a little bit of code and unit tests to exercise it. This will help identify weaknesses in your overall approach. The trick to this is to only do enough to identify issues without making a gold plated shit house (sorry if that offended anyone, but it's a common phrase). I would recommend thinking of this as prototyping code THAT SHOULD NOT BE USED FOR PRODUCTION without a lot of thought.

deal with code that comes to mind when you are designing the interfaces

Honestly this depends on the situation. A snippet file somewhere may work for this. Generally I'll just use a post-it note to capture the thought or idea versus any specific code since I haven't written anything (noteworthy) to this point. Occasionally I will go ahead and start a implementation of the class that I intend to use for production.

Updated response: I don't think there is any one answer to this question. Honestly I think it comes down to experience as a software developer/engineer and knowing what you are ultimately trying to do/solve. For instance I certainly would not expect someone fresh from college with no practical experience to design an application from scratch without some significant design help. Mostly I think that if you don't understand the problem you are trying to solve then you most likely will spin your wheels trying to design the wrong solution.

My gut feeling is that the less you understand the technology being used and/or the problem to be solved the more readily you should accept that your refactor(s) will be more significant. I honestly also think that if you feel you can design an entire application without ever refactoring anything then you should probably not be the one designing the application. How significant the refactor is though is the question.

confusedGeek
I have used post-its in the past for the exact same reason, but I ended up with a pretty big stack of them after a while which flew everywhere because half didn't stick anymore. Enter the notepad...
NomeN
agreed it does have it's limits, if it's going to be around more than a few days I usually track it else where (at the office we use TFS so often I will stick it in there).
confusedGeek
+2  A: 

Mark Brackett makes an excellent point on TDD.

However, what I find when doing this is that I have an even harder time coming up with the unit tests I should implement. This is probably mainly due to the same problem of inexperience you are struggling with. So this is how I deal with it:

  1. Start out strictly on paper (I do not even turn on the computer at this point). Sketch the classes/modules I think I'll need and think about how they interact this gives me the classes and methods I need to implement. If I'm not familiar with certain things, I'll notice it at this point and can investigate to find out.

  2. After a while of sketching, I'll either have a good idea of what I need to do or am utterly stuck without trying some bits and bobs out. This is when I start to code. After a while I'll probably find out that I need to change some things in my design. This is not a problem, I have the power of refactoring!

  3. During sketching (or while writing totally unrelated pieces of code) I also come up with code solutions to things that are nagging me. If I already have the file where the code goes I'll write it quickly in some pseudocode in a comment and a TODO tag and make a note of it on my notepad. If it's more complex or it doesn't have a place to go yet, I'll just jot the whole pseudocode on my notepad. At that point I can let go of the idea and go on with what I was doing. The point being that I have a paper notepad on which I keep track of everything I need to do and what I have done (I cross of the ideas I implemented). (Typing and indenting code is just to annoying for quick ideas on the computer)

NomeN