1

Why is writing code when you encounter a tricky problem considered "bad" programming practice? And why is thinking a problem completely through on paper or in your head before you write code "good" ? From what I've been working with, I'm able to see problems in multiple different ways or special cases I didn't think of at first by typing out code and debugging than solving the problem completely first ?

Also, I can't really find any appropriate hashtags for this. So any help is much appreciated!

  • Answer here: http://ravimohan.blogspot.com/2007/04/learning-from-sudoku-solvers.html (note - you'll have to use the wayback machine for Jeffries' stuff, the original links are dead) – Aaronaught Apr 29 '11 at 20:21
  • Are you really asking why thinking about what you are about to do is a good idea? – JohnFx Apr 30 '11 at 16:32
  • No, I'm just saying, thinking it through in code is a better idea than thinking it through on paper. – Tejaswi Yerukalapudi Apr 30 '11 at 20:05

11 Answers11

5

It is worthwhile to think out any problem while coding, no matter how trivial you perceive it to be.

Why? (in no order of importance)

  • Your implementation can affect any number of different areas, and you may adversely affect dependents with your changes.
  • You can throw away paper designs a lot faster than re-writing code
  • You can have someone else vet your ideas easier on paper than trying to have them look through code that they're not familiar with
  • Designing on paper forces you to think through the entire problem rather than just the small chunk you're current writing.
Demian Brecht
  • 17,555
  • 1
  • 47
  • 81
  • I feel once you have a system level design, say you're writing a function that interfaces with some API or implements some algorithm that's of a moderate difficulty, they can be thought through much easier by just writing code instead of, say, reading through the entire API documentation or writing pseudo code for the algo on paper? – Tejaswi Yerukalapudi Apr 29 '11 at 19:14
  • 2
    @tejaswi: It's easier in the cases that you're *right* :) However, when you just sit down and code, you're running with scissors in the dark. One of the things that seasoned engineers look for (*especially* in interviews) is that candidates do *not* just dive right into the code. You need to understand the problem in its *entirety* prior to solving it. – Demian Brecht Apr 29 '11 at 19:23
  • 3
    Exploratory coding can be a way to try to understand the problem. If you do that, use a language like Lisp or Python or Perl where you can write what you need without infrastructure, and throw it away when you understand the problem. Throwing it away is essential to making this work, so don't do so much work that you feel invested in it. – David Thornley Apr 29 '11 at 19:52
  • 1
    @David: Sure - using Python and the like for prototyping is tremendously useful. However, it's *still* easier to get a solid grasp on a problem in its entirety on paper than just sitting down and blindly hacking away at something. You will undoubtedly miss some technical issues in your paper design (which will be flushed out by the code prototype), but you'll still understand the big picture problem *much* better. – Demian Brecht Apr 29 '11 at 19:56
  • 2
    @Demian: I think this is probably one of those things that vary by individual and by problem. I've done both ways, and found both useful. – David Thornley Apr 29 '11 at 20:11
  • @David: Sure, I can kind of buy that. However, when you consider what senior engineers much smarted than myself at Microsoft and Google look for in a candidate and one of those items is speccing out a problem before tackling it in code (diving into code right away is generally considered "junior" behavior), you've *gotta* assume that there's a reason for it :) – Demian Brecht Apr 29 '11 at 20:28
  • @DavidThornley - Different techniques work for different people, but I've found that jumping in and writing code is often a counter-productive knee-jerk reaction for me and I'm actively looking for techniques to avoid it. I even opened this short lived question about it: http://programmers.stackexchange.com/questions/178075/how-do-you-avoid-jumping-to-a-solution-when-under-pressure – GlenPeterson Dec 03 '12 at 13:00
4

After thinking about my previous answer, I realized that the best answer to the original question is to present a third option: write tests. Test Driven Development combines the best qualities of "just writing code" with the best qualities of "thinking the problem through in your head". You can think the problem through in your tests instead.

