43

I'm a CS student and I have been coding for a few months shy of a year now, and I seem to have developed what I think may be a "bad" habit and I'm wondering if anyone does the same (or whether it's a bad habit at all). When I'm coding / solving a problem with code, I find that my initial implementation is lengthy and overly-complicated; in other words, there is a lot of extraneous code (variables, checks) that is simply not needed. When I finish the initial "draft," and make sure the code actually works, I simplify it and make it easier to understand/less verbose.

I think the reason I do this is that I have trouble foreseeing what I will need to complete a task and end up over-compensating and creating complexities that should not or need not exist. Anyone have any tips or advice on how to improve this facet of my coding style, or any input as to whether the habit is actually a bad one?

5
  • 4
    If you use that method to solve small to medium tasks, then, as others told you in their answwers, I'd say there is nothing wrong with it, preferrably with some unit tests as additional quality measure. If you intend to create the architecture of some big solution this way I'd recommend to rethink the approach.
    – Thomas
    Apr 28, 2013 at 20:15
  • 1
    I suggest you read Code Complete 2 (or at least the relevant parts), which talks a lot about the non-programming aspects of programming. You may try to plan more before you start coding so you have an idea of what your goals are, what the restrictions on the inputs are, etc. One strategy mentioned is to write pseudo-code before writing the actual code. You'll be able to see the same problems you see with real code, but will be able to get to that point much quicker.
    – mowwwalker
    Apr 28, 2013 at 22:41
  • Another suggest is Clean Code. The book maybe doesn't have the exact answer to your question, but there are some principles that you can use after make your code work. amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/…
    – yfklon
    Apr 29, 2013 at 10:37
  • 1
    "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away." -- Antoine de Saint-Exupery
    – Bobson
    Apr 29, 2013 at 18:12
  • possible duplicate of When to refactor and of Prototyping vs. Clean Code at the early stages
    – gnat
    Apr 30, 2013 at 22:38

12 Answers 12

47

Sounds like a good habit to me. First rule in coding is to make it work. Once you've done that, clean up your code and make it neat, understandable and simpler if you can.

However - if you are spending a lot of time over designing your solution and wasting a lot of time creating stuff that doesn't need to exist, that's possibly a bad habit - like if you were creating a bunch of classes and just going a bit overdesiging mad. But as long as you're working towards "making it work" then it doesn't sound like it's a problem.

1
  • 8
    I'd disagree with your first rule - I'd make that the second rule. Rule 1: Understand what you are trying to do Rule 2: Make it work
    – Andrew
    Apr 29, 2013 at 15:55
20

My answer may be little off topic, but this method works for me.

Before you even start programming you have to think: what kind of structures I need to solve a problem, and what kind of algorithms.

Often you will find that solution already exist and that you only have to implement it into your project*. Never try to reinvent a wheel - if you need something there is always significant chance someone already done it better.

Once you do that you are only left with gluing those parts (algorithms and structures) together and that is usually simpler than thinking about a problem as a whole.

*That's why education is so important in IT. The more algorithms and kinds of structures you know the more often, during programming you will catch yourself thinking: "Oh, I know, I have to use this. Oh, and here I need to use that."

4
  • 2
    shock, horror... you have to think and design before coding.. I thought that approach went out in the 90s :-)
    – gbjbaanb
    Apr 28, 2013 at 22:22
  • 31
    weeks of programming can save you hours of planning
    – Matsemann
    Apr 29, 2013 at 7:19
  • 1
    Isn't that what Design Patterns was invented for?
    – ott--
    Apr 29, 2013 at 14:06
  • 1
    As a student I believe there is huge learning value in trying to reinvent the wheel, I also found it really enjoyable in my student years.
    – bughi
    May 4, 2013 at 18:09
10

That habit is typical for TDD. First implement it and than refactor. I think every developer does not implement the best way on his first try. As long as you have unit tests to verify that everything still works after refactoring there's no problem with that.

3
  • 1
    Unnecessary length is orthogonal to TDD. Overcomplication is not TDD because your initial implementation is supposed to be the simplest code needed to satisfy the test.
    – snakehiss
    Apr 28, 2013 at 20:41
  • 4
    @dietbuddha The simplest code to write is not always the shortest :) Basically thats what this question is about. Apr 28, 2013 at 22:37
  • Although the shortest code is also not always the right one. For example think about some quickly coded prototype and something that actually follows design patterns like MVC or whatever...
    – zduny
    Apr 29, 2013 at 7:43
7

I find that when I work out on paper what I want to do ahead of time, that I make less unnecessary code. Sometimes I end up with several drafts on paper, so it's still an iterative process, but the iterations tend to be faster, since you don't have to get all the way to working code to realize that something you thought was a good idea won't work after all. (It doesn't even have to be as detailed as pseudo-code; a simple drawing can be quite helpful. Also, there's nothing magic about paper, whiteboards work well too.)

Cleaning up code is a good habit, but so is aiming for clean code in the first place. You'll still need to clean things up even if you plan ahead, but you won't have quite as much of a mess to start with.

2
  • That is really the best way. I'm still in high school, and I already use this to come up with my data structures and algorithms on paper (usually during English and History class...) before writing them on the computer. Apr 28, 2013 at 21:50
  • Planning your approach before touching the keyboard is something not enough people do. It really makes you focus on what needs to be done before getting caught up in the intricacies of how. Flowcharts, pseudocode, pictures, they all help formulate the ideas in your head so that implementation flows better. I also find it helps me avoid dead ends. But it does make project managers who can only comprehend progress in LOC very frustrated.
    – alroc
    Apr 29, 2013 at 13:56
4

Writing and re-writing code isn't a problem, nor is writing more code than is absolutely necessary. Every time you write code and throw it away or refactor it you are learning--in fact it's possibly the best way to learn. Trying to be "Optimal" about your coding type or typing time is really harmful to all involved.

Also, all those "Extra" variables are often a good idea--if they help you understand your code initially then they are best left in there! Don't fall into the trap of writing minimal code thinking that's the way to make it readable, Terse code does not equate to readable.

I'm suggesting you don't get too enthusiastic about "Removing" your code. If it's absolutely unnecessary, sure, but creating extra functions and more variables tends to be a fairly good thing, if you remove them once you understand the solution, you are only hurting everyone who looks at the code after you (including yourself a few months later).

It IS, however, important to keep your code DRY, in fact that's what I consider the single most important principle in all of software development, but once your code is DRY, further reducing verbosity from what helped you comprehend and design it is usually harmful.

9
  • +1 for Terse code does not equate to readable. Of course, the opposite holds as well: long-winded code is not necessarily any more readable than terse code is!
    – user
    Apr 29, 2013 at 14:36
  • Although I admit it's fully possible, I have never encountered code that was DRY, did not take unnecessary actions and was too long winded--in like 30 years of programming. I have seen a lot of code people THOUGHT was dry that wasn't--It's not just combining identical code, it's searching out similar logic and finding ways to combine it. All the other code I'd call "Long Winded" was just not broken up enough into functions, methods or classes--orginizational problems but not problems with the amount of code.
    – Bill K
    Apr 29, 2013 at 17:19
  • I was talking about the relationship between code length (in, let's say, SLOC in a given language to solve a given problem) and code readability. There probably exists a sweet spot, but it is more likely somewhere in the middle than at either end of the scale.
    – user
    Apr 30, 2013 at 11:00
  • Perhaps, as I said I've never seen too much verbosoty without redundancy, but it could be done if one really tried I guess. I'm a little curious to see what dry code could only benifit from pure reduction rather than reorginization though. If you have an example I'd be quite interested.
    – Bill K
    Apr 30, 2013 at 17:19
  • string s; if (a == "hello") { s = "world"; } else { s = "hello"; } Spread that out with a reasonable whitespacing scheme and it gets quite a lot longer than string s = (a == "hello" ? "world" : "hello"); which accomplishes exactly the same thing. Using the conditional operator also puts the emphasis on the declaration and assignment rather than the condition, which in many (not all) cases can be a good thing. (Obviously, that example is made up, but I've seen plenty of very similar code in production systems. Assuming familiarity with ?:, the longer form adds little readability.)
    – user
    May 2, 2013 at 7:28
3

The best coders and average coders usually have similar code, the difference is how long it takes them to do it. If you take the time to plan ahead and solve the problem before you start coding it will help you become one of the best coders. Obviously you won't be able to foresee every problem so you will have to make the little things work and that can get pretty messy so what you are doing is called refactoring the code (and this is a good practice). The best thing to do is first solve the algorithm on paper and figure out how you are going to accomplish the task. Then code it and get it to work, then refactor to clean up, make more readable and optimize. Look at how long it is taking you to solve/code/debug and of those three the debugging should take the least time, then coding a little more and solving the problem the most time. Hope that helps out.

3

Nothing wrong with this habbit in my opinion. The longer you code, the better your coding and problem solving skills will get, thus all of the "extra" code will get less.

I've been working as a junior software engineer for about two years now, and still use this sort of approach, with the difference being that as time has gone by, I've been more often gunning straight to the trimmed down solution/algorithm.

Test variables is still a common thing for me, but gets used much more efficiently.

So no real worries here, just ensure that you keep it as clean as possible, and use lots of comments and regions.

1
  • Yup, it's an experience thing. With 15 years of experience, I now can discard the superfluous code before hitting [Compile].
    – MSalters
    Apr 29, 2013 at 12:32
2

Just try to mark your extraneous code if possible. Variable checks can be written as assertions for example which add semantical information to your code, I.e. these properties have to be fulfilled etc. Since assertions are usually dropped in "release mode" (depending on language/plattform) lots of assertions do not have to be removed but can function as further debugging help when changing parts of your program.

Similarly for temporary variables that you use for code debugging, name them with a debug_ prefix or something similar, so you can tell their purpose right away. Programming is an iterative process,therefore what you do is perfectly normal.

One thing to notice: Assertions can be even better than comments in explaining your code. Use them (wisely)!

2

Verbosity is very common for junior programmer, but you are more advanced that you aware those verbosity and try to remove it.

At first it might sounds like a good habit that you always refactor, but if you need a lot of refactoring after first time it means you should improve your initial coding performance.

Refactoring more often is the key. Don't wait until your implementation complete before refactoring. If you function is too long, make new function. If your code is repetitive, make a function out of it. Think of refactoring all the time when you code, not just after you finished coding.

Constantly refactoring will help you when you need to review what you have written, and it's easier to debug. It is common that your code won't work correctly after the first time, and even yourself in few days later might forgot your own logic if your code look like a mess.

1

I guess having trouble "foreseeing what is needed" is only natural given your short experience: you are just beginning to learn how to write programs. It takes a lot of trial and error to learn to design and that is the skill needed to avoid extraneous coding. It seems you are on the right path.

Perhaps you already write detailed comments but if not, you could try using comments as a tool of small scale design. Try writing descriptions first. Before writing a single line of code into a method, write a description for it: what it does, what parameters it takes and what it returns, what side effects it has and what kind of exceptions it could throw. You could also outline the implementation using comments before writing code. The same goes for classes or modules: try describing them as a whole before actually diving into details and implementation.

This approach forces you to design something before coding. It could also lead you to thinking about structure first which will be essential further down the road.

0

The usual sequence is 'make it correct, then make it elegant, then make it efficient'. The first step may result in as lengthy code as you need, as long as you can keep track of what's going on.

Gradual refining of code is an ongoing process, and even best programmers are known to say that some of their most productive days were when they removed 1000 lines of code. You should worry when you can't simplify your large and complex code any more, not the other way around.

0

The "Do more, then simplify" approach has a major downside: The big and complex methods are very hard to test. And you want a test that documents that your refactored code produces the same results.

So you really need to start thinking about separation of concerns as early as possible, or else you will spend a lot of time wrestling with really difficult unit tests, that could be prevented. You need small pieces of code from the get go. For me, understanding the "Single Responsibility Principle" (SRP) was very important in this context. Also, decency injection plays a very big role here.

It is hard to do this in the beginning ( it still is for me a lot off times), but as you gain experience, you will slowly learn identify patterns in the code, and know how to break those patterns up into simple and testable structures.

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