zby has asked for the wisdom of the Perl Monks concerning the following question:

I proposed an API change to a CPAN author - it amounts to removing one 'reserved name' - it looks for me as a clear gain - because it simplifieds the mental model. Then I thought how to support that reasoning and that it is an interesting subject it itself - and it would beneficial to be conversant in that subject.

So here is my question - are there any objective complexity measures for APIs? I am sure there must be some literature on that subject - but some quick googling did not reveal much science.

Replies are listed 'Best First'.
Re: API complexity measures
by stvn (Monsignor) on Jun 10, 2008 at 14:00 UTC
    are there any objective complexity measures for APIs

    No, pretty much all of them are arbitrary to one degree or another. I think complexity is a really hard thing to measure for APIs. For instance a complex problem domain will necessitate a complex API and that is a good thing. IMO, a simple API over a complex problem domain very rarely works. It is either not powerful enough, because the compromises the author had to make for the sake of simplicity removed too many features/options. Or it is actually more complex because the author applied their own personal world-view/metaphor-model to the problem domain and you have to understand that before you can even think about using the API itself.

    Personally I have always been a fan of consistency being a good way to manage complexity in APIs. A few years ago I got a book called Reusable Software : The Base Object-Oriented Component Libraries by Bertrand Meyer off of eBay. It sat on my shelf for a while until I found myself needing to write a large-ish set of libraries for $work, and not having any clue how to approach it. The book has lots of really good advice, but the thing that stuck with me the most was the idea of using consistency as a way of managing complexity. Not only consistency in class, method and variable names, but consistency in abstractions as well. Meaning that similar concepts should be broken down in similar ways and provide similar features.

    A side effect of consistency is also that it can breed habitual behavior. Around the same time I read The Humane Interface by Jef Raskin and The Invisible Computer by Donald Norman, neither of which are about APIs, but whose deeper messages can be applied to API design. The core ideas I took away from them was that a good interface is one whose use can become habitual, thereby moving from a conscious act to a (partially) subconscious act. This is not to be mistaken for "intuitive" which basically means "well it makes sense to me, what are you so stupid that you don't get this". To me a habitual API is one where after using it for a while it becomes possible to make educated guesses and have them be correct a fair portion of the time.

    -stvn

      This is a terrific answer (++ to dragonchild below too). This embodies something I've been harping on lately -- why I really dislike XML::Simple and ended up with the decidedly not-simple XML::LibXML. The disguised/compromised complexity versus the consistent interface to the other layer (the DOM).

      OK - it might be hard to measure in the general situation - but sure there are cases where you can say that "this API is more complex than that one" in some objective way?

      Ad. consistency - this is another very interesting subject. How would you argument that one interface is more consistent than another one?

      My question is actually mostly about communication - what I want is to have a vocabulary and references to discuss those matters in some informed way. I understand that it might be very difficult - that is why I asked for references instead of expecting ready made answers.

        A trivial (but very important) example of consistency in an interface is to always pass the same parameters in the same order and, as far as possible, match the order to any relevant prior art.

        For example: if your API provides a number of move and copy related elements, you might ensure that they are all (target, source, length).

        To the extent that an API is consistent in the way it manages parameters, conceptual units, data structures and so on the API is consistent. 'Orthogonal' is often used and is a related concept.


        Perl is environmentally friendly - it saves trees
      This "simple API over a complex problem domain" sounds like "leaky abstractions" - is that what you have in mind? By the way this article describes a similar sentiment I think: Complexity of APIs.

      But I don't agree that measuring API complexity is hard - what is hard is judging if the complexity can be reduced without introducing "leaky abstractions", but you can have quite simple measures. By splitting the problem into two - first analysing the functionality and how much of it can be abstracted away - and then measuring the complexity of the API we can make the evaluation of an API more manageable.

Re: API complexity measures
by dragonchild (Archbishop) on Jun 10, 2008 at 14:24 UTC
    To follow on stvn's response, there is a certain amount of complexity inherent to a given system. That complexity has to be dealt with. It cannot be wished or designed away. To illustrate, I once worked for a medical claims company as their web guy. My internal client had this idea that we should reduce the number of mouse clicks. Not a bad plan, except he wanted the user to be able to make three unrelated choices with two mouse clicks. We could have done it, but that would have necessitated tying unrelated ideas together. The complexity was going to come out, no matter what. It's like water in a river. You cannot stop the water - you can only channel it.

    Your API change may have simplified your mental model, but would it have simplified the overall model that the author was dealing with? With DBM::Deep, people are constantly asking me for a bunch of optimizations that work extremely well if your process is the only consumer of the DB. Unfortunately, I can't work them in yet because the other use-case is if there are multiple processes accessing the DB. What should I do?


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      Sure there is inherent complexity that cannot be sensibly reduced. But there are also cases where there is too much complexity in an interface. My question was about that second case.
        You asked about a measure. That measure is how you would determine between the first and the second cases. Otherwise, you have your gut to go on. Guts are very poor measures of anything.

        My criteria for good software:
        1. Does it work?
        2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: API complexity measures
by BrowserUk (Patriarch) on Jun 10, 2008 at 16:43 UTC

    The best way of investigating the ways of reducing interface complexity, is to look at the evolution of competitive products in the consumer electronics industry.

    For example, my LCD TV, has all the usual options for adjusting color/contrast/brightness etc. of the picture. It also has all the usual setting for sound: base/treble/brightness etc. And all of these options can be accessed and adjusted individually via on screen menus. However, there are also individual buttons for 'sound' & 'picture' which cycle through 4 presets. ('movie','music','speech' & 'user') and ('statndard', 'movie', 'vivid' & 'user') respectively. A dozen or more individual options with their up & down settings reduced to a couple of buttons that are easy to access and quick to change. It works.

    There is a similar mechanism in some of the better designed CPAN modules. The whole ':xxx' option mechanism that pre-selects a whole set of imports. Of course, that mechanism can itself be abused because all of the individual elements are also individually exportable, which makes these 'convenience bundles' add to the interface complexity, rather than reducing it.

    One of the possibilities to simplify interfaces, especially of OO modules, is to simply not expose all the internal fields. One of the problems with some of the myriad "OO foundation classes" on CPAN, is that they automatically generate setters and getters for every internal field. In most cases, this is the very last thing an OO module needs.

    Far too often OO module authors encapsulate their internals, only to substitute 2 interface elements (getter + setter), for each individual element and so increase complexity rather than reducing it.

    Alternatively, they will use some real-world metaphore for the underlaying representation as an abstraction that is actually more complex and less inutative than the underlying abstraction. For example, (sorry to pick on the author, but its an example that is fresh in my mind), the whole Thread::Conveyor::* hierarchy wrapped over a simple shared array renders an interface that is far more complex and less intuative than the underlying representation.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      This 'xxx:' option mechanism - I would call it Huffman coding of the interface complexity. You add some complexity (some additional options) - with the benefit that for most operations you can ignore the much more complex full set of settings.