Unfortunately I only agree with a handful of these particular proverbs. The set of proverbs that I've found are truly useful to programmers would be "The Zen of Python" (open a Python session and run `import this`)
The Zen of Python:
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
These are some good maxims. But I have to be "that guy" and suggest that maxims and proverbs might not be the best ways to practice zen. I find that the more I memorize how i'm supposed to do it takes me away from thinking about how I could be doing it, with other people in mind.
There are some humorous/insightful koans from ESR, the Tao of Programming, the Codeless Code, etc. The best ones do not tell you how to program; they open up your mind and let you discover the True Path. (They also sound more poetic, and programmers could seriously use more poetry in their lives)
I agree with you: the playful exploration of an idea space can lead to really creative solutions. However, I think what we need to focus on is hacking at the appropriate level.
For example, trying to iterate on regexen to see how well they validate credit cards on your shopping cart form is at a different level to say, trying out a new database system. The former can be undertaken in a desultory way more easily than the latter--and therein lies the trap. It's easy to generate a false sense of progress, seeing code being output and test cases passing, all the while without really understanding or learning anything about the code or the problem at all.
Precision understanding of the mechanics of coding, on the other hand, free you to concentrate on higher problems. You don't need to play whack-a-mole with locks and semaphores to eliminate race conditions, and can focus on developing that revolutionary game.
Yea, that's about the worst advice to give a programmer/hacker. The "maybe I can try this" and "I wonder if I could do this" is the core of my world. I've been told by actual engineers that things I wanted to do were impossible, but I played, and did the impossible. Play with your code.
I find it hard to really understand certain things: design patterns, data structures, and sometimes algorithms, without trying them.
I knew a very, very bright person who could come up with some great and clean code. He definitely understood the problem and his solution was "optimal." Problem, before he even started coding he did an insane amount of research. Not just learning syntax, common patterns, etc.. but to the point of memorizing the entire standard library and reading several books on the problem domain before even beginning with some hash-it-out code. This wasn't for hard problems, just simple CRUD apps (for the most part.) Made it impossible to work with him as a team member.
I'm not seeing the drawback to him. It may have even worked out to his benefit, as over time his knowledge of the craft would grow out of proportion to the rest of his team, say, who were solely focussed on getting things done.
I must say I'm really curious. What was his career trajectory? Has he been successful since?
I think it's talking about people who don't know how to read code and discern what's happening and just end up tweaking things, cutting and pasting code, etc. just kind of crossing their fingers that it will work.
I guess this is a problem with proverbs: lack of context. For architectural design or requirements elicitation it's all about improving with iterations. However with detailed design you can be quite precise and shouldn't just wing it.
They also tend to be the ones who have only a superficial understanding of what their code/the language is doing, and to whom edge cases are an almost unknown concept. Those people would be well advised to apply the Feynman Algorithm more.
I think you might have misunderstand the Feynman Algorithm (alternative possibility, I misunderstood it).
My understanding of the Feynman Algorithm was that it was basically a joke by Gell-Mann. Gell-Mann was pointing out that no one else on earth (even himself, a Noble prize winner) could work the way Feynman did, the joke being that he only needed three steps: (1) Write down the problem. (2) Think real hard. (3) Write down the solution. It was about the absurd brilliance of Feynman, not intended as any sort of useful model to follow.
In my experience, it ends up being much more efficient (in the long term) to "understand with precision" - think and think and think about it, and only after you've thought it through, write the code.
"Try until it works" is a mark of an inexperienced craftsman - simply not knowing enough about the tools, the particular domain and the problem at hand forces one to try and try again until something works.. but that kind of "accidental" approach is inefficient compared to an intentional, measured approach.
It's very humbling to work alongside an older, experienced developer - the proportion of time they spend writing actual code is relatively low; most of the time is spent on working out the assumptions, the constraints, teasing out the larger picture from the details, and constructing a technical design... the actual code-writing is like a few quick yet measured strikes of a samurai sword - quiet, almost invisible, frighteningly effective.
I was struck by how the backgrounds had utterly nothing to do with the verbiage. At least Despair.com strives for some connection between image & words.
I don't know, I can imagine quite a number of fresh programmers marching into a meeting room, believing they've solved all the company's problems with a pithy yet profound statement.
1. Start with the answer, then work back.
2. Don't repeat yourself. (DRY)
3. Normalize the data. The process will follow.
4. Isolate. Isolate. Isolate.
5. It worked. You touched it. It doesn't work. It was you.
6. Write for the next programmer, not the machine.
7. If you don't hate your old code, you haven't grown enough.
8. The first A/B test is your own.
9. Focus on the microseconds & the nanaseconds take care of themselves.
10. The fastest code is the code you don't write.
11. The 2nd worst programmer is who wrote what you're maintaining.
12. The worst programmer is the one who changes your code.
13. Comments don't execute.
14. The best technical co-founder is a code generator.
15. The user never knows what they want until UAT.
16. Fast. Cheap. Right. Choose 2.
17. Perfect specs or rapid iterations. Choose 1.
18. Start with "Hello World", then amend.
19. Never deploy on Friday.
20. Forget to unit test? That's a paddlin'.
That's true, but my recommendation to newer programmers is still learn to practice radical DRY first, then as the final polish, learn when to back off (i.e., "the rule of three"). Far, far more programmers do not understand DRY, and accidentally avoid over-sharing by virtue of simply having bad coding practices in general and rewriting everything every time than overdo DRY.
Someday I ought to write up a post about this sort of thing on my blog. I think part of our eternal warfare about coding practices (though by no means all of it) comes from the fact that there are different practices that should be followed by someone with two years of experience than someone with ten. For instance, I think test-driven development is great... for a new programmer. It is something that you will outgrow eventually. But in the meantime, TDD will teach you good design much more quickly than you would have learned any other way, and in the meantime, you'll produce better code than you would have otherwise just blundering around in the traditional manner. And for myself at coming up fast on 20 years of experience, I don't do "TDD" but I still do a lot of automated testing (and the damned code keeps surprising me, and punishing me whenever I think this time for sure I can skip the tests...).
So too here with DRY; you may someday outgrow it, but you'll learn better design and programming skills in the meantime, and in the end I still think you'll find the optimum point is closer to DRY than farther from it. I think that's because beyond the surface gloss of DRY from a perspective of simply "not repeating code" you come to understand how a bit of code can embody a concept, and what DRY is really trying to teach you to avoid is having a concept live in two places, rather than raw code repetition, and that idea will stick with you until the end of your career. But to get to that level of understanding, practice radical DRY until you understand.
I don't know your language's tooling, but I don't think that the decision of when to share code or not - (i.e. if it actually represents the same concept) is something that is solved by a specific tool, or is limited to a specific language.
I've never seen a problem that comes from code being shared, and I think that comes from maven getting the rules right:
* Releases are immutable
* Releases can only depend on releases
* Releases can only be made when all tests pass. Twice.
* The transitive dependency graph is a deterministic function of the config file; upstream changes cannot affect it
* Dependency versions are only updated by an explicit manual step
You never worry about "synchronizing" changes because other components can perfectly well depend on an old version of the library. You never accidentally break a downstream project, because everything's explicit. I have genuinely never seen the problems described in your link.
You are talking about binary compatibility and immutable dependencies. That's nice, but it's a different topic to the conversation that jerf and I are having about the semantics of shared code. I'm sure maven is good at what it does, but it's not completely relevant.
Fine, then let me put it this way: your initial claim in no way matches my experience. "Beware the Share" is bad advice; that wiki page is simply wrong. Factoring out common code is a good thing and will not bite you.
It's a wiki page, but it's also a book [1]. I have an actual paper copy, and I would highly recommend it. I've seen several of the authors give talks, most were good. Kevlin Henney (the Editor) was particularly so.
However I shall also treat the data from your deep experience with all due reverence.
Discrimination, when not applied to people, is a good thing. If you have spent years learning some discipline, and you have developed no preferences, you are not "avoiding stagnation", you are indecisive to the point of paralysis.
Challenge them occasionally, sure, but failure to develop preferences is a massive judgment failure.
For what it's worth, this is the first one in that list that I looked at and decided was garbage... I kept scanning for another few and saw little reason to change my mind, as it was not an exception. Pretty landscapes notwithstanding, this entire list was quite sophomoric... it seems to me the criteria for inclusion was sounding wise rather than being wise.
Right, which is exactly why "The first symptom of stagnation is preference." is dumb. How do you tell the difference between "stagnation" and knowing the best tool for the job? What's that you say? It takes time and thinking beyond a pithy saying? Then why bother with the pithy saying?
Knowing the best tool for the job means that you pick different tools for different jobs. Having a (strong) preference means you pick the same tool if at all possible.
I don't know why, but I'm still consistently surprised that we have the ability to link to the obscure sources of well-known quotes from 24+ years ago.
Actually hoped to see more true, but satirical, statements like: "It usually takes a long time to find a shorter way." or "Debugging software is the practice of removing bugs. Programming is the art of putting them in." Currently seems more like criticising a lecture.
Back in the days of Windows 3.11, in frustration, I coined one that so far has not gained any traction:
"that which can be configured must be configured"
Just like there are few people with IQ exactly 100, there are few users for whom all the default settings are appropriate. One has to review all config panels to be sure, and I have never done so without finding one critical default or another that was just plain problematic.
Lesson: make defaults clear, as few as possible, and all found in one place.
There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies.
http://theprofoundprogrammer.com/post/28552672458/text-maybe...
http://theprofoundprogrammer.com/post/30809835982/text-race-...
http://theprofoundprogrammer.com/post/34818584135/text-do-no...