← Back

Refactoring a Project's Structure

Refactoring also means organizing a project's structure. Simplifying modules, libraries, and tests improves agility and lowers maintenance costs.

RefactoringBest Practices

In The Programmer’s Black Book, like any other book that teaches us to become better professionals, strongly emphasizes that code refactoring is not just a tool we should use; it is a habit we should practice every day, and one that distinguishes the best software developers.

However, refactoring is often understood only as changing and improving lines of code without affecting its external behavior. In doing so, we clean up the code to some extent, making it better quality, more readable, and more maintainable.

I always insist that this isn’t something we either do or don’t do: it is part of programming a solution; it’s inherent to the process.

When we finish implementing a new feature, we should always ask ourselves: can we improve what we’ve implemented in some way? Can it be simplified? Can it be improved as part of the overall project so it can be reused? And so on. The surprising thing is that once you develop the habit of asking these questions, you hardly need to do this at the end of an implementation, because you already have the habit of keeping things clean from the start. As a result, the effort or time spent purely on refactoring at the end is minimal.

Still, refactoring is usually understood as improving the code. But what about the structure of a project that keeps growing over time? I’m not talking about design, but about how folders, subprojects, and so on are organized.

As a project grows (with scattered libraries, numerous subprojects, too many external dependencies, or even a complex test-project structure), it too must be refactored.

We recently completed a new release of one of the projects we’re currently working on: the IRIS Remote Management and MDM Platform for PRIME metering devices. I proposed spending a few days improving its internal structure to keep it from becoming increasingly complex to manage and work with.

Specifically, some of the things we’ll evaluate include:

  • Consolidating scattered libraries that could live in a single project.
  • Integrating small subprojects that could fit coherently into others.
  • Improving the layout and structure of integration tests.
  • Laying the groundwork for the task manager—which is now tightly coupled to the solution’s specific characteristics—to become a project-independent framework that can be reused by other projects we launch.
  • And so on.

What am I hoping to achieve?

As a project grows more complex and reaches hundreds of thousands of lines of code, even if everything is exceptionally clean and its overall architecture and micro-designs are carefully crafted, the distribution of the project’s artifacts itself can become a problem, making it difficult to find things easily and comfortably. A project can become spaghetti-like not only in its code, but also in the structure of its modules.

By improving and simplifying how things are distributed and organized, we become more agile and comfortable when working on a new release. What’s not so obvious is that this agility and comfort translates into many hours of work saved. We achieve the highest quality when we have an environment that’s comfortable to use and work in. Maintainability has a lot to do with this, too.

Every act of refactoring, whatever its kind, saves time in the future by reducing the effort needed to evolve a well-built application. In other words, the time invested in refactoring leads to better productivity (= fewer financial resources needed to get something done).