Mistake #1 - Using an existing codebase to understand product requirements

How many times during our professional career have we come across the situation where we're looking at existing code to understand the whole product flow. While that can give a good idea of how things are implemented, we may miss out on one aspect or another while only looking at the current codebase. Let's not forget that AB experiments can also add to the risk of missing out on product paths.

For instance, consider the following:

Situation: We have to design an API that returns a currency code & format to use across pages. To understand all the use-cases, we look at the various existing apps and debug to find how currency is used today.
We reviewed most pages and concluded that they were rendering the traveler's chosen currency. Hence, we designed our API to return the traveler's chosen currency and format.

Problem: We were not aware of another page which showed the host currency instead, and this lead to a bug! We missed that flow. Now, we have to update the API to cater to more use-cases like this one.

Solution: Reach out to the Product Manager of the applications, they can list all the product flows and help with our use-cases.

While it may be good to understand how the code is implemented for a product flow, it may be best to reach out to the product team working on that part of the project instead.

Mistake #2 - Rushing to finalize a design

Designing a system or an API has to be an iterative approach. We cannot wait indefinitely for all the use-cases to unfold before we start designing.

For instance, consider the following:

Situation: We have to design a new API for a property description. For now, we only know that it'll return some description text, however we must finalize the design around it.

Problem: At a later stage, we learn that returning just the plain property description isn't sufficient. The requirement is to also filter by attributes (like room type, property type, etc.) and we must return a map of description attributes.
We'll have to re-iterate on the design.

Solution: Gather all the basic requirements but expect to update your API design as you learn more.

It's best to make designing an iterative approach, where we can refactor and refactor till we have a good system design.

Mistake #3 - Not thinking about how an end-user would use your design/solution

Another common mistake that we tend to make is not thinking about how our design will be consumed. Will it be easy or difficult to use? We must think about end-user use cases.

For instance, consider the following:

Situation: We have designed an API returning an unstructured list of property details specific to some type (location/stay policy/amenities, etc). Each property detail can further have secondary text and an availability flag, where applicable.

Problem: Team A only wants to read the availability for a specific detail of a property. But they have to iterate through the entire list to find the required detail and then read if it's availability.
This led to unnecessary & avoidable code to read the data they need.

Solution: Design the API in such a way that the end-user doesn't need to do any avoidable work, reducing complexities at their end. Maybe return a structured response in the above given situation, or request for just that detail/or all available details and return only that.

While designing & implementing the system, we should keep in mind the challenges that end-users may face while using it.

Mistake #4 - Not thinking about extensible solutions

Having an extensible design does not only mean having code which can be extended further, but also that the solution can be extended to other consumers of your design.

For instance, consider the following:

Situation: We designed an API to return booking policies that are to be displayed on Page A. We modeled our API in a way that it's easy for the team working on Page A to display them.

Problem: Team B working on Page B has a similar requirement to display the same booking policies, and also wants to use our API. But because the API was too tightly coupled to how Team A uses it, Team B can't use it directly.
We have to refactor/redesign it all over again!

Solution: An API design shouldn't be tightly coupled to the needs of the current/only consumer, which also means that our changes shouldn't affect the other systems using it.

Our design should be able to cater to similar needs of other consumers as well.

Mistake #5 - Trying to add too many features leading to a complex design

While it's true that we shouldn't have a separate system/endpoint for every related requirement, we must also ensure that our system is not complicated because it's handling too much stuff, especially if it could have been separated better.

We should always try to optimize the features our design caters to, while also maintaining separation of concerns.

For instance, consider the following:

Situation: We have to design an API for a library, which can return a list of books and also supports updating book details (E.g. type, author, and name) by both librarians and book issuers. The API can also return filtered lists of books and sort them. It can also search for books by any of their attributes.
We added all the functionality at a single place in the code (data model to our API).

Problem: We have to separate out the few features specific to librarians only.
It's complex to understand all features implemented at one place, to be able to identify specific ones.

Solution: Design a system in such a way, that related features/functionalities are together. Separate out the concerns by customers (librarians vs borrowers), and also by functionality.

The design shouldn't get too complex to use and understand.

Attachments

  • Original document
  • Permalink

Disclaimer

Expedia Group Inc. published this content on 09 September 2021 and is solely responsible for the information contained therein. Distributed by Public, unedited and unaltered, on 09 September 2021 13:21:06 UTC.