43

I was watching Bob Ross paint some "happy trees" tonight, and I've figured out what's been stressing me out about my code lately.

The community of folks here and on Stack Overflow seem to reject any whiff of imperfection. My goal is to write respectable (and therefore maintainable and functioning) code, by improving my skills. Yet, I code creatively.

Let me explain what I mean by "coding creatively":

  • My first steps in a project are often to sit down and bash out some code. For bigger things, I plan a bit out here and there, but mostly I just dive in.
  • I don't diagram any of my classes, unless I'm working with others who are creating other pieces in the project. Even then, it certainly isn't the first thing I do. I don't typically work on huge projects, and I don't find the visual very useful.
  • The first round of code I write will get rewritten many, many times as I test, simplify, redo, and transform the original hack into something reusable, logical, and efficient.

During this process, I am always cleaning. I remove unused code, and comment anything that isn't obvious. I test constantly.

My process seems to go against the grain of what is acceptable in the professional developer community, and I would like to understand why.

I know that most of the griping about bad code is that someone got stuck with a former employee's mess, and it cost a lot of time and money to fix. That I understand. What I don't understand is how my process is wrong, given that the end result is similar to what you would get with planning everything from the start. (Or at least, that's what I have found.)

My anxiety over the issue has been so bad lately that I have stopped coding until I know everything there is about every method for solving the particular problem I am working on. In other words, I have mostly stopped coding altogether.

I sincerely appreciate your input, no matter what your opinions are on the issue.

Edit: Thank you all for your answers. I have learned something from each of them. You have all been most helpful.

9
  • 7
    Nothing is wrong with the way you work, you know what is important in the final outcome, and that is what really matters. It is just that you might have a hard time working with a large team that way, but you will probably adapt if that is the case. It really sounds like you are heading straight for Analysis Paralysis: sourcemaking.com/antipatterns/analysis-paralysis Dec 5, 2010 at 11:55
  • 39
    Months of rewriting will save you days of planning!
    – Jonas
    Dec 5, 2010 at 14:00
  • 4
    @Jonas: Good one. But you really should not underestimate Analysis Paralysis. With all the "good advice" on methodologies, design patterns, etc. these days, it is really easy to get the impression that you should be planning, analyzing and designing for days and days on end before you even touch a single line of code. And that can easily become very counterproductive. The reality I believe is to understand what planning and designing up front can help you in the long run, and understand when to dive in to get some feeling with what you are working on, and to actually get something done. Dec 5, 2010 at 14:40
  • 4
    From the Agile manifesto: "Working software is the primary measure of progress."
    – Gary
    Dec 6, 2010 at 11:15
  • 2
    It's almost as if the programming world is full of primadonnas. I can't tell you how frustrating it is to go onto SO and see a perfectly valid question downvoted 5 times because the user doesn't write in perfect English or the code is considered "too beginner" for the elite to deal with.
    – Scottie
    Mar 18, 2015 at 17:03

15 Answers 15

30

There's nothing wrong with code-test-refactor-repeat, just tell people you're prototyping.

On the other hand, for larger projects you will find that some thought given to the design up-front will save you a lot of time in the oh-crap-now-what loop!

P.S.: Diagramming techniques help you to learn visual thinking skills, which are valuable even if no one but you ever sees your diagrams.

5
  • 5
    "code-test-refactor-repeat" (or some permutation of it) is how we write code. Maybe Superman is "code-done", but mortals need to iterate. Dec 5, 2010 at 13:04
  • 5
    @Martin: some up-front thinking in that loop is often advantageous ;-) Dec 5, 2010 at 14:58
  • 4
    as long as you know how much "some" is! Dec 5, 2010 at 17:09
  • thank you for your reply. I had never thought of what I was doing was prototyping, but indeed, that is exactly what I am doing. Your reply has given me a fresh way to look at things, and I greatly appreciate your response.
    – Brad
    Dec 5, 2010 at 19:15
  • 8
    @Brad, remember that occasionally prototypes need to die instead of evolve.
    – user1249
    Dec 5, 2010 at 20:27
22

I always prefer clear, readable, simple code to any visually presented, UMLed, design-patterned code, where class/interface include pattern names like "ItemVisitor" (?!). Design patterns, OO techniques, and everything else are to formalize rules. That rules come from the common sense.

It is impossible to work without that formalization (unless you work alone on your own project) and the over-formalization increases the projects costs. Never disregard others' needs to understand your code. The best code is the simplest one.

Never hesitate to re-write your code. I'm going to get X downvotes (X>=10) for this, but I'll make it bold: reusability of code is not the most important thing.

Before staring coding you should consider the use-cases that code is going to implement. Because the software is to be used, and not to be developed. Usability, usefulness are two most important targets and it doesn't matter who is going to use that software - another developers of dependent parts of the project, or the end-user.

5
  • 4
    +1 for "reusability of code is not the most important thing". Sometimes you need a Swiss Army Knife, sometimes you need a scalpel. Dec 5, 2010 at 17:49
  • thank you for your comments. Regarding what the resulting software will be used for, that is definitely something I keep in mind throughout the entire process. I agree, that is the most important part. I mentioned code reusability, as it goes a long way to achieving that goal.
    – Brad
    Dec 5, 2010 at 19:18
  • +1 again for "reusability of code is not the most important thing" and not a single downvote (so far)
    – Gary
    Dec 6, 2010 at 11:13
  • I think the extreme focus on "reusablity" was an inchoate version of Don't Repeat Yourself and elimination of duplication.
    – Rob K
    Mar 18, 2015 at 15:17
  • "Use before reuse" even made it into a nice little book:97things.oreilly.com/wiki/index.php/…
    – Lovis
    Mar 18, 2015 at 16:06
15

I'm much the same way. Listen when other people tell you about things that worked for them, but ignore anyone who tells you what you "should" be doing as though there were some moral imperative to it. If you find something that works for you, go with it. I mean, the end result is what's important isn't it? Who really cares about the path you took to get there?

Remember: people are different. That's a good thing. Don't listen to people who try to make you like them, and resist the urge to make other people like you and you'll do fine.

4
  • Any one who says something should be done a certain needs to have good reasons for suggesting it. If they can't provide a good, clear and logical reason, then their "should" becomes a "maybe should". Dec 5, 2010 at 7:37
  • 1
    @Greg - Even still, a good, clear, and logical reason for you might be completely illogical to me. Dec 5, 2010 at 7:41
  • 1
    +1. Anyone who says that you absolutely should be doing this and that is just plain wrong. Sure, you must study and listen to others (especially the great and experienced ones), think hard, try out and compare alternative approaches etc., but in the end, do what you find right. If you just want to be mediocre, then go ahead and follow The Design Process, but for anything worthy, you must trust yourself. Dec 5, 2010 at 7:46
  • +1 - I personally might start with a diagram or do it the official way, but that is because the official way happens to work for me. You cannot really teach people to become smarter or more creative. They are adults set in their ways. You either hire them or you do not.
    – Job
    Dec 5, 2010 at 14:02
6

It seems you are:

  1. Trying stuff out to find the best approach (experimenting, incremental design)
  2. Rewriting code to get it cleaner (refactoring)
  3. Constantly writing tests (test driven development)

What you are doing is awesome! It looks like you are doing it perfectly right, especially if you've figured it out by yourself and not learned it from an (agile) programming book. There is obviously more to this but you've got the values nailed. Just remember to refactor and improve the design while you are adding code and there should be no need for a BDUF.

Have you considered focusing on one small feature at a time, and release after each feature is completed? That might help you get unstuck from any analysis problem you are struggling with and demonstrates real progress to you employer.

Also, I don't know what "professional development community" you are talking about, but if were you, I'd tell them to go back to their ivory towers so you can get on with your work!

1
  • I fully side with you on this, which echoes my own answer. Dec 5, 2010 at 16:40
4

Brad, you're not alone. I know very good programmers who work in exactly the same way as you describe. :)

If you clean up your code and know how to make it efficient and readable, then you certainly have developed a sense of how to write clean and efficient code upfront too.

Furthermore, nothing can fully be planned in advance, and the shortest route to discovering subtleties is often to run the code and understand details that were overlooked.

I think that you're doing perfectly fine, and that the programming style that you describe is perfectly valid.

4

I think it worth completing the answers above with a quote from Alan J. Perlis, from the foreword of the well-known MIT book "Structure and Interpretation of Computer Programs", commonly called "SICP" :

Every computer program is a model, hatched in the mind, of a real or mental process. These processes, arising from human experience and thought, are huge in number, intricate in detail,and at any time only partially understood. They are modeled to our permanent satisfaction rarely by our computer programs. Thus even though our programs are carefully handcrafted discrete collections of symbols, mosaics of interlocking functions, they continually evolve: we change them as our perception of the model deepens, enlarges, generalizes until the model ultimately attains a metastable place within still another model with which we struggle."

1
  • well put. They are primitive models, humanistic models, and finally superhuman models as the programmer pours more and more thought into the actions that are taking place within the code. Mar 18, 2015 at 19:18
3

There's Good Clever and Bad Clever.

Good Clever -- high ratio between clever lines of code vs lines of in a non-clever alternative. 20 lines of code that saves you from writing 20000 is Extremely Good Clever. Good Clever is about saving yourself work.

Bad Clever -- low ratio between lines of code written written vs. lines of code saved. One line of clever code that saves you from writing five lines of code is Bad Clever. Bad clever is about "syntactic masturbation".

Just to note: Bad Clever is almost never called "Bad Clever"; it will often travel under the aliases "beautiful", "elegant", "concise", or "succinct."

3
  • 1
    "beautiful", "elegant", "concise", or "succinct." ..... I think I saw this on the Ruby on Rails home page at one time. :-D
    – Brad
    Dec 15, 2010 at 14:12
  • 1
    Maybe it's just me, but I think an 80% reduction in LOC is worth some cleverness.
    – recursive
    Aug 8, 2011 at 14:39
  • I've found many to label stuff "syntactic masturbation", when in fact it's just a matter of them being too lazy to actually learn the language they're using though...
    – Svish
    Mar 9, 2018 at 19:31
3

I can definitely recognize myself in the way you describe your workflow. Here's the thing: when I started working in a group environment, almost all that stuff HAD to change.

The job I've been in for about 8 months now is really my first experience at working in a team of developers on a single project. Until now, literally my whole career has been as a lone-wolf coder who didn't have to deal with all that comes with teamwork. Even when I worked in a group, it was always fairly siloed work--I had my project that was MINE, or my section of it that was MINE, etc. It was an interesting learning curve as I brought myself up to speed with a truly collaborative team work environment.

Here's the main thing I've realized: if it's not bloody obvious what you're doing, you're probably writing a colleague's next headache. Most of the "process-oriented" fussiness you see here has to do with the fact that many of us have BEEN the colleague with the headache. And most software process management theory has to do with minimizing that headache.

So things like planning out an agreed-upon plan ahead of time, etc... Those are about having a team on board and in sync. If you're the team, you're already in sync with yourself, and that's not really necessary.

2

There is nothing wrong with your approach as a creative art form. If you are developing for personal benefit, and what you are doing works for you, and that you find enjoyable are probably just as important as the final outcome as the product itself.

In a professional work environment, if your project time scales are short, perhaps around 2 - 3 weeks or less, then your approach is called rapid prototyping and is quite appropriate to the tasks ahead.

However on longer projects, even ones when you are working on your own, such an approach is probably an expensive luxury for your employer. Spending a few days of the project budget on upfront architecture design and then testing the architecture against what if management decide to change the spec by... is normally time well spent and will develop your skills to becoming a more valuable programmer/architect further on in your career.

2

Two perspectives:

  1. Nobody has to maintain a painting.

  2. Anyone who has ever watched Bob Ross paint a painting knows that paintings have structure. If you were going to take one lesson away from Bob Ross, it'd be that planning ahead and working in an organized manner makes the process go smoothly and look simple.

1
  • 1
    Bob Ross never painted the happy trees before painting the sky behind them.
    – Rob K
    Mar 18, 2015 at 15:20
1

I code pretty much the same way. I'll just start writing and as I see patterns emerging, I refactor. You can paint yourself into a corner that way, you have to know when to sit back and think a problem through, but sometimes you just to take a stab at it to really understand the problem.

But I'm curious about this:

The community of folks here and on Stack Overflow seem to reject any whiff of imperfection. [..] My process seems to go against the grain of what is acceptable in the professional developer community, and I would like to understand why.

How would anybody at Stack Overflow know your process? And what do you mean by "reject"? Naturally, code posted to a programming community is going to be critically examined. But if someone spots areas where your code can be improved, that can only be a good thing, right?

Hopefully, when posting a question to Stackframe, you cleanup up your code and try to reduce it to the simplest form possible, out of respect for your readers (you sometimes solve your own problem just trying to make it presentable to others), in which case any feedback is good. If you post code that you know is bad, and you know why it's bad before you post it, you shouldn't take it personally if people notice that it's bad.

