Saturday, December 10, 2011

Keep structure when going Agile with BPMS, refactor continuously!

BPM suite implementations highly benefit from an agile implementation approach. They are build to allow you to embrace change, add business value quickly and learn as you go. Realized by offering an integrated requirements approach, by providing decision tables to be changed by the business itself, by generating code rather than coding it and by making it possible to deploy new software with a key press.


Agile approach need constant attention to architecture

When using an agile approach you don’t design everything up-front. Remember that one of the promises of using an agile approach is to allow us to embrace change; we only want to build that piece of software that has highest business value at this moment. As Thomas Carlyle stated in the 19h century: “Our main purpose is not to see what lies dimly at a distance, but to do what lies clearly at hand.”, we in the 21th century discover that this holds true in software development so we better not take decisions on things we can only guess about; but rather focus on problems we really have to solve at this moment. The same statement holds true for the software architecture. Rather than guessing on what a good architecture could be for the envisioned solution, we now develop the architecture as we go. This means that when we implement a new piece of functionality that touches an existing part, we have to pay special attention to structure (the architecture).  If not enough attention is paid to this aspect, the structure of the solution will surely deteriorate causing severe problems: Newly added models may conflict with existing ones, models may become duplicated leading to unexpected results and to a structure which is hard to see and to maintain.


How to obtain a solid architecture in agile approaches? Refactor!

So how to continuously develop an architecture in the ongoing process of implementing pieces of software and not having an overview of the final solution. An interesting technique introduced by Martin Fowler is called refactoring. This technique is often used in traditional software development. Currently most IDE’s support basic refactorings by choosing a code fragment and choosing the refactoring to apply to it. Not only for traditional software development this technique is useful, also BPM suite implementations can benefit from it. Let me elaborate a bit on the technique itself and give you some examples.


How does refactoring work?

Refactoring is based on making small controlled changes to the software and using automated tests to validate whether the change doesn’t break down functionality. The refactorings described by Martin Fowler focus on improving one aspect of the code and for each refactoring possible side effects are described.

I will give an example of refactoring in traditional source code. Suppose we have the following source code:

if (customer.rating > 25) {
total = (price * 0.95) * (1.0 + VAT_percentage / 100.0) ;
Send();

}
else {
total = price * 0.98 * (1.0 + VAT_percentage / 100.0) ;
Send();
}

Since it is quite a small fragment we can quite easily understand what is going on. But, suppose the calculation for the total price requires adding up of order lines amounts with different VAT_percentages; code will quickly grow giving real need for more insight and structure. For the example however I will use this small fragment to explain the approach.

The first thing one could notice from the fragment, is that the calculation is duplicated. Having such duplications in the code makes it harder to maintain, and more likely that errors are introduced when changing the calculation in one part of the code, but forgetting to update it in the other. This “bad smell” can be fixed using the “Extract Method” refactoring. In our case we extract method “CalculateTotalPrice”, leading to the code fragment below:

CalculateTotalPrice(price, discountPercentage) {
return (price * discountPercentage) * (1.0 + VAT_PERCENTAGE / 100.0) ;
}

if (customer.rating > 25) {
total = CalculateTotalPrice(price, 0.95)

Send();
}
else {
total = CalculateTotalPrice(price, 0.98)
Send();
}


After running the unit tests we should find that we didn’t break anything. However should we have broken the test, it is only one little thing we have been changing and the failing result can be pinpointed to this change easily.

With this one refactoring we’ve improved the structure slightly, still some other “bad smells” remain. In the code fragment above you can see that the “Send” method  is called from both branches of the condition. This also is a well known bad smell for which refactoring “Consolidate Duplicate Conditional Fragments ” exists. After applying the refactoring we get the following code fragment:


if (customer.rating > 25)
totalPrice = CalculateTotalPrice( price, 0.95)

else
totalPrice = CalculateTotalPrice( price, 0.98)

Send();


I hope you see that the code resulting from the refactorings lead to better maintainability; less side effects if changes are made. Note that there are more refactorings applicable to the code fragement above, but for the explanation I expect this suffices.


How to apply refactoring to BPM suite implementations?

Now the question is how can we apply refactoring to models in our BPM suite. I’ll try to demonstrate how the same refactorings can be applied to a mirco-flow in a BPM suite.To understand the model I’ll describe the visual elements used (originating from Aquima’s open source BPM suite)

A flow is a graph-like structure that can consist of forms, services, sub-flows and conditional nodes. You can use flows to create event-driven applications. This means the occurrence of an event can determine the path the application is taking within the flow. The path that is taken, in its turn, determines which events may occur. (source Aquima)

A flow can be used as a starter flow that kicks of when the user has to perform a task in the process flow, or as a subflow in another flow for reuse and to improve ma intainability.

A service is used for two situations: To connecting your application with external applications or data sources and to transforming your application data, for instance for a complex calculation. Several service types come out of the box, but they can also be custom made using java or dotNet.(source Aquima)

Forms are used to interact with end-users and contain logical blocks of questions, information etc. these pages are placed in flows. They publish events that can be catched in a process flow.

Now we know what a micro-flow is made of, we can look at a micro-flow found in an implementation below. The subsidy request form shows all kind of information needed for a subsidy request to be made. One of the options clients can choose from is to look for an subsidy advisor. Advisors typically work for an organisation and this organization may or may not have been chosen in a previous process step. 

Mirco-Flow showing a form, conditions, services and subflows

One good practice is to model a flow, showing sequential steps top-to-bottom or left-to-right but not mixed. Doing so will already reveal issues more easily...

Mirco-Flow showing modeled flow top-down not changing any connection

A first “bad smell” from the model is the double check for the subsidy type on both sides of the condition is organization known. A first refactoring “Consolidate Duplicate Conditional Fragments” is used to remove the double, see the resulting flow below. Applying this refactoring results in the following flow.

Micro-flow after “Consolidate Duplicate Conditional Fragments” refactoring

The service set_Control_Search however is to set the functioning of the subflow, by setting a Control Parameter. To make the sub flow more reusable this control remains outside the sub flow.

Micro-flow after changing the order of activities

Three activities in the flow set an element in the search condition. This search condition is further detailed and used in the sub-flow “addAdvisorToSubsidyRequest” (not shown here) to make a selection of all available advisors. Apparently this micro-flow grew and some elements that actually belong closer to the addAdvisorToSubsidyRequest sub-flow where placed outside of it. The intent of the flow becomes less clear because one can only grasps it, analyzing the services. We use refactoring “Extract method” to add the services to the already existing addAdvisorToSubsidyRequest sub-flow. The remaining flow is shown below:

Micro-flow after “Extract Method” refactoring
I hope you agree with me that the readability of the flow has improved enormously. Using a complementary test driven approach makes it possible to test every single step in the process and validate that the model still produces the right results. Structure has improved leading to better readability and better reusability of assets. Other analists can more easily grasp the intent of the flow which leads to better understanding, quicker bug-fixing and better maintainability.


Some difficulties with refactoring micro-flows

Although several refactorings presented by Martin Fowler, can easily be translated to their BPM suite model counterpart, there are also some difficulties with refactoring micro-flows depending on the possibilities the specific BPM suite offers:
  • As it isn’t always possible to parametrize a micro-flow or flow element it becomes harder to reuse the flow or element and makes it impossibly to apply certain refactorings proposed by Martin Fowler.
  • It may or may not be easy to copy flow elements between different micro-flows making it easier or more difficult to move functionality from one place to the other which is necessary to apply certain refactorings swiftly. Refactoring flows can be a quite tedious job if their is no good support to move items around.
  • Creating unit tests may lead to some challenges depending on the BPM suite used. If the BPM suite doesn’t support automatic testing, It may require you to use a test robot to set certain values in a form and press buttons to  kick off a micro flow.

and finally...

I hope you will come to appreciate Martin Fowler’s work on refactoring as I do. In the description above I’ve shown you some refactorings in action for the micro-flow model in a BPM suite implementation. Different types of models in BPM suites benifit from different refactorings. The question that keeps me busy these days is what specific BPM suite related refactorings can help us structuring our work further... I am open to suggestions:-)
http://sourcemaking.com/refactoring

1 comment: