Govern software architecture with Fitness Functions in Python

This article was first published on Python – Makimo – Consultancy & Software Development Services , and kindly contributed to python-bloggers. (You can report issue about the content on this page here)
Want to share your content on python-bloggers? click here.

In 2019, Paula Paul and Rosemary Wang wrote a blog post about the fitness function-driven development concept. I will explore this concept here and show you how we can write simple fitness functions using Python and what advantages and disadvantages this concept may introduce to your projects. The article is not a full-scale guide, but rather an introduction to the concept so you can start digging yourself.

Fitness Function 

A fitness function is a concept that allows you to keep an eye on software architecture metrics that are important to you. The core of the concept is to ensure that the system’s architectural metrics are close to (or do not violate) the architectural goals that we currently have in our project when the developers are developing the application.

Fitness function-driven development

Most developers know TDD (Test-driven development), which focuses on writing automated tests before adding code related to the features. Fitness function-driven development re-uses part of that approach. However, in this case, we focus on automated tests not for specific features but rather on automated tests for the entire system architecture. Thanks to that, we can check how close we are to our architectural goal or if developers do not violate anything on each application build using CI tools.

Why would we use it?

The world is constantly changing, and so is the software. Software architecture is usually a complex structure that takes time to judge. Having a tool that would check if the system meets its architectural criteria without manual intervention is very useful, especially for software where some metrics are not visible at first glance.

An added benefit of automated architectural metrics is that with the growth of the system the earlier decisions won’t be swept under the rug and at some point where the metrics stop reflecting the business reality, a conscious decision of the development team must be made whether they should go back or change architectural drivers of the application.

Core metrics

The authors of the concept listed several metrics/concepts that could be monitored with fitness functions, and I will focus on these two:

  • Code quality — whether our code is on some level of quality. For example, we may have a function that checks the test coverage across the system. The other idea that comes to mind is to check whether code is accessed in the correct layer in the layered architecture.
  • Performance — we might monitor whether our core modules are good enough to support the production workload.

Advantages

The biggest advantage is that we can monitor the quality of architecture with each improvement/change made to the code. For example, if we decide that performance is the most important concern, we could monitor the performance of core modules of the domain and see if it’s good enough for us. 

Disadvantages

The first thing that comes to mind is that we need to write the fitness functions first. Also, we need to maintain them, and it wouldn’t be wise to keep them out-of-date when our architectural aim has changed. 

Examples

Fitness Function to watch over layers

To watch over layers in Python, we could create a simple function that analyzes the imports of a given file and verify if a specific keyword is not used in the file that we should check. The fitness function could be created using a simple lstrip function that would check whether something is an import. However, to maximize the results, I will use Python’s ast module to help me process the syntax from the file that I specify in the path argument. It may look like this:

Usage

Given the following structure of files:

/app
    /web
        gateway.py
    /component
        __init__.py
        persistence.py
        service.py

We want to test that persistence layer functions are not used in the web layer. We could create the following pytest test:

If the analyze_imports function raises the ValueError, then the persistence module is accessed in the gateway.py file in the web layer.

Fitness Function to watch over the performance

Performance should almost always be taken into account when developing an application. More often than not, good performance is required by the client. That’s why we might want to check whether the performance of our code stays on a good enough level throughout the changes applied during the development. The simplest example of a fitness function that would check performance is measuring the time of the execution of a given function. For example, it could look like the following snippet of code:

As you can see above, we simply take the callback function, execute it and check how long the execution took. Now, it’s time to generate a proper test that uses the measure_execution_time function. For starters, we could create a simple example-based test with one example of the following implementation:

We can create a property-based test if we want to check more than one specific example. To do that, we have to install the hypothesis library using pip package installer:

pip install hypothesis

If we have the hypothesis installed, we can create a simple property-based test that will generate more examples for us:

Conclusion

Fitness functions are a great way to support the architect. They can help you more quickly diagnose potential architectural problems in the code from the very beginning of a project you’re working on. Furthermore, they can be a good way to find out which system components might require a refactor to decrease the technical debt. Sadly, we need time to write and adjust them during the project. Thus, use them wisely and don’t overengineer your projects with tons of them for modules that are unimportant to both your client and the project.

Fitness functions can be an important step to long-lasting, maintainable software…

Schedule a consultation

To leave a comment for the author, please follow the link and comment on their blog: Python – Makimo – Consultancy & Software Development Services .

Want to share your content on python-bloggers? click here.