4 Balancing flexibility and complexity

 

This chapter covers

  • Flexibility and extensibility versus const of maintenance and complexity of your API
  • Providing maximum extensibility by using Listeners and Hooks API
  • Tackling the complexity and guarding against unpredictable usage

When designing our systems and APIs, we want to find a balance between a set of features that it supports and the maintenance cost that arises from those features' complexity. In an ideal world, every API change, such as adding a new feature, would be backed by empirical studies. For example, we can analyze the traffic on our website, and according to a need, add a new feature. We can also conduct A/B testing to decide which feature should be retained and which one was not needed. Based on the results of A/B testing, we can remove not-needed features.

When we build APIs(libraries) used by other engineers and teams in our organization, we need to foresee a need for some features. If we create a library with a minimal set of features and design that is not extensible, we may end up in a situation when we need to refactor the code and change the API frequently. On the other hand, we can create a super extensive code and allow for its customization in all places. By doing so, we try to foresee all possible use cases and usages of our code. We are also increasing the complexity of our code, and often it ends up over-engineered.

4.1   Creating a robust but not extensible API

4.1.1   Designing a new component

4.1.2   Starting with the most straightforward code

4.2   Allowing clients to provide their own Metrics framework

4.3   Providing extensibility of your API via Hooks

4.3.1   Guarding against unpredictable usage of the Hook API

4.3.2   Performance impact of the Hook API.

4.4   Providing extensibility of your API via Listeners

4.4.1   Immutability of our design

4.5   Analyzing the flexibility of an API versus the cost of its maintenance

4.6   Summary