Software, projects & software projects

Refactoring: Boundaries

I enjoy clarifying program boundaries through refactoring. Making sure the program has an “outside” and an “inside”. The outside handles the constraints imposed on the program. The format in which it receives its inputs and how it should produce its outputs. Does it get data via a web form? Does it write data in a specific Avro schema to a queue? These things matter, yet they shouldn’t pollute the business logic, the “inside”, of your program. They're in flux; today it’s JSON, tomorrow it’s protobuf. But your software, at its core, still solves the same problem. Working out a clear separation between this “outside” and your “inside” comes with plenty of advantages.

Your “inside” doesn’t have to resemble their “outside”. The data you receive is based on certain assumptions and adheres to a specific model. The transport format may have restrictions, such as only allowing values to be represented as strings or having nested tree structures. Defining clear boundaries can help translate these limitations into more useful structures for your specific use case. This is where you parse strings into more meaningful data types and flatten hierarchical structures. So, the core of your program does not need to repeatedly deal with those issues.

Use domain-specific names for entities and their fields within your program. You and your team are the ones who will be reading and rereading that code many times. Using consistent language in code makes it much easier to discuss and understand. While your upstream may distinguish between sales, refunds, and chargebacks, to you, they are all transactions with an amount.

Writing code this way makes it more adaptable to external changes. If you need to read data from Parquet files instead of Avro, your business logic should not be affected. Simply make the change in your translation layer and be confident that the rest of your program will still work.

You won't even have to touch it.

Other posts