37
votes

When building a non-trivial application, is it best to focus on getting things working quickly, and taking shortcuts in the code like mixing model logic with your views, breaking encapsulation - typical code smells? Or, are you better off taking the time upfront to build more architecture, build it right, but running the risk that all this extra code might not be used since your design is quite fluid and you might have to throw it away if feedback causes you to go in a different direction?

For context, I'm building a desktop application. I'm the only developer, and I'm doing this part-time since I have a day job. Now, for work, I try to do things the right way, schedule permitting. But for this project, which I expect will morph as I get feedback from people, I'm not sure that's the right approach. I spent several hours this week putting in a textbook Model View Controller design in place to communicate changes in the model to the view. This is great in general, but I'm not sure if I need multiple views to display the data and I know that I could have had things displayed more quickly without the additional architecture. With maybe 10-15 hours a week to spend on the project, I feel it will take ages to get something built that I can demo if I follow good software practices. I know that my users won't care that I used MVC internally, they just want something that solve their problem. But I've also been in the situation where you've incurred so much technical debt from short cuts that the code is just incredibly difficult to maintain and add new features to. I'd love to hear how other people approach this kind of problem.

11
  • 10
    "There's never time to do it right, but there's always time to do it over." Jan 21, 2011 at 16:52
  • 1
    You know how financial advisors say just don't go into debt? Don't go into technical debt either :)
    – Nicole
    Jan 21, 2011 at 18:02
  • 3
    obligatory xkcd reference: xkcd.com/844
    – user281377
    Jan 22, 2011 at 9:50
  • @ammoQ beat me to it.
    – user7043
    Jan 22, 2011 at 15:35
  • 1
    Steven: In my experience, that assumption holds while the future requirements fall into the expected (and conceptionally prepared) range; but sometimes, a new requirement needs some "spooky interaction over a distance" that is even harder to implement in a proper design, because all those neatly separated classes, layers etc. suddenly need to communicate in a way the design wasn't prepared for.
    – user281377
    Jun 8, 2011 at 11:22

17 Answers 17

48
votes

Build it well.

Building it "fast" is a logical fallacy if you look at the big picture. It will prevent you from ever having it built well, and eventually you will become bogged down by bugs and fundamental architecture flaws that prevent refactoring or even makes adding new features next to impossible.

Building it well is actually the opposite. At first it may be slower, but eventually you will realize the efficiency gains from having taken the time to make the right choices up front. In addition, you will be able to adapt to future requirements easier (refactoring if needed) and you will have a better end-product due, at the very least, to fewer bugs.

In other words (unless this is a one-and-done contract), built it fast = build it slow, build it well = build it fast.


Also there is something important to realize about "building it well" and designing an architecture. You asked...

...but running the risk that all this extra code might not be used since your design is quite fluid and you might have to throw it away if feedback causes you to go in a different direction?

That is not really a true risk from "spending architecture time". Architecture design should be organic. Don't spend time designing an architecture for any part until it's justified. Architecture should only evolve out of observed and confirmed patterns in your project.

John Gall's law from Systemantics:

A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over, beginning with a working simple system.

9
  • 9
    I can't upvote enough. Another good quote is from Uncle Bob "The only way to go fast is to go well"
    – CaffGeek
    Jan 21, 2011 at 20:18
  • 1
    +1 because once you've done it well, you can reuse that code and approach again in the next project and it'll be even faster. Rinse and repeat until it's second nature.
    – Gary
    Jan 21, 2011 at 20:18
  • 4
    In honor of my dad, "If you half-ass it the first time, then you will have double the amount of work when you go back to fix it."
    – Mr. Ant
    Jan 21, 2011 at 22:15
  • Heh... the formula made me think: build it well = build it fast = build it slow. I guess the last "build it fast" should be build for less which is in terms of technical debt. Since less work is needed to build on a well made system.
    – Spoike
    Jan 22, 2011 at 16:58
  • @Spoike I agree but also, the idea is "build it well = build it fast later ". So many managers don't want to give up the speed for a few months that will actually increase speed later.
    – Nicole
    Jan 22, 2011 at 17:00
