Question

I have just started a new personal project (Python), and am writing what amounts to a "rough draft" of the program, the minimum required to do what I want to do. I am not yet putting in extensive error/exception handling or aesthetic UI elements (even in cases where I know these things will ultimately be needed), and the documentation is just enough to help future me see what I was doing.

Is it against any set principles of project design/management to start so rough? I am a scientist, not a programmer, so am not up to speed on these things. So the main question is, is there a consensus on where one should aim to fall between the two extremes of:

  1. Write thorough, high-quality code from the start, with all the exception handling and such that you know you will ultimately need.

  2. Write a minimally working rough draft from the start, and go in to fill in all the minutiae later.

Related question: When is it OK to sacrifice the "neatness" of the design to get a project done?

Was it helpful?

Solution

There is no single answer, as this depends entirely on the project. We need to think about two things here. What is your eventual target? How do you expect to get there?

End Result

Are you writing Mars Orbiter control software? Then you better make damn sure you are writing the most robust code possible, You better be check every exception is handled in a sane matter.

Are you writing a program that only you will run, and you'll only run manually every once in a while? Then don't bother with exceptions. Don't bother with heavy architecture. Get it working to the point where it works for you.

How do you expect to get there?

Are you doing heavy waterfall development, where you spend lots of time figuring out what is needed, and then you will go off for months, developing? If so, then you want to hit that target quality mentioned above fairly early. Get all your error checking infrastructure planned out at the start.

Are you doing heavy agile development, where you are putting something together for a week or two, which will then be shown to stakeholders, who may ask for radical revisions, and where you expect to be able to iterate over many 1-2 wee sprints until you hit the target? Then you may be better off getting something working, but fragile together fast, and only adding belts-and-suspenders as the product requirements solidify.

If you are in control over the waterfall or agile decision (which is actually a continuum not a binary choice) then make that decision based on expected change. If you are sure you know exactly what the end result will look like, then waterfall is your best choice. If you only have a vague notion of what you need to end up with, agile is your best choice. (Agile is more popular these days not because it is inherently better but because the second situation is far more common.)

Now find your own answer

For most, the answer will lie somewhere in the middle. Answer both those questions about your project, and it should lead you in a basic direction.

I can say that for myself, if I often write one-off scripts that are abysmally designed and have no error checking whatever. I also handle production code, where error handling and architecture get large amounts of attention. It all depends on what you are doing.

One final caveat: If you decide you are doing one-off scripts that can be done quick-and-dirty, make sure. Unfortunately, it often happens that quick-and-dirty scripts that do something interesting get leveraged into broad usage when others notice them. Make sure that when this happens, time is given for hardening.

OTHER TIPS

All software design and coding concepts and patterns arise in response to some problem. The pattern or concept is a solution to that problem. Over time, some patterns become "well-known" as preferable solutions because they solve the problem in a way that fulfills certain requirements for consistency, familiarity, performance, maintainability, and so forth.

It follows that, if the problem that the software pattern is meant to solve doesn't exist in your particular software, then you don't need the pattern. Further, any discussions of what patterns your software might need must also include detailed discussions of your proposed software: what is it supposed to do? What problem does it solve? How many users will there be? Will the users be sharing data in some way? And so forth.

The problem that exceptions are supposed to solve is when something happens that the code can't do anything about. An example would be a File/Open operation where a file name is specified that doesn't exist on the storage medium. Exceptions give the code a way to say to the caller "Something happened that prevents me from continuing, and there's nothing I can do about it, so I'm giving up." If you don't have any places in your code where conditions like that exist, then you don't need exceptions. Or, you can simply return an error code, and avoid the exception altogether.

As you gain experience, you will learn about software patterns and when their use is appropriate. You will also know how much up-front design you need; again, that totally depends on the application you are writing. Small utilities are written in a fundamentally different way from large, enterprise applications, in other words.

There is a very simple and practical approach to this, which works for a wide range of small to medium size projects. Even though it probably won't work well for Mars Explorers.

First, work out what you want the system to do and note down each of the individual features. This can be as sophisticated as a whole user story board or as simple as a few bullet points jotted down on a piece of paper in front of you. But it is important you know what you want it to do.

Based on that draw up the general structure of the system. Again, this is very often just a quick drawing of the different classes/modules and how they relate to each other, but might be as complex as a whole document. The important thing is that you have some sort of idea of how you are going to implement the system. But, this is probably going to get refined as you work on it, so don't try to go to complex and detailed.

Out of all these features work out what the key things are that the program needs to do - the core features.

Then implement them one-by-one. Now the key thing here is that to actually make sure that once you implemented a feature this is done and fully working - ideally this is accompanied by a unit test that makes sure it keeps working. I usually go on the assumption that I will be so busy that I will never have time to come back to the feature and fix it.

Once the core features are implemented, I generally try to put the system to use as close to the production environment as possible. This gives you a) any bugs you might have missed earlier and b) you get a good idea of the priority of the next features.

Then you can keep implementing the remaining features as needed.

Code Quality vs. Features

With the above in mind, I tend to sacrifice features over quality of code, if I have to make a deadline. Simply because, at least in my line of work, when I finish something my management assumes it is done. And that they can give me the next task. I don't have a lot of time making code nicer after the fact.

Now, what about exception handling?

If you don't want to implement that off the bat, you could just list that as another feature on the list. And when you get to it you can implement that. But most likely in your case there are probably many other things that are more important first.

However, there is a minimum requirement for exceptions: Make sure the user is notified if anything goes wrong - no matter how ugly the output may be. Don't swallow exceptions somewhere.

Licensed under: CC-BY-SA with attribution
scroll top