2
  • I wasn't referring to any questions or answers that I personally have asked. When I post questions, I break them down into the simplest case possible, and same with my answers. I have noticed that when others post not-so-perfect code in their questions, or aren't really sure how to ask the right question, they get repeatedly shot down. On those border-line cases where the question is close to a good one, I often edit it, or add comments to push the OP in the right direction. I don't feel that is what normally happens though. [more in next comment]
    – Brad
    Dec 5, 2010 at 19:21
  • In any case, after reading the responses to my question here, I feel that I have mis-read the community, and projected criticism of answers to criticism of complete projects, which as you made clear, are two different things.
    – Brad
    Dec 5, 2010 at 19:22
1

I also use your approach. It works better for me, since it reduces the risk of overengineering.

What I do very often is solve a problem with probably the least code possible, which usually leads to evidently unneccessary dependencies or other design problems. Then I refactor working code into beautiful code.
For example I reduce the dependencies between different modules to concise interfaces and put thought into the question which data should be held where, until every modules only depends on very minimalistic abstractions of the other modules. You could say, I postpone the final decision, which module should have which responsibility. I postpone abstraction.
Putting too much thought into seperating a problem into distinct responsibilities, into distinct abstractions, is not good. It will force you to bend your implementation to fit the abstractions you made. Code works, if it produces the results you want and if it is maintainable. A design works, if you can implement it through good code. If code doesn't work, you change it. Ergo, if a design doesn't work, you will need to change it as well. You can only see if a design works, once you implemented it.

Thus having a simple sketch in mind is just about enough as a design, before you start bringing it to life. Redesign, abstract and refactor as needed.

1

I think if you're going to be good at programming, at least sometimes it has to be fun, and that means being creative.

Surely when programming in groups there are at least minimal standards that should be followed, not for "moral" reasons, but for practical ones, when they apply.

Outside of that, it's interesting and fun to probe the boundaries to see what can be found there. Once when working on a Mini in assembly language, I discovered that you could make co-routines that could switch from one to the other with 1 instruction. Then I figured out how to make a self-co-routine that could go two steps forward, one step back, etc. Was it useful? I doubt it. That's not the point.

Once I heard a talk by Edsger Dijkstra, talking about creativity in programming. He mentioned how a student found a way to do an n-bit rotate of an n+m-bit word. It was done with 3 bitswaps. First you swap the n bits, then you swap the m bits, then you swap the whole n+m bits. Useful? No. Clever? Yes.

It's good to feel free to try things that nobody in their right mind would do.

1

This may be a case of "one size does not fit all". You've made your style work for the projects you've been on, so who's to argue with that? However, the critics you are reading here and on SO may be working on bigger projects, or on projects that require complex coordination between the team members.

Your development style could become a problem if you were ever involved in larger projects involving cooperation between multiple developers. It's hard to schedule it, it's hard to track your progress, and there's no way for you fellow programmers to plan the bit of their work that depend on knowing what your bit of work is doing.

You may be interested in reading Dreaming in Code to see what can happen when a large project adopts a development style similar to yours.

1
  • 1
    thank you for your reply. Your comments are helpful to me.
    – Brad
    Dec 5, 2010 at 19:25
1

Plenty of reassurance that your method isn't wrong, but let me add some personal experience. I started off your way, but in the meantime I learnt the benefit of planning beforehand at least part of the general structure, and this for a number of reasons:

  • biggest extra is that it's easier to see which code can be reused if worked around a bit. I often write a piece of code that, while writing, suddenly seems useful for another part in the general scheme I have hanging next to my screen (drawn on paper in a only-readible-for-me-style).

  • Having a scheme allows you to refactor not only the code, but the scheme as well. Sometimes I'm busy writing a class that suddenly appears useful for some other part in the scheme as well. As a result the scheme becomes simpler when the project runs on

  • Every time I update that scheme as well with required input and given output of functions/methods, and available slots in classes. This goes faster for reusing bits: I don't have to dive in the code every time to check what exactly goes in and out. Even if it's in the comments, I still have to browse to get the comments up

So actually, I use your method as well. I just start, try out, refactor, try out again, change another bit and so on, but my cycle includes the scheme as well. And when that's done, I add the information for the next one that works on that code.

Mind you, this is for projects where I work on alone. If you work with more people on the same code, planning ahead is not only logic, it's essential. But I guess you know that already.

And as others said: this is my way, your mileage may vary.

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