Monday, January 26, 2004

Two lessons learned

Premature synchronization is the root of all evil:

No matter how sure you are that part of an interface will never need to block, you are wrong. Even the simplest task will be expensive or slow for someone, at some point. Design interfaces to deal with asynchronous responses from the start. How did I learn this? I designed a mailbox framework and make the "select mailbox" operation synchronous, almost alone among the 30 or so other functions in the interface, because I was certain it was such a simple operation it would never need to block.

Loading data is expensive; loading unnecessary data is inefficient:

For the sake of simplicity, the "list all mailboxes" operation was implemented in terms of objects already defined by the interface. Specifically, it was defined to return a list of mailboxes, but only a few fields of each mailbox are ever actually used. How did I learn this? Tonight discovered that my implementation of this operation ran over ten thousand times faster if the implementation only returned the required data, instead of whole mailbox objects. Oops.

1 comment:

  1. 1. maybeDeferred is a nice tool to use for ease of migration from sync to async. This means people who already implemented a sync operation don't need to change their code.
    [I know you know this.]

    2. Thick/Thin interfaces solve this exact problems -- letting you have something that can operate in terms of other operations and later replaced by custom more efficient equisemantic code.