Using Design Patterns To Build Reusable Assets

October 2, 2009

Design patterns are common solutions to design problems based on a given context. When used appropriately, they help address changing requirements. There are several books on design patterns and I don’t want to repeat that information here. Instead, we will look at design patterns in the context of building and integrating reusable assets. Here is a starter list:

  • Strategy – Polymorphically bind concrete implementations to execute a flavor of logic. This is useful when encapsulating product variations. If you need to support multiple flavors of a feature at runtime it is applicable. For instance, searching a product catalog feature could use exact text matching for product A while using fuzzy matching for product B. This could also be used to support multiple flavors within the same product and choosing a concrete implementation based on criteria. For this feature, it could be type of user or the nature of input parameter or volume of potential results.
  • Adapter – Used for translating one interface from another in order to integrate incompatible interfaces. This is useful in a couple of situations. Introduce an adapter when reusing a legacy asset. It is also useful when there are multiple versions of a reusable asset that you need to support in production. A single implementation can be reused to support the new version and the old version. The old version of the asset can be wrapped by an adapter for backward compatibility.
  • Template method – Used to define a generic set of steps to execute with placeholders for concrete steps that need customization. I tend to use this pattern for reusing business process flows across varying product types. It can also be used when implementing a standard request processing flow for both library components and web services. This is a common pattern when introducing horizontal concerns (such as security, logging, auditing etc.) as part of the processing algorithm.
  • Abstract factory – Used to build a family of products that need to be created as a cohesive unit. You also don’t want your calling code to know the nuances and complexity of constructing domain objects. This pattern is very useful when creating domain objects that require business rules and you want the complex creation in a single place in your codebase. I typically use this pattern with supporting bundling of product features. If you want to reuse a set of product features across bundles you will have several objects that all need to be carefully chosen at runtime for consistent behavior.
  • Decorator – Used with a core capability that you want to augment at runtime. Decorators are pluggable components that can be attached or detached at runtime. The upside is that the decorators and the component being decorated are both reusable but you want to watch out for object proliferation. I use this for pattern when the same data needs to be formatted or rendered differently or when you have a generic set of data fields that needs to be filtered based on some criteria.
  • Command – Used to encapsulate information that is used to call a piece of code repeatedly. Can also be used to support undo/redo functionality. The commands can be reusable across different product interfaces and act as entry points to invoke backend logic. For instance, I have used this pattern to support invocation of services from a self-service portal and interactive voice response channels.

There are additional patterns that help you organize your application code better (such as Model, View, Controller (MVC) and avoid point to point coupling between applications (publish/subscribe) fostering reuse.

what patterns have you used?

Like this post? Subscribe to RSS feed or get blog updates via email.

add to del.icio.us: Digg it : post to facebook: Stumble It! : :


Refactoring To Reuse #3

September 25, 2009

#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).

Like this post? Subscribe to RSS feed or get blog updates via email.

add to del.icio.us: Digg it : post to facebook: Stumble It! : :


%d bloggers like this: