Hacker News new | past | comments | ask | show | jobs | submit login

Hell, it’s Saturday and I feel talkative. If somebody is stuck, several steps come to mind:

Do they understand the problem(s) they’re being asked to solve? Toy or otherwise, this strikes me as a necessary condition.

Can they express their solution in discrete steps? Software is brilliantly stupid, and must be told in detail what to do. This step should be independent of language, and is more of a logic exercise.

Can they express their “discrete steps” in the language(s) that are required. This is an engineering problem that can be solved with references, practice, etc. Perhaps we can think of the steps stage as writing in ones native language and the implementation stage as writing in a nonnative tongue.

Debugging. This is a generally applicable skill for any multi step problem. In the case of software there is language and hardware issues in addition to logic and understanding the problem space that usually make things worse. But I have found that if these two aspects can be separated things go much better than blurring the two.

If needed, tuning can be seen as both a (re)design or additional debugging step which is outside the initial discussion. But aside from design, one should separate making something work vs. work fast unless they have a very good grasp of their problem and solution. Much of what we do is separable, as things like abstractions are so useful.

If a student is struggling, the mentor can help them determine which step they are hung up on and the kind of nudging that would be most helpful. People who can create sound, stepwise solutions are useful - they can apply this to pretty much any environment. Knowing the nooks and crannies of a language without good logic/design merely creates hard to maintain code.




A lot of this is mirrored in "Code Complete" -- especially the part about expressing a solution.

Most of it was self-evident information you would naturally pick up, as you made your way through your "programming journey," but the parts about planning were the ones I took copious notes on (and integrated into my own craft).

If you don't know -- exactly -- what problem you're solving, then you're either gonna sit there dumbfounded, unsure of where to go from there, or you'll frenetically start brute-forcing the problem, trying -- sloppily -- everything you can think of.

It never really occurred to me before I read that book that writing the actual software shouldn't be just about 95% of the process. ~40% should be planning: understanding the problem, understanding the tools you have available, and building out a rough outline of how everything's going to work (preferably in pseudocode comments you can then convert into actual code).

Or that you could write code without painstakingly testing every few lines to make sure you "did it right" a la code cowboy.

Wasted a lot of time, and spent too many nights up on caffeine trying to force my way through a problem (albeit it usually worked, with the cost of having to rewrite everything ;).


Yup. That was on of the books I read, along with the pragmatic programmer and other most technical, Unix-y things. People always said I was a step by step kind of guy and that seemed to map well to programming/hacking. Although it helped seeing external reinforcement to solve things ina logical manner without skipping steps.


> you could write code without painstakingly testing every few lines to make sure you "did it right"

This technique would eliminate many of the bugs I create (mostly careless mistakes), if I could be bothered to do it, so I'm surprised to see it presented in a negative light.


How careless is careless?

If they're basic typos/syntax, having something like Rust's "cargo watch" running in a terminal to rebuild files that have changed can be useful. Usually, when I'm done writing a big abstraction, I'll do a quick proof-read, and then go maximize that terminal to see what the compiler found.

A heavy-weight IDE would also serve that purpose. But, I personally cannot stand all the distractions they introduce (drop-downs, red lines, auto-complete shadows, etc.), so I stick with emacs, and just run my unit tests after I'm done writing a big logical block.

If they're matters of logic/constructs/and such: I've found reasoning about in my head the piece I'm writing, first -- and understanding exactly what it's going to do and how it's going to do it, before I even start programming -- to be useful in preventing bad code.

The main problem I've had with "code a few lines, test, code a few more lines, test" is that it always pigeon-holed me into thinking tactically, rather than strategically.

"OK, I gotta write a class that handles X, Y, Z. How's that gonna happen? I don't know. The compiler is a fickle mistress, so I have to focus on getting it to work at all first, before I even think about the grand scheme of things."

When, I could've just written the whole piece in one go, and then dealt with my lexical errors. As long as the logical expressions all make sense, and I understand what my code should be doing, I can make small adjustments here and there.

Dealing with the interpreter/compiler is a distraction, that's best left to a dedicated chunk of time to go over all my errors -- so I can learn from them, and not just give them a quick patch, and move on to the next challenge, without really reflecting on why I had errors.


It's tedious, and tedium is unpleasant. What's surprising about that?


Yes, which is why I often don't do it, and only discover my mistakes far later in the process.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: