4

I am in the process of designing a small library, where one of my design goals is that the API should be as close to the domain language as possible. While working on the design, I've noticed that there are some cases in the code where a more intuitive, readable attribute/method call requires some functionally unnecessary encapsulation. Since the final product will not necessarily require high performance, I am unconcerned about making the decision to favour ease-of-use in my current project over the most efficient implementation of the code in question.

I know not to assume readability and ease-of-use are paramount in all expected use-cases, such as when performance is required. I would like to know if there are more general reasons that argue for a design preferring more efficient implementations—even if only marginally so?

4
  • 11
    Marginal performance improvements are rarely worth anything.
    – user7043
    Aug 28, 2012 at 14:41
  • 2
    possible duplicate of Do you prefer conciseness or readability in your code?
    – user8
    Aug 28, 2012 at 17:10
  • 1
    I don't see the questions as being the same. I would not equate efficiency to terseness.
    – jmlane
    Aug 28, 2012 at 17:14
  • Nothing prevents you from having an API that is both easy to use and optimized. Sep 26, 2012 at 19:09

4 Answers 4

6

To answer the title question: When you really need the performance gain. Real-time systems, embedded systems, or something like this. Or when the code is at the very low level and there are abstraction over abstraction layers built over it. Even then I'd prefer proven bottlenecks before optimization. You won't win much when the code is called once in an hour. When it is called hundred thousands of times a second, then there's a number.

Since the final product will not necessarily require high performance...

There. Seems like you should go for readability and ease-of-use first and put a comment there: "Optimize by doing Foo. Maybe. If necessary. Better not."

4

API == interface

This should be as simple and intuitive as it can be. It is also totally independent of the implementation.

Implementation == inner working

Make a clean implementation, with well structured code and good design decisions. Premature optimization is the root of evil. Take a profiler and check where you bottlenecks are.

1
  • Agreed, yet there seems to be some cases where implementation influences interface. For example, if I want to access a Python method by way of "module.realClass.anAttributeAsClassB.becauseINeedThisMethodCall()", I've encapsulated what could have been an attribute in a class, simply to give that method a call path that mirrors the domain language. The implementation of anAttributeAsClass is effected by the desired interface for becauseINeedThisMethodCall(). This is a contrived but adequate example to illustrate the context of my question.
    – jmlane
    Aug 28, 2012 at 15:05
3

When you're building a library, or any tool that will be used by many people for different purposes, this is a problem, because they all have different needs.

What I try to do is get some representative use cases, and make sure my product makes a reasonable choice for those cases, and is not atrociously bad in any case.

If I can just give one example of what can happen:

The LAPACK routine DGEMM is a general routine for multiplying matrices. Its calling sequence contains initial character arguments for specifying certain options, like whether either argument is to be transposed.

The customizing arguments are in there for two purposes: to make programming easier for the user, and to make it easier for the library writer. Without them, either the user would have to transpose the arguments him/her-self, or the library writer would have to provide multiple routines.

To handle those arguments, DGEMM calls a function LSAME that compares characters. That also makes life easier for the library writer, because character representation can be very different for some machines.

The downside of this is, if the matrices are not very large, that DGEMM spends most of its time calling LSAME, compared to the time it spends multiplying matrices! If the user's program spends a large fraction of time calling DGEMM, that means a large fraction of time is spent calling LSAME, comparing characters (even though those characters are practically always the same). Repeated effort is wasted effort. If a user can figure that out, such as by random pausing, they can make ad-hoc routines for multiplying their matrices.

But the more general point is - that is the problem in writing libraries or any tools. You have to try to be useful for a spectrum of needs.

0
1

Never optimize unless you have very good reasons. There is so much going under the hood (there is a ton of obscure optimizations in the compiler or even in the CPU itself) that it's very hard to know what kind of impact your optimization will have. You could make it faster or slower, you will never know unless you profile it.

Also, if your application is already fast enough, why should you bother making it faster? It's time you will waste when you could spend it making your code more readable.

4
  • Nothing personal, but "never optimize unless you have very good reasons" sounds load of BS to me. It gives an impression that optimizing code somehow would be bad thing and would somehow result in less readable code. This is very rarely the case, and even if it is, then code comments should explain what and why. It feels as if optimizing code is being frowned upon by people for some reason - usually by people who never write code which would need to be optimized - and as such by people who hardly have any experience with optimizing code. Algorithmic optimizations have no impact on readability.
    – zxcdw
    Aug 28, 2012 at 17:35
  • So you would say that one should optimize even if he doesn't have good reasons?
    – plmaheu
    Aug 28, 2012 at 17:47
  • 1
    I'm saying that code efficiency should be taken into consideration all the time. If you decide to implement an algorithm, by all means implement the fastest one which suits your needs. Of course trusting the compiler with simple optimization is recommended, but actually keeping in mind that code efficiency is never a bad thing is something I'd wish people to think about. These days hardware does not progress as fast as it did 10 years ago, and more and more software is written for mobile devices where code efficiency is important, not only for run-time performance but also for battery life.
    – zxcdw
    Aug 28, 2012 at 17:54
  • I strongly disagree with "If you decide to implement an algorithm, by all means implement the fastest one which suits your needs". What if this algorithm accounts for 1% of your total execution time? That means you will waste time for an absolute maximum of 1% speed improvement. Again, profile and decide if the improvement is worth the effort.
    – plmaheu
    Aug 29, 2012 at 23:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.