The best solutions don't come from hacking, but by grasping the problem and it's full scope, the chance raises that you find a solution that can not only be used for the current problem, but also for similar other problems. A good programmer always tries to find similarities and to reuse old solutions in as many other areas as possible, but not more.
Such a behavior also boosts the maintainability of the solution. On the other hand, when it is ignored, a solution quickly can become unmaintainable and the solution that was implemented so "quickly" can become a black hole of man power.
I personally experienced more than one project, where the source code has become in very short time so complex and so bug ridden, that development times literally exploded.
As women we should be able to birth the same babies?
After the baby is born anyone can raise the child, some better than others, but its easy. We call that adoption. Until its born though, the baby, and it's mother are symbiotically connected to each other.
I think this is similar to the process of programming. Break down an interface, and work on a team at that level. Behind the interface though, keep it small. one or two people max if possible, and those people have to be on exactly the same brain wave as each other. Even well planned code takes some time to stabilize, and it's hard to even find that if other people are actively changing interfaces etc.
That analogy only seems to work well if the software you're developing can autonomously interact with other software, like how humans can interact with other humans.
Very well put. I have a similar (slightly younger) age, and often pose myself the same set of questions on speed, tooling, typing. Needless to say, my answers are very similar to yours.
As for the Design Process, it works in the exact same way you describe in other fields like Architecture, which I studied and practiced ages ago at a more than decent level.
Money (VCs'), the myth of the young billionaire, and a few other things are probably what make developing different.
> The casualty of my being a slow programmer among fast programmers was a form of dysrhythmia – whereby my coding rhythm got aliased out of existence by the pummeling of other coders’ machine gun iterations. My programming style is defined by organic arcs of different sizes and timescales...
Boy oh boy. Look, I'm all for coding slow, taking time and understanding what you're doing. But there is something to be said for "playing well with others". We're all trying to make things, not be the backdrop for your exquisitely-crafted sense of craft.
To me that reads a lot like "I would have done something really good if I weren't surrounded by those philistines". Well, maybe so, but you are surrounded by them. So choosing a method of working that does not result in "dysrhythmia" or whatever strikes me as rather prudent.
"Everyone around you is building this bridge in clay.... what are you doing fooling around with this 'steel' crap for?"
Of course you can spin it the other way too, which just goes to show this isn't a useful comment. Don't do what everybody else is doing just because they're doing it, do the right thing. If that does happen to be clay, great, but there's a great deal more people using inappropriately sloppy engineering than people using inappropriately careful engineering, so I'd expect to hear a lot more about the former.
The only people in real life that I've met that I would consider saying were being inappropriately careful were really just masking fundamental incompetence under a veneer of concern about process. I'm not sure I've ever seen anybody correctly apply massive overengineering to a programming task in real life. I'm absolutely sure it has happened, but it is not common enough to be worth talking about.
Don't do what everyone else does if you can do something better that leads to better results. The last part matters -- otherwise you're just crapping on everyone who can go faster than you and attributing the difference to "quality" (conveniently left nebulously defined).
Put another way, how do you know what you're working with is steel, and others clay? What if your "steel" is really just clay that is slower to produce and more brittle? How do you reassure yourself that this isn't the case? The answer is, make a big deal about going slower and drink tea and stroke your beard and say "hmmmm." and lots of other things that connote wisdom but do not actually bring it to bear.
I am extremely skeptical of all this, not because I am unsympathetic but rather the contrary. We can get extremely wrapped up in our signifiers of skill and wisdom, to the point that we mistake the map for the territory. Instead of cursing the punk kids, try to learn from them and beat them at their own game.
I find this sort of thing fascinating. I think it nicely showcases how perspective matters on this sort of thing. I almost feel like the whole fast/slow dichotomy is missing the point, since you can have two polar opposite views agree. What the point it... well, I guess that's why there's hundreds of replys in this thread.
> But there is something to be said for "playing well with others". We're all trying to make things, not be the backdrop for your exquisitely-crafted sense of craft.
I had the same reaction here. Everybody wants good design. This article seems to walk the line between providing valuable insight and just complaining about how other people work.
The problem is clean code is only a net gain when it sticks around. So, some teams are toxic to clean code. Let's refactor to use library X, no wait, libarary Y. There is a conflict with foo unless you use bar version 0.37c. Or the classic: "Works on my machine."
I used to think it had to stick around for some time. In practice you start paying for bad code after about a month and you pay back many times over. If a bunch of people are throwing poor code in, the payback becomes exponential before you know it.
Most of my work at the moment is done for a client which had exactly this problem, and it nearly destroyed their business. I came in about two years into the cleanup and things were still a mess. With a lot of work all around (and some pushing by me to focus on code contracts more), things have continued to steadily improve.
But the problem you mention is real and it can sink businesses.
One of the things I have had to learn is how to code slowly in a fast code organization. This means understanding where I am going and doing lots of small iterations to get there.
One of the reasons for small iterations of a working system is that it gives you a limited QA footprint. This is far underrated. But it means that over the course of many iterations, my code ends up coming out, well designed and elegant, and playing well with others.
Short iterations and fast releases of a production web site, for example, are not the enemies of slow coding. In fact they have a role to play as well. What is the enemy is trying to do everything at once within a fast release cycle.
And yet, most coding rounds in interviews are rigorously timed. Almost always, the importance is given to code completeness rather than code design/elegance. I'm sure a lot of talented engineers lose out here.
Most interviews I've done have expected me to write code on a whiteboard. This is pretty unnatural for me. I'm a very fast typist, so it's frustratingly slow to have to draw letters manually on the whiteboard.
At least in my experience, the main point of coding interviews has always been to expose and analyze the way that you approach and solve problems, not to see how fast you write code. It's usually better to take a step back and re-evaluate the design of your solution rather than dive into the first solution you create, since you'll usually find a better way to express the solution that is short enough to write down on the whiteboard without pressing against the time constraints.
It's also important to see how reliant people are on their tools.
If you're asking them to design something rather than build something off a pre-existing design, you might like to know that they actually understand the principles of design, and aren't relying on a tool to pretend they do.
It is completely reasonable to rely on a text editor and the language interpreter. Hell, even the language documentation.
This could be an issue with really fancy IDE features, but there's a world of difference between a whiteboard and an IDE - namely, a text editor and an interpreter/compiler.
I don't think the whiteboard interviews expect an executable at the end of the process. It's not a complete test, but a partial one: testing if you can come up with suitable algorithms within a reasonable time - and perhaps how you work/your process. None of which is dependent on any (software/IDE) tools
> most coding rounds in interviews are rigorously timed
In the real world you will have to work against a deadline. As much as code gardening is fun and does produce better software, in the real world shipped software always wins over well designed software.
Can you get it done, is a more important question to answer than can you make it beautiful.
In the real world, you'll be spending more time on code design than typing it out. The race against a deadline mostly affects design choices. eg. Whether implementing a certain feature yourself with rigorous testing, or introducing a new technology which has been tested before. There are pros and cons of each. You go ahead based on the constraints involved (time, cost, expertise, etc.). I'm not talking about making the code beautiful. I'm talking about the /right/ way to do it.
I joined one of those 7-day coding competitions for a game. I ended up with a framework for making games, but no game. Needless to say, I came in last place.
If you can't write a simple function to reverse a string, or words in a string, in a rather short amount of time, is that a good sign? Sure, everyone can pop out the "well the most elegant is use the stdlib's reverse function". But then you say well implement that as efficiently as possible, and we know the end result is a simple little loop -- what should taking more time mean? Someone that takes 10 minutes to come up with the function makes me a bit more nervous than someone that takes 1 minute. Is that wrong?
You have decades on me and I still wish to work your way. It maybe anecdotal, but the more timepressure a codebase has been under the less i've liked it, roughly speaking.
I recently disregarded the competence of a coworker (who is in a programmer position) because I took a class with them and saw that they could not type. They were hunting and pecking. (This guy is 50 years old so has had plenty of time to learn)
Is that wrong? Does being bad at typing force you to be more thoughtful and actually make you a better programmer? Or does it just mean it takes you longer?
My thinking is that you are not doing much thinking while you are actually typing, so not being able to type proficiently just means you're slower and that's it. So all else being equal, a programmer that can't type well is a red flag.
I would say it's wrong, typing faster will not produce better software. Most of the time involved in writing software is not actually writing it. You may type 3x faster but if he is 5x faster at coming up with a quality solution then your gains will be lost.
Think it the other way around: if someone can come up with a solution 5x fater than you and also type 3x faster than you, then how long you are going to catch up with him.
I type about 105 wpm using four fingers (my index fingers and my thumbs); I don't touch type at all but I also don't look at the keyboard, I just know where the keys are from muscle memory (when switching to a keyboard that is unfamiliar to me it takes me a minute or two to adjust if the keys are particularly different in shape/size from ones I usually use). I'm not sure what that says about me as a programmer.
In any case I don't think it makes sense to use typing speed as a measure of programming competence because typing speed is never the bottleneck in producing real, useful code.
Things get really weird when you consider the effect of template / tab completion systems like yasnippet in emacs and numerous non-free alternatives.
(template systems are an editor extension where you type "i" "f" "tab" and magically an entire if statement stanza instantly appears all perfectly formatted and ready for the details to be filled out.)
So if I type at 40 wpm, but 4 keystrokes of mine do more than 16 keystrokes from someone who doesn't use a template system, does that mean I'm effectively typing at 160 wpm? I guess so.
I also use an extension that magically aggressively indents so I don't indent, my editor takes care of it for me, so I guess I'm typing at infinite wpm when formatting code, compared to someone who hand indents.
I guess it is touch typing if you define touch typing as any kind of typing without looking, but it isn't what most people think of touch typing, I don't have any sort of "rest" or "home" position.
I never really considered a "home" position, but I think my fingers do tend to end up around roughly the same keys between thoughts: [L-shift]SDF / KL;'
There's no correlation but at least it makes you more productive. Like using an IDE or good editor does not make you a good programmer, but it could improve your productivity in the right situations. For example, I don't want to waste a lot of time hunt-and-pecking emails or IM. Touch typing helps.
Sure, if they are hunting for the correct keys that is a bad sign. However I don't equate super fast typing with actual speed of progress. Very rarely am I coding as fast as I can type. In fact, that never happens.
Sure, if they are hunting for the correct keys that is a bad sign. However I don't equate super fast typing with actual speed of progress. Very rarely am I coding as fast as I can type. In fact, that never happens.
Yes, typing speed, when looked at in isolation, does not cause the production of high-quality code. But there is an argument to be made for reducing the friction between one's mind and the code on the screen. Insofar as we can ignore that transference of data from biology to technology, we can think more fully and clearly. So, emacs commands that are fully ingrained in one's subconscious may be good, but probably not the C-u 12 C-x TAB; at least for somebody simple like me.
Actually, I've found that the act of moving what's in my mind to a source file is in itself an act of revision for my ideas. I don't need to type fast for it to happen, because I'm not going to write anything at all until I have a solid idea or path in my head. The actual act of typing consumes less than 10% of my programming time, and is for the most part a mere formalization of my thoughts. Would a 50% increase in typing speed make me finish the feature in 4 days instead of 5? Nope.
I used to believe that. It's why I picked up coffee script. I thought, the less there is to type, the more you can focus on the problem rather than the code.
I found out I was wrong.
The redundancy actually helps. There's somehow a calming effect in it. I don't know how to put it into words.
I found out that I never actually think while typing per se. I have to first jot down my thoughts on paper. Typing out the code becomes almost a mechanical process. I already know what I'm typing, I've figured it all out and put it in paper (or some plain text note in another text editor or note taking app).
There's stress in trying to hold it all in your head. That stress is released when you jot things down. Then you can just mechanically write out code with less levels of stress.
The explicit syntax means you have more to type but less to think about.
I know it sounds paradoxical. But that's been my personal experience.
It doesn't work that way for me - for some reason the syntax makes a huge difference in my productivity and level of energy.
Coffeescript works way better than JavaScript, Elixir better than Erlang, Slim better than ERB. It shouldn't make that much of a difference, but it does.
It's not paradoxical at all. I think that the more syntax you have (thus shortening the code), the less you can reason about what you write while writing it, because the mental overhead of writing itself goes up. Compare stenography to latin in that regard - stenography is almost never used to write down ideas, only to transcribe.
My hands sometimes get pain and there's a hardwired response that makes me feel awkward, physically, I've I start typing out a lot of repetitive code. When I read Java or most C# code, I just cringe at all the extra crap, at all the pomp and boilerplate. Every time I have to write it, I feel annoyed that I need to type more stuff out like an idiot, because some compiler writer had misguided ideas, or because they already dug enough technical debt to allow more expressivity.
I agree with you to a point. I am a touch typist. There's something to be said about a lack of friction.
However, at the same time, there is also something to be said for friction and learning to work with friction. It is about time and the amount of deliberation the concentration of holding a thought in your mind for longer.
I am a touch typist and I appreciate that I am. However, I also find that spending some time periodically with a quill pen, writing thoughts down with that, is extremely valuable for the opposite reason.
One of the core challenges is how to slow down thought. This is something which has many, many benefits, and touch typing at the speed of thought would not be conducive to quality code.
He makes a reasonable point, but this piece is largely a strawman. And
> For the same reason that many neuroscientists now believe that the fluid-like flow of neuronal firing throughout the brain has a temporal reverberation which has everything to do with thought and consciousness, good design takes time.
> As long as everyone makes frequent commits, and doesn’t break anything, everything will come out just fine.
He is presenting the arguments and beliefs of his intellectual opponents in a way they probably have not or would not, and then attacking that argument.
Now in a piece like this there is nothing wrong with that -- but in terms of the strength of an argument, it is no greater than just enthusiastically stating his preference.
Yea, the article kinda reads like "bad programmers are bad, and I'm a code master, and the kids don't program like me, and they're bad-bad-bad. their fast is so slow. my slow is so fast."
It's weird how he like does this thing where he equates their fast with thoughtlessness, and his slow with actual fast.
That being said, I'm all about white-boarding, project planning, and clearing out dependencies, but if an engineer is slowly coding something without any deliverables, chances are their going to hit a wall near the deadline. I've seen this happen too many times.
I probably spend just as much or more time sitting, thinking, and staring at partially written code, than I do actually writing the code. It's frustrating when you have superiors who don't understand that time spent thinking is just as productive as time spent typing.
That's just my personal style, although I've never worked in "large" teams on a single codebase so can't comment on what styles work best in those situations.
The best analogy I heard for communicating this to superiors is that programming is like doing a crossword puzzle. 95% of the time you're doing a crossword you're not writing but that doesn't mean you're not intensely working on solving the puzzle.
> Fast programmers build hacky tools to get around the hacky tools that they built to get around the hacky tools that they built to help them code.
This resonates so much with me. Sometimes I worry that I'm falling behind on keeping up with technology, but whenever I try to learn something new it seems like I have to install a package manager, then another package manager inside the first one, then pull a million other tools and libraries and frameworks before I can even begin doing something with this stuff I'm trying to learn. No, thanks.
I love computers, I love computing, I love thinking about solving problems using computers, but I hate the direction things seem to be taking. I'm seriously considering a career change in the immediate future because all this crazy tooling truly burns me out.
Try Go, seriously. There's just the one tool. No package manager, no dependencies... And the code it produces is the same. Just a binary. "Here, have this tool, just run it." It's small, simple, and the community actively searches out simple solutions.
I don't know that I agree with that. Tooling bloat was specifically mentioned, and Go is quite good with respect to that.
There's just the one go tool to install, which can be installed just by unzipping a zip file. From there on in, you don't need any other tools. It just uses VCS for package management. You don't need an IDE... the single go tool has support for pretty much every part of the development cycle - compiling, testing, code formatting, profiling... there are no other tools you need to create real deliverable software. I've been writing Go for over two years and still haven't added any other tools to my standard workflow - git and go are the only two commands I type while writing go code. (At work we use a revision pinning tool, but I haven't needed that on my side projects.)
I found go to be quite cumbersome in comparison to npm. Magic folders in the filesystem and such. With node you never have to do more than npm install and everything is ready.
Go has a couple wonky conventions, but it's a very very simple system. Once you accept and learn to deal with the GOPATH quirks, that's pretty much the only tooling weirdness in the whole ecosystem.
npm (and the CommonJS module system) is the #1 reason I use Node.js. I don't care if Javascript is ugly, npm totally makes up for it. I don't get why most module systems implicitly import symbols in the scope (Python, Ruby) or worse, those that pollute the global scope (PHP).
Brew (Ruby) is not that bad but Python's package ecosystem is a complete mess (distutils, setuptools, pip, etc.). Cabal (Haskell) is pretty good too in comparison to C/C++ (installing dependencies usually involves following instructions in a README file, that is, if there are available instructions for your OS). I haven't tried Go.
I believe the language of the future will be built around, and win mainly because of, its package system/ecosystem.
npm is easily the worst. Python is a lot better. I hold the C library model as the golden standard, so we're not going to see eye-to-eye.
The worst part of npm is the sub-dependencies. Having enabled them, they proliferate endlessly. Each time I improve the efficiency of deploying a strictly controlled tree of modules, the front-end devs manage to double the number in use. 200, 350, 650, over 1000... oh and these improvements come from realizing that npm-shrinkwrap isn't 100% reliable, and ending up with scripts comparing npm-ls output and doing full wipe and replace with a tarball for even the slightest change to the dependency tree.
If some serious bug is discovered in one of these things, there's no way the 20 copies of it at various levels of this tree of 1000 modules are going to get patched. No one really has a handle on what's in these hundreds of megs of various versions of modules. This is the true fast code movement - serious problems can't be fixed in there, they'll just be ignored and replaced with other bugs in the twice-yearly full rewrite. Don't get me wrong, our frontend devs are among the best I've seen, but the pressures and environment they're in make them focus on churning out the latest fad in web design and skimping on engineering quality everywhere possible.
Python doesn't do implicit import of symbols into a scope if you don't use "from blah import (star)". Don't use the (star).
Managing, and using, a list of python modules, each at a particular version, is way simpler, more reliable, and more efficient (than npm style). Pip can reliably list installed module state (freeze) and install from source tarballs or git tag checkout.
You need to fully control and understand the versions of all libraries installed and used on a system in order to have a fully reproducible deployment state, and be able to reliably roll back to a previous state. Given that, the Python or C model is much easier to work with.
Go's model is pretty good. This is why there's just a single $GOPATH and every package has exactly one location on disk, so even if 100 dependencies use the same subdependency... you only have to update one spot if it needs a patch. And again, this only needs to be done at development time. It's baked in when you compile, and from there on, deployment is just a file copy of your binary. No dependencies during deployment.
Maybe I'm missing something, but this seems like a bad idea to me. What if projects are relying on differing versions of the same package? What if two developers collaborating on the same project have different versions of that dependency installed?
Sure, it's space-efficient, but disk is cheap, and developer hours are expensive. I certainly wouldn't want two employees burning man-hours trying to figure out why some app is behaving differently on their respective machines, only to fix the problem and unwittingly break another project in the most expensively subtle of ways.
I'd really like to think I'm missing something though, I certainly don't presume to be more insightful than the collective Go team.
There's a philosophical disagreement here. It's true, developers are expensive. But I think it's a fallacy that what's less efficient for a computer is better for a developer. The npm-style dependency tree enables and encourages much more complexity, which developers then have to deal with when debugging or deploying. They need new tools to help them get a handle on the huge number of modules. That's more expensive than a system kept more "under control".
> I think it's a fallacy that what's less efficient for a computer is better for a developer.
I don't think that was ever said; I claimed that trading disk space for developer hours is a good trade-off in this case.
> The npm-style dependency tree enables and encourages much more complexity, which developers then have to deal with when debugging or deploying.
I don't believe this is the case. When developing an app (as opposed to a library) it's considered a best practice to check your node modules into source control, ensuring that there's never a mismatch between installed dependencies on developer machines. If you don't want to do that, you take what comes - but even before I picked up on that, I never ran into issues even when collaborating with 5+ developers. You just need to make sure your package.json locks your versions appropriately.
So, in theory, any particular import path should be stable. There are no "different versions" of the same import path. A different version would be a different path.
So, for example, github.com/natefinch/lumberjack is an import path. When I wanted to change the API, I have to put my project at a different import path so I don't break projects that use this version. I could just make a new github repo called lumberjack-v2 and that would work fine.
Of course, reality and theory don't always see eye to eye, and the Go community realizes this. That's why there are several community-made tools to help out.
The most well-respected one is godep, which has the ability to pin revisions on your dependencies. That is, it'll look at the git commit hash (or equiv for hg/bzr/svn) for every repo that you depend on, and record it in a file in your repo. It can then reset those dependencies to those specific hashes. Then all members of your team just need to use godep to make sure they're all using the exact same git commits for all dependencies. Bam - now you're insulated from someone updating a dependency with breaking changes, and your team can test new revisions and decide when they want to start using them.
Godep has a second function that lets you copy all your dependencies into your repo and renames all import statements to reference the copied paths. This is an even more extreme version of the above, which not only insulates you from changes in dependencies, but also insulates you from those dependencies disappearing entirely.
Godep is definitely a good tool. One thing that gives me pause, though, is that this functionality is not built into `go get`. Failing to put hard versioning into the canonical package manager seems short-sighted to me. I'd much prefer that over something like the race detector.
We definitely have a philosophical disagreement. The fact that an app (especially a server side one where storage is usually cheap) has hundreds of dependency signals to me that the package system is successful. It tells me that there is a lot of code re-use going on and that it's presumably easy to import new dependencies. By now, I believe the number of NPM packages outnumbers any other package manager by far despite being relatively new.
So basically, I think your point is that a project should have as few dependencies as possible whereas I think the opposite is good. Both philosophies have their pros and cons. If you are writing mission critical software that handles financial data, it's probably a good idea to know about every line of code that gets executed. However, if your goal is to release something as fast as possible, have a more manageable code base and security is not as critical, using lots of dependencies makes sense.
FWIW, Go namespaces everything by default, so if you import a package called foo, all types, functions, etc from that package are namespaced by foo, i.e. "foo.whatever"
The thing I love about Go's packaging is that your VCS and package manager are the same thing. There's no need to wonder where the code from package foo comes from... because you know you imported it from github.com/jimbob/foo It also means there's no fighting over namespaces, since it's just done by domain name (i.e. I can have the package npf.io/foo because I control that domain, and I don't have to to fight over who gets to use that name).
npm is without a doubt the best module system I've come across in my years of development. RubyGems is kind of a pain, .NET dependency management is a joke, Python is super fragmented, and Go doesn't have one. Godeps is an okay tool, and `go get` is cute, but I have yet to use a package manager that couldn't stand to borrow a thing or two from npm.
In Go, the dependencies only matter during development not during deployment. Let the developer hash out what specific version of each library works, and then during deployment, it's all baked into a single statically linked executable.
That's the nice thing about using tools written in Go. There is no npm install. There's a file copy. Bam, done. You don't even need to know it was written in Go unless you're using the code for your own development.
The magic folders in the filesystem exist in every package manager, it's just more obvious in Go. So, for example, npm puts code it downloads into /usr/local/lib/node. I'm very far from a Node expert, but this doesn't sound terribly different from GOPATH.
Yeah, I was also about to post a comment recommending Go. It's not completely immune to tooling bloat, but it's actively reductionist in that respect. It's relatively pleasant.
There's no required package manager. By default, your VCS is your package manager. You can write code for a long long time with just the default go tool. Those are optional tools that you can use once you become comfortable with the language and understand their tradeoffs. You really don't need any of those tools until you want to write a professional project with multiple people on a team.
It is not the fault of these tools. You can think of code as data, and programmers producing this data, just like many other professions are producing data, too. Programmers often have a variety of far better tools to handle this data. I think the reason for this are of course the programmers dogfooding, but also the culture of life-long learning, which minimizes UI design to just API design. An intuitive GUI for a crowd less open to learning new things is so much harder to make.
I nevertheless see this as a gift. It is your attitude with these tools, that makes you unhappy. I I often have this strange feeling of missing out on an even better technology, the cool kids might be using. I think the key here is to be confident with your choices of tools, improve them, when their is pain and identify when something is good enough for some time (measured in years) before you should reconsider again. In the end it is also about handling the tools. This sounds very reasonable but in practice it is often hard to overcome the urge to use the new shiny tool, which seems to make you a better programmer, when you define yourself as one.
I don't think the extremist view of skipping them altogether and condemning the whole thing is the solution. I believe people, who feel they can't keep up in this imaginary race either search for ways to define themselves in another way e.g. in alternative careers (like you) or in their opposing way of programming (like the article author) throwing the others in a bottle of people, who do it wrong. There is a middle-ground between the Node developer and his weekly changing recursive package managers and the Coldfusion shop not doing scm.
> Curious which languages you use that don't have this problem?
None. It's why I'm burnt out and want to so something different. Not something different from my current job. Something different from developing software.
I've lost count of how many times I've spent entire work days battling against the environment which is supposed to help me write the code I need to, to make a customer happy. Entire days of trying to figure out why IIS is acting crazy, or why Visual Studio is crashing, or why is Windows so damn slow all of a sudden. Entire days of trying to align the planets so that service A can talk to service B, because for some reason there's a cryptic SSL error that's not giving me any helpful information as to what's happening. Or entire days just pulling things from a dozen different sources and figuring out where to place each other so they can work together.
I've recently been to the Living Computer Museum in Seattle. You can play around with old computers there. I was fascinated by the old machines where you'd boot into a REPL. The shell was a REPL to the language you programmed the system in. I think despite all the advances we've made in the past decades and all the great performing technology we have nowadays, we've lost that essence of simplicity along the way.
VS is an awesome development environment, but I was having your problems with Windows and programs running under Windows for most of my adult life. I switched to Linux full-time at about 5-6 years ago, and I've been happy ever since. I can leave the OS running for weeks with no issues, and it would probably go for months but I'll turn the power off.
Oh, and with Linux, if you don't run a graphical desktop environment like Gnome or KDE (which most distros have the option of doing), then you boot into a REPL you can program the system in (Bash shell). Windows used to have the same with DOS, but no more...
I feel the same way you do about everything you said, including considering a career change for this same reason.
I'm now fiddling with Tcl/Tk as a way to quickly throw some visual ideas around. I'm using it to build an idea for a tabular programming language that is more visual and allows for letting go of incidental details like syntax, argument order, etc.
Simplicity for simplicity's sake isn't a virtue. I often feel that Go chooses that path ideologically, whereas real world use cases should have more innings (yes, it's the generics and shitty type system thing again, I'm not expecting us to agree, I'm just pointing it out).
To that end, Go doesn't work for me. I use a fairly straightforward stack atop the JVM because I can hold the whole thing in my head (nothing in either Dropwizard or Play is deep magic) and have the expressiveness in Scala to be clear with my code.
And the issue isn't so much whether or not a programmer can hold the "entire system" in their head so much as, if they don't need to, they can be doing a whole lot more. This is, after all, what computers are good for.
I can do a lot more when I can trust my system to evaluate my code and throw compile-time errors. I can't trust Go's you're system in the same way I can Scala.
I noted the simplicity of the stack mostly to forestall the usual tired complaints about complexity, nothing more. What you call "academic", I call "building at scale."
I largely agree w/ the argument here, but "slow" is going to be self-defeating nomenclature, and is also inaccurate. Business doesn't want slow. So if we're pitching slow, we're setting ourselves up to lose and the speed-hackers are going to win.
Our goal is architectural soundness. I believe the biggest fallacy of our industry is we think the only way to get these is to go "slow". Not true.
What we're really saying is our industry is short on skill sets. With specific skill sets, you can build architecturally sound systems at no extra cost.
If I were to build a house today it would take me much longer than someone else because I don't have the necessary skills. I might hurry in which case the house would be shoddy. Is the shoddiness of the house necessarily because I hurried? No. It's because I didn't acquire the required skill sets first.
The software industry has no such (practical) concept of the skill sets required to build architecturally sound systems. We have a bunch of well-meaning hackers, and as a result shoddy systems that decay into technical liabilities.
Our industry needs to solve this skill set problem. The challenge is that academia has a hard time teaching these skill sets, because they are so removed from the practitioner. And businesses can't teach it b/c it takes years and special experience to actually teach it. So it's not advantageous to a business to teach those skill sets.
So how do we do it? And how do we organize an industry around professionals who know how to build architecturally sound systems and code? This is a very difficult problem for a world that has such high demand for code and such little understanding of what the professional skill set would afford them.
from what I understand the slow movement came out of the hard left in italy - and from what hhe told me the internet is still regarded as a yankee/capitalist plot based on his experiance trying to sell the idea of .coop to italian coop's
I see it like a Craftsman woodworker vs a high school shop class. At the end of the day they can both build a birdhouse though the quality of final result will be very different.
Yep -- and I argue that the craftsman can finish at least as fast as the shop student. When someone says "I don't have time to make it sound", they're really saying "I don't have the skills."
By the way, I think these skills can be acquired and even taught. They just aren't yet being taught afaik.
I would also bet that the craftsman will show less overt progress as he works. He will appear to be moving slower, but will in fact complete the three to requirements faster. And in the initial phase, in particular, the craftsman may take a lot more time. The speed will be shown not over the initial design, but over the whole production cycle.
It's mostly statistical and based around comparing your skill level to other players. While a 7kyu level is not necessarily that well defined, and might differ between different ranking systems, there's still a meaning to the difference between the levels. When a 5kyu (stronger) is playing a 7kyu, the 7kyu player is given 2 stones in advance (handicap) to make the game even. The number of stones given as a handicap is determined by (or defines) the difference in levels.
It's not immediately obvious how such a system could be adapted for programming skills. But the idea of having levels, and having ways to measure one's level, is very interesting, and might be quite useful.
Japanese (and probably other languages) have standardized tests[1] to determine one's language abilities.
You don't take a test to determine your level. Rather, you take a test designed for a particular level. You either pass or fail.
N5 is the lowest level (beginner)
N1 is the strongest level (near-native or even better maybe)
When you feel you are at say, level N3, you take the N3 test, and if you pass, then you can say that you have passed the N3 test. If you fail, you just fail. It doesn't mean you are N4 or N5. (As far as I know - I might actually be wrong here).
I wonder if some standardized tests can be, in principle, constructed to measure programming abilities.
The tests must be crafted such that, even if all the questions are known to the public, then studying for the test is the same thing as studying to build up your skill level.
I'm more interested in measuring abilities relevant directly to software as a profession (or craftsmanship), such as: how well can you architecture a system to solve a complex problem?
This is important: you can separate handling complexity from the profession of building architecturally sound systems.
We can teach people how to do math correctly. That doesn't guarantee that they will be able to solve arbitrarily complex problems. But to solve math problems, you MUST at least have the skill sets.
So there is a test to measure do you have the skill sets. How much one is willing and/or able to handle complexity is a separate thing to consider.
> I wonder if some standardized tests can be, in principle, constructed to measure programming abilities.
This absolutely misses the point of the article. It is definitively not about programming abilities, or speed of these abilities.
Many authors have hit TFA's points from different angles. For example, Tom Demarco's excellent Slack[1] introduces uses of "efficiency" (what speed is the organization moving at?) versus "effectiveness" (is the organization moving in the right direction?). DeMarco uses these to illustrate that many organizations optimize for the wrong parameters: they want to move at breakneck speed ("efficiency", "butts in seats", etc.), but in doing so trade off their vital strategic ability to think, design, to steer the ship!
In an organization without slack (briefly, the ability of knowledge workers in an organization to engage in vital reflective tasks, a key part of TFA's design process), everyone's so focused on Getting There that no one remains to decide if There is the right place to be going. This can and does result in everything from classic technical debt to strategic business failure. DeMarco describes a pile of organizational anti-patterns that stem from this philosophical damage.
I like that TFA's author connects these concepts explicitly to more recent thinking on the importance of design process.
It is the MOST trivial thing to measure performance in a Go game.
It is the LEAST trivial thing to measure the "code quality"/"unit of time" metric in a programmer. For example, you might bang out an implementation that looks fine, but 1 guy will say "that will become unmaintainable in 1 year" or "that will be a problem if we ever switch databases" or whatever and sure enough, a year later, the team has to do that... and that 1 guy was fucking RIGHT.
Who's to say how you measure such a thing?
The longer you spend in a career that has ANY creative component, the more you will come to loathe the importance placed on "performance evaluations." In fact, I'd argue that the more advanced you are in those creative jobs, the SLOWER and BETTER you work... the problem is that the newbies won't be able to recognize the "better" portion.
"that will become unmaintainable in 1 year" or "that will be a problem if we ever switch databases" or whatever and sure enough, a year later, the team has to do that... and that 1 guy was fucking RIGHT.
And sometimes YAGNI, we'll cross that bridge when we come to it, nice problem to have, good enough is good enough, do the simplest thing that could possibly work, premature optimization, perfect is the enemy of good, grass is always greener somewhere else, better a bird in the hand than two in the bush, he's right but it's still not worth the cost right now, etc.
That is a perfect mindset to have to the problem of the type "that will be a problem if we ever switch databases". However, "that will become unmaintainable in 1 year" is a "bridge" you want to cross sooner rather than later. If you have a deadline to meet, fine, but come back and fix it asap if the software is something that needs to be maintained. I really cannot explain it well, it's just something most developers realize after a while when they've had to maintain an old codebase.
They key point however is, that one guys insight shouldn't be ignored. You can take the words of wisdom and proceed to not do anything about it, but at least you know the cost down the road. All experienced managers I know personally, know the cost of umaintainable software and are more than willing to do something about it if ressources allow it. They need to, otherwise it's their ass that is in the line of fire when it cost a factor 10 to implement a new feature and bugs creep up at the customer time after time, even though they spend a factor 10 more on QA.
>It is the MOST trivial thing to measure performance in a Go game.
Actually in terms of very old games Go is one of the harder ones to measure performance of during the game. In terms of measuring performance in any 1v1 game however it is easy.
> I largely agree w/ the argument here, but "slow" is going to be self-defeating nomenclature, and is also inaccurate. Business doesn't want slow. So if we're pitching slow, we're setting ourselves up to lose and the speed-hackers are going to win.
German has a very nice word for that: "zügig". It means "speedy" as well, but goes a bit towards "stable", "steady" and "friction-free". It's the good kind of fast, which sometimes needs a step back and a look at things.
So, if I came to work "zügig", I didn't speed, but there was no traffic jam, I didn't stop for a coffee somewhere, etc.
Zügig is just so..Germanic!
It's exactly how I imagine the stereotype of German efficiency.
In the anglo-saxon world we pride ourselves on how many hours we work.
In Germany they work fewer hours and produce more and of better quality.
At least that's my impression.
Please note that another german culture is to be overly pedantic in following rules, no matter if their initial intention applies or whether we just set them five minutes ago. Rules are followed because.
This culture makes administrative processes bulky and tedious and tiring.
It often fuels my Ungeduld, because I want to get st done zügig.
Indeed. I needed some paperwork when I got married with a german. I'm from Sweden. I called the tax office in sweden that was taking care of the papers I needed to file for marriage certificate in Germany and the woman on the phone was laughing heartily saying "Then you know how byrocrazy feels!" :-) They happily sent all papers I needed in the mail to me in Germany, translated to English. The clerk in Germany was eying it suspiciously and asking some colleagues and took quite some time before finally putting down his stamp.
Before anybody else gets funny ideas: the claims in that article aren't entirely correct.
First of all, I find the claim about 35 hours being the average a bit dubious. It may have been the average some years ago, but today it's probably closer to 38-40 hours, with service jobs (from retail to agencies) often adding unpaid overtime to that. On the other hand our work laws are pretty employee-friendly (e.g. a mandatory uninterrupted resting period of 24 hours per week in case you have to work on sundays) and larger companies are more likely to follow the letter of the law.
The rules regarding Facebook and private e-mail have more to do with German privacy law: if the private use of work computers is explicitly forbidden, there are less legal landmines involved with intercepting or monitoring Internet use. In practice many places have an informal policy that allows these things, just not officially.
The bit about employees not hanging around after work is also inaccurate. For many people a lot of friendships (and relationships) involve co-workers. In fact, this is one of the reasons there was such an outrage when Walmart tried to implement its US work policies in Germany (which forbade romantic relationships between co-workers -- not that that rule would have held up in German courts to begin with).
There are indeed more days of paid vacation and families do receive preferential treatment when it comes to scheduling vacations during the major holidays or summer break.
The difference when it comes to "Handwerk" is also very striking. Mediocre pay (and rampant moonlighting) aside, craftsmen are generally held in high regard and like most professions take a lot of pride in correctness and precision. This probably again goes hand in hand with Germany having a lot of laws, rules and standards for various fields of work (e.g. you can't just set up a shop as a car varnisher, you need a formal qualification for that).
Also, bureaucracy. Although the sibling is right in that you do usually get the expected result if you follow all the rules, the paperwork can be daunting. Most people joke about the tax law in particular, but we have laws, rules and standards for everything. German law generally tends to define even edge cases clearly rather than leave them up to interpretation by the courts, consequently the legal system tends to be less shady than in the US, but trickier cases can still take years (but on the plus side, they are much cheaper than in the US).
That article reads like the inverse of the Japanese "salaryman" (company as family, patriarch, protector, provider of all material comforts), which is also sometimes fetishized in Western circles (in terms of results) as "more efficient" or somehow better than American working culture.
I like to tell that "vitesse" (noun), French for speed, comes from "viste" (adj.) and latin "vistus", rooted in vista, to see. The only way to go fast is to see, to know; and for that, one often needs to go slow.
As said below Latin has it in festina lente -- "Make haste slowly."
I like this word, we should adopt it. It says a lot about the German mindset that they have a word for this.
I don't think English has any equivalent (but it's a big language so I wouldn't be surprised to find out I'm wrong). We do have a very similar and pretty common idiom though: "slowly-but-surely", often used in the phrase "slowly but surely wins the race". This of course comes from The Hare and the Tortoise in Aesop's Fables.
Another analogy that works in programming terms is comparing the speed of a container ship to the speed of a Ferrari. One of them zips about a lot and goes round corners really fast. The other one takes a while to load up and takes an hour to turn, but it will shift a hell of a lot more cargo, a much greater distance, in the same time.
There's a place for both and the most important thing is knowing the difference; not sticking to one or the other dogmatically.
Expeditious is used rarely enough, and 'expedited' services are spoken of frequently enough, that I don't think that expeditious would at all capture the notion.
Things that are expedited are put on a 'fast track,' obstacles removed -- and, frequently, corners are cut.
Not quite. "Steady" usually implies a certain slowness. "Zügig" generally implies the opposite.
For example, if I asked you to leave a hotel in a "zügig" manner, I would be asking you to quickly pack up your things and then leave. In other words, it's about doing something "faster than normal", but not so fast you can't take proper care.
If I told you to leave "zügig" and you'd first finish watching a TV show, I would probably be slightly irritated.
In this case "zügig" is better translated as "in a timely manner" (rather than with haste, which would imply dropping what you are doing and running away).
In every explanation of the word 'zügig' here on HN, the word that pops into my head is 'directly'. Not sure how to make that work beside the word 'programming' but it matches the same concept.
It implies that you are following that one named goal and considering nothing else.
Zug does mean train but it comes from ziehen (to pull) as others mentioned. So I am not sure whether zügig comes from the original meaning or from 'train'. The english cognate for Zug/ziehen is tug btw (follows the common t -> z shift in german)
The IPA would be /tsygɪç/. Pseudo-English would be more like "tsoo-gish", though obviously not completely accurate.
You can enter it in Bing Translate[0] to get a text-to-speech rendition. I can't figure out how to make a direct link with text already entered. (You can type "zuegig" if you don't have easy access to the ü key.) Interestingly enough, the translation there is "swift".
German has a very nice word for that: "zügig". It means "speedy" as well, but goes a bit towards "stable", "steady" and "friction-free". It's the good kind of fast, which sometimes needs a step back and a look at things.
We have a term for that as well -- cruising speed.
> I largely agree w/ the argument here, but "slow" is going to be self-defeating nomenclature, and is also inaccurate. Business doesn't want slow. So if we're pitching slow, we're setting ourselves up to lose and the speed-hackers are going to win.
I like to use the word "deliberate" when I mean "slow", but think that "slow" will be misinterpreted.
It takes a certain amount of time to build a house (that will be durable and to code) no matter how much people want "skill sets".
If it takes a longer time than management wanted for something to be built, that isn't necessarily because "skill sets" are lacking.
If the product is shoddy, that is probably not because the team lacked the magical ability to make sound products instantly, but because the team was rushed (on the theory that they are not professionals and have to be micromanaged)
The odds are that the feature spec was bloated and management was bad at estimation (perhaps because they demanded estimates out of programmers who are also not good at estimation, in a bid to squeeze as much output from them as possible).
Hackers aren't the problem. A pogrom on "hackers" is unlikely to solve anything. "Professional" in the sense of wearing this or that, or following whatever you personally consider to be best practices isn't going to fix scope creep, wrong estimation, fundamental facts about project coordination, or the laws of physics.
Building serious stuff takes time.
It's management's job to handle that without flipping its shit.
I'm not saying that it doesn't take time to build software and I'm not making a case for how to do management.
In my decade of experience on different teams and products, the main impedance to productivity has by far been to do with bad code and architectural choices. The justification is always "speed" but my point is that is wrong. It's not speed that is at fault, it's that most software engineers don't know how to properly engineer software -- they haven't been taught nor had the time to learn it. It's absolutely an issue of skill sets.
Yes, management and project estimation are other issues to work out. I'd say we're actually much further along on these fronts than we are on the technical skill sets front. That is, the skill set of building architecturally sound systems.*
* Note: I do believe there is a time trade off between features and feature flexibility -- but there is no time trade off necessary for achieving architectural soundness, again so long as the right (presently rare) skill sets are present.
There are three types of "good architectural choices"
The first: The ones that can be made after the original, bad ones. The second draft, which is an improvement in the first draft, in every field.
The second: His (or her) own. We all know there are developers out there who think they're the greatest thing to ever write code, and that everyone else's decisions are bad.
The third: The ones that really should have been made, in place of the ones that really shouldn't have been made. As in, "You wrote your own SQL parser using hardcoded strings and no grammar parsers?"
You've probably heard it as ones that lead to low-coupling and high-cohesion, which is correct. But in my experience this needs to be made more concrete -- many people can say these words, but couldn't tell you accurately to what degree a system was cohesive and uncoupled.
> The justification is always "speed" but my point is that is wrong.
Not necessarily. Proper architecture takes time and planning and reasoning. If it didn't, we could make a program do it for us. There is absolutely a time tradeoff between coming up with the proper architecture for the application vs just using something that looked cool from a google project. The latter will always be faster at first, but not in the long term.
100% agree. Though a lot of the churn here could be reduced with the right education and mentorship. There is a mathematics to good architectures -- a mathematics that can be taught. But currently the initiative of us are left to find the way ourselves. We need to find a way to formulate and teach this mathematics to the next generation/s so they can get there faster.
Good point. How many "rockstar" developers show up at Company X, build the initial versions of a product or architecture, then move on to the next company never to understand the longer term consequences of their choices?
Practice. As well as trying to notice when things work or don't (I have colleagues that see "firefighting" as a normal part of a running system. If something keeps needing attention, it is probably badly written or architected).
Linus said something along the lines of bad programmers worrying about the code, and good ones worrying about the data structures. I think there is truth in this, even though I develop Django database applications most of the time. If I find myself doing too much work at the application level, taking a step back I can usually see a better approach when I rearrange the database.
This is exactly my experience. The vast majority of software failures are the results of dysfunction outside of the software team - this is why more best practices or process rarely fix the issue, it was an organization one to begin with. In my career there's been a strong correlation between healthy functional organizations and healthy functional software
"Well considered" is too subjective, I think. There are specific, concrete skill sets that lead to systems with specific, well-defined properties (i.e., architectural soundness).
Your system may be well-considered but if it's not architecturally sound it's going to increasingly tumble over time.
This seems similar to michaelochurch's thinking about 'guilds' - which I guess is a precursor to formalised 'engineers' or master craftsmen, which is something Software 'Engineering' seems to be in dire need of.
When was the last time you engaged a journeyman carpenter? This problem runs much deeper than just software. Any skilled craft is always at odds with a manager/employer/clients view that you are a fungible asset.
> Wu wei is an important concept in Taoism that literally means non-action or non-doing ie. "effortless doing"
Set goal, think and explore a little, rest a lot and wait until you get clear picture. Then and only then start coding.
Pros: No burnouts, less stress, etc, and constantly moving forward (in contrast to 2 steps forward 1 step back cycle) what results in overall faster progress.
Cons: Personally it's sometimes pain in the ass to wait, but it's important to understand -> not to be obsessed with job. Get a hobby, do something else and let unconscious part of your brain deal with what needs to be done -> mind blowing discovery for me that actually works, but still have to get used to this concept :-)
> I largely agree w/ the argument here, but "slow" is going to be self-defeating nomenclature, and is also inaccurate. Business doesn't want slow. So if we're pitching slow, we're setting ourselves up to lose and the speed-hackers are going to win.
Agreed. The ideas in this article are sound, but I'm not sold on this "slow programming" term. It's more like "careful" programming, or how about "care-full" programming, in which you put your full amount of care into every character you write.
The reason we've been able to speed things up is because of these tools, like CI systems and test frameworks. Faster iteration means getting results back faster and that means you can spend more time thinking about the problem and less time implementing it. That is the major benefit of what the author calls "fast programming" and it's something he glossed over completely. Just because you move fast doesn't mean you can't be careful along the way. You just need tools that extend your own visibility in order to catch problems faster and more accurately solve them.
There's also the question of what you work on, not just the quality of your work. You can do a barely-works version of something that it turns out people really want and it's better than if no-one had built it...
Maybe slow programming means finding important things to work on.
I would like to respond that the maintenance costs and thus TCO will be lower for the better designed system - however I have no idea how to formulate this into a tenable economic argument since I have absolutely no data to back this up.
Today, yes. But that's a problem our industry needs to solve. A lot of our labor force has already paid in money and time for education. Our education system has simply failed to deliver the full skill sets. Not necessarily the education system's fault -- our industry needs to know what skill sets to ask for and what is their value.
Our education system has simply failed to deliver the full skill sets.
Even if you ignore the question of what material post secondary education should be teaching, the more substantial bounds are the time limitation of school. Even a hyper-specialized curriculum can't cover everything, and isn't a substitute for real world experience.
It's soothing to sit around and find ways to opine and blame external parties (education is a popular choice) for the fact that experienced and skilled developers can't be had for the cost of green developers. But it's just an activity that releases energy without changing anything, aka (mental) masturbation.
Instead of slow, continuously evolving the domain abstractions is key. Faster & more effective is better. If slow creates effective judgement instead of prejudice, then go slow.
There are two systems in the brain at play. "Fast thinking" involves gut reactions & intuition. "Slow thinking" involves logical analysis & formations of models. Both contribute to effective solutions.
Recognizing iteration as the cycle of evolution & growth creates working systems in congruence with natural law.
I am not so sure. The point of "slow programming" is the same as "slow food" and "slow democracy." I think you have to see the three together. The point is to slow down, deliberate, and then do. That doesn't mean long iterations, nor does it mean deferring progress. It means ensuring solidity of the progress as you make it.
I once interviewed for a job at one of the most recognized and big Perl shops in the world and didn't get invited to face to face because I "took my time" with their puzzles. My response was that my first drafts were faulty, and that I preferred to program slowly because I could deliver more code, faster, and better by taking my time with it. In the end, their loss.
Deliberation is important. That often means slower apparent progress but faster progress overall.
Yep - there are benefits to a slogan being counter-intuitive because the whole point is to challenge the intuitive way of approaching a problem and making you see it anew.
In the reverse case, facebook's "move fast and break things" works because it suggests you move fast enough to dare breaking things to try an overcome the caution that holds people back from doing great things.
In this case the equivalent slogan might be "Do it right and ship it late" i.e. its so important to get it right its worth risking missing a shipping date. Practical principles, like the agile manifesto, describe a preferred trade-off rather than just naming a good attribute like swiftness, because who doesn't want the good attribute? It would be irrational.
I think this also highlights why moving faster is nearly always better even if uncomfortable for some: its a more effective way of handling uncertainty and learning faster that in most commercial environments is more important than quality. Quality in the wrong places is waste.
I am not sure that ship it late necessarily becomes a part of slow coding. The point is to code deliberately and with quality. Once you have a production codebase, if you do things right, there's no reason you can't ship on a fixed schedule. You might ship less initially than you expected, but in the long run, you will ship more than you expect, because the delay of design pays back later.
This is also why I don't think moving faster is almost always better. There's a certain point at which moving faster slows you down.
A better way of saying it might be "optimize your progress over the next 10 years, not over the next week."
I think there is a false choice usually presented between agile, move fast and break things, vs old waterfall approach. I don't think waterfall is the right alternative. The waterfall approach is really difficult to get right because to some extent it insulates design from coding. The integration of these two is something that agile gets right.
But what agile gets wrong is in de-emphasizing design too much. Design is important, and it is important regarding long-term progress. And if you don't design, you will pay for it a hundred times over. But the best design is where technology is designed bottom-up and UX is designed top-down. Done right, this integrates design into coding but it also emphasizes design and code contracts.
I largely agree w/ the argument here, but "slow" is going to be self-defeating nomenclature, and is also inaccurate. Business doesn't want slow. So if we're pitching slow, we're setting ourselves up to lose and the speed-hackers are going to win.
I think a better adjective would be robust. But I'd hate "Robust Programming" become as much of an abortion as "Agile", now an excuse for micromanagement and business-side mediocrity, has proved itself to be.
I agree about what the term 'agile' has become, but in many situations (especially in startups), spending too much time and energy to make something robust in version 1 is worse than hacking it together with spaghetti code. The key is to know which mode is appropriate for what you're doing.
If we want to create more tolerance for good engineering practice, we can't act like primadonna artists obsessed with building our perfect masterpieces on someone else's dime. We're hired by businesses, so our arguments need to be grounded in business value.
"It's a shitty architecture" isn't going to get you anywhere.
"It's going to fall apart and cost you millions if you do it that way, but if you take out these less important features and spent more time on what matters, we can do it right for the same cost..." People might just listen to that one.
The best and most concise way I've found to explain this is a systems focus.
We aim to focus on systems, because it is the most efficient way to work. By using good methods, designing complex systems well, and spending adequate time designing, we achieve a net speed increase, productivity increase, cost decrease, and additional positive benefits such as programmer morale and overall quality.
In my mind, quality is the genesis of everything, but you do have to word that really well so that the overlords comprehend the consequences correctly.
That's actually the problem! Many current engineering disciples were before handled by craftsmen until scientific principles were applied to it, making it engineering.
There have been very few scientific studies about the basics of building software, like how much unit tests really affects the bug density, and those few studies go often unnoticed when teaching future software engineers.
It would require a major effort to first study the existing emergent software craftsmanship practices to find common patterns and to scientifically evaluate their effectiveness, and the results would have to be taught in the hypothetical future curriculum where future software engineers would be made. Then we might have software engineering instead of just software craftsmanship.
It's almost a bit amazing that software "engineers" who can be very obsessive about getting the data or A/B-testing will craft software based on methods they have no data about.
> There have been very few scientific studies about the basics of building software...
There hasn't been a lot of great quantitative scientific study on how to productively do science either. Academic science is a craft, and is more or less learned through apprenticeships.
I'm trained as a physicist, and I'm certainly a fan of quantitative scientific methods, but I think it's important to realize that there are some areas where quantitative science is effective and rewards the required work well, and other areas where it is largely an ineffective waste of time.
I suspect trying to quantitatively study things like "how much unit tests really affects the bug density" is one of these cases with a poor reward to effort ratio.
There's a danger in trying to apply quantitative science to complex phenomena, when many or most relevant factors are actually uncontrolled and unmeasured. Once you have a number--any number--the tendency is to fetishize it at the expense of broader thinking. Make no mistake: quantitative measurements of the behavior of people performing complicated tasks do not carry the same epistemological force as quantitative measurements of the magnetic dipole moment of the electron.
Scientists themselves more typically try to understand their own craft through case studies and "professional wisdom" passed down from practicing experts to apprentices. Software developers would probably do well to (continue to) do the same.
It's not just that not a lot of science is applied to the craft of programming. It is that many programmers are actively hostile to the concept. For example, the rules of programmers.se forbid asking for statistics. So if you want to know objective facts about the craft of programming, you're forbidden from asking for it on the most popular forum about that craft. When I asked why this rule was in place, it became apparent that the only real reason was an irrational dislike of statistics. With that kind of attitude our craft will never become an engineering discipline..
Maybe that future isn't too far away! Have you checked out Code Complete? My university used it as a textbook for a Software Engineering course. To borrow your example, it cites multiple studies about the effectiveness of unit testing on errors, as well as many other software engineering topics.
Career vocational software craftsman here. Academic background in math and science have served me well as I self-taught all the CS and application development skills I have collected over the years. Vocational training probably would not have hurt, but I don't see how it could fit a traditional curriculum; I have only accelerated my pace of learning as the internet and quality of free tools and instructional material have grown, and I attribute that entirely to the buffet nature of online training.
Well, what I wanted to say was that the "craft", i.e. skills learned when working on a real project with experienced developers, is something I use all the time. Academic knowledge less so. Take, for example, complexity theory. I use that once a day or even less. And in 95% of those cases I could just consult a simple cheat sheet (stuff like "sorting is O(n log n)").
Unfortunately, the process of building houses can't be compared to building software. Houses don't get bolted sideways onto scyscrapers 5 years after they're built, or suddenly need to accommodate multiple order of magnitude more people than they were originally built to hold. These are regular occurrences in the software world.
You are right that most people that come out of university are woefully unprepared to design software systems. However, that doesn't change the fact that what ends up being the "best" design in the end is rarely apparent (or appropriate) in the initial planning stages of a software project. Requirements change, and the architecture needs to adapt with them. These architectural changes do have a very real cost. The tough sell is trying to show management that the alternative creates technical debt that will strangle the project if it isn't addressed, and that the longer the refactoring is deferred, the more expensive it will be.
> The tough sell is trying to show management that the alternative creates technical debt that will strangle the project if it isn't addressed
If you're worried about that, then the problem is that you have someone managing a software project who doesn't know how to manage software projects. That's not a failure of the methodology; it's a failure organizational design.
> Unfortunately, the process of building houses can't be compared to building software. Houses don't get bolted sideways onto scyscrapers 5 years after they're built, or suddenly need to accommodate multiple order of magnitude more people than they were originally built to hold. These are regular occurrences in the software world.
Most likely, not a lot of things compare to building houses in all aspects.
The point is, if developers are having problems wrt. scaling, then we need to build tools that abstract away scale. Define a language that allows the runtime to auto-scale, depending on load. As far as I can see, it's "just" another engineering challenge, not essentially different from figuring out how to make a skyscraper withstand heavy winds.
Deliberate Programming might be a better term; it encompasses the idea of steady progress, and solid intent.
- update - I see this has already been suggested. Still like it...
You are probably right about the marketability of "slow" as a movement, but in hacker circles these ideas need to be discussed honestly and directly.
The analogy with house building is flawed. Home construction generally follows a preplanned architecture, schedule, and process that has been refined and tested over a long time in an environment which doesn't change much over time. The process of building houses is well understood and if a delay occurs it can be attributed to a lack of skills as you say (or funding problems, etc).
Software has a different nature. If you have thoroughly solved a problem, the solution can often be automated. There is no button you can press to build the same house you built once before. It still takes time, money, and materials. With software, if you are not spending a large portion of your time working on a problem that has a novel component or two, you or someone else has probably failed to automate enough.
As a result, you never quite possess the necessary skill set to solve your current task. You are always pushing some boundary, even if small. Gross skill set mismatch is a separate problem, of course, but a transient skill mismatch is an inherent aspect of good software development and I don't think it's justified to place any blame on moderate and transient skill mismatches as a result.
Whenever you are dealing with something novel, you will need to go slower than usual. It's the same for new types of buildings that use newer construction tools or technology.
How do developers currently learn to build scalable, maintainable, well-architected systems? Certainly there are some books on the subject, and that might be a good start, but I'd be willing to bet that these skills are largely learned "on the job" through a bunch of trial and error.
Are there any good ways to dive in and get experience with a lot of smaller examples, similar to the "code school" approach but for more advanced topics and systems?
Maybe we need something like that. Code School: Advanced. There's a lot of thought going into training the next generation of software engineers from the ground up, but there doesn't seem to be much work toward improving the skills of the ones who already have a bit of experience.
It is all trial and error from my perspective. I like this line of inquery. The problem I see is the technology is constantly changing, and the meaning of 'scalable' is always expanding. Ie the 'Enterprise' archticture of the past didn't scale to 'internet scale', will 'internet scale' scale to 'internet of things' scale?
That's a good point -- things are constantly evolving and current tech becomes outdated so quickly.
At the same time though, I think it supports my point that the training for these kinds of things should be faster than reading a big thick book followed by a bunch of trial and error.
This is a good article, and the constant need to code bigger bowls of spaghetti faster is definitely a problem. However, I think that it's a stretch to imply that only older engineers do this.
I usually really enjoy reading Steve's posts, but I have a hard time with this one. Many great programmers admit to being clumsy typers (IIRC Joe Armstrong mentions he's a poor typer in his interview in Coders At Work).
I don't think it has a direct correspondence in terms as you might be implying i.e. the fast in this context is mostly still the slow Type II reflective thinking DK refers to. The "fast" coders are making small iterative changes but that doesn't mean the thinking is automatic, just localised and frequent.
The deeper analytical and design oriented thinking where someone takes extended time to identify goals, prototype and review different implementations is an important variation of Type II but not really addressed in TFAS. There might be plenty of Type I micro-decisions involved in that process too.
I'm pretty interested in how cognitive biases do rear their heads in design problems. I'm scared silly by framing effects where given options A and B, an individual chooses A but adding a third option C and now they would choose B. There are so many decisions that crop up during design/development that are vulnerable to those issues.
It seems like most of his problems would be alleviated by working on a non-volatile version of the code in a private branch. The kids these days tend to favor a VCS that has this feature.
To all the web agencies who expect jobs (design, code it & WordPress it with custom post types) a mid-size website; 20 to 40 pages) that take 60 hours to be completed in two to three days (pay you for 24 hours of work only) you can go take a flying leap.
This industry especially in the web agency world has me burnt out. The agencies all are in competition with each other .. lowering costs and thus expect their people to get things done in manner where their employees have no life but getting their work done. It's exhausting and the work is not very fulfilling.
Now I have done the same work at Fortune 500 companies and for someone with a family and who wants a balance work & family/social life that is where you want to be!
wow, this is great! I definitely have always fallen into the "slow" camp. Though I've always considered it more a matter of being careful and with purpose, and not being haphazard.
Quality over quantity. Painting a wall is easy, painting a painting takes much more precision and care, especially when you have to exercise your design skills as a developer.
Though often, a lot of the time goes into understanding what it's supposed to be doing in the first place, and from there it's a matter of making it more resilient, isolated and friendlier to work with.
I'm the slowest dev on my team, but I squash the bugs that nobody could figure out, or knew were there. Taking things apart takes time and patience, but when you're done you know how it all works and can refactor it to be clearer/simpler, and appropriately comment on what it does and how.
I hesitate to recommend my process to other people, because I don't think I'm a very good programmer.
But for the past year or so, I find that I program best by actually writing out my program in a notebook (in my case a quad-ruled lab notebook). I don't even start typing until I have it laid out pretty much in it's entirety on paper.
This sounds ridiculous (and I can imagine it's not practical for all types of programming), but I've found that it's been tremendously helpful in getting me to understand what all the code that I'm writing does.
Most of the code I've written this past year has been in Haskell, so that helps somewhat by not having a lot of syntax to write down, but I'm sure I'd be doing the same thing even if I was writing in Java.
Paper is my favorite programming tool. The beauty of paper is that it's easy to find out when you're wrong, when you're pursuing the wrong path, without going deeply in and getting distracted by the small-scale details of the code.
No, I need to get away from the computer completely. Word docs (or any other computer typing) is still bound by the computer structure and the computer distractions.
With paper, I can draw graphs of relationships, write tables, add notes to things I drew earlier, etc. It's far more expressive, and far faster, than any computer tool I've tried.
I think most people would agree that writing things on paper first is a total necessity if you are writing mathematical code (I mean, are you going to do the equations in your head and type them out?), and I think the benefits to paper increase in proportion with the mathiness.
On the non-mathy side, I find it useful to take the concept of "rubber duck" debugging (which is totally applicable to original design and creation, and not just debugging) but write a "duck" document rather than talk out loud. Aside from not looking crazy, I find writing easier for thought organization.
Sometimes preparing slides can also be a nice way to really force your thoughts into simplest and clearest form. And hey, when you're done, you can present it to your co-workers.
As a beginner I recall myself asking other programmers "is using pen and paper cool before writing any actual code?" and they giggled before nodding in agreement.
I had this false expectation in my head that when programmers tackle a new problem (be either writing a small program or solving a challenge) they're able to think about it for a few minutes then straight up write code and if I can't it's because I suck and this job isn't for me.
Then I realized that what I expected was unrealistic and the "no pen and paper" stage only occurs to people who already met the same or similar challenge before and can recall even the slightest hint of what they did back then.
Paper is awesome. I find I rarely visit my notes afterwards. I just need a medium to spit out my thoughts, or I end up going in circles. As soon as I flush to paper, then my mind is unblocked to go solve the next problem. Most of the time, I remember most of what I've written down, so the paper is write-only.
My best work I do while half-napping with a notebook by my side.
I find it very hard to convince my students to pull out a pencil and a notebook before they start coding.
"Draw some pictures. Make some notes. Write a function that you suspect will be tricky. Make a flowchart. List the methods that will have to be in that class. Write out how the user will interact with it. Try to list all the pain points for the user. You can write it any way that helps you think. Make up a notation if you want."
Yes, the assignment is due and they need to get code on the screen. But one of these days I'm going to give them a programming assignment and tell them that I only want to see their notes.
I had to add a new feature to a decades old user facing codebase with had to interact with all of the existing system. The implementation of the core of the new feature took only a few hundreds of lines of code since it was just a bunch of graph operations basically. Interfacing with the rest of the system was hell.
I began by just investigating the requirements and designing on paper. I realized on my paper designs quickly that a few graph operations would be sufficient. Understanding how it fit with the rest of the system was only achievable to me by documenting for myself on paper how the bits and pieces worked I had to touch.
Took half a year to get the sucker ready.
Worked just like it was supposed to and my colleague praised how easy the codebase was to extend later on.
This is the way I work too. I don't handwrite pseudocode, but I draw data structures and relationships in varying degrees of granularity at least until I'm sure I understand the problem. Only then do I begin writing tests and coding.
To me, the confrontation posed there is not between speed and quality, but which constraints affect the system design most: coherence, or overall simplicity. I would claim the "worse is better" school of design aims to lower overall complexity by cutting the corners where the added complexity to maintain design coherence does not seemingly add any value to the implementation nor the end users.
"This advice is corrosive. It warps the minds of youth. It is never a good idea to intentionally aim for
anything less than the best, though one might have to compromise in order to succeed"
The dupe detector is left porous on purpose to allow good stories multiple cracks at the bat. A small number of reposts is ok.
It's true that who ends up getting the karma on a multiply-posted story is just a roll of the dice. On the other hand, you can stack your long-run odds as high as you want by submitting more and better stories. So it tends to even out in the end.
You're not really stacking your long-run odds any more than you're stacking your odds by playing the lottery a lot. The odds are stacked in favour of anyone who submits a lot and submits early rather than in favour of someone who submits well.
I'm not sure what you mean by submitting "early", or what experience you're drawing on here (your account has submitted zero stories!), but am pretty sure that the odds favour a user who submits a lot that is good [1] and that the latter is where the emphasis should be. We're also working on systems to amplify this effect, so it is going to get more true with time. The point as far as karma goes is not to be attached to any one post, but rather to play for the long run.
1. What counts as good on HN: stories of intellectual substance that many good hackers would find interesting.
I guess I just found the response "submit more, it evens out in the end" a bit glib (as is, 'your account has submitted zero stories'). I do have some experience submitting stories as well as plenty of just reading and commenting on the site. It seems to me the current system amplifies negative tendencies like being 'first to post' or reposting variants of the same story.
I'm perfectly happy to take your word that you're working on something better.
"There's never time to do it right, but there's always time to do it over".
This reminds me of something I've been saying for a while. I'm a practitioner of TDD - Test Driven Development, not Test Driven Design. I like test-first coding not because it's faster, as many proponents claim, but because it's more comfortable and thoughtful. It forces me to slow down and think about what I'm actually doing. I don't think I'm any faster when I'm coding to tests. I do, however, feel much safer. I hate that feeling of cranking out a bunch of code, then it breaks, and I don't know what broke or why.
But good design is absolutely not an emergent property of the process of coding! Thoughtless coding leads to poorly structured spaghetti. Well-tested spaghetti is still spaghetti! Good design is always a matter of compromises. You can either make those compromises in a conscious and thoughtful way, or you can close your eyes and hope for the best. Good luck with that.
>> But good design is absolutely not an emergent property of the process of coding!
>> Good design is always a matter of compromises.
You need to have coded something to have shined the flashlight into the darkness so you can put a few dots on the wall and start envisioning a path. I have small scrap projects to let me shine the light and see what reflects back.
345 comments
[ 3.7 ms ] story [ 254 ms ] threadSuch a behavior also boosts the maintainability of the solution. On the other hand, when it is ignored, a solution quickly can become unmaintainable and the solution that was implemented so "quickly" can become a black hole of man power.
I personally experienced more than one project, where the source code has become in very short time so complex and so bug ridden, that development times literally exploded.
Thinking about your design has not got a lot to do with the speed you type at.
Secondly as programmers we should be able to work on the same code base.
After the baby is born anyone can raise the child, some better than others, but its easy. We call that adoption. Until its born though, the baby, and it's mother are symbiotically connected to each other.
I think this is similar to the process of programming. Break down an interface, and work on a team at that level. Behind the interface though, keep it small. one or two people max if possible, and those people have to be on exactly the same brain wave as each other. Even well planned code takes some time to stabilize, and it's hard to even find that if other people are actively changing interfaces etc.
Besides the one thing I strongly disagree with is how typing slow can help you produce better software.
Taking time and thinking about your design certainly does help but typing slowly and taking your time designing are not the same thing.
As for the Design Process, it works in the exact same way you describe in other fields like Architecture, which I studied and practiced ages ago at a more than decent level.
Money (VCs'), the myth of the young billionaire, and a few other things are probably what make developing different.
Boy oh boy. Look, I'm all for coding slow, taking time and understanding what you're doing. But there is something to be said for "playing well with others". We're all trying to make things, not be the backdrop for your exquisitely-crafted sense of craft.
To me that reads a lot like "I would have done something really good if I weren't surrounded by those philistines". Well, maybe so, but you are surrounded by them. So choosing a method of working that does not result in "dysrhythmia" or whatever strikes me as rather prudent.
Of course you can spin it the other way too, which just goes to show this isn't a useful comment. Don't do what everybody else is doing just because they're doing it, do the right thing. If that does happen to be clay, great, but there's a great deal more people using inappropriately sloppy engineering than people using inappropriately careful engineering, so I'd expect to hear a lot more about the former.
The only people in real life that I've met that I would consider saying were being inappropriately careful were really just masking fundamental incompetence under a veneer of concern about process. I'm not sure I've ever seen anybody correctly apply massive overengineering to a programming task in real life. I'm absolutely sure it has happened, but it is not common enough to be worth talking about.
Put another way, how do you know what you're working with is steel, and others clay? What if your "steel" is really just clay that is slower to produce and more brittle? How do you reassure yourself that this isn't the case? The answer is, make a big deal about going slower and drink tea and stroke your beard and say "hmmmm." and lots of other things that connote wisdom but do not actually bring it to bear.
I am extremely skeptical of all this, not because I am unsympathetic but rather the contrary. We can get extremely wrapped up in our signifiers of skill and wisdom, to the point that we mistake the map for the territory. Instead of cursing the punk kids, try to learn from them and beat them at their own game.
I had the same reaction here. Everybody wants good design. This article seems to walk the line between providing valuable insight and just complaining about how other people work.
But the problem you mention is real and it can sink businesses.
One of the reasons for small iterations of a working system is that it gives you a limited QA footprint. This is far underrated. But it means that over the course of many iterations, my code ends up coming out, well designed and elegant, and playing well with others.
Short iterations and fast releases of a production web site, for example, are not the enemies of slow coding. In fact they have a role to play as well. What is the enemy is trying to do everything at once within a fast release cycle.
It's also important to see how reliant people are on their tools.
I like to measure a carpenter's skill based on whether they can build a nice looking bookshelf with just a pocket knife said no one ever.
This could be an issue with really fancy IDE features, but there's a world of difference between a whiteboard and an IDE - namely, a text editor and an interpreter/compiler.
In the real world you will have to work against a deadline. As much as code gardening is fun and does produce better software, in the real world shipped software always wins over well designed software.
Can you get it done, is a more important question to answer than can you make it beautiful.
I also find I am a code gardener and a slow programmer but I get told I ship working code faster than most of the fast programmers out there.
Is that wrong? Does being bad at typing force you to be more thoughtful and actually make you a better programmer? Or does it just mean it takes you longer?
My thinking is that you are not doing much thinking while you are actually typing, so not being able to type proficiently just means you're slower and that's it. So all else being equal, a programmer that can't type well is a red flag.
In any case I don't think it makes sense to use typing speed as a measure of programming competence because typing speed is never the bottleneck in producing real, useful code.
(template systems are an editor extension where you type "i" "f" "tab" and magically an entire if statement stanza instantly appears all perfectly formatted and ready for the details to be filled out.)
So if I type at 40 wpm, but 4 keystrokes of mine do more than 16 keystrokes from someone who doesn't use a template system, does that mean I'm effectively typing at 160 wpm? I guess so.
I also use an extension that magically aggressively indents so I don't indent, my editor takes care of it for me, so I guess I'm typing at infinite wpm when formatting code, compared to someone who hand indents.
> I also don't look at the keyboard
> I just know where the keys are from muscle memory
You are touch typing though. You may have an unconventional style, but that is irrelevant.
I mean how much do you even have to type to program, if I produce a page of good code in a day, thats a good day, and it doesn't take long to type.
Yes, typing speed, when looked at in isolation, does not cause the production of high-quality code. But there is an argument to be made for reducing the friction between one's mind and the code on the screen. Insofar as we can ignore that transference of data from biology to technology, we can think more fully and clearly. So, emacs commands that are fully ingrained in one's subconscious may be good, but probably not the C-u 12 C-x TAB; at least for somebody simple like me.
:)
(I believe in fast typing, usually I'm at some 120wpm, but it does help more with writing than it does with coding)
I found out I was wrong.
The redundancy actually helps. There's somehow a calming effect in it. I don't know how to put it into words.
I found out that I never actually think while typing per se. I have to first jot down my thoughts on paper. Typing out the code becomes almost a mechanical process. I already know what I'm typing, I've figured it all out and put it in paper (or some plain text note in another text editor or note taking app).
There's stress in trying to hold it all in your head. That stress is released when you jot things down. Then you can just mechanically write out code with less levels of stress.
The explicit syntax means you have more to type but less to think about.
I know it sounds paradoxical. But that's been my personal experience.
Coffeescript works way better than JavaScript, Elixir better than Erlang, Slim better than ERB. It shouldn't make that much of a difference, but it does.
However, at the same time, there is also something to be said for friction and learning to work with friction. It is about time and the amount of deliberation the concentration of holding a thought in your mind for longer.
I am a touch typist and I appreciate that I am. However, I also find that spending some time periodically with a quill pen, writing thoughts down with that, is extremely valuable for the opposite reason.
One of the core challenges is how to slow down thought. This is something which has many, many benefits, and touch typing at the speed of thought would not be conducive to quality code.
> For the same reason that many neuroscientists now believe that the fluid-like flow of neuronal firing throughout the brain has a temporal reverberation which has everything to do with thought and consciousness, good design takes time.
is just pure nonsense.
In what way?
He is presenting the arguments and beliefs of his intellectual opponents in a way they probably have not or would not, and then attacking that argument.
Now in a piece like this there is nothing wrong with that -- but in terms of the strength of an argument, it is no greater than just enthusiastically stating his preference.
It's weird how he like does this thing where he equates their fast with thoughtlessness, and his slow with actual fast.
That being said, I'm all about white-boarding, project planning, and clearing out dependencies, but if an engineer is slowly coding something without any deliverables, chances are their going to hit a wall near the deadline. I've seen this happen too many times.
That's just my personal style, although I've never worked in "large" teams on a single codebase so can't comment on what styles work best in those situations.
This resonates so much with me. Sometimes I worry that I'm falling behind on keeping up with technology, but whenever I try to learn something new it seems like I have to install a package manager, then another package manager inside the first one, then pull a million other tools and libraries and frameworks before I can even begin doing something with this stuff I'm trying to learn. No, thanks.
I love computers, I love computing, I love thinking about solving problems using computers, but I hate the direction things seem to be taking. I'm seriously considering a career change in the immediate future because all this crazy tooling truly burns me out.
There's just the one go tool to install, which can be installed just by unzipping a zip file. From there on in, you don't need any other tools. It just uses VCS for package management. You don't need an IDE... the single go tool has support for pretty much every part of the development cycle - compiling, testing, code formatting, profiling... there are no other tools you need to create real deliverable software. I've been writing Go for over two years and still haven't added any other tools to my standard workflow - git and go are the only two commands I type while writing go code. (At work we use a revision pinning tool, but I haven't needed that on my side projects.)
npm (and the CommonJS module system) is the #1 reason I use Node.js. I don't care if Javascript is ugly, npm totally makes up for it. I don't get why most module systems implicitly import symbols in the scope (Python, Ruby) or worse, those that pollute the global scope (PHP).
Brew (Ruby) is not that bad but Python's package ecosystem is a complete mess (distutils, setuptools, pip, etc.). Cabal (Haskell) is pretty good too in comparison to C/C++ (installing dependencies usually involves following instructions in a README file, that is, if there are available instructions for your OS). I haven't tried Go.
I believe the language of the future will be built around, and win mainly because of, its package system/ecosystem.
</rant>
npm is easily the worst. Python is a lot better. I hold the C library model as the golden standard, so we're not going to see eye-to-eye.
The worst part of npm is the sub-dependencies. Having enabled them, they proliferate endlessly. Each time I improve the efficiency of deploying a strictly controlled tree of modules, the front-end devs manage to double the number in use. 200, 350, 650, over 1000... oh and these improvements come from realizing that npm-shrinkwrap isn't 100% reliable, and ending up with scripts comparing npm-ls output and doing full wipe and replace with a tarball for even the slightest change to the dependency tree.
If some serious bug is discovered in one of these things, there's no way the 20 copies of it at various levels of this tree of 1000 modules are going to get patched. No one really has a handle on what's in these hundreds of megs of various versions of modules. This is the true fast code movement - serious problems can't be fixed in there, they'll just be ignored and replaced with other bugs in the twice-yearly full rewrite. Don't get me wrong, our frontend devs are among the best I've seen, but the pressures and environment they're in make them focus on churning out the latest fad in web design and skimping on engineering quality everywhere possible.
Python doesn't do implicit import of symbols into a scope if you don't use "from blah import (star)". Don't use the (star).
Managing, and using, a list of python modules, each at a particular version, is way simpler, more reliable, and more efficient (than npm style). Pip can reliably list installed module state (freeze) and install from source tarballs or git tag checkout.
You need to fully control and understand the versions of all libraries installed and used on a system in order to have a fully reproducible deployment state, and be able to reliably roll back to a previous state. Given that, the Python or C model is much easier to work with.
</rant>
Sure, it's space-efficient, but disk is cheap, and developer hours are expensive. I certainly wouldn't want two employees burning man-hours trying to figure out why some app is behaving differently on their respective machines, only to fix the problem and unwittingly break another project in the most expensively subtle of ways.
I'd really like to think I'm missing something though, I certainly don't presume to be more insightful than the collective Go team.
I don't think that was ever said; I claimed that trading disk space for developer hours is a good trade-off in this case.
> The npm-style dependency tree enables and encourages much more complexity, which developers then have to deal with when debugging or deploying.
I don't believe this is the case. When developing an app (as opposed to a library) it's considered a best practice to check your node modules into source control, ensuring that there's never a mismatch between installed dependencies on developer machines. If you don't want to do that, you take what comes - but even before I picked up on that, I never ran into issues even when collaborating with 5+ developers. You just need to make sure your package.json locks your versions appropriately.
So, for example, github.com/natefinch/lumberjack is an import path. When I wanted to change the API, I have to put my project at a different import path so I don't break projects that use this version. I could just make a new github repo called lumberjack-v2 and that would work fine.
Of course, reality and theory don't always see eye to eye, and the Go community realizes this. That's why there are several community-made tools to help out.
The most well-respected one is godep, which has the ability to pin revisions on your dependencies. That is, it'll look at the git commit hash (or equiv for hg/bzr/svn) for every repo that you depend on, and record it in a file in your repo. It can then reset those dependencies to those specific hashes. Then all members of your team just need to use godep to make sure they're all using the exact same git commits for all dependencies. Bam - now you're insulated from someone updating a dependency with breaking changes, and your team can test new revisions and decide when they want to start using them.
Godep has a second function that lets you copy all your dependencies into your repo and renames all import statements to reference the copied paths. This is an even more extreme version of the above, which not only insulates you from changes in dependencies, but also insulates you from those dependencies disappearing entirely.
So basically, I think your point is that a project should have as few dependencies as possible whereas I think the opposite is good. Both philosophies have their pros and cons. If you are writing mission critical software that handles financial data, it's probably a good idea to know about every line of code that gets executed. However, if your goal is to release something as fast as possible, have a more manageable code base and security is not as critical, using lots of dependencies makes sense.
The thing I love about Go's packaging is that your VCS and package manager are the same thing. There's no need to wonder where the code from package foo comes from... because you know you imported it from github.com/jimbob/foo It also means there's no fighting over namespaces, since it's just done by domain name (i.e. I can have the package npf.io/foo because I control that domain, and I don't have to to fight over who gets to use that name).
npm is without a doubt the best module system I've come across in my years of development. RubyGems is kind of a pain, .NET dependency management is a joke, Python is super fragmented, and Go doesn't have one. Godeps is an okay tool, and `go get` is cute, but I have yet to use a package manager that couldn't stand to borrow a thing or two from npm.
That's the nice thing about using tools written in Go. There is no npm install. There's a file copy. Bam, done. You don't even need to know it was written in Go unless you're using the code for your own development.
The magic folders in the filesystem exist in every package manager, it's just more obvious in Go. So, for example, npm puts code it downloads into /usr/local/lib/node. I'm very far from a Node expert, but this doesn't sound terribly different from GOPATH.
I nevertheless see this as a gift. It is your attitude with these tools, that makes you unhappy. I I often have this strange feeling of missing out on an even better technology, the cool kids might be using. I think the key here is to be confident with your choices of tools, improve them, when their is pain and identify when something is good enough for some time (measured in years) before you should reconsider again. In the end it is also about handling the tools. This sounds very reasonable but in practice it is often hard to overcome the urge to use the new shiny tool, which seems to make you a better programmer, when you define yourself as one.
I don't think the extremist view of skipping them altogether and condemning the whole thing is the solution. I believe people, who feel they can't keep up in this imaginary race either search for ways to define themselves in another way e.g. in alternative careers (like you) or in their opposing way of programming (like the article author) throwing the others in a bottle of people, who do it wrong. There is a middle-ground between the Node developer and his weekly changing recursive package managers and the Coldfusion shop not doing scm.
[1] http://www.drdobbs.com/tools/just-let-me-code/240168735
Usually the point of package managers is to allow you to leverage the work of others, so you don't have continually reinvent the wheel.
I've yet to run into a programming environment that did not have it's shares of headaches and nuances.
None. It's why I'm burnt out and want to so something different. Not something different from my current job. Something different from developing software.
I've lost count of how many times I've spent entire work days battling against the environment which is supposed to help me write the code I need to, to make a customer happy. Entire days of trying to figure out why IIS is acting crazy, or why Visual Studio is crashing, or why is Windows so damn slow all of a sudden. Entire days of trying to align the planets so that service A can talk to service B, because for some reason there's a cryptic SSL error that's not giving me any helpful information as to what's happening. Or entire days just pulling things from a dozen different sources and figuring out where to place each other so they can work together.
I've recently been to the Living Computer Museum in Seattle. You can play around with old computers there. I was fascinated by the old machines where you'd boot into a REPL. The shell was a REPL to the language you programmed the system in. I think despite all the advances we've made in the past decades and all the great performing technology we have nowadays, we've lost that essence of simplicity along the way.
VS is an awesome development environment, but I was having your problems with Windows and programs running under Windows for most of my adult life. I switched to Linux full-time at about 5-6 years ago, and I've been happy ever since. I can leave the OS running for weeks with no issues, and it would probably go for months but I'll turn the power off.
Oh, and with Linux, if you don't run a graphical desktop environment like Gnome or KDE (which most distros have the option of doing), then you boot into a REPL you can program the system in (Bash shell). Windows used to have the same with DOS, but no more...
Yes, this is extremely problematic. The hacky junk built by hacky developers is frustrating and a direct contributor to my burn-out quotient.
I'm now fiddling with Tcl/Tk as a way to quickly throw some visual ideas around. I'm using it to build an idea for a tabular programming language that is more visual and allows for letting go of incidental details like syntax, argument order, etc.
To that end, Go doesn't work for me. I use a fairly straightforward stack atop the JVM because I can hold the whole thing in my head (nothing in either Dropwizard or Play is deep magic) and have the expressiveness in Scala to be clear with my code.
I noted the simplicity of the stack mostly to forestall the usual tired complaints about complexity, nothing more. What you call "academic", I call "building at scale."
Our goal is architectural soundness. I believe the biggest fallacy of our industry is we think the only way to get these is to go "slow". Not true.
What we're really saying is our industry is short on skill sets. With specific skill sets, you can build architecturally sound systems at no extra cost.
If I were to build a house today it would take me much longer than someone else because I don't have the necessary skills. I might hurry in which case the house would be shoddy. Is the shoddiness of the house necessarily because I hurried? No. It's because I didn't acquire the required skill sets first.
The software industry has no such (practical) concept of the skill sets required to build architecturally sound systems. We have a bunch of well-meaning hackers, and as a result shoddy systems that decay into technical liabilities.
Our industry needs to solve this skill set problem. The challenge is that academia has a hard time teaching these skill sets, because they are so removed from the practitioner. And businesses can't teach it b/c it takes years and special experience to actually teach it. So it's not advantageous to a business to teach those skill sets.
So how do we do it? And how do we organize an industry around professionals who know how to build architecturally sound systems and code? This is a very difficult problem for a world that has such high demand for code and such little understanding of what the professional skill set would afford them.
[0] - https://en.wikipedia.org/wiki/Slow_Movement
By the way, I think these skills can be acquired and even taught. They just aren't yet being taught afaik.
The game of go[0] has a ranking system where players progress from 30kyu (complete beginner) to 1kyu, then 1dan to 9dan (very strong).
[0]: http://en.wikipedia.org/wiki/Go_ranks_and_ratings
It's mostly statistical and based around comparing your skill level to other players. While a 7kyu level is not necessarily that well defined, and might differ between different ranking systems, there's still a meaning to the difference between the levels. When a 5kyu (stronger) is playing a 7kyu, the 7kyu player is given 2 stones in advance (handicap) to make the game even. The number of stones given as a handicap is determined by (or defines) the difference in levels.
It's not immediately obvious how such a system could be adapted for programming skills. But the idea of having levels, and having ways to measure one's level, is very interesting, and might be quite useful.
Japanese (and probably other languages) have standardized tests[1] to determine one's language abilities.
[1]: http://en.wikipedia.org/wiki/Japanese-Language_Proficiency_T...
You don't take a test to determine your level. Rather, you take a test designed for a particular level. You either pass or fail.
N5 is the lowest level (beginner) N1 is the strongest level (near-native or even better maybe)
When you feel you are at say, level N3, you take the N3 test, and if you pass, then you can say that you have passed the N3 test. If you fail, you just fail. It doesn't mean you are N4 or N5. (As far as I know - I might actually be wrong here).
I wonder if some standardized tests can be, in principle, constructed to measure programming abilities.
The tests must be crafted such that, even if all the questions are known to the public, then studying for the test is the same thing as studying to build up your skill level.
Anyone who can build reliable systems using unreliable parts (like humans) will have an edge.
EDIT: If you're going to measure the worker's programming concept knowledge, Alison Tew's work seems to be at the leading edge.
[1] 'Developing a Validated Assessment of Fundamental CS1 Concepts', Tew, Guzdial, http://dl.acm.org/citation.cfm?id=1734297
We can teach people how to do math correctly. That doesn't guarantee that they will be able to solve arbitrarily complex problems. But to solve math problems, you MUST at least have the skill sets.
So there is a test to measure do you have the skill sets. How much one is willing and/or able to handle complexity is a separate thing to consider.
This absolutely misses the point of the article. It is definitively not about programming abilities, or speed of these abilities.
Many authors have hit TFA's points from different angles. For example, Tom Demarco's excellent Slack[1] introduces uses of "efficiency" (what speed is the organization moving at?) versus "effectiveness" (is the organization moving in the right direction?). DeMarco uses these to illustrate that many organizations optimize for the wrong parameters: they want to move at breakneck speed ("efficiency", "butts in seats", etc.), but in doing so trade off their vital strategic ability to think, design, to steer the ship!
In an organization without slack (briefly, the ability of knowledge workers in an organization to engage in vital reflective tasks, a key part of TFA's design process), everyone's so focused on Getting There that no one remains to decide if There is the right place to be going. This can and does result in everything from classic technical debt to strategic business failure. DeMarco describes a pile of organizational anti-patterns that stem from this philosophical damage.
I like that TFA's author connects these concepts explicitly to more recent thinking on the importance of design process.
[1] http://www.amazon.com/Slack-Getting-Burnout-Busywork-Efficie...
It is the LEAST trivial thing to measure the "code quality"/"unit of time" metric in a programmer. For example, you might bang out an implementation that looks fine, but 1 guy will say "that will become unmaintainable in 1 year" or "that will be a problem if we ever switch databases" or whatever and sure enough, a year later, the team has to do that... and that 1 guy was fucking RIGHT.
Who's to say how you measure such a thing?
The longer you spend in a career that has ANY creative component, the more you will come to loathe the importance placed on "performance evaluations." In fact, I'd argue that the more advanced you are in those creative jobs, the SLOWER and BETTER you work... the problem is that the newbies won't be able to recognize the "better" portion.
And sometimes YAGNI, we'll cross that bridge when we come to it, nice problem to have, good enough is good enough, do the simplest thing that could possibly work, premature optimization, perfect is the enemy of good, grass is always greener somewhere else, better a bird in the hand than two in the bush, he's right but it's still not worth the cost right now, etc.
They key point however is, that one guys insight shouldn't be ignored. You can take the words of wisdom and proceed to not do anything about it, but at least you know the cost down the road. All experienced managers I know personally, know the cost of umaintainable software and are more than willing to do something about it if ressources allow it. They need to, otherwise it's their ass that is in the line of fire when it cost a factor 10 to implement a new feature and bugs creep up at the customer time after time, even though they spend a factor 10 more on QA.
Actually in terms of very old games Go is one of the harder ones to measure performance of during the game. In terms of measuring performance in any 1v1 game however it is easy.
Small difference.
German has a very nice word for that: "zügig". It means "speedy" as well, but goes a bit towards "stable", "steady" and "friction-free". It's the good kind of fast, which sometimes needs a step back and a look at things.
So, if I came to work "zügig", I didn't speed, but there was no traffic jam, I didn't stop for a coffee somewhere, etc.
This culture makes administrative processes bulky and tedious and tiring.
It often fuels my Ungeduld, because I want to get st done zügig.
To get your fishing permit you will need to provide all the right bits of paper and stamps, no exceptions.
The flip side of this is that if you follow a set of precise, unambiguous instructions you will get your fishing permit.
Source: moved from UK to Germany 8 years ago.
And even if you succeed, in the end there'd be a rule that requires the Pdf to be printed, signed, copied, filed, scanned and filed again, digitally.
First of all, I find the claim about 35 hours being the average a bit dubious. It may have been the average some years ago, but today it's probably closer to 38-40 hours, with service jobs (from retail to agencies) often adding unpaid overtime to that. On the other hand our work laws are pretty employee-friendly (e.g. a mandatory uninterrupted resting period of 24 hours per week in case you have to work on sundays) and larger companies are more likely to follow the letter of the law.
The rules regarding Facebook and private e-mail have more to do with German privacy law: if the private use of work computers is explicitly forbidden, there are less legal landmines involved with intercepting or monitoring Internet use. In practice many places have an informal policy that allows these things, just not officially.
The bit about employees not hanging around after work is also inaccurate. For many people a lot of friendships (and relationships) involve co-workers. In fact, this is one of the reasons there was such an outrage when Walmart tried to implement its US work policies in Germany (which forbade romantic relationships between co-workers -- not that that rule would have held up in German courts to begin with).
There are indeed more days of paid vacation and families do receive preferential treatment when it comes to scheduling vacations during the major holidays or summer break.
The difference when it comes to "Handwerk" is also very striking. Mediocre pay (and rampant moonlighting) aside, craftsmen are generally held in high regard and like most professions take a lot of pride in correctness and precision. This probably again goes hand in hand with Germany having a lot of laws, rules and standards for various fields of work (e.g. you can't just set up a shop as a car varnisher, you need a formal qualification for that).
Also, bureaucracy. Although the sibling is right in that you do usually get the expected result if you follow all the rules, the paperwork can be daunting. Most people joke about the tax law in particular, but we have laws, rules and standards for everything. German law generally tends to define even edge cases clearly rather than leave them up to interpretation by the courts, consequently the legal system tends to be less shady than in the US, but trickier cases can still take years (but on the plus side, they are much cheaper than in the US).
Also, universal healthcare.
A lot of the studies on it I've seen come down to "work time is for work, free time is for not working" and respecting that.
As said below Latin has it in festina lente -- "Make haste slowly."
I don't think English has any equivalent (but it's a big language so I wouldn't be surprised to find out I'm wrong). We do have a very similar and pretty common idiom though: "slowly-but-surely", often used in the phrase "slowly but surely wins the race". This of course comes from The Hare and the Tortoise in Aesop's Fables.
Another analogy that works in programming terms is comparing the speed of a container ship to the speed of a Ferrari. One of them zips about a lot and goes round corners really fast. The other one takes a while to load up and takes an hour to turn, but it will shift a hell of a lot more cargo, a much greater distance, in the same time.
There's a place for both and the most important thing is knowing the difference; not sticking to one or the other dogmatically.
Best I could fined.
Things that are expedited are put on a 'fast track,' obstacles removed -- and, frequently, corners are cut.
In English, I'd say a train has a fast & steady speed, therefore I propose the translation "steady".
For example, if I asked you to leave a hotel in a "zügig" manner, I would be asking you to quickly pack up your things and then leave. In other words, it's about doing something "faster than normal", but not so fast you can't take proper care.
If I told you to leave "zügig" and you'd first finish watching a TV show, I would probably be slightly irritated.
In this case "zügig" is better translated as "in a timely manner" (rather than with haste, which would imply dropping what you are doing and running away).
It implies that you are following that one named goal and considering nothing else.
You can enter it in Bing Translate[0] to get a text-to-speech rendition. I can't figure out how to make a direct link with text already entered. (You can type "zuegig" if you don't have easy access to the ü key.) Interestingly enough, the translation there is "swift".
[0] http://www.bing.com/translator/
We have a term for that as well -- cruising speed.
I like to use the word "deliberate" when I mean "slow", but think that "slow" will be misinterpreted.
If it takes a longer time than management wanted for something to be built, that isn't necessarily because "skill sets" are lacking.
If the product is shoddy, that is probably not because the team lacked the magical ability to make sound products instantly, but because the team was rushed (on the theory that they are not professionals and have to be micromanaged)
The odds are that the feature spec was bloated and management was bad at estimation (perhaps because they demanded estimates out of programmers who are also not good at estimation, in a bid to squeeze as much output from them as possible).
Hackers aren't the problem. A pogrom on "hackers" is unlikely to solve anything. "Professional" in the sense of wearing this or that, or following whatever you personally consider to be best practices isn't going to fix scope creep, wrong estimation, fundamental facts about project coordination, or the laws of physics.
Building serious stuff takes time.
It's management's job to handle that without flipping its shit.
In my decade of experience on different teams and products, the main impedance to productivity has by far been to do with bad code and architectural choices. The justification is always "speed" but my point is that is wrong. It's not speed that is at fault, it's that most software engineers don't know how to properly engineer software -- they haven't been taught nor had the time to learn it. It's absolutely an issue of skill sets.
Yes, management and project estimation are other issues to work out. I'd say we're actually much further along on these fronts than we are on the technical skill sets front. That is, the skill set of building architecturally sound systems.*
* Note: I do believe there is a time trade off between features and feature flexibility -- but there is no time trade off necessary for achieving architectural soundness, again so long as the right (presently rare) skill sets are present.
I think in the end the best architecture is that which is thought through from a contract-oriented approach, rather than a buzzword checklist.
The first: The ones that can be made after the original, bad ones. The second draft, which is an improvement in the first draft, in every field.
The second: His (or her) own. We all know there are developers out there who think they're the greatest thing to ever write code, and that everyone else's decisions are bad.
The third: The ones that really should have been made, in place of the ones that really shouldn't have been made. As in, "You wrote your own SQL parser using hardcoded strings and no grammar parsers?"
(Shuffles away sheepishly)
Not necessarily. Proper architecture takes time and planning and reasoning. If it didn't, we could make a program do it for us. There is absolutely a time tradeoff between coming up with the proper architecture for the application vs just using something that looked cool from a google project. The latter will always be faster at first, but not in the long term.
Linus said something along the lines of bad programmers worrying about the code, and good ones worrying about the data structures. I think there is truth in this, even though I develop Django database applications most of the time. If I find myself doing too much work at the application level, taking a step back I can usually see a better approach when I rearrange the database.
The fast food industry did not "win" the restaurant industry; it did succesfully quantify the (minimal) skillsets around manufacturing food.
Your system may be well-considered but if it's not architecturally sound it's going to increasingly tumble over time.
http://en.wikipedia.org/wiki/Wu_wei
> Wu wei is an important concept in Taoism that literally means non-action or non-doing ie. "effortless doing"
Set goal, think and explore a little, rest a lot and wait until you get clear picture. Then and only then start coding.
Pros: No burnouts, less stress, etc, and constantly moving forward (in contrast to 2 steps forward 1 step back cycle) what results in overall faster progress.
Cons: Personally it's sometimes pain in the ass to wait, but it's important to understand -> not to be obsessed with job. Get a hobby, do something else and let unconscious part of your brain deal with what needs to be done -> mind blowing discovery for me that actually works, but still have to get used to this concept :-)
Agreed. The ideas in this article are sound, but I'm not sold on this "slow programming" term. It's more like "careful" programming, or how about "care-full" programming, in which you put your full amount of care into every character you write.
The reason we've been able to speed things up is because of these tools, like CI systems and test frameworks. Faster iteration means getting results back faster and that means you can spend more time thinking about the problem and less time implementing it. That is the major benefit of what the author calls "fast programming" and it's something he glossed over completely. Just because you move fast doesn't mean you can't be careful along the way. You just need tools that extend your own visibility in order to catch problems faster and more accurately solve them.
It's possible to change the entire world in half a page of code. That should be the goal...
Maybe slow programming means finding important things to work on.
Except the extra labor costs of someone with that skillset.
Even if you ignore the question of what material post secondary education should be teaching, the more substantial bounds are the time limitation of school. Even a hyper-specialized curriculum can't cover everything, and isn't a substitute for real world experience.
It's soothing to sit around and find ways to opine and blame external parties (education is a popular choice) for the fact that experienced and skilled developers can't be had for the cost of green developers. But it's just an activity that releases energy without changing anything, aka (mental) masturbation.
There are two systems in the brain at play. "Fast thinking" involves gut reactions & intuition. "Slow thinking" involves logical analysis & formations of models. Both contribute to effective solutions.
Recognizing iteration as the cycle of evolution & growth creates working systems in congruence with natural law.
I once interviewed for a job at one of the most recognized and big Perl shops in the world and didn't get invited to face to face because I "took my time" with their puzzles. My response was that my first drafts were faulty, and that I preferred to program slowly because I could deliver more code, faster, and better by taking my time with it. In the end, their loss.
Deliberation is important. That often means slower apparent progress but faster progress overall.
In the reverse case, facebook's "move fast and break things" works because it suggests you move fast enough to dare breaking things to try an overcome the caution that holds people back from doing great things.
In this case the equivalent slogan might be "Do it right and ship it late" i.e. its so important to get it right its worth risking missing a shipping date. Practical principles, like the agile manifesto, describe a preferred trade-off rather than just naming a good attribute like swiftness, because who doesn't want the good attribute? It would be irrational.
I think this also highlights why moving faster is nearly always better even if uncomfortable for some: its a more effective way of handling uncertainty and learning faster that in most commercial environments is more important than quality. Quality in the wrong places is waste.
A better way of saying it might be "optimize your progress over the next 10 years, not over the next week."
I think there is a false choice usually presented between agile, move fast and break things, vs old waterfall approach. I don't think waterfall is the right alternative. The waterfall approach is really difficult to get right because to some extent it insulates design from coding. The integration of these two is something that agile gets right.
But what agile gets wrong is in de-emphasizing design too much. Design is important, and it is important regarding long-term progress. And if you don't design, you will pay for it a hundred times over. But the best design is where technology is designed bottom-up and UX is designed top-down. Done right, this integrates design into coding but it also emphasizes design and code contracts.
I think a better adjective would be robust. But I'd hate "Robust Programming" become as much of an abortion as "Agile", now an excuse for micromanagement and business-side mediocrity, has proved itself to be.
If we want to create more tolerance for good engineering practice, we can't act like primadonna artists obsessed with building our perfect masterpieces on someone else's dime. We're hired by businesses, so our arguments need to be grounded in business value.
"It's a shitty architecture" isn't going to get you anywhere.
"It's going to fall apart and cost you millions if you do it that way, but if you take out these less important features and spent more time on what matters, we can do it right for the same cost..." People might just listen to that one.
We aim to focus on systems, because it is the most efficient way to work. By using good methods, designing complex systems well, and spending adequate time designing, we achieve a net speed increase, productivity increase, cost decrease, and additional positive benefits such as programmer morale and overall quality.
In my mind, quality is the genesis of everything, but you do have to word that really well so that the overlords comprehend the consequences correctly.
There have been very few scientific studies about the basics of building software, like how much unit tests really affects the bug density, and those few studies go often unnoticed when teaching future software engineers.
It would require a major effort to first study the existing emergent software craftsmanship practices to find common patterns and to scientifically evaluate their effectiveness, and the results would have to be taught in the hypothetical future curriculum where future software engineers would be made. Then we might have software engineering instead of just software craftsmanship.
It's almost a bit amazing that software "engineers" who can be very obsessive about getting the data or A/B-testing will craft software based on methods they have no data about.
There hasn't been a lot of great quantitative scientific study on how to productively do science either. Academic science is a craft, and is more or less learned through apprenticeships.
I'm trained as a physicist, and I'm certainly a fan of quantitative scientific methods, but I think it's important to realize that there are some areas where quantitative science is effective and rewards the required work well, and other areas where it is largely an ineffective waste of time.
I suspect trying to quantitatively study things like "how much unit tests really affects the bug density" is one of these cases with a poor reward to effort ratio.
There's a danger in trying to apply quantitative science to complex phenomena, when many or most relevant factors are actually uncontrolled and unmeasured. Once you have a number--any number--the tendency is to fetishize it at the expense of broader thinking. Make no mistake: quantitative measurements of the behavior of people performing complicated tasks do not carry the same epistemological force as quantitative measurements of the magnetic dipole moment of the electron.
Scientists themselves more typically try to understand their own craft through case studies and "professional wisdom" passed down from practicing experts to apprentices. Software developers would probably do well to (continue to) do the same.
Can you reference those claims? If I ever repeat this claim, I would prefer to be able to link to the administrators' statements directly.
It's pointed, poignant and accurate as well as precise; self-defeating it is not.
You are right that most people that come out of university are woefully unprepared to design software systems. However, that doesn't change the fact that what ends up being the "best" design in the end is rarely apparent (or appropriate) in the initial planning stages of a software project. Requirements change, and the architecture needs to adapt with them. These architectural changes do have a very real cost. The tough sell is trying to show management that the alternative creates technical debt that will strangle the project if it isn't addressed, and that the longer the refactoring is deferred, the more expensive it will be.
If you're worried about that, then the problem is that you have someone managing a software project who doesn't know how to manage software projects. That's not a failure of the methodology; it's a failure organizational design.
Most likely, not a lot of things compare to building houses in all aspects.
The point is, if developers are having problems wrt. scaling, then we need to build tools that abstract away scale. Define a language that allows the runtime to auto-scale, depending on load. As far as I can see, it's "just" another engineering challenge, not essentially different from figuring out how to make a skyscraper withstand heavy winds.
"Measure twice, cut once"
I'd argue that a lot of projects these days suffer a death of a thousand cuts.
The analogy with house building is flawed. Home construction generally follows a preplanned architecture, schedule, and process that has been refined and tested over a long time in an environment which doesn't change much over time. The process of building houses is well understood and if a delay occurs it can be attributed to a lack of skills as you say (or funding problems, etc).
Software has a different nature. If you have thoroughly solved a problem, the solution can often be automated. There is no button you can press to build the same house you built once before. It still takes time, money, and materials. With software, if you are not spending a large portion of your time working on a problem that has a novel component or two, you or someone else has probably failed to automate enough.
As a result, you never quite possess the necessary skill set to solve your current task. You are always pushing some boundary, even if small. Gross skill set mismatch is a separate problem, of course, but a transient skill mismatch is an inherent aspect of good software development and I don't think it's justified to place any blame on moderate and transient skill mismatches as a result.
Whenever you are dealing with something novel, you will need to go slower than usual. It's the same for new types of buildings that use newer construction tools or technology.
Are there any good ways to dive in and get experience with a lot of smaller examples, similar to the "code school" approach but for more advanced topics and systems?
Maybe we need something like that. Code School: Advanced. There's a lot of thought going into training the next generation of software engineers from the ground up, but there doesn't seem to be much work toward improving the skills of the ones who already have a bit of experience.
At the same time though, I think it supports my point that the training for these kinds of things should be faster than reading a big thick book followed by a bunch of trial and error.
[1] http://steve-yegge.blogspot.com/2008/09/programmings-dirties...
http://www.amazon.com/Thinking-Fast-Slow-Daniel-Kahneman/dp/...
The deeper analytical and design oriented thinking where someone takes extended time to identify goals, prototype and review different implementations is an important variation of Type II but not really addressed in TFAS. There might be plenty of Type I micro-decisions involved in that process too.
I'm pretty interested in how cognitive biases do rear their heads in design problems. I'm scared silly by framing effects where given options A and B, an individual chooses A but adding a third option C and now they would choose B. There are so many decisions that crop up during design/development that are vulnerable to those issues.
This industry especially in the web agency world has me burnt out. The agencies all are in competition with each other .. lowering costs and thus expect their people to get things done in manner where their employees have no life but getting their work done. It's exhausting and the work is not very fulfilling.
Now I have done the same work at Fortune 500 companies and for someone with a family and who wants a balance work & family/social life that is where you want to be!
Quality over quantity. Painting a wall is easy, painting a painting takes much more precision and care, especially when you have to exercise your design skills as a developer.
Though often, a lot of the time goes into understanding what it's supposed to be doing in the first place, and from there it's a matter of making it more resilient, isolated and friendlier to work with.
I'm the slowest dev on my team, but I squash the bugs that nobody could figure out, or knew were there. Taking things apart takes time and patience, but when you're done you know how it all works and can refactor it to be clearer/simpler, and appropriately comment on what it does and how.
But for the past year or so, I find that I program best by actually writing out my program in a notebook (in my case a quad-ruled lab notebook). I don't even start typing until I have it laid out pretty much in it's entirety on paper.
This sounds ridiculous (and I can imagine it's not practical for all types of programming), but I've found that it's been tremendously helpful in getting me to understand what all the code that I'm writing does.
Most of the code I've written this past year has been in Haskell, so that helps somewhat by not having a lot of syntax to write down, but I'm sure I'd be doing the same thing even if I was writing in Java.
This gets right back to the design thing.
With paper, I can draw graphs of relationships, write tables, add notes to things I drew earlier, etc. It's far more expressive, and far faster, than any computer tool I've tried.
On the non-mathy side, I find it useful to take the concept of "rubber duck" debugging (which is totally applicable to original design and creation, and not just debugging) but write a "duck" document rather than talk out loud. Aside from not looking crazy, I find writing easier for thought organization.
Sometimes preparing slides can also be a nice way to really force your thoughts into simplest and clearest form. And hey, when you're done, you can present it to your co-workers.
I had this false expectation in my head that when programmers tackle a new problem (be either writing a small program or solving a challenge) they're able to think about it for a few minutes then straight up write code and if I can't it's because I suck and this job isn't for me.
Then I realized that what I expected was unrealistic and the "no pen and paper" stage only occurs to people who already met the same or similar challenge before and can recall even the slightest hint of what they did back then.
My best work I do while half-napping with a notebook by my side.
"Draw some pictures. Make some notes. Write a function that you suspect will be tricky. Make a flowchart. List the methods that will have to be in that class. Write out how the user will interact with it. Try to list all the pain points for the user. You can write it any way that helps you think. Make up a notation if you want."
Yes, the assignment is due and they need to get code on the screen. But one of these days I'm going to give them a programming assignment and tell them that I only want to see their notes.
One advantage, I think, is that we can type faster than we can write with pen and paper. Thus paper is a more deliberate medium than a keyboard is.
I had to add a new feature to a decades old user facing codebase with had to interact with all of the existing system. The implementation of the core of the new feature took only a few hundreds of lines of code since it was just a bunch of graph operations basically. Interfacing with the rest of the system was hell.
I began by just investigating the requirements and designing on paper. I realized on my paper designs quickly that a few graph operations would be sufficient. Understanding how it fit with the rest of the system was only achievable to me by documenting for myself on paper how the bits and pieces worked I had to touch.
Took half a year to get the sucker ready.
Worked just like it was supposed to and my colleague praised how easy the codebase was to extend later on.
Paper and carefull design. It just rules.
To me, the confrontation posed there is not between speed and quality, but which constraints affect the system design most: coherence, or overall simplicity. I would claim the "worse is better" school of design aims to lower overall complexity by cutting the corners where the added complexity to maintain design coherence does not seemingly add any value to the implementation nor the end users.
http://www.dreamsongs.com/Files/worse-is-worse.pdf
"This advice is corrosive. It warps the minds of youth. It is never a good idea to intentionally aim for anything less than the best, though one might have to compromise in order to succeed"
It's true that who ends up getting the karma on a multiply-posted story is just a roll of the dice. On the other hand, you can stack your long-run odds as high as you want by submitting more and better stories. So it tends to even out in the end.
1. What counts as good on HN: stories of intellectual substance that many good hackers would find interesting.
I'm perfectly happy to take your word that you're working on something better.
This reminds me of something I've been saying for a while. I'm a practitioner of TDD - Test Driven Development, not Test Driven Design. I like test-first coding not because it's faster, as many proponents claim, but because it's more comfortable and thoughtful. It forces me to slow down and think about what I'm actually doing. I don't think I'm any faster when I'm coding to tests. I do, however, feel much safer. I hate that feeling of cranking out a bunch of code, then it breaks, and I don't know what broke or why.
But good design is absolutely not an emergent property of the process of coding! Thoughtless coding leads to poorly structured spaghetti. Well-tested spaghetti is still spaghetti! Good design is always a matter of compromises. You can either make those compromises in a conscious and thoughtful way, or you can close your eyes and hope for the best. Good luck with that.
>> Good design is always a matter of compromises.
You need to have coded something to have shined the flashlight into the darkness so you can put a few dots on the wall and start envisioning a path. I have small scrap projects to let me shine the light and see what reflects back.