> I believe programming, in this regard, can learn something from writing: when writing the first core of a new system, when the original creator is still alone, isolated, able to do anything, she should pretend that this first core is her only bullet. During the genesis of the system she should rewrite this primitive kernel again and again<p>This is a very subtle and interesting point. This notion of the 'primitive kernel' that is hard to change, is the problem of how much abstraction to invest in, at the beginning of a feature or project. It seems to always be a balance between doing what is needed for the immediate specifications, and doing what is needed for future reusability and extensibility of that same piece of code. In other words, how much should this piece of software be abstracted for future reusability?<p>It is tempting to think that highly abstracted code is overkill. However, abstracting code on the first introduction of a feature, allows for this "primitive kernel" to be as solid as possible, such that it doesn't need to change often. There is an illusion of doing too much work by considering all the use cases before needing them, but what I think really happens is that<p>*the longer you put off abstracting something (i.e. copying code instead) the more expensive the abstraction will be once you get to it.*<p>So the first abstraction, nicely put in the quote above, "During the genesis of the system she should rewrite this primitive kernel again and again", illustrates why it should be done right the first time around. It is cheaper to do so on the first try when nobody is using the abstraction. Compare this to a later time, a time when the kernel is already being used by lots of other components, now you have to take those use cases with their exceptions into account, making the process of abstracting more complicated and risky.<p>*NOT abstracting as much as possible, is setting the software up for an inevitable increase in complexity, and therefore cost in effort to reduce it.*<p>Summarizing: abstracting code on the first pass is avoiding the increase in cost of that same abstraction if you wait until there are multiple concrete cases of it. I suspect it's a function of how many concrete cases there are to abstract, multiplied by environment's stability (once it's shipped, abstracting gets even more difficult and costly).