The trade-off between power and ease of use in library interfaces
Rusty has
another great contribution to the discussion about locking down interfaces (a/k/a "final good or bad" also a/k/a "concrete good, abstract bad").
Rusty points out that restricting an API makes it more accessible:
The I in API stands for interface, and interfaces are for people, not just machines. APIs can be complex, confusing things... The smaller and simpler the API is, the easier it is to learn and use; the more likely it is that the API will be used correctly.
I'm going to repeat and double underscore my suggestion that there are different approaches to the problem of designing software that other programmers must incorporate into their own designs.
Rusty points out the obvious: there is a far greater 'market' for smaller and simpler things than for powerful things:
For instance, you can switch a class from storing persistent data in a file to storing it in a database or vice versa. Sometimes this is important; but be honest: how many times have you really needed to do this? Out of the thousands of classes youÂve written, how many have had significant changes in their internal data structures? Maybe 1 in 10? And in how many have you actually needed multiple simultaneous implementations? Maybe 1 in 100, or less?
True. But ummm... Does it matter whether you want to do something like this once a day, once a week, one a month, or once during a project? If you ever want to do this, why shouldn't it be possible?
Let me jump in and answer the question for you:
there's a trade off to be made between power and ease of use. The power to do unusual things (like climb roof cracks or modify frameworks) comes at the expense of ease of use (as measured by the narrowness of the interface).
So if you make it possible for me to do powerful things, you might make your code harder to use for some class of people who never need to do these things. I'm all for that. There's a knob you can turn when you create your design: power vs. accessibility for the masses.
(I don't say power vs. simplicity: thanks to the
Turing Tar Pit, it is possible to make something extremely simple, but have extraordinary power because you have provided the basic building blocks that allows your client programmer to do almost anything. For example, the programming language Scheme has just five 'special forms'. Almost all of the resulting power in the language, including the ability to define new Domain Specific Languages, comes from the way these five elements can be combined to create new forms.)
I really think it comes down to thinking about your 'clientele' when you design frameworks or libraries. Remember that this started with someone calling for the final keyword to be deprecated from the Java language. C'mon. Java.
Think about the Java programming culture for a moment. If I were writing a Java library for widespread use, I would consider Rusty's position carefully. After all, most of the people who would lament any restrictiveness have probably
bailed and are hacking rails right now. But the remaining Java folks want their IDE and their compiler to catch all of their bugs for them. So if you 'cut against the grain', you provide power nobody wants at the expense of the simplicity they need to be productive in their environment.
But if I were writing a Rails plugin... wait! You couldn't write a Rails plugin if DHH had locked rails down to begin with. Anyways, anything you do in the Ruby world should be far more open. You have a different clientele, with a different culture. It's really that simple.
Of course, there's a trivial argument that all that 'powerful but unrestricted stuff' only works in small teams. That once you have 100+ programmers hacking on something you need more safeguards than a Missile Silo.
All I can say in response is that (1) everything that has ever impressed me in software was done by small teams, not big ones. Just
twenty-nine people created the entire Macintosh computer, for example. And (2) given that productivity diminishes sharply with team size, shouldn't we be trying to find ways to make big teams smaller, such as by giving them more powerful tools?
So I think that for a different programming culture, with a different kind of client programmer, you want and need to follow a different design philosophy that emphasizes trusting your client and providing as much power and flexibility as possible.
This isn't a 'bad practice you can get away with in a small team' any more than rear-wheel drive and a manual transmission are bad engineering choices that you can get away with if a driver actually knows how to drive. Or than Scrum is a bad practice you can get away with if your team is gelled and motivated. They are appropriate choices under specific circumstances for a specific clientele that has the requisite skills and attitude.
This is my theory.
Conclusion:
So you ask me, is my theory bad? And I reply with a question,
for whom?
Labels: java