views:

486

answers:

10

I'm sure others agree, when code hits the pavement it is much easier to think of all the elements that will go into your application. Meaning, once you get going, you think of the what's next because you have reached a point where you have to design another table or class.

The drawbacks of this approach are obvious and we don't need to go into it.

The question is, for those of us who can't conceptualize the design without "seeing it", how do we go from design at the seat of our pants to a more structured methodology?

The only solution I can think of is detailed specifications, which forces one to think of exactly how things are going to work.

Is this just a case of how people think differently, or is there something else I am ignoring?

+12  A: 

Well, I don't know if this is quite what you are asking, but reading this question strongly reminded me of TDD (Test Driven Development).

The goal of TDD is to produce clean, testable code along with a suite of automated regression tests.

It is amazing to me how clean the code can end up when you just go at it with TDD... you think up problems, write tests for it, implement to make the tests pass, then refactor to ensure the code is clean and readable.

I don't think you really NEED a lot of up front design with TDD, but it may help... I'm kind of with you on "design by coding", but at the same time you can maybe catch major flaws ahead of time if you think about it in a bigger picture, even if minimally.

Mike Stone
I think you could say that most of the agile methods lean towards not doing heavy design. Not just TDD, though I am a fan of TDD.
Dan Blair
As a person learning how to develop software, I think TDD is great. I think you only need a vision of the end product when you apply TDD. You know your start point and end point and you fill in the blanks as you progress. A rough sketch helps get started, but then you just code what you need.
Ben Robbins
Yep, and it also helps you stay on track... I tend to not over engineer individual classes as much when I'm doing TDD (it helps me focus on just what I need rather than all the cool features I COULD add to the class that won't ever be used).
Mike Stone
+7  A: 

If you haven't looked at this book Refactoring by Martin Fowler you really should. The crime isn't so much the rapid prototyping/development it's knowing how to role that last little bit into something more maintainable in fairly short order. Yes you will discover new objects as you go, now spend a little time cleaning up and then push on. Often you end up with a better product than if you tried to design most of the solution before hand.

Dan Blair
+2  A: 

You're doing parts of Extreme Programming without even realizing it. From the wiki:

BigDesignUpFront is avoided because YouArentGonnaNeedIt. However, once the SimplestThing is done the programmers RefactorMercilessly, because in the end things should be expressed OnceAndOnlyOnce. Read more about SubsystemsInXp.

As it turns out, this type of programming isn't necessarily wrong. It's all about the approach you use and what you can do to better drive your own success.

Jim Puls
A: 

Test Driven Development (TDD) is a technique that immediately springs to mind to support your existing practice of "Design by Coding". Implemented properly this will allow you to refactor your code with confidence and that is essential if you are evolving your design incrementally.

Incidentally TDD works very well with a Scrum style approach to project management which is also usually light on documentation.

One of the Agile mantras is to release early and release often. It sounds like you are doing something similar already, you just need to put the structures in place so that you can respond to the changes in design without the fear of breaking your code.

Nathan Smith
A: 

You are pretty much doing it right by now because to follow a design spec that has been written from scratch is a minefield of trouble. You can design up front but you have to be prepared that you'll end up throwing away or redesigning most of the design as you code. In my opinion this is regardless if you're doing it TDD or not, you have to design by coding to verify the initial design.

Remember kids: to freeze a design spec before coding it is stupid.

I'm not saying you're not supposed to design up front as thinking ahead before you code helps out in some situations. You should be able to balance the coding vs. design quota yourself. Intuitively if you know a lot how the code should be then plan and then code. If you don't then hack on it and and then redesign (i.e. refactor).

Spoike
+1  A: 

I disagree with the notion that design while coding is wrong.

In fact, I'm a big proponent of the idea that coding is design. Programming is not a mechanical labor, but a creative one, where you need to be taking decisions between implementation alternatives all the time.

I'm not against specs or architectural design, but certainly the design work does not end when the architecture document is finished.

Sergio Acosta
+1  A: 

Just a few points.

In every generation ... you'll find people eager to adopt the latest metodology out there and use it. I'm an early tester, meaning I usually test every new thing that comes out but ...

About TDD, really, why the hell should I write a Test before even writing the code? The purpose of a test is ... well, to test something, you don't code a test for something that maybe doesn't need a coded test. Maybe if you do you'll run out of time (there are project schedules you know), maybe the test itself is so complex you'll need to verify it in order to prove it's correct. We work in order to live, not the opposite, and we code some test in order to test some pieces of code, not the opposite. Also, remember this is bussiness, there have to be a return rate,the profit of making something perfect but not getting paid is zero, no matter how good it is.

About designing by coding. Seriously, this works for every aspect in life, think before you do (and think before you speak). What's wrong with thinking in the design before doing it? Get a pen and a piece of paper and sketch your design, plan some classes, try to imagina WHAT it will do first, the PARTS of the system second, and HOW WILL THEY BE RELATED last. Then you can start thinking about how exactly is it gonna be implemented. What sense does it make to start coding without thinking about what you're doing?

If you can't think about the design over a piece of paper, if you can only think about the code you're gonna write then, sorry you are not the appropiate person to architect the system but don't start coding before having the design. Code is a living entity, and so is design, meaning they are suppose to evolve and adapt during the development process but they are not supposed to be taken lightly or be rushed into.

Edit: I know I'm hard on TDD, I'm sorry and I'm willing to listen to experiences but I'm still looking to find one use of TDD over a large project (let's say more than 7000 work hours) which has worked using TDD. I mean, real project with precise dates and money involved.

Jorge Córdoba
+1  A: 

Flexible BDUF (Big Design Upfront). Doing BDUF will help you catch any gotchas and things you'll need to be aware of, once you hit the code though you need to be flexible with your BDUF, some parts of it might be plain wrong.

Use both but keep applying common sense.

Quibblesome
+5  A: 

I agree with most of what people said here, but I think a more elaborate description is needed:

@public static: Your statement is spot on regarding the problems of designing up-ahead... Even if you're one of those amazingly smart people - the creme de la creme of geniuses - you can't design a whole system up front. You might think you can, but you're fooling yourself. The source of this problem is that, like they say, "God is in the details". The idea of nailing an appropriate design up front is pure hubris. But... That doesn't mean we shouldn't put anytime into designing up-front.

Lets see what's our purpose in "designing" a system is anyway:

First of all, we need a framework to think in. Have you ever tried to start a new project? The hardest part is writing the first line. Why? Because you have a writer's block - you have no idea where you're getting at. For example, lets say you want to write a computer game, lets call it "NotSoFarShout", which will be the next super-cool first-person-shooter that will conquer the world and make you rich for all eternity. Let's design by coding...

We'll start with our program's "main" function:

void main(){
   // Um, what the h*** should I put in "main"?!
}

So maybe designing by coding wasn't the right decision. Let's try a different way:

We are planning to write a first-person-shooter. What is a first person shooter anyway? OK, roughly speaking, it's a 3-D world where there's a player character, NPCs (Non-player-characters, like bad people, good people, monsters, gerbils etc), objects (trees, buildings, cars). The world is viewed from the player character's point of view. The player character can obtain all sorts of objects like weapons, ammo, health-packs etc. There are a gazillion other things that describe a first person shooter, but lets move on for a moment.

I know a first person shooter takes a long time to develop - definitely more than a week or two. How would I even begin? I start little, and incrementally write and design the system. So I choose a small, attainable, short-term goal that I can grasp conceptually and actually think on how I will implement - for example, I'll start with the visualization of a 3-D world. I know there are a few good 3-D engines out there, I'll do a little research, pick one, and make it show my world, which is currently made out of a single sphere floating in a void. This is something that shouldn't take more than a week or two.

OK, done. Didn't take me two weeks - it took me three instead, but now I have something to build on. Next thing I might decide I want to build a single scene - static for now, nothing moves, no AI, no special meaning objects, people etc. Now comes the design part... As I start to think about depicting a scene, different aspects of the 3-D world would come into my mind:

  • My scene depicts two people standing in the desert, one of them is completely sun-burnt, the other is wearing a suit and a hat and holding a gun in his hand.
  • Question 1: How do I describe the content of the scene? The 3-D engine needs a specific representation in order to render the scene. Is it intuitive and easy to work with? If I want to change the scene and move the gun to the other hand of the character, how hard is it? What if I want to move it to the other character? What if I want to add a third person - how hard is it? What if I want to add 100 people in random locations in the scene, each of them randomly possessing a gun and/or a hat?
  • Question 2: What if I want the skin color of the character to change over time? For example, one of the characters is sun-burnt. If the other one stays in this desert scene long enough, I want her to gradually get sun-burnt as well?
  • Question 3: The sun is shining in the scene, but I want that to change over time - let's say each minute is real time is equivalent to 1 hour in the game, so I want the sun to move over the sky and for the scene to gradually turn into night, with or without a moon. Maybe I want the moon to go through its phases as days and nights go by. How would I represent that?

The idea of this lengthy example is to outline these issues with design:

  1. There are multiple levels of design. At the beginning of writing a product/subsystem/very-large-module you can usually only perform very High-level design. That is, you can define basic large entities like in our example: 3-D engine, storage, Networking, etc. This is important so you can choose where you want to start, where you think the biggest risks will be and suchlike. Note that later on in the process, that initial high level design will not only be broken into smaller, finer details, but most chances are you'll find it has flaws and it will change to accommodate the needs of the product.

  2. Once you've chosen a manageable piece you want to work on, you might have to create a detailed design of that piece. This is where designing by coding usually comes into play. You know you want to render a 3-D world, but you have no idea of what it takes. So you write a prototype to render a single 3-D scene. Then you create a single static scene. Then you look at what you have and think - "OK, what next? What do I need to make this useful for a FPS game? I'll need to render a lot of different scenes. OK, it took a lot of "describe" the current scene in code, how could I make it easier to make variations on the current scene? To create a whole new scene? How would I store scene descriptions? Graphic files? Sound files?...". This is the manifestation of what someone here said before (quoting the XP way of programming) - you write what you have to instead of writing a generic and complex framework up front, but once you have to write the same code again with some variation (rendering a second scene, making variations on the current scene etc.), that's when you generalize and enhance the framework.

  3. Don't be afraid to write throw-away prototypes that will highlight the different aspects you need to consider in your design. That way you have a concrete implementation on which to base your thinking.

  4. Again, quoting some one here - don't freeze your design! It's just plain stupid - if you realize you made a mistake in your design, refactor to change it. Just make sure not to make the mistake of throwing away everything and starting from scratch. Making incremental changes through refactoring usually works much better.

Last but most important - I'm not presenting anything special or revolutionary here - all these ideas have been outlined by other people in the industry, much smarter and more experienced than me. I recommend you read a little about "Extreme programming", Scrum and other agile methodologies, as well as general books on the subject like "The pragmatic programmer", "Code Complete", "Refactoring", the "Gang Of Four" book (a.k.a. "Design Patterns: Elements of Reusable Object-Oriented Software")...

Hope all this text was helpful :)

Hershi
+1  A: 

I have had experience from both the standpoint of complete design up-front all the way down to design by coding. Here is my attempt to describe my personal view on the topic:

Requirements are the single most important and crucial part of development. In the business world, this document is what defines your deliverable, what you legally need to give the customer and get paid for. In the case of your own personal projects, this is where you take out a sheet of paper and write down the goal of your project and then figured out your requirements from that goal.

If you have good requirements and can avoid changing requirements on a whim, this is where you can turn to napkin based design. Think through what you want to code and draw it out on some paper, this helps you think through several possibilities and helps you write better code later because you have done some thinking already. If requirements change, try and work it into a new revision, if that makes sense.

Start writing code, writing tests and keep good comments in code. When you start on another module or section of your application, take a couple minutes to think through the overall design of that part, go back and forth between your napkin design and your code. Accept that you will have to change and modify anything you thought was perfect before you started on another part of the application and adopt an iterative approach to your development.

If it is one thing I have learned, any documentation of design is always out of date and you end up looking at the code anyway, keeping good comments is worth so much because of this. The only documents that I believe that are important to keep up-to-date and solid is the requirements and any API references (if you have them).

Redbeard 0x0A