raganwald
(This is a snapshot of my old weblog. New posts and selected republished essays can be found at raganwald.com.)

Thursday, June 01, 2006
  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:

 

Comments on “The trade-off between power and ease of use in library interfaces:
BLOODY Here HERE!
 
"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. "

Wouldn't the open nature or Ruby allow on to write the plugin anyway, no matter how "locked down" the base application?

Having explicit hooks for such things may make things easier, but they may be less important in a language such as Ruby.
 
"Wouldn't the open nature or Ruby allow on to write the plugin anyway, no matter how "locked down" the base application?"

Don't you think DHH had that in mind when he chose Ruby to begin with?

My proposition is that if a designer prefers to place strictures on other programmers, she will eschew languages that do not provide locks and hurdles.
 




<< Home
Reg Braithwaite


Recent Writing
Homoiconic Technical Writing / raganwald.posterous.com

Books
What I‘ve Learned From Failure / Kestrels, Quirky Birds, and Hopeless Egocentricity

Share
rewrite_rails / andand / unfold.rb / string_to_proc.rb / dsl_and_let.rb / comprehension.rb / lazy_lists.rb

Beauty
IS-STRICTLY-EQUIVALENT-TO-A / Spaghetti-Western Coding / Golf is a good program spoiled / Programming conventions as signals / Not all functions should be object methods

The Not So Big Software Design / Writing programs for people to read / Why Why Functional Programming Matters Matters / But Y would I want to do a thing like this?

Work
The single most important thing you must do to improve your programming career / The Naïve Approach to Hiring People / No Disrespect / Take control of your interview / Three tips for getting a job through a recruiter / My favourite interview question

Management
Exception Handling in Software Development / What if powerful languages and idioms only work for small teams? / Bricks / Which theory fits the evidence? / Still failing, still learning / What I’ve learned from failure

Notation
The unary ampersand in Ruby / (1..100).inject(&:+) / The challenge of teaching yourself a programming language / The significance of the meta-circular interpreter / Block-Structured Javascript / Haskell, Ruby and Infinity / Closures and Higher-Order Functions

Opinion
Why Apple is more expensive than Amazon / Why we are the biggest obstacles to our own growth / Is software the documentation of business process mistakes? / We have lost control of the apparatus / What I’ve Learned From Sales I, II, III

Whimsey
The Narcissism of Small Code Differences / Billy Martin’s Technique for Managing his Manager / Three stories about The Tao / Programming Language Stories / Why You Need a Degree to Work For BigCo

History
06/04 / 07/04 / 08/04 / 09/04 / 10/04 / 11/04 / 12/04 / 01/05 / 02/05 / 03/05 / 04/05 / 06/05 / 07/05 / 08/05 / 09/05 / 10/05 / 11/05 / 01/06 / 02/06 / 03/06 / 04/06 / 05/06 / 06/06 / 07/06 / 08/06 / 09/06 / 10/06 / 11/06 / 12/06 / 01/07 / 02/07 / 03/07 / 04/07 / 05/07 / 06/07 / 07/07 / 08/07 / 09/07 / 10/07 / 11/07 / 12/07 / 01/08 / 02/08 / 03/08 / 04/08 / 05/08 / 06/08 / 07/08 /