#3 Separate Formatting from Core Domain Entities
You may have a core set of classes or services that represent the domain. These classes need to relate to each other cohesively. In the same vein, they should avoid getting too bulky with functionality that isn’t aligned with the business domain. What could they be? Classic examples include data access and remote host connectivity. Also common are formatting logic that is specific to a business channel or view. I talked about decoupling connectivity earlier so in this post I will expand on formatting logic and is a continuation of the earlier post on formatting. Just like any other aspect of your design you can make formatting as complex as you need. The key thing is to encapsulate formatting into its own layer and not let it pollute your core domain entities. This layer might vary by locale (internationalization), distribution/marketing channel (retail branch, online web, kiosk etc.), file format (HTML, PDF, XML), and device or medium (print, web, mobile devices). Even if you have a simple formatting requirement it makes sense often to isolate the logic away from code that does complex calculations and/or executes business decisions. At the very least, you can create a FormatUtility class to move formatting code there. It would be better to identify the formatting logic and identify an interface to create. You can implement the interface for a specific need and evolve it over time.
Let’s say you have a class that execute business decisions and also contains formatting logic to create data into a text file as a comma separated value (CSV) file. Refactor the file creation out of this class. Look closer on what exactly the formatting is doing. Is it changing values from numeric to text? Is it changing values from non-compliant value to a standard one? Is it doing locale-specific formatting? So, this code may not just be writing to a text file but transforming data and then writing to a file. You want to reuse the transformation logic as well – if you end up writing an XML document instead of a text file you will need this piece of work again. Now, the file creation logic itself can be reused. It may not need to know that a particular process or function is creating it. This will be useful if all your files have standard header records or place specific processing instructions in them for consuming applications. If there isn’t any, don’t refactor this yet. Finally, the text file format may vary – today it is CSV and you might need fixed width. If you have a definite need you can have the file writer take additional configuration information (e.g. field name and width for a row).