Rein Henrichs
  • 13,112
  • 42
  • 66
  • Instead of opening a new answer, revise your old answer to be better. –  Apr 30 '11 at 08:43
  • Except that would mean totally changing it, which I think is not the intent. – Rein Henrichs Apr 30 '11 at 08:46
  • 1
    well, _you_ changed your mind... so both answers are equally valid? –  Apr 30 '11 at 08:54
  • I think the other answer is valid. I just think this answer is more valid. I'm happy to merge them into the same answer. In general I worry about editing a post to totally change its meaning after it has gotten comments or upvotes, but in this case neither of those obtain. – Rein Henrichs Apr 30 '11 at 16:17
  • I'll have to disagree with this. Doing TDD cannot compensate for bad design. How do you write your test cases if the desing is not clear in your own head. You will start with the frames , write test cases, keep coding and testing in cycles until you figure that your desing is the problem in the first place. Then you will change your design and your TCs and then code again. Bad idea. – DPD May 01 '11 at 10:28
  • @DPD What does TDD stand for? Sounds to me like you don't know how to do it properly. – Rein Henrichs May 01 '11 at 13:06
  • 1
    TDD : Test Driven Development. Whether I know how to do it properly or not is irrelvant to the question here. TDD is about validating the code you have writen against your design, not about designing it. – DPD May 02 '11 at 04:15
  • Only someone who has never done it would make that claim. TDD *is* about design. – Rein Henrichs May 02 '11 at 04:56
2

My motto:

If it doesn't work on paper, it's not going to work in the computer. That goes for business process too. If you automate a broken manual process, you end up with a broken computer process.

Christopher Mahan
  • 3,404
  • 19
  • 22
1

it depends on the problem size :-) Also there is an element of "commitment". It is difficult to throw away code we usually spend time writing and debugging, while we can throw away some "paper" more easily.

It the problem is trivial, then yes you should code "only", but if there is a big algorithm with external calls/systems etc? Think a payment system of a large company or a video game or a database. Would you start from void main(args) ?

Dimitrios Mistriotis
  • 2,220
  • 1
  • 16
  • 26
  • I actually feel a bit differently about it. If the problem is trivial, then I should be able to know how I am going to approach it before I start to code. If the problem is difficult I might need to write some cheap tests of my ideas to make sure they make sense. Of course I would do some thinking before writing those tests, but there's nothing like running code to prove your ideas. – T Duncan Smith Apr 29 '11 at 20:26
  • I was influenced a lot by Code Complete 2 and the pseudocode programming method, where you basically: decide the algorithm, write it in pseudo-code commented and then incrementally substitute pseudocode with real code. But in order to argue in favour of my opinion lets think a bit in lines of code. Would you follow the same approach if you had to handle a problem which would roughly translate to 10K LOC? 100K? Time constraints? A complex data structure (b-tree). Do you know the CLRS book? Why does it also have diagrams? It has to do though with each person's brain and how it comprehends. – Dimitrios Mistriotis Apr 29 '11 at 20:45
1

It's not always a bad thing, IMHO. But the key is that when you start writing code in order to solve a problem you don't fully understand you should be doing it in order to understand the problem better, and because it is the fastest way for you to do it. You should be willing to throw the code away once it has served that purpose. Concomitantly you shouldn't put any more work into that code than is necessary to serve that purpose.

I'm a big believer in prototyping certain difficult problems. I actually spent about 6 months last year just prototyping various aspects of a problem I am working on. I also did a lot of pencil and paper work during that time. The reason was that the problem really was very difficult (for me at least,) and also very hard to precisely define. So we would develop an idea for an approach, and then code a bit to see if it worked out. In a lot of cases that revealed that our idea was flawed, so we would go back, think up another approach, and then code up the simplest test of it we could.

One big danger is that you will start coding before you understand a problem and get so attached to your sub-optimal code that it winds up in the finished product. Another is that you will spend way too much time "gold-plating" something that is never going to work.

One way we avoided this was implementing our prototypes using a higher-level (and ultimately too slow) language and a much lighter-weight platform than we were eventually targeting. We ignored a lot of the rules of good software engineering- our code was not meant to live much past the point where it had answered our questions satisfactorily so over-engineering it would have been a waste of time. We did the absolute minimum we had to to get the answers we needed. And we worked as much as we could out on paper or a whiteboard before starting a prototype.

I'm a big believer in thinking things through as far as you reasonably can in advance. But sometimes you need to code something up to make sure what you are thinking makes sense. When to think and when to code (well, hopefully you keep thiniing while you code ;) ) is a hard question, and like a lot of things in software development, a matter of judgment.

EDIT: The main thing I wanted to get across here is that I think it's important to know why you're coding. Some code is meant to wind up in production. Some code is meant to answer questions. Where you get into trouble is confusing the two.

T Duncan Smith
  • 597
  • 3
  • 7
1

Different problems require different approaches to solving them. For example...

When I go about solving problems with bad data or misunderstood data in a database I find it very helpful to create interactive views (constantly modifying filters) to narrow down the issue. When I think I have identified the issue or pattern I then beef up the view or create several views to validate my assumptions. Then I move on to thinking about how to fix the data.

When developing a process from scratch I like to use yellow stickies (turning them 90 degrees for decisions). This lets me move them around, insert inbetween, or rearrange them until the thought process and flow has been worked out and I feel comfortable about writing code.

There are other times where I need to create something that is similar but different to something I've already created. At this point I usually make a copy of the original code and start commenting out chunks and adding new chunks.

1

When you try to solve a problem while writing code, you're suddenly faced with solving two problems

  1. The problem you started with, and
  2. How to express the solution for 1) in code . . . and you don't have that solution yet.

Some folks (who tend to take the second approach) think that these are the same problem, but nope, it's two problems.

Solving 1) before you start 2) means you're not trying to solve two completely different problems, you are focusing on the most difficult problem and getting that out of the way first.

Binary Worrier
  • 3,112
  • 2
  • 25
  • 23
  • 1
    For a lot of folks, code is the easiest and most precise way to express the solution; in other words, the second "problem" is no problem at all. No one ever suggests that before solving a math problem, we should try to write the solution "in words". – kevin cline Apr 30 '11 at 00:35
  • 1
    @Kevin: expressing problems isn't the issue, expressing solutions is :) I'm not saying you plan out every line of code or class, but you need to know - or have a fair idea - where your going to end up as you start writing. The biggest waste I've seen junior - mid level developers make, is starting to codeca solution to a problem and they're unaware they don't know the solution. They get confused and bogged down in implementation details, they - wrongly - equate this with solving the first problem – Binary Worrier Apr 30 '11 at 18:02
  • Some do, but not EVERYONE gets bogged down in implementation details. With modern languages, there is very little difference between design and high-level coding. – kevin cline May 10 '11 at 22:39
0

The former is commonly called "coding into submission", and it's "bad" when it causes you to create overly complex, poorly designed solutions that could have been simplified by some amount of thinking before doing. However, writing a prototype solution in code can be a useful aid to thought as long as you don't try to put the prototype code into production.

On the other hand, the latter (when taken to its logical extreme) can also be "bad". Too much time thinking means not enough time doing. Perfect is the enemy of good, and so on.

The best thing to do is the simplest thing that could possibly work. This means thinking just enough about the problem to come up with a reasonable solution (and no more) and then trying that solution out. Try to find a good balance between thinking and doing.

Rein Henrichs
  • 13,112
  • 42
  • 66
0

If you look at all approaches (some would call them "methodologies") to developing software, it always boils down to:

  1. Define requirements - what exactly are you trying to solve.
  2. Define functional specifications - if you have multiple modules, how are they going to interact with each other. What are inputs, what are outputs
  3. Define software design of each module
  4. Code

A mistake done early on, will always be the most difficult to fix after your code is written. If you have a coding error, usually you can fix it within few lines. If you have a design error, you'd typically need to go back, redefine your classes, move things around and come up with new interfaces. If you made a mistake in the requirements, your design may not even be solving the right problem.