17
votes

Fast, then well

This is from my personal experience having tried lots of different methods.

The problem with only working fast (and releasing) is generally that you'll tack feature after feature onto your application and since it's released it's very hard to do fundamental changes to your program. You pay a steep price in the long run for nothing having a sound underlying architecture, it's like building a ramshackle on quicksand.

The program with doing it well is that you're going to waste a lot of time and code. It's like building an mansion without any blueprints. Writing applications is a learning process and almost (in my experience) impossible to design up front. That means you'll do a lot of refactoring, and if you write everything "well" all the time, you'll end up throwing away lots of code.

Thefore, fast , then well!

The main thing when you get started is just to get everything down in code so can nail all the features and see what kind of architecture you need to support. Another good thing about this methology is that i'll keep you motivated since you'll quickly have something running. It's also important to implement some "edge-case" functionality since that'll have impact on your general architecture. Don't bother writing unit-tests or working on details at this stage. If you think you'll need to support multilanguage in the future, a plugin architecture of whatnot, implement it, but quick and dirty. Do some refactoring to keep the application manageable but nothing excessive.

After you've feel you have a working "prototype" it's time to start refactoring. Basically you want to redo the application as you'd do it if you started from scratch knowing everything you now know. The important thing is to get the architecture right, not to reimplement all the features you did in phase one, but you should have the architecture in place to support it later on.

This way you'll end up with an application with a sound architecture as efficiently as possible, in my experience anyways :)

3
10
votes

Build it

Fast if time to market is more important than quality

Well if quality is more important than time to market

8
votes

Building it fast will yield you short-term benefits and long-term losses.

Building it well will incur short-time losses but long-term benefits.

Building it well asks for patience and wisdom but you will be rewarded.

Building it fast is only good for quick prototyping and throw-away things. Long-term goals can only be achieved with the right attitude from the start.

5
votes

For projects that you plan to distribute for others to use I would always error on the side of up front work. A well thought out architecture is easier to extend if needed. Taking short cuts is just the model for accumulating technical debt.

It can be frustratingly slow at times. Things worth doing are worth doing right.

1
  • 1
    Just to qualify the "well thought out" statement: it doesn't mean thinking about everything up-front (this cannot be done), but simply taking some time to think how integrating a feature rather than tossing it somewhere and be done with it. Jan 21, 2011 at 19:19
5
votes

Building it well = building it fast

Shortcuts tend to turn around and bite you even faster then you think. Sometimes even before lunch.

About your context; don't abstract immediately. Stick to YAGNI and remove duplication. Implement that View based pattern when you actually have a second view not because you think you may have one in the future. When that second View does arrive the abstraction you create is typically much better then the one you would have made around that first single occurrence.

3
votes

Well if you already know what you're doing, fast if you don't

I'm a research scientist and I write a lot of exploratory code before I have any clue what the big picture is or how the project will develop. In these cases it's hard to even see how "well" should be defined. Also, it's usually hard to see all the little details and ways things might be extended upfront. Therefore, the old adage applies:

  1. Make it work.
  2. Make it right. Making it right second has the advantage that you can better define "right" once you've had the experience of making it work.
2
votes

Build it well.. always, but give the illusion of going fast

but to make it fast just make it smaller. Build a small subset of the whole that is sufficiently significant to get feedback. Progressively adding to it in a constant pace will yield much of the same benefit of building fast without selling your soul to the chain reaction of sleepless nights playing whack-a-bug.

1
  • +1, build only what is really needed.
    – Nicole
    Jan 21, 2011 at 21:16
1
vote

I think it should always be "built well". If time to market is a big concern then use an incremental development process. Worst case scenario you have a product with less features, but at least you have a high quality product to ship that can be extended in future feature releases.

1
vote

Balance

Its not practical to either engineer your code to perfection or mash-up some code together in a jiffy, is it? Its really about the striking the right balance. What matters in my opinion is what you do when.

I think the most important thing here is to absolutely ensure the core of the application, the fundamental structure, is built really well. Air-tight. Once that is achieved, depending on time constraints, if in case you're short on time, you could get some code together, and re-factor it later, and you can afford that luxury because you would have taken care to get the foundation right, and it wouldn't hurt to re-factor code.

1
  • correct. Build it as good as possible given the time allowed.
    – jwenting
    Jun 7, 2011 at 10:56
1
vote

Do the simplest thing that could possibly work. In your particular case, your program won't become very large, with you being the only person working on it part time. I'm not advocating bad manners like goto abuse, nondescript variable names etc., but you should not make it more complex than it has to be. Maybe MVC is just an overkill for your particular project.

0
votes

which I expect will morph as I get feedback from people

You said it best yourself:

But I've also been in the situation where you've incurred so much technical debt from short cuts that the code is just incredibly difficult to maintain and add new features to.

If you're short on time, don't be afraid to ask more for time to complete the project from your employer using this same reasoning. I'm sure they will grant it to you. Having said this, I understand how frustrating it can sometimes feel to work so hard on something and not be able to show off very much of a result. But don't worry, you'll get there, and building it well will certainly be worth it when you do.

0
votes

Typically I like to build the structure well, and save time by not worrying about specific implementation details. Like you say, they will change anyway. The Idea behind building a well made understructure is that changes can happen very fast, once the base is built. I try to focus on being as generic as possible in my classes and making them reuable where possible. I usually give the user an well built app that satisfies only the most basic usablility requirements. Users get all kinds of Idea's once a tool is in there hands, so there is no use in thinking to far ahead.

0
votes

Build it well. If you have no time, reduce feature set.

Design it as universal as can be. E.g. design a plugin architecture, even if you know, only one plugin will be used first time. Use universal configuration schemes (extensible config, organizing language), even there's only one parameter in the beginning. It's a very good investment, and you can make this investment only at the beginning of the project.

0
votes

is it best to focus on getting things working quickly, and taking shortcuts in the code like mixing model logic with your views, breaking encapsulation - typical code smells? Or, are you better off taking the time upfront to build more architecture

In my ears, the way you put it there, you are listing the two extremes. The first choice, breaking encapsulation, putting model logic in the views, that is just poor lazy programming. IMHO, solving those problems is not the same as putting in more architecture. Perhaps unless what you are talking about is that the UI code is executing SQL statements. But then I would not say build more architecture, then I would say that you have a complete lack of design and architecture and you should get one.

When it comes to architecture, I would choose the simplest one that solves you problem right now, and then expand as problems arise.

E.g. Is what you need right now the functionality to return data from a single database table, I wouldn't worry about the problems like how do I load data from related tables, even though I would know that the problem would eventually arise. I would start worrying about it when I get to implement that functionality.

So for my own home development projects, I would take the following approach: Build the simplest possible solution that solves the problem that I am working with right now, but build it well. I would then refactor the solution as more complexity is needed. Following TDD practices make refactoring safe, and also helps avoiding code smells (it is difficult to create good unit tests, if you are breaking encapsulation).

That is incidentally also the approach I take when working professionally. ;)

0
votes

I would recommend that first you should stand up the software , cover every aspect and stand the software first and gradually then decorate and improve its performence

-1
votes

You usually want to be in the middle of these two edges:

Build it well = life critical real-time software that people's lives depends on. i.e., software controlling: Nuclear reactors, Dialysis machine, MRI machines, etc.

Build it fast = useless software that no one actually uses.

2
  • ha! build a useless software...
    – pmod
    Jan 21, 2011 at 22:25
  • Any reason on the negative vote?
    – vz0
    Jan 22, 2011 at 15:16

Not the answer you're looking for? Browse other questions tagged or ask your own question.