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.
July 10, 2010
Tip #26 – Build Reusable Services
The following are useful tips when designing and implementing reusable services.
Expose only logical data attributes and “standardized” values to external consumers in the service contract. This will ensure that the data service has maximum flexibility to change physical system implementations underneath and the consumer will not be adversely impacted.
Reuse business object schemas across data service operations and while preparing WSDL documents. This will ensure logical data model alignment as well as consistent definition of business objects simplifying consumption and maintenance effort.
Expose event driven publication services for data propagation to downstream consumers using standard publication messages. This will greatly reduce (and potentially eliminate) the need for source specific messages and needless data transformations. Standard publication messages could be versioned and new consumers could be added via configuration on a messaging broker without requiring development effort.
Provide multiple flavors of services based on commonly used use cases for the data service. A light flavor of a service will be useful for clients who do not want to parse a large business object message returned by the full flavor.
Strive for abstraction of data source specific semantics in order to insulate the consumer from physical data source processing/logic. This practice applies to identifiers, data values, data structures, and data orchestration logic that could be coupled to a physical source if proper care isn’t taken.
Prefer reliable transports when invoking data services asynchronously. Although it is possible to simulate asynchronous processing using transport protocols such as HTTP it is not advisable to do so. In the event the data consumer becomes unavailable messages are lost.
April 18, 2010
There is always an element of additional complexity when building resuable assets – whether it is because of externalizing configuration, adding additional interfaces/classes to provide flexibility, or introduction of additional layers of abstraction (to name a few). There is also the increased cost of design, testing, and integration with reusable assets. The question isn’t whether reusable assets are more or less complex – a more pragmatic question would be:
is the additional complexity absolutely essential and worth the cost?
This is a straightforward question to answer if you have visibility into what is coming up in the near future. If this isn’t the case – which is “most of the time” – the question becomes a trickier one. One way to address this issue is to introduce domain-relevant abstractions.
Instead of guessing what should and shouldn’t be an abstraction – work with domain experts and uncover true domain-relevant concepts. For example: Let’s say you decide to build a reusable library for providing customer data. Say this is used to populate a financial statement that shows a customer’s net worth (i.e. financial assets). Initially your software might have used the checking account balance to report this value. Why? Because, that was the only kind of account that was used to calculate this value. In the initial version the team might have thought ‘net worth’ was a data attribute – a number that is derived from the checking account balance. Over time, as domain understanding deepens, ‘net worth’ might become – not just a single account’s balance but a whole host of other things (e.g. accounts where the customer is a joint account holder including not only checking accounts but also savings, brokerage, etc.). ‘Net worth’ might still be a single number but it would have evolved to encompass a different meaning than just a single account’s balance. Not to mention business rules that have to be applied based on a plethora of account and client characteristics and quickly this would evolve into something more complex.
At the time of the initial release your team might not have this knowledge – and that is perfectly okay! Key is to evolve the codebase along with your increased understanding of the domain. Will net worth be it’s own class or interface in the initial version? If you don’t have even the preliminary understanding, why introduce needless complexity? wouldn’t it be better to refactor to reuse rather than build for reuse with an imperfect understanding?
November 6, 2009
In an earlier post, I elaborated on agile principles that facilitate reuse. As a follow up, I want to emphasize how principles of service orientation do the same from a complimentary perspective.
||How is this supported?
||Why is this supported?
||Service logic is built independent of specific product, technology, channel, and transport. Legacy services are wrapped to avoid direct coupling between providers and consumers. Both techniques are performed iteratively using refactoring. Decouple horizontal concerns such as logging, error handling, metrics, security from core logic.
||Lower the coupling, higher the opportunity for service reuse. Promotes agility by making less assumptions about upstream and downstream dependencies. Gives flexibility to service provider for performing continuous refactorings. Reuse horizontal capabilities for non-service components in the codebase.
||Code reviews and refactoring used to simplify and consolidate service contracts that aren’t well abstracted. Applies to both legacy and new services in the domain inventory. Abstract common service needs using multiple iterations and user stories.
||Abstraction clarifies domain intent and reduces needless coupling between providers and consumers. It eliminates point to point coupling between legacy services and consumers facilitating graceful migration.
||Refactor both new code and legacy modules within iterations. Identify opportunities for compositions when brainstorming implementation options for user stories. Use design patterns such as template method to design orchestrations.
||Composability is key for high levels of service reuse for implementing task services.
||Code and design reviews will be used to ensure reuse of data types, error codes, schema definitions, and that the contracts don’t expose implementation/technology specific details. If contract changes late in an iteration, add needed refactorings to iteration backlog and fix in a future iteration. A service is not “done,done” unless the contract is reviewed.
||Helps align contracts with logical data models for enterprise data entities. Delivers consistent behavior when a service is reused across physical transports. Helps create loose coupling among legacy interfaces and consumers.
||By decoupling legacy modules from being tightly bound increasing autonomy. Host services in a standard runtime environment.
||Autonomous services are easier to reuse both as standalone entities as well as in service compositions.
||Reuse strategy used to identify stateless services. Code reviews will identify and remove state that inhibits reuse.
||Stateless services offer higher degree of reuse and are simpler to scale to accommodate increased traffic.
||Building reusable services that can be mapped to user stories. Using legacy services to implement user stories and code reviews to remove duplication across the service inventory. Iteration planning allocates time for wrapping legacy services, unit testing, and working on refactoring backlog. Release planning is performed to ensure services are built within the context of an overall reuse strategy and a real consumer. Use product line techniques such as to allow service variations to accommodate varying consumer functional and quality of service characteristics.
||Minimize service development without a real consumer. Facilitates iterative and incremental manner for building reusable services. As user stories become better understood and code reviews have been done future iterations are continuously used to refactor the service.
Do these resonate with how you approach SOA and service orientation while building reusable service capabilities?
Like this post? Subscribe to RSS feed or get blog updates via email.
October 28, 2009
Tip # 21 – Identify Repetitive Steps Consumers Perform
There are a variety of places to look for reuse opportunities – one that is my favorite is looking for patterns with customer integrations. If a customer is setting ten properties to execute a common service call or method, why not provide a convenience function to accomplish the same in fewer steps? The other classic example is initializing objects. If every consumer is creating the same set of objects and initializing it in a specific way – resulting in a lot of repetitive code – you can provide a factory class or a façade interface. Additionally, look for activities that customers do that should be part of the reusable asset or can be useful to others. For instance, maybe after receiving output your customer converts that data to another format (say from XML to JSON or XML to plain text) – why not provide an option to get that right out of the reusable asset? Note of caution here though: what I am referring to is only common capabilities that aren’t specific to a single consumer. If you place logic that is specific to a consumer the asset is no longer reusable.
Like this post? Subscribe to RSS feed or get blog updates via email.
October 27, 2009
Introduce an abstraction API when integrating with a BPM solution. Why do I say that? Several reasons:
- Good software design practice to bind to an interface as opposed to an implementation. So individual applications won’t be directly coupled with an external vendor solution.
- Provides you the flexibility to augment solution using multiple vendors. Related to above point, you can utilize one vendor for a subset of capabilities and another for a different set.
- This API can be the ideal place to integrate your enterprise capabilities within the context of BPM solutions. Instead of making one-off or tactical modifications to a vendor solution that could be both expensive and proprietary, you can augment missing capabilities using the abstraction API. For example, if the BPM solution doesn’t support authentication based on active directory, this abstraction API can provide that capability (most likely you already have this component in your enterprise). Additionally, this is also the place to integrate horizontal capabilities such as message routing, metrics, monitoring, and error handling. Do you want your BPM solutions to report exceptions differently than other applications? In the same vein, this API can integrate with services or libraries that encrypt/hide sensitive data attributes before returning process state to a calling application. This has the potential to reduce duplication of such logic across user interfaces that integrate with related business processes.
- Can potentially simplify complexities associated with a native API. If the native API needs a set of steps for starting process instances or get task/work items for a particular user – this abstraction API can simplify those calls. This not only makes it easier for integration but reduces the opportunities for errors across development efforts. This API in essence can act as a façade.
- The API standardizes access to BPM capabilities and reduces the possibility of competing integration mechanisms across development efforts. If one team uses the native API as-is and another builds a new one on top – you have two ways of accessing the BPM engine. This problem gets worse as additional teams start to use BPM.
- This API could also make every business process support a core set of functions in addition to start/stop/suspend/resume calls. For instance, every business process can provide a getCurrentStatus() or reassignProcessInstance() that will make it easier for managing processes at runtime.
This API could be realized as a web service depending on the level of heterogeneity and performance requirements. This would essentially act as a service enabler for your business processes.
The above list isn’t exhaustive – are there additional ones to add to this list?
Like this post? Subscribe to RSS feed or get blog updates via email.