This is really kind of the whole idea behind the "red, green, refactor" mantra. The point isn't to write perfect code right out of the gate, it's to write working code. Once the test is green, then you can refactor as necessary with the confidence that you aren't going to accidentally break things (as the test will backstop you).
Ironically, I think this is something that affects seasoned programmers more than new ones; the more you know about the trade, the more voices you have saying "no, that's wrong! Don't do that!", which can freeze progress. The way I combat it is by writing down pseudocode in my source code - literally just english, non-compiling pseudocode - which I then "refactor" into working code (thus the first "green" is "it parses"). By making step 0 the expression of the idea rather "writing the fist line of code", I can get right into the process rather than getting hung up on the "how".
Also kind of related - programming by "wishful thinking". You first lay out the flow of the program as calls to high level functions which don't yet exist, and then go back and fill in the functions as you can. The first few SICP video lectures are all about this style, and I found the idea simple but very useful to avoid trying to hold too much of a problem in your head at once.
Yes, exactly. By writing pseudocode, I end up writing business code rather than implementation code, which inherently assumes the a high-level interface to the nitty-gritty details. This leads to an approach where the idea is expressed at a high level first, rather than getting stuck in the implementation details of some small piece of the problem.
It's kind of "breadth-first search" on software development, while the classic approach is more "depth-first search".
On the other hand, it is also important to quickly get into the state of a running program, because only that allows for iterative development where you can catch bugs shortly after you wrote them, rather than having tons of bugs after weeks of (not sufficiently tested) work.
I've always heard it as top down development, as opposed to bottom up development. I always say that's what I'm going to do, and then end up not doing it.
I've found what I think is the SICP book, but I can't track down the video lectures - can you provide some links? Thanks - I thought I was the only one programming by "wishful thinking"!
Sometimes I'm surprised at the lack of parallels between writing long-form articles and writing code. How many people draw a general outline of their program, what they want each part to do, and how the whole thing should be layed out? Who plans before they start coding it?
Code is a planning language, so rather than boxes and noodles or pseudocode, I tend to sketch out my plans in code itself. In SICP this is called "design by wishful thinking": you pretend that you already have a library of primitives that do the nitty-gritty work and write the high-level bits of your program using those primitives. Then, you go back and implement the primitives.
Indeed, the "design by wishful thinking" was a real eye opener for me. It is one of my favourite parts of SICP.
It can also be explained as way to postpone decisions you can't clearly make right now. First, you pretend to have made the decision, and later on you implement the decision "you wish you had made".
Definitely an effective technique. Personally I like doing this on a whiteboard so I don't get distracted by errors or Compiler/IDE notifications and can just sketch mostly in realistic looking code.
For smaller segments though, I'll just write out function signatures, an then go back and fill em out or restructure them.
I think these types used to be derogatorily referred to as "cowboy coders" in the 90's by overly process oriented developers who came from an era of mainframes and punchcards.
I think a big shift in modern software development came about when people finally realized that developing software is by nature a "messy" process. Loose text files, REPL sessions filled with red lines on the console, randomly scribbled boxes with arrows on loose sheets of paper strewn about the room; traversing object graphs in your head while on the drive to work. There is no "outline" to frame any of that. The outline only exists after the software has been built.
Yup; which is why the people getting hired for those projects would flounder if asked to make a large individual contribution without much handholding; and also why those types of project team structures yield such incomprehensibly shitty software (at ridiculous cost to the client.)
Seriously? Many of the enterprise devs I know do make large individual contributions in their own (side) projects, or in smaller projects within the organization. Part of enterprise dev is that you are developing within a series of constraints, not least the thought in mind that there is likely to be someone maintaining this code in 10 years time, and it's unlikely to be the team building it today.
I would agree about the general outcome, though - enterprise software often is built _despite_ the politics between various departments and vendors, and much of the solution is as a result of compromise and integrating with "not quite suitable for current purpose" legacy systems. That is where a large amount of the cost goes. (It's also important to remember that what we're building today is also going to become the legacy system of tomorrow, and to include that thought in the design).
Maybe I've been spoiled by working with embedded C++ on Arduinos, where we have 3 sections -- Initialization, Setup function, and Loop function. We set variables and include libraries in the Initialization section at top. We run first-time code and open serial & other connections in Setup. Most code goes into the Loop section, which is the function that does the heavy lifting. Extra functions (i.e. the math to convert inches to mm) can be written below, and called in either Setup or Loop.
This is why programming language history is so important. Every programming language has a large number of opinions/assumptions. Code structure is one of them. The Arduino language, based on C/C++, has assumed a simple code structure that helps people learning embedded programming, because the Arduino platform was designed to help people learn.
developing software is not messy process. what is disturbing is that you think it is and that is normal state. Sure it is messy if you develop by accident so lets see what sticks.
Recently (as in a crazy experience over the past week), I've been feeling the same way described by you, and by the OP; but I've scaled this up to a much higher abstracted level.
The only way I can really describe it is (in terms of what you just said): "red, green, refactor" your life, not just your job. Constantly question everything you're doing, and find out what you don't like about it. Find the root cause of that feeling, and figure out what you can do to fix it. Find and take the steps to complete that.
Edit: I will add though, that the trick is to do so without stopping progress, as you said.
I really like your common English approach to coding. As a designer I often do the same with a few key points that my client and I have discussed with some additional influences taped up around my desk.
Using a visual git client greatly helps with this approach, especially if you are coding in multiple files at once. Once you have "green" status, look over the changed lines in the git GUI and look for lack of patterns, code smells, etc. This separates the coder in you from the reviewer in you.
Perhaps I'm misunderstand you, but what difference do you see for this use case between visual and command-line git clients? I do this all the time with git-diff on the command line, and it might just be a failure of my imagination, but I can't think of how the process would be any different with a visual client. Can you give an example?
Different strokes. I'm like you: I do a git status from the CLI for peace of mind. Others in my company gotta have their SourceTree, and hate the CLI. I disagree, but it's their choice.
Ironically, I think this is something that affects seasoned programmers more than new ones; the more you know about the trade, the more voices you have saying "no, that's wrong! Don't do that!", which can freeze progress. The way I combat it is by writing down pseudocode in my source code - literally just english, non-compiling pseudocode - which I then "refactor" into working code (thus the first "green" is "it parses"). By making step 0 the expression of the idea rather "writing the fist line of code", I can get right into the process rather than getting hung up on the "how".