Bad code is the first step towards good code
medium.com
medium.com
So it is with software.
It provides two major benefits: 1) it lets you give yourself permission to take unwise shortcuts and h=just hack it together til it works, because 2) you've agreed with yourself it's going to get a ground up rewrite, which you'll approach with a much better understanding of the problem (and the solution and the customers and...)
(I'm much more careful these days about either writing properly secured "demo code", or at least hard-coding non-routable ip addresses into it - with comments pointing out the lack of security right where someone would need to be looking to change those hard-coded addresses…)
I started with some really ugly C# code, learned some more about OO, and tried again. Now I just have some bad C# code, but its doing what I need. I'm definitely a better programmer now than I am when I started, and maybe if I find myself a free week sometime later, I'll rewrite the whole thing again.
Refactoring is when you rework a specific section of code, usually that you're about to work on, or just worked on, to be cleaner. It's a long-term approach, and it's how large applications stay maintainable over the long term. For your specific example, you'd leave your app alone. You wouldn't rewrite it, or touch it, until you find a bug, or need to add a new feature, and then you'd rework anything you need to to add the feature cleanly.
On a related note, Refactoring by Martin Fowler is a great book, and I'd recommend everybody pick up a copy. It's a beautiful hardcover and looks great on a shelf, too.
http://www.amazon.com/Refactoring-Improving-Design-Existing-...
api iteration is something most of my projects go through as i use my own systems and refactor the internals to reduce the almost inevitable initial complexity as it begins to piss me off.
to a degree, i suppose the adage still holds true, but moreso as "bad api design on product A leads to better api design on product B (or v2)"
But then, this is really just doing what the author advocates, privately, within your team, before releasing the API.
The internet is rife with v1 APIs that don't have version designators and are deprecated in favor of a version two that was released to "clean things up" but which never really supplanted the version one.
Same with code. Just go out and build something. Iterating upon the idea is what's important and you code can get better as you go.
Whenever I'm working on my personal project I do things that many modern developers would balk at. I'll design and redesign components left and right, I'll leave components in a half completed state, and I'll write the bare minimum of tests to ensure the system works. This is the risk that comes from approaching programming as an art-form. However, as any other artist, I will not go out there to show off my project until it's done, so I don't have to worry too much about pissing people off with my erratic style and questionable intermediate decisions.
On the other hand programming as a profession must be wholly different. If I am getting money for code the expectation is that people want to see whatever they're paying money for. In this case I don't have the opportunity to screw around and try to match the perfect set of ideas to the problem set. Instead I will give myself two or three iterations to do what I've been paid to do, and then I'll clean it up so it satisfies the technical requirements.
Fortunately the latter style of programming tends to lend itself a lot better to TDD, agile, responsiveness and all those other terms we love to throw around until our clients give us that blank stare. At the very least projects you get paid for should have some sort of spec, so you'll be able to say for certain whether you have or have not done what's expected of you.
Even when working professionally, different approaches fit projects of different scales. Processes and tools that keep you sane and productive if you’ve got multiple small teams to co-ordinate over a multi-year project could be absurdly over-managed and inefficient for a couple of developers at adjacent desks who are spending a month writing a bit of in-house automation software.
(Insert obligatory citation of The Mythical Man Month here. It’s about more than just why adding people can make late projects later.)
1. Make it work
2. make it right
3. make it fast
1. Make it right.
2. Make it work.
3. Make it fast.
Once code works, it's all too easy to move on and leave it the way it is. It also usually takes significantly more time to take code that works but is god-awful and clean it up than to take code that is well-factored and make it work correctly. The former usually involves rewriting large fractions of the code (frequently breaking it somehow in the process), while the latter usually just requires minor tweaks after automated testing."Make it right, then make it work" seems to me to take about twenty percent more effort than just "Make it work", but half the effort of "Make it work, then make it right." And dramatically less effort as the time between "making it work" and "making it right" grows.
The stereotype of the young coder, when given no oversight, is to skim over something, declare it crap, and start rewriting without even trying to maintain the original. Sometimes that is the correct move, but since they haven't engaged with long-term maintenance before, they can't tell the difference.
Then I realize that I wrote it.
To really analyze whether your code is good or not you must do what you did with that self-identified bad code: step away for months, forget everything about it, and re-visit it to modify it in some way. Or get someone else to do it for you now and tell you why it sucks.
Code written "in the zone" is more likely to be bad, because when you're "in the zone" even bad code makes sense to you.
Take JavaScript, for example. It's a clear step backward in almost every respect from languages like C++, Java, C#, Python and Perl. JavaScript is full of inexcusable, inherent problems that just plain should not exist. It has basically no standard library, and what does exist is not good at all. Third-party libraries help slightly, but they're rife with problems caused by a lack of proper namespacing or other modularity-enabling language features, and the numerous different ways to fake badly-needed class-based OO functionality. The developer basic development tools (editors, debuggers, and so forth) are lacking in so many ways, and the various runtimes aren't much better.
The only thing it has going for it is that it's widely available in web browsers. That's it.
When using an inferior language compared to what we were using in the 1980s, 1990s and the early 2000s, it wouldn't surprise me at all if inferior software systems are produced. It's just not feasible to build robust systems upon such a shaky, rotten foundation.
When I wish to learn something new, I choose a new technology stack. I read a lot about it, and try my best to code in an idiomatic and clean style for that tech. I might have a couple of iterations right from the start, where I just want to get something to work, and then change it to be clean.
Then there is the kata-mode, where I do something that is familiar to me, but just try to do it better than before. Just to improve my existing skill set when I don't have the energy to do something new.
Then there is the project mode where I got to get paid. This is where the shortcuts are made. When I have time, I will code a version that works with some planning; and I'm talking at micro level, macro level planning has been done already. Then I commit it. And then I refactor it, if I'm happy, I will amend the previous commit. But when the pressure gets higher and there is just no time, the second step is dropped. This is where the technical debt starts accumulating, but at least it works and the project progresses. The first moment I get more time, I try to do some refactoring, but at this point, there never is time or reason to fix all those TODO's and broken windows.
It's a balancing act for me; and at work I have seen both extremities of this balance. And those who are the most experienced, can switch between different modes depending on the deadline; and I see that as one of the most important skills to have in our craft.
It has nothing to do with bad code not working. I think its when bad code works that you learn. You should have seen my pet project when it was started in 2011 (which I'll shamelessly plug, https://writeapp.me). It was a series of scripts all string together. Then it was rewritten using a framework when the first version couldn't be extended. From there the models, views, and controllers have been refactored many times over each time making the app more extensible, less buggy, and from a code perspective, more "right".
It's a one step backward, two steps forward kind of situation. Each time you hit a wall you go back and not only fix one problem but move forward helping yourself avoid other common pitfalls.
1. Write ugly tests
2. Write bad code
3. Refactor the bad code to make it good
4. Refactor the ugly tests to make them pretty
5. Goto 1It's not a novel observation that people improve as they go on. Strange that the community considers this to be a front page article.
Instead, when you've gotten to X ability level, go ahead and make something at X ability level, don't let learning about a new, better way of doing that something stop you from doing it.
There was a saying that I'm going to butcher here from PHP: "While many people obsess over the little details that don't matter and quibble over language wars, the person that knows PHP just gets things done."
This article is in that similar vein where it's more important to ship than to quibble about the things that don't matter that much.
There is a time that this is good advice, and a time that it is bad advice. It is good when it helps you get over analysis paralysis. It is bad when it helps people justify their turning the opportunity to gain 15 years of experience into having gained one year of experience, 15 times.
There was a saying that I'm going to butcher here from PHP: "While many people obsess over the little details that don't matter and quibble over language wars, the person that knows PHP just gets things done."
Being snarky, PHP stands as an example of where you should take a step back, and learn better ways to do it.
Absolutely. I agree 100%. It should definitely be a case-by-case basis.
It's been my experience that for a lot of software, the bad code stays bad code, especially if its being written by people who really don't care about the craft.
I guess we have a lot of perfectionist's on HN who might salivate over every variable or function name (I say this in jest, as I used to be guilty of this).
And so on