This is why they say that instead of jumping into code as soon as you in front of a computer, take a step back and actually define what exactly you are doing and make determination at that point given the scope of the problem, how much requirements and design should you really do upfront. It may take more time in the beginning, but 9/10 times it saves a lot of time down the road. And even for simpler projects, I would recommend going through the motions of layout down design because it's always a good practice for the future when you start doing not-so-trivial work.

DXM
  • 19,932
  • 4
  • 55
  • 85
  • No, that is definitely not what it boils down to. That's called "waterfall" development and it's a failed strategy. – Rein Henrichs Apr 29 '11 at 19:03
  • other companies do iterative waterfalls where each iteration takes 6 weeks. My team does agile development. We still have release planning stage where we lay down stories (i.e. requirements) and before each story we still have a design phase where we review which components have to change and how that affects the rest of the product. And yes, we do this EVERY TIME before anyone writes code. Simple stories have design phases that last 15 minutes. I'm working on new server and we had "research spikes" which were all consumed by design and defining the foundation – DXM Apr 29 '11 at 19:07
  • @Rein - DXM's suggestions are often required in many cases. I have personally seen it work. – Ramhound Apr 29 '11 at 19:17
  • Perhaps. In any event, describing a full iteration lifecycle is not really an answer to the question. – Rein Henrichs Apr 29 '11 at 19:19
  • 3
    @Rein - I don't care for flinging around methodology names like waterfall, agile, xp... it doesn't matter. Our job as developers is to come up with solutions. A project, big or small, where you put any thought into a design, will be more readable, reliable and extensible. And regardless of methodology, if you don't take the time to identify real-world problem you are solving, then there's a good chance you are wasting your time on all that good design you are doing. – DXM Apr 29 '11 at 19:29
  • @DXM Full ack. +1 – Rein Henrichs Apr 29 '11 at 19:36
  • @DXM I'd be happy to give a +1 if you felt it appropriate to edit your answer to indicate somehow that design/thought time should be proportional to complexity/problem space size. – Rein Henrichs Apr 29 '11 at 21:23
  • @Rein: How can you know the complexity/problem space size before you have a functional spec? – Aaronaught Apr 29 '11 at 21:50
  • The OP's question was in regards to "tricky problems", not entire systems or products. Do you write a functional spec every time you need to make a programming decision? (I write a test case, but that's rather different.) – Rein Henrichs Apr 29 '11 at 21:54
  • "...and actually define what exactly you are doing and make determination at that point given the scope of the problem, how much requirements and design should you really do upfront" -- I think we interpreted the question a bit differently. OP did say "problem" but the rest of the question sounded like solution to the problem would need new code, instead of the "problem" being with the code he already has like a bug or badly written SQL statement. – DXM Apr 30 '11 at 01:38
0

I don't think it's always a clear good/bad issue, it depends a lot on the coder. I have no doubt that there are some people who are completely effective at seeing solutions to some problems clearly in their mind, and can starting to code solid first drafts without having to draw things out. For most people, myself included, problems past a certain degree of complexity do tend to lend themselves to some pencil and paper work.

That said, where you get into the "bad" practice is when someone who can't clearly visualize the solution to their problem starts throwing down code instead of doing the thinking and design work they need to do. Rein calls it "coding into submission" in his response, I personally call it "debugging things into existence". No matter what you call it, it tends to yield poor results with unhandled edge cases, more than the necessary amount of code and poor organization.

Adam Smith
  • 111
  • 3
0

Sometimes it's better to grab a stool instead of a hammer. In code we don't think this applies because bad code doesn't do permanent damage - just undo it or restore the backup. The problem is when you leave the code you just banged away because it 'appears' to work. You can just keep nailing enough boards to patch a leaky roof only to find you've been diverting the water to your electrical panel.

The real problem is inexperienced programmers may not be aware of all the elements involved.

JeffO
  • 36,816
  • 2
  • 57
  • 124