Skip to content
Logo Theodo

The rocky road to investigation: how useful can it be?

Alix Larroque10 min read

A cartoon drawing of a woman driving a red car filled with luggage. A dog wearing sunglasses on its head is in the backseat.

Developing a feature inevitably comes to writing the actual code that will integrate that feature, but preparing that development phase is just as important as actually typing the code on your keyboard. Figure a car trip going from Paris to Montpellier: it is perfectly possible to get to your destination without any preparation ahead, but looking at a map will surely save you some detours through Morbihan if French geography isn’t your forte. Similarly, multiple itineraries can bring you to a functional product, but preparing your development can help you figure out the most efficient route.

tl;dr: Different obstacles may arise during the development phase of a feature. A deep-dive into your codebase or framework documentation can help prevent surprises requiring you to rework the code you’ve just written from popping up. Figuring out whether an investigation is needed — or not — is the aim of this article.


Getting behind the wheel and following an itinerary is the development of the feature. At the end of this phase, the feature is fully developed and able to be tested.

Before that, choosing your itinerary and the roads you will take to get to your destination is what we call writing the technical strategy of the feature. This is what gives the developer the key informations to bring the feature to life: the different files to create or edit, the logic to implement, the libraries to use, etc… It can be more or less detailed, to the extent needed for the developer to be comfortable in their development. At the end of this phase, the steps to follow in order to develop the feature are clear, and an estimated time of development has been agreed upon.

However, there are times the technical strategy initially written is insufficient to develop the feature. Just like construction work blocking the planned road, surprises may pop up during the development, that weren’t anticipated during the writing of the technical strategy. A missed API call, a refactoring revealing a mountain of unresolved dependencies or an incomplete refactoring… All things that can come up as you code and exceed the time of development that had been initially estimated during the writing of the technical strategy. In order to keep the development time from doubling or tripling the estimations made during the technical refinement, an investigation can be done to resolve uncertainties ahead of writing the technical strategy. This will allow the developer to estimate with more accuracy the time needed to complete the feature.


We will now see an instance in which an investigation would prove useful.

What’s the point?

Let’s take an example: the application SeeMyBooks allows me to list my favorite books, those I own, those I wish to acquire, and allows me to see that of my friends and family. In a context A, the developer wishes to develop a new feature B: displaying the person in possession of a book on that book’s page. That information is already stored in the database, so the only thing needed to add that information on the page should be to add a book.owner to the information displayed about a book:

// BookController.php

function bookInfo(Book $book): Response {
	return getTemplate('book_info.html.twig', $book);
}
<!-- book_info.html.twig -->

<div class="book-info">
	<span>{{ book.title }}</span>
	<span>{{ book.author }}</span>
	<span>{{ book.owner }}</span>
</div>

Simple enough! This itinerary is represented by the red arrow in the following diagram:

A red arrow going from context A to feature B, however an obstacle is set in its course.

Alas… Although the owner of a book is stored in the database, it may change: SeeMyBooks gets this information from another application’s API, BookBuyer, allowing users to buy and sell their books to other users. (For the educational purpose of this article, the legacy code of SeeMyBooks has been badly reworked. You should not keep a field in your database for a property you fetch from an API!) Therefore the initial technical strategy will not work if a book has changed owner through the BookBuyer application, as is represented by the yellow warning on the diagram above.

With that knowledge, we understand that an API call is necessary to update the owner of a book before displaying that information, as it may have changed if the book was sold through the BookBuyer application. The following code will handle that:

// BookBuyerService.php

public function updateBookOwnerFromAPI(Book $book): void {
	$url = 'https://www.book-buyer.com/api/book/owner/'.$book->getBookBuyerId();
	$response = $this->client->post(
    $url,
    [
      'body' => serialize($book),
      'headers' => ['Content-Type' => 'application/json'],
    ]
  );
	$bookOwner = json_decode($response->getBody()->__toString());
	$book->setOwner($bookOwner);
}
// BookController.php

public function bookInfo(Book $book): Response {
	$bookBuyerService->updateBookOwnerFromAPI($book);
	return getTemplate('book_info.html.twig', $book);
}

With this additional code, we managed to handle the edge case of a book changing owner through the BookBuyer application. This is represented by the blue path on the diagram below:

A blue arrow going from context A to feature B, and avoids the obstacle the red arrow was going through in a short curve.

However, the fact that this property is updated by an external application was not known by the developer at the time of coding this feature. It is only after following through the technical strategy illustrated in red and given the feature to be tested by the product owner (PO) of SeeMyBooks, that the PO informed them a bug was introduced: the book owner information was not up to date. So the developer had to get back to coding, and through a process of trial and error to figure out what was going on, finally reached their destination. This is the path illustrated in green below:

A green arrow going from context A to feature B, but makes a wide convoluted unnecessary detour compared to the path of the blue arrow.

It is clear in this case that the lack of knowledge of the codebase caused the developer to waste time (their own, and that of the product owner), and in turn exceed the previously estimated time of delivery of the feature. Altogether, it can decrease the confidence the PO has in the development team and reduce customer satisfaction. To prevent such a turn of event, an investigation could have been carried out.

The aim of an investigation is to allow a technical strategy to be written with no remaining technical uncertainties. The path to take to develop the feature is clear and leaves no ambiguities.

To investigate, or not to investigate?

Of course, although it is important not to go head first into a complex development, it is not always necessary to spend long hours investigating when the feature you need to implement is simply adding an icon before a page title. Asking yourself a couple questions before diving into a technical refinement can help you figure out if an investigation would prove useful in your case:

A monocle emoji framed by two bubbles with the words "framework" and "codebase".

Let’s take two examples about the same application — SeeMyBooks, although at different points in time:

Without investigation, the technical strategy will be established with the knowledge of the codebase that the developers already possess, which saves time during technical refinement. This configuration is well adapted for projects from scratch or well known by the development team, and allows them to deliver quickly simple features, or features that the developer is used to program.

In our first example about the favorite books, the developer decides to skip a potential investigation, because he knows that this favorite books property is only used on one other page so far, since he was the one who coded it. On top of that, although he doesn’t know all the in and outs of the templating engine, he knows how to display relation properties.

A speed meter labeled "time spent investigating" with a low speed and text saying it is suitable for projects from scratch, a well known codebase or experienced developers.

On the other hand, an investigation helps resolving the subsisting technical uncertainties before settling on a technical strategy in order to limit nasty surprises during actual development. This configuration is well adapted for a legacy project or rookie developers, but requires spending additional time on conception.

In the case of the import of the new book store data, the developer decides to carry out an investigation, because she knows that although those objects are handled in the settings, she doesn’t know where and how they are used in the rest of the application.

A speed meter labeled "time spent investigating" with a high speed and text saying it is suitable for legacy projects, rookie developers or a new framework.

And because of this investigation, she discovers that the Bookshop entity, is not an entity representing a bookshop object: it actually is a relation between a bookshop and a book! There are 78 bookshops known to the application, and about 1000 books, and although a bookshop carries about 50 different books only, an object instance is persisted anyway, and the information about if a bookshop carries a book is contained in the property presentInBookshop on the Bookshop entity. The size of the bookshop table is 78,000 lines and contains much unnecessary information! A refactoring is therefore necessary to implement the new feature, in order to be compatible with the new data format given by the API.

A refactoring implies knowing the existing code clearly in the aim of overhauling it, and an investigation allows developers to acquire that lacking knowledge.


Through these two examples, we have illustrated why an investigation may be needed. Especially in the case of structuring changes such as refactoring parts of the application, having a clearly defined and doable technical strategy to reach your destination will save you from many back and forths. Particularly when knowledge gaps prevent you from resolving all uncertainties before writing the technical strategy.

Conclusion

For smooth feature development and to avoid wasting time and resources, a clear and exhaustive technical strategy is needed. To achieve that goal, an investigation may be in order. Using this article frame, you should now be able to figure out if an investigation would be necessary in the prospect of your next feature.


Two checkpoints defining a good investigation:

In this article, we shared the questions you need to ask yourself to make sure that first checkpoint is being met. That second checkpoint will be the subject of another article, to ensure the itinerary you choose for the development of a feature is straightforward, and does not require you to make constant U-turns as you code.

Liked this article?