There has been talk of 10x developers for as long as there has been software engineering.
I have had the good fortune to work with some profoundly great engineers, and it is fantastic.
But do you know what is much more motivating? 10x codebases.
The codebase you can’t fuck up because you have tests covering your ass.
The codebase you can add new features to without breaking step, because it was thoughtfully designed with change in mind.
The codebase you don’t have to wait for, because the build, test, packaging and deployment are automatic and rock solid.
Is the 10x developer a myth? Who cares. But we have all worked on 0.1x codebases. Do the math.
In my life as an architect, I find that the single thing which inhibits young professionals, new students most severely, is their acceptance of standards that are too low. If I ask a student whether her design is as good as Chartres, she often smiles tolerantly at me as if to say, “Of course not, that isn’t what I am trying to do. . . . I could never do that.”
Then, I express my disagreement, and tell her: “That standard must be our standard. If you are going to be a builder, no other standard is worthwhile. That is what I expect of myself in my own buildings, and it is what I expect of my students.” Gradually, I show the students that they have a right to ask this of themselves, and must ask this of themselves. Once that level of standard is in their minds, they will be able to figure out, for themselves, how to do better, how to make something that is as profound as that.
Two things emanate from this changed standard. First, the work becomes more fun. It is deeper, it never gets tiresome or boring, because one can never really attain this standard. One’s work becomes a lifelong work, and one keeps trying and trying. So it becomes very fulfilling, to live in the light of a goal like this. But secondly, it does change what people are trying to do. It takes away from them the everyday, lower-level aspiration that is purely technical in nature, (and which we have come to accept) and replaces it with something deep, which will make a real di ff erence to all of us that inhabit the earth.
Christopher Alexander, Forward to Patterns of Software (pdf available here)
In software, so much of our history can be traced back to this man, Melvin E. Conway.
In 1968, he wrote what became a classic paper in our cannon, How Do Committees Invent? This was to be the first exploration of how organizational structure effects the technical outcomes of projects. The most quoted line of the paper is in its conclusion:
“organizations which design systems … are constrained to produce designs which are copies of the communication structures of these organizations”
It later became to be known as Conway’s Law. Like all good “laws”, it is still as valid today as is was when it was first articulated. I don’t want to explore organizational structures here, however there is another illuminating but lesser known quote from the paper that I want to highlight:
“This point of view has produced the observation that there’s never enough time to do something right, but there’s always enough time to do it over”
Here Dr. Conway is talking about how systematic top-down design processes break down in the face of the uncertainty of discovering a software design. This breakdown causes us to “abondon our creations” with predictable regularity.
But how often do we get the opportunity to do our software over these days? Is it really common to throw away our projects and start again? How much time do we spend re-implementing systems compared to extending the systems we have?
Here are the slides from the presentation I gave at the ACCU conference this year:
Two pieces of input struck me this week that caused a bit of a brainwave. The first stimulus I chanced upon was Michael Feathers’ article on the sloppiness of refactoring, in which he proposes a nice solution to getting the habit of refactoring to completion: do it first.
For every story/feature that you accept in planning imagine how you would implement it if the code was in a state where it would accept the feature easily. Then, create a task for that refactoring work and make sure it is done before the other tasks for the feature
I like this idea a lot, and I want to introduce it in to the working agreement (how I hate that term) of our team. This would solve a lot of forgotten refactorings that seem to only be remembered at retrospective time.
The second thing that I chanced upon is The Mikado Method book. In it the authors propose a method for improving legacy code that begins with determining the dependency graph for the mini-tasks in the implementation, then starting the work at the leaves of the graph (these are the most independent areas of change in task).
What both these approaches essentially give us is a pre-refactoring step in implementation. I was so excited by both these commalities that caused me to coin the term Prefactoring. Imagine my dismay at learning that not only Prefactoring was already coined as a term in our lexicon, but also that there was even a book written with that title. Unfortunately it means something entirely different…
Beijing will participate in Global Day of Coderetreat again this year! Sign up here: http://www.meetup.com/BeijingSoftwareCraftsmanship/events/90858762/
One of the first steps in any embedded software project is to implement an assert macro. This is true for a few reasons:
- you have certain assumptions about how the hardware should behave and you want to know when those assumptions are broken,
- you need a way to signal outside of the custom hardware when something has gone wrong,
- there is no standard function that can deal with these problems.
This might seem like a wasteful thing for every project to undertake, but actually it is a very constructive place to start. Firstly, it frames the development around verification. Secondly, when you find a bug you don’t start printf debugging, instead focusing on adding assertions. And finally, from the very outset of the project you demystify the black box of your embedded system.
In the same way, I think that the first step in learning test driven development should be to write a testing framework. And it needn’t be difficult – a simple test framework can be written in a few lines of code. This is the test framework for testing the fake function framework.
/* Test Framework :-) */
#define TEST_F(SUITE, NAME) void NAME()
#define RUN_TEST(SUITE, TESTNAME) printf(" Running %s.%s: \n", #SUITE, #TESTNAME); setup(); TESTNAME(); printf(" SUCCESS\n");
#define ASSERT_EQ(A, B) assert((A) == (B))
#define ASSERT_TRUE(A) assert((A))
It could be even more concise, but I wanted to make it compatible with the googletest framework so I can re-use the test cases in both C and C++ without modification. Anyway, you get the point.
I am a big fan of testing frameworks, and for sure there is no need to re-write junit every time we start a new java program. But for learning TDD, I think a lot of the mystery would disappear when participants make a simple test framework and use that to make their first few tests.