Facilitate Reuse Through Interfaces

March 10, 2013

Predicting and designing for systematic reuse is hard – in trying to design for future requirements, team often bake in accidental complexity. One effective way to avoid that trap is to separate your concerns via well designed interfaces. It is important to point out that although separating concerns is essential, which ones to prioritize and plan for is heavily dependent on your problem domain. Additionally, it is not pragmatic to provide for variability across all points in your design.

Here is an example of facilitating reuse via interfaces – the example class takes a ReportResult object and needs to format them into a variety of formats (XML, PDF, etc.). Although this is a simple example it is powerful – as new requirements for supporting additional formats arise it can gracefully be extended. Plus, more importantly, formats that aren’t required don’t have to be implemented until there is a real requirement.

public interface Formatter {
    public T format(ReportResult reportResult) ;
}

The above can be implemented using specific formatters as shown below:

public class XmlFormatter {
    public String format(ReportResult reportResult)  {
       //implement logic for XML formatting
    }
}

With the report generation and formatting separation in place, additional formatters can be implemented with ease – e.g. PdfFormatter, HtmlFormatter, or PlainTextFormatter, etc. This decouples formatting logic from report generation classes thus enabling reuse for the report generation functionality.

Advertisements

Systematic Reuse Needs Extensibility

February 3, 2013

Accidental complexity is a real risk with trying to pursue systematic reuse . In trying to get reuse, you don’t want developers to jump through layers of indirection and complexity before they can write any useful code. Accounting for extensibility is a pragmatic approach when striving to design for systematic reuse.

Extensibility needs to be supported at various points in the design – it could be in user interface, integration, data contracts/definitions, system flows, services, and many other points. There are a plethora of choices and the question then becomes – how does one know what needs to be extensible? The answer lies in “finding what varies and encapsulating it”[1].

If a reusable component provides an extensibility hook – the consumer of the component can extend / replace default behaviour. Extensibility can be provided in a variety of ways – there ins’t a magic bullet here and each tactic needs to be considered in context. Here are various examples:

Spring Framework provides application context loader listeners that a developer can use to plugin custom logic. The listener doesn’t allow customization of how Spring constructs the beans or injects dependencies. However, it does provide a convenient mechanism for the developer to provide logic after container startup and before shutdown – place logic specific to a legacy/proprietary API that doesn’t support dependency injection. Alternatively, if there is a specific way to guarantee cleaning up resources prior to destroying context – that logic can be placed here as well.

Another extensibility strategy is from SLF4J – it is a logging facade and provides logging API methods that can be wired with concrete providers such as Log4J. Here, the idea is to free up individual classes from coupling with a specific provider. It provides much more points of extensibility than the above example.

Finally, the nature and number of extension points needs to be carefully weighed in the context of real applications. Not enough extension points hurts reusability. Similarly, too many increases learning curve, complexity, and possibly investment prior to making it usable in an application.

1. Alan Shalloway, James Trott, Design patterns explained: a new perspective on object-oriented design


Benefits of Decoupled Service Contracts

March 13, 2011

The Decoupled Contract pattern separates the service contract or interface from the physical implementation. The service interface is independent of implementation yet aligned with other services in the domain or enterprise service inventory.This is a follow up to the podcast episode on building contract-first services

Distributed development technologies such as .NET and Java allow easy creation of service contracts from existing or newly created components. Although this is relatively easy to accomplish the service contract tends to get expressed using the underlying technology platform – one of the many anti-patterns to avoid. This inhibits interoperability and increases integration effort for service consumers. Additionally, service consumers get forced to a specific implementation thereby considerably increasing technology coupling. Finally, this is problematic for the provider as well. If there is a need to upgrade/replace/change the service implementation, there is high probability that existing consumers will need to change their code.

The Decoupled Contract pattern solves above problems by decoupling the service contract from the implementation. Instead of auto-generating service contract specifications via a WSDL document, this pattern advocates the creation of contracts without taking implementation environment/technology into consideration. This contract will be free of physical data models instantiated in a backend data store and proprietary tokens or attributes specific to a technology platform. Consequently, the service consumers are bound to the decoupled contract and not a particular implementation.

The service and the consumers will still be coupled with any limitations associated with a service implementation (for instance, an implementation may not be able to realize all features of the contract or guarantee policy requirements etc.). It is also possible for a particular implementation technology to impose deficiencies across the service inventory in its entirety. But even given these impacts, the contract-first approach that this pattern facilitates is significant and foundational to service-orientation.

This pattern is beneficial to several design techniques that use Web Services or benefit from a decoupled service contract. Contract Centralization and Service Refactoring patterns are greatly enhanced by this pattern. Service Façade is often applied alongside this pattern as well to realize Concurrent Contracts.


Pursuing BPM? Avoid Reuse Inhibitors

December 20, 2010

Implementing business process re-engineering and/or automation involves several moving parts from a technology perspective – stateful business process data, interfaces for external systems/user interfaces to interact with process information, and rules that determine several aspects of process behavior.

Here are some practices to avoid/minimize when pursuing BPM projects:

  • Building monolithic process definitions – as the number of process definitions increase there will be opportunities to refactor and simplify orchestration logic. As projects start to build on existing processes, there will be an increasing need for modular process definitions that can be leveraged as part of larger process definitions.
  • Placing business rules that validate domain objects in the process orchestration graphs. This will effectively tightly couple rules and a specific process hurting the ability to reuse domain-specific rules across process definitions. Certain class of rules could change often and need to be managed as a separate artifact.
  • Invoking vendor specific services directly from the process definition. Over time this will result in coupling between a vendor implementation and multiple process definitions. This also applies to service capabilities hosted on legacy systems. Hence, the need to use a service mediation layer.
  • Defining key domain objects within the scope of a particular process definition. This will result in multiple definitions of domain objects across processes. Over time, this will increase maintenance effort, data transformation, and redundant definitions across processes and service interfaces.
  • Integrating clients directly to the vendor-specific business process API. This will result in multiple clients implementing boiler plate logic – better practice will be to service enable these processes and consolidate entry points into the BPM layer.

This isn’t an exhaustive list – intent is to to highlight the areas where tight coupling could occur in the business process layer.


Refactoring to Reuse #4

November 13, 2009

#4 Separate Message Construction from Message Delivery

There are a variety of scenarios where you will build a message and deliver it to a destination. The message itself could be free-form text, delimited/fixed-length text, XML, or some other format. The destination itself could be a system, service, application, a server, or a human user or group of users (in the case of email). If you decouple message construction from its destination, that will drive in reuse of both of these assets. For example, you can take a message and send it via email or send to a message queue. In the same vein, you can potentially use the same code that sends email to send a newsletter message and a reminder message.

To illustrate this idea, take a look at this code fragment:

MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("someone@xyz.com"));
message.setSubject("Hello there...");

FileReader fr = new FileReader("some-template.html");
StringBuffer sb = new StringBuffer();
BufferedReader reader = new BufferedReader(fr);
String line = reader.readLine();
while (line != null) {
     sb.append(line);
     line = reader.readLine();
}
reader.close();

message.setText(sb.toString());
// Send message
Transport tr = session.getTransport("smtp");
tr.connect("host-name", "user", "some-password");
message.saveChanges();
tr.sendMessage(message, message.getAllRecipients());
tr.close();

There is a file that is read from the file system and a data buffer is being constructed. The data is then used to send an email. However, this class isn’t very reusable because of the tight coupling between message construction and delivery logic.

Now examine, a newer version that has modularized this code – Publisher sends the message using an EmailConfiguration and TemplateBuilder constructs the message using an instance of Template.

Publisher publisher = new Publisher();
EmailConfiguration eConfig = new EmailConfiguration();
publisher.setConfiguration(eConfig);
TemplateBuilder builder = new TemplateBuilder();
Template template = builder.build();
publisher.publishMessage(template);

Now, Publisher, EmailConfiguration, Template, and TemplateBuilder are all candidate assets that are available for other classes to reuse. If you have other types of configurations, they can be included as well and bound polymorphically. This concept can be further extended based on the quantity and quality of variations. For instance, the message construction can be realized using a common interface with multiple implementations. The message itself might have standard and personalized content.

You may move to a more modular version iteratively. Which version do you think facilitates reuse, faster integration, and higher productivity? This new design will make it easier to test message construction independently from publisher.
Like this post? Subscribe to RSS feed or get blog updates via email.

tweet this add to del.icio.us post to facebook

MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("someone@xyz.com"));
message.setSubject("Hello there...");

FileReader fr = new FileReader("some-template.html");
StringBuffer sb = new StringBuffer();
BufferedReader reader = new BufferedReader(fr);
String line = reader.readLine();
while (line != null) {
     sb.append(line);
     line = reader.readLine();
}
reader.close();

message.setText(sb.toString());
// Send message
Transport tr = session.getTransport("smtp");
tr.connect("host-name", "user", "some-password");
message.saveChanges();
tr.sendMessage(message, message.getAllRecipients());
tr.close();

Software Reuse Quick Tip #22

November 6, 2009

Tip #22 – Ensure Service Capabilities Stay Effectively Decoupled

The rationale for contract-first services (as opposed to code-first) is to effectively decouple service capabilities from needless implementation-specific, vendor-specific, and data-source specific realizations. You put the initial service capability out and ensured that the contract is decoupled – no legacy system specific details, no database-vendor or technology platform-specific attributes are present and your consumers are happy.  So, are you done? Well, no…because we all know that the technology environment, business requirements, regulations, and continuous innovations are the realities of modern development. You have to be careful not to succumb to these pressures and tread towards needless coupling. It is very easy to add one more attribute or element to your service contract and not pay attention to tight coupling being introduced.

As you add new versions, introduce enhancements, and make bug fixes take care not to introduce needless coupling. You can tie in code reviews – focused specifically around service contracts – to ensure this happens as part of your overall governance strategy. I will post detailed examples for this quick tip in a follow up post.

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

tweet this add to del.icio.us post to facebook


Software Reuse Quick Tip #18

September 19, 2009

Tip #18 -Separate Request Origination From Processing

Often times you have a core piece of processing logic that weaves together a variety of components and services in order to fulfill use cases. The processing logic might be a sequential procedure, a stateful business process, or a stateless service capability. You typically implement complex processing within the context of projects that has a defined manner in which the processing logic will be invoked. It is useful to decouple request origination from processing. The idea is that you want to reuse the processing logic in a variety of scenarios and don’t want to depend on the specific nature of how requests are sent for processing from a particular application. For example, let’s say you implement an order processing service that looks up the order details, executes business rules to validate order information, and runs inventory and credit check and notifies a shipping module. This might be built for an application that sends requests using a web-based form. You can isolate the logic that constructs order processing requests that assumes the execution environment and user type etc. That way the order processing modules can be used via asynchronous messaging, for business-to-business integrations, composite services, etc. Additionally, if you want to invoke processing via bulk upload using an excel file or text extracts you can construct the request accordingly and submit it to the same processing modules. If your processing logic is too tightly bound to a web-based form being the input your reuse potential is diminished. If not, do plan to refactor the tightly coupled logic.

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: