Creating rules dynamically with Drools

This “how to” walks through a solution to dynamically create and execute business rules.

Why we need this

It’s common the necessity to implement some kind of rules to choose between one and other action. Often, these rules are expressed in a sort of business thinking. Drools is a Business Rules Management System maintained by Red Hat and JBoss, and the answer when we need a robust, flexible and open source solution!

What we need

  • JDK 1.7+
  • Drools 6.5+
  • Maven 3.0.5+

How to

First of all, is needed to understand what rules mean in this context. Each rule in Drools works like a if statement in a programming language, thus basically we have two parts; conditional and action. This is written by someone who understood the business rule and adapted it in the schema of Drools Language Rule:

rule "Apply 10% off over all items of $4 or more"
when
    Product(price >= 4.0)
then
    product.discount(10);
end

Pretty easy, right?!

Line 1 says the friendly name of the business rule.
Line 3 is the condition to satisfy. In this case, the price of product has to be equal or more than 4 bucks .
Line 5 shows the action to be executed, so apply 10% discount over product’s price.

We can write how many rules are needed and all of them are saved in a file with extension .drl. But, as a file it is static and the goal here is to create something dynamic, therefore writing files is not an option!

Hands-on mode

Let’s think about the supermarket where we work. It’s time for promotions and the manager asked for applying a set of discounts on some products.

  • Apply 10% off over all items of $4 or more
  • For all items with due date on next 7 days, apply 45%
  • Give 5% off over every kind of Beans

There we go…

Before starting code, just make sure to have the following dependencies in your project file pom.xml:

<dependency>
  <groupId>org.drools</groupId>
  <artifactId>drools-compiler</artifactId>
  <version>6.5.0.Final</version>
</dependency>
<dependency>
  <groupId>org.drools</groupId>
  <artifactId>drools-core</artifactId>
  <version>6.5.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
  <artifactId>drools-decisiontables</artifactId>
  <version>6.5.0.Final</version>
</dependency>

Next approach is to use Rule Templates, where we can write the pattern of our rules, and populate it after with concrete rules. Following is what we need to accomplish our mission, the file Product.drl:

template header

name
object
conditional
action

package drools.templates;

global net.itfromhell.howit.dummy.Product product;

import java.text.SimpleDateFormat;
import function net.itfromhell.howit.dynamicdrools.util.DroolsUtility.debug;

dialect "java"

template "Product"

rule "@{row.rowNumber} - @{name}"
when
  @{object}(@{conditional})
then
  product.discount(@{action});
  debug(drools);
end

end template

The structure used to create a template file is similar to regular rule file. Please, take a look on:

  • Line 1: describes this file as a template
  • Line 3-6: parameters expected in this template
  • Line 15: declares the dialect used as java
  • Line 19-25: rule defination
  • Line 27: end of template

Now we have a template to handle all rules about the products in promotion, the next step is to write a couple of rules describing how to apply the discount on them. We will do it programmatically, using a set of classes that I coded to make the dirty job:

  • Rule.class: encapsulate all that is needed to create one single business rule.
  • Condition.class: describe one specific condition to be evaluated.
  • DroolsUtility.class: tool to operate everything in memory.

The complete source code, compiling and ready for duty is available in my GitHub.

In my opinion, you wanna see everything working, who knows if it isn’t a joke… in this case, run ShowMeTheDrools.class:

public class ShowMeTheDrools
{
 public static void main(String args[]) throws Exception
 {
  //List to keep all rules
  List<Rule> rules = new ArrayList<Rule>();
  //Load each business rule
  rules.add(createDiscountOverpriced());
  rules.add(createDiscountSoonDueDate());
  rules.add(createDiscountBeans());
  
  //Create a session to operate Drools in memory
  DroolsUtility utility = new DroolsUtility();
  StatelessKieSession session = utility.loadSession(rules, "drools/templates/Product.drl");
  
  //Define the products to be processed using our rules
  Product blackBeans = new Product("Black Beans", 2.20, "30/12/2017");
  Product cannelliniBeans = new Product("Cannellini Beans", 4.15, "05/02/2018");
  Product kidneyBeans = new Product("Kidney Beans", 2.05, "20/11/2017");
  Product rice = new Product("Rice", 1.10, "28/10/2017");
  Product milk = new Product("Milk", 3.50, "10/11/2017");
  
  /*
  Now, the magic happens!
  For each product to be processed, we have to face it over rules to get, or not, a discounted price.
  */
  System.out.println("Applying over " + rice.getName() + " with price $" + rice.getPrice() + "...");
  session.setGlobal("product", rice);
  session.execute(rice);
  System.out.println("...price after review: $" + rice.getPrice());
  
  System.out.println("Applying over " + blackBeans.getName() + " with price $" + blackBeans.getPrice() + "...");
  session.setGlobal("product", blackBeans);
  session.execute(blackBeans);
  System.out.println("...price after review: $" + blackBeans.getPrice());
  
  System.out.println("Applying over " + milk.getName() + " with price $" + milk.getPrice() + "...");
  session.setGlobal("product", milk);
  session.execute(milk);
  System.out.println("...price after review: $" + milk.getPrice());
  
  System.out.println("Applying over " + kidneyBeans.getName() + " with price $" + kidneyBeans.getPrice() + "...");
  session.setGlobal("product", kidneyBeans);
  session.execute(kidneyBeans);
  System.out.println("...price after review: $" + kidneyBeans.getPrice());
  
  System.out.println("Applying over " + cannelliniBeans.getName() + " with price $" + cannelliniBeans.getPrice() + "...");
  session.setGlobal("product", cannelliniBeans);
  session.execute(cannelliniBeans);
  System.out.println("...price after review: $" + cannelliniBeans.getPrice());
 }
 

As result we got:

Applying over Rice with price $1.1...
Triggered rule: 1 - Apply discount on all soon due date
...price after review: $0.605

Applying over Black Beans with price $2.2...
Triggered rule: 2 - Discounting on all beans
...price after review: $2.0900000000000003

Applying over Milk with price $3.5...
...price after review: $3.5

Applying over Kidney Beans with price $2.05...
Triggered rule: 2 - Discounting on all beans
...price after review: $1.9474999999999998

Applying over Cannellini Beans with price $4.15...
Triggered rule: 2 - Discounting on all beans
Triggered rule: 0 - Give some discount on overpriced
...price after review: $3.5482500000000003

In order to verifiy the promotional price, we noted a discount on Rice which started for $1.1 and now is $0.605 (what bargain! don’t forget to check the due date). We know why, it’ s because the rule named “Apply discount on all soon due date” was triggered applying its huge discount.

Black Beans started from $2.2 and finished to $2.09, 5% less because of rule “Discounting on all beans”.

But wait, we got no discount on Milk since the start and final prices are the same 3.5 buks! The simple answer is just because no rule was triggered (you can check it).

Something different happened to Cannellini Beans, there are two rules triggered, is it right? Yes it is. The first rule about Beans is triggered applying 5%, next the rule about overprice is triggered applying more 10%, so the final price is now $3.54. It is intersting since we are able to chain rules, increasing the complexity of our solution.

Back to source code of ShowMeTheDrools on lines:

  • 25-27: all three business rules are created (next section we see details)
  • 31: our tool is used to get a session to operate rules
  • 34-38: a set of products is defined
  • 44-67: we submit each product against all business rules and watch what happens on price

To make it easy to understand, I created a specific method for each business rule. In the real world it doesn’t make any sense. Anyway, let’s see how it works for asked business rule “Apply 10% off over all items of $4 or more”:

private static Rule createDiscountOverpriced()
{
 //First of all, we create a rule giving it a friendly name
 Rule rule = new Rule("Give some discount on overpriced");
 //Here we need to say what kind of object will be processed
 rule.setDataObject(Product.class.getName());
 
 //As expected, a rule needs condition to exists. So, let's create it...
 Condition condition = new Condition();
 //What data, or property, will be checked
 condition.setProperty("price");
 //What kind of check to do
 condition.setOperator(Condition.Operator.GREATER_THAN_OR_EQUAL_TO);
 //What is the value to check
 condition.setValue(new Double(4.0));
 
 //Next, is needed to set rule's condition
 rule.setCondition(condition);
 //Finally, this is what will be done when ours condition is satisfied
 rule.setAction("10");
 
 return rule;
}

What about “For all items with due date on next 7 days, apply 45%”:

private static Rule createDiscountSoonDueDate() throws Exception
{
 Rule rule = new Rule("Apply discount on all soon due date");
 rule.setDataObject(Product.class.getName());
 
 //Is possible to create multiple conditions, therefore, data range or more complex situations could be expressed
 Condition greaterThan = new Condition();
 greaterThan.setProperty("dueDate");
 greaterThan.setOperator(Condition.Operator.GREATER_THAN);
 greaterThan.setValue((new SimpleDateFormat("dd/MM/yyyy").parse("23/10/2017")));
 
 Condition lessThan = new Condition();
 lessThan.setProperty("dueDate");
 lessThan.setOperator(Condition.Operator.LESS_THAN);
 lessThan.setValue((new SimpleDateFormat("dd/MM/yyyy").parse("30/10/2017")));
 
 //You can define as many as necessary conditions to achieve your necessity
 rule.setConditions(Arrays.asList(greaterThan, lessThan));
 rule.setAction("45");
 
 return rule;
}

Finally we have the third business rule “Give 5% off over all Beans”:

private static Rule createDiscountBeans()
{
 Rule rule = new Rule("Discounting on all beans");
 rule.setDataObject(Product.class.getName());
 
 //This is the simplest way to define the rule' condition
 rule.addCondition("name", Condition.Operator.CONTAINS, "Beans");  
 
 rule.setAction("5");
 
 return rule;
}

Let’s take a look over most important pieces of code of each class, starting from beggining; Rule.class

As we discussed before, the engine understand Drools Rule Language, the method conditionAsDRL transforms all conditions of the rule into textual expressions.

 public String conditionAsDRL() throws IllegalStateException, IllegalArgumentException
 {
  if ((conditions == null) || (conditions.isEmpty()))
  {
   throw new IllegalStateException("You must declare at least one condition to be evaluated.");
  }
  
  StringBuilder drl = new StringBuilder();
  //For each condition of this rule, we create its textual representation
  for (int i = 0; i < conditions.size(); i++)
  {
   Condition condition = conditions.get(i);
   drl.append("(");
   drl.append(condition.buildExpression());
   drl.append(")");
   if ((i + 1) < conditions.size())
   {
    drl.append(" && ");
   }
  }
		
  return drl.toString();
 }

The class Condition.class has buildExpression, executed by Rule and responsible to return its own expression of the conditional.

public String buildExpression() throws IllegalArgumentException
{
 StringBuilder drl = new StringBuilder();
 
 if (value instanceof String)
 {
  drl.append(expressionForStringValue());
 }
 else if (value instanceof Number)
 {
  drl.append(expressionForNumberValue());
 }
 else if (value instanceof Date)
 {
  drl.append(expressionForDateValue());
 }
 else
 {
  throw new IllegalArgumentException("The class " + value.getClass().getSimpleName() + " of value is not acceptable.");
 }
 
 return drl.toString();
}

For each type of value, there is a specific method responsible to create the specialized expression, as exemple of expressionForNumberValue, used to transform a Number instance:

private String expressionForNumberValue() throws IllegalArgumentException
{
 StringBuilder drl = new StringBuilder();
 
 if ((operator.isComparable(Short.class)) || (operator.isComparable(Integer.class)) || (operator.isComparable(Long.class)) 
     || (operator.isComparable(Double.class)) || (operator.isComparable(Float.class)))
{
  drl.append(property).append(" ").append(operator.getOperation()).append(" ").append(value);
 }
 else
 {
  throw new IllegalArgumentException("Is not possible to use the operator " + operator.getDescription() + " to a " + value.getClass().getSimpleName() + " object.");
 }
 
 return drl.toString();
}

Last but not less important, the class DroolsUtility.class has two methods to see:

/**
 * Loads a session to execute rules in memory using a template file.
 * 
 * @param templatePath Relative path to template file describing the rule's pattern.
 * @param rulesAsParameters List of maps representing each rule as a set of parameters.
 * @return Session for execution of rules.
 * @throws Exception 
 */
private StatelessKieSession loadSession(String templatePath, List<Map<String, Object>> rulesAsParameters) throws Exception
{
  ObjectDataCompiler compiler = new ObjectDataCompiler();
  //Compiles the list of rules using the template to create a readable Drools Rules Language
  String drl = compiler.compile(rulesAsParameters, Thread.currentThread().getContextClassLoader().getResourceAsStream(templatePath));
   
  System.out.println("drl:\n" + drl);

  KieServices services = KieServices.Factory.get();
  KieFileSystem system = services.newKieFileSystem();
  system.write("src/main/resources/drools/templates/rule.drl", drl);
  services.newKieBuilder(system).buildAll();
  
  KieContainer container = services.newKieContainer(services.getRepository().getDefaultReleaseId());
  StatelessKieSession session = container.getKieBase().newStatelessKieSession();
  
  return session;
}

The highlight line 56 is a trick, it will print in console the concrete generated .drl‘s contents, which is used by the engine in memory. See below:

package drools.templates;
global net.itfromhell.howit.dummy.Product product;
import java.text.SimpleDateFormat;
import function net.itfromhell.howit.dynamicdrools.util.DroolsUtility.debug;
dialect "java"

rule "2 - Discounting on all beans"
when
  net.itfromhell.howit.dummy.Product((name.toUpperCase().contains("BEANS")))
then
  product.discount(5);
  debug(drools);
end

rule "1 - Apply discount on all soon due date"
when
  net.itfromhell.howit.dummy.Product((dueDate > (new SimpleDateFormat("dd/MM/yyyy HH:mm:ss")).parse("23/10/2017 00:00:00")) && (dueDate < (new SimpleDateFormat("dd/MM/yyyy HH:mm:ss")).parse("30/10/2017 00:00:00")))
then
  product.discount(45);
  debug(drools);
end

rule "0 - Give some discount on overpriced"
when
  net.itfromhell.howit.dummy.Product((price >= 4.0))
then
  product.discount(10);
  debug(drools);
end

As suggests its name, this method can be used to get some details of the triggered rule when the engine acts.

/**
 * Debug tool to show what is happening over each triggered execution.<br>
 * Name of rule trigger as well the object inspected are printed.
 * 
 * @param helper Injected when a consequence is fired.
 */
public static void debug(final KnowledgeHelper helper)
{
 System.out.println("Triggered rule: " + helper.getRule().getName());
 if (helper.getMatch() != null && helper.getMatch().getObjects() != null)
 {
  for (Object object : helper.getMatch().getObjects())
  {
   System.out.println("Data object: " + object);
  }
 }
}

That’s all folks!

Remember it: living on your own rules 🙂

Download the complete project from my GitHub.

 

 


The danger of persistence of decision-making in project management

Recently I’ve been talking to a colleague, during a happy hour, about good projects that lead to bad results. Despite the fact that in happy hour meetings one isn’t supposed to talk about work, the conversation brought some good reflections.

Gize Piramides

If the pyramids were software, the ones in the front would be the beta version

Since the time I attended high school in data processing – long seventeen years ago – I already looked at the numbers regarding information-system projects as a laughingstock. I remember one of my professors at that time comparing software engineering with civil engineering, invariably praising the management and construction capability of civil engineering in relation to software engineering. Anyway, civil engineers started building the pyramids five thousand years ago, we barely started punching cards a bit over fifty years ago. Historically, they are way ahead of us – I used to think.

Returning to the subject, this colleague used to talk about a project of which he was the manager, and which potentially represented an important evolution in the Company, but that at last was becoming a millionaire failure. My insane curiosity did not cease to be teased in order to understand, after all, why there was such a discrepancy between what was planned and what was achieved.

That project, with a budget of almost one and a half million reais, met four of the five classic reasons for initiation: strategic need, market demand, client request and technological advance. Not only fit to meet the legal requirements. Avoiding further discussion on so many other details, especially for ethical reasons, I can say that the project that was the subject of our discussion was interesting and promising. But then, what failed?

Chaos Report 2009

Chaos Report 2009

According to the 2009 Chaos Report published by Standish Group, 32% of IT projects were successful – within the deadline, budget, scope, and quality (!). In a comparison with the previous report published in 2006, the percentage fell by three points, when it was 35%. Even so, the scenario improved a lot, because at the time I was in high school, the 1998 report showed a 26% success rate.

We can certainly point out many reasons why so many projects have failed (if we built bridges, imagine that 68% of them fell). Here we will just focus on my colleague’s project. Of all this sad story, what caught my attention, and that could even be left in the background, was the direct intervention of the IT Director during the procedures for the selection of suppliers. After defining the necessary acquisitions, and passing through the ritual of proposal requisitions, the project team classified the suppliers and identified the one that best met the requirements defined at the beginning of the process. Although it is questionable, the final decision as to which supplier would be contracted was the Director’s, and he decided for the supplier with the lowest cost and biggest risk (according to the team reports). This is where my particular analysis begins, not to question the decision tree of my colleague’s company – who said it is questionable? – but to draw a parallel to the interesting psychological theory of the “freezing effect”, grounded by Kurt Lewin after World War II.

Kurt Lewin

Kurt Lewin has grounded the Three Step Theory

After the Director’s decision to hire the least suitable supplier, according to the project team, the software development work began. It was not long before problems of quality and timing began, and at first they were bypassed within project management. With time and the persistence of occurrences, timeline milestones remained disregarded, and reports were issued with alternative solutions and their projected scenarios defined. Finally, the management team directly called on the Director to make a decision regarding the supplier. In the first foray, the decision was for the maintenance of the supplier, and a discreet request for the latter’s attention. There were still other three or four rounds, where the same process of identification, creation of options, and decision making was repeated, always with the same result; the maintenance of the supplier. Or would it be the maintenance of the decision?

People tend to adhere to their own decisions, promoting the maintenance of the commitment to the first decision, in an escalation of decisions. This helps to explain why the Director kept his decision for that supplier, even though he had access to reports that advised against it. The decision for the supplier selection was deliberately his. This first decision is the foundation of the “Escalation of Commitment” effect (Barry M. Staw, 1976). According to the psychological theory, the initial decision freezes the system of possible choices of the individual, causing him to focus on committing himself to the behavior that makes more sense to his decision. After all, this is the common and expected behavior of people, because in an organized society what would happen if everyone started behaving one way after having committed to another? Therefore, this effect is a basic block in the construction of personality.

Just as the Freeze Effect process explains the Director’s attitude in maintaining his decision, it also explains why the project management team, after analyzing the supplier’s performance, was able to seek solutions and even to suggest the replacement of the supplier: the original decision was not theirs. Without commitment to the decision, the team was free to use rationally the information obtained. It is especially interesting to understand that this psychological phenomenon exists and how it works so that we can manage it and seek ways to prevent its perverse effects by exploring and maximizing its virtues.

Of course my colleague’s episode is not an exception, as the Chaos Report figures prove. With even more certainty, not all projects have problems with suppliers. Information system projects have so many points of attention that an IT project manager should be promoted to a god (a bit of chauvinism). What is important to extract from this tale is the lesson.

As the freezing effect comprises the Escalation of Commitment, two other concepts are also related: the Irreversible Expense and the Trap.

I can imagine that at a certain moment, while presenting themselves to the Director, the project management team suggested replacing the supplier. The Director, on the other hand, must have argued – with more or less emotion – that the project had already spent financial resources with said supplier and therefore would not be prudent to replace it. This is an example of the judgment by Irreversible Expense, the phenomenon that occurs when the individual persists in the decision because he had previously invested money, time, effort, in detriment of other decisions, which had potentially more advantages.

It is worth remembering that the hypothetical manual of good project management says that in deciding for the continuity of the project, efforts which have already been made must not be considered (these costs are sunk in the accounting norm). Therefore, a good project management, in itself, should be enough to prevent the Irreversible Expense phenomenon from contaminating the decision making.

And as far as timeline milestones are concerned, isn’t it one of their functions to serve as a checkpoint to help control the project? Yes, but, perhaps they were not used satisfactorily. The last phenomenon, the Trap, can help the understanding of how to improve the use of those milestones. Who knows, maybe in my colleague’s project, this concept could have helped correct the course, and ensured that the end result was the one intended.

Prompt to continue with the project

What now?

An experiment conducted in 1979 by Joel Brockner, Myril C. Shaw and Jeffrey Z. Rubin, showed that players who were exposed to the opportunity to decide whether to continue or stop betting, lost less when they were forced to decide to continue. On the other hand, those who, on the same occasion, would only act if they decided to stop, lost more.

The timeline milestone generally works as the first case of the cited experiment. There is a milestone, where the opportunity for decision occurs. If a strong decision is not taken, the project will continue automatically. Like the bettor who loses more, the project remains consuming more resources, even if it is out of control. The lesson learned comes in here, as it would be enough changing the way the timeline milestone works so that the initial decision Trap is controlled. Thus, at each milestone of the project, if there is no decision, the project is then discontinued. Radical? Perhaps. Now, think about the resources that would be saved in exchange for more aggressive management.

In this conversation with my colleague, and consequently in the reflection of the case he presented, I did not expect to discover the philosophical stone of project management. But I was glad that we understood human psychology a little more, and how it guides us in a subtle and transparent way.


Generating client for SOAP using CXF

What is needed

  • WSDL file describing the services
  • Apache CXF (3.1+)
  • JDK (1.7+)

Straight to point

In order to create the set of Client’s classes, verify for the following environment variables:

  • JAVA_HOME: Path to JDK location, eg. C:\Progra~1\Java\jdk1.7.0_80
  • CXF_HOME: Path to CXF location, eg. C:\Java\apache-cxf-3.1.13

Now, open a command prompt and execute the command: wsdl2java.bat -p net.itfromhell.itsatrap.serviceclient -d C:\Temp\TestClient -all -ant -exsh false -dns true -dex true -encoding UTF-8 -verbose Test.wsdl

Where…

  • wsdl2java.bat: Tool to generate encapsulated service’s client from WSDL document
  • net.itfromhell.itsatrap.serviceclient: Package of generated classes
  • C:\Temp\TestClient: Output directory to generated classes
  • Test.wsdl: WSDL file

PWC6345: There is an error in invoking javac.

Accessing your application in GlassFish you get this error message:

org.apache.jasper.JasperException: PWC6345: There is an error in invoking javac. A full JDK (not just JRE) is required

Try to verify the parameter AS_JAVA inside of file glassfish\config\asenv.bat(.conf). This parameter should be the JDK path.


Get access to DAS for other Domain than default using shell

Need to access your GlassFish as administrator but in other Domain than default. Use the tool asadmin, to do that you need to specify the port of DAS to this specific Domain:

asadmin --host localhost --port 4848 enable-secure-admin

Error setting expression ‘X.Y’ with value ‘[Ljava.lang.String;@6791525e’

If you get this error message:

[OgnlValueStack]: CommonsLogger.warn{60} Error setting expression ‘X.Y’ with value ‘[Ljava.lang.String;@6791525e’

Try changing the order of setter method is implemented, move to first sequence the method with String as a parameter.


A irracionalidade à serviço da racionalidade na tomada de decisão

A decisão compartilhada, ou em grupo, é uma das pedras fundamentais da civilização ocidental moderna, a própria democracia tem como base este conceito. Mas até onde grupos tomam a melhor decisão? O quanto do objetivo esperado –enquanto decisão do grupo- é obtido em um comitê de aprovação do projeto ou na reunião de equipe para validar o cronograma?

No reino de Arthtur, as decisões eram compartilhadas pelos iguais

No reino de Arthtur, as decisões eram compartilhadas pelos iguais

Diz a lenda que o Rei Arthur possuía uma mesa de reuniões redonda, a Távola Redonda, onde todos eram iguais e portanto participavam igualmente das decisões ali tomadas. Na empresa em que trabalhamos, gostamos da ideia de participar dos eventos relevantes, incluído aí a tomada de decisão, este é o desejo natural pela democracia, ainda que uma empresa não seja uma instituição democrática.

A tomada de decisão em grupo nas empresas é uma teoria administrativa que mira em diversas vantagens como o aumento da satisfação no local de trabalho, a motivação propiciada pela participação, e que por fim resulta no clima organizacional positivo bem como no aumento de produtividade. O conceito popular de que “muitas cabeças pensam melhor do que uma” pode materializar-se em decisões com níveis de qualidade superiores aquelas decisões individuais. Apenas ainda não sabemos o que fazer com a percepção de que a tomada de decisão em grupo pode ser improdutiva e frustrante ao desperdiçar tempo -e dinheiro.

Max Gehringer, administrador de empresas e escritor, autor do livro Clássicos do Mundo Corporativo, diz em seu artigo As Sete Regras do Manual do ‘nunca’ para projetos: “nunca tente convencer, se você pode mandar”.

Existe um aspecto macabro da tomada de decisão em grupo e que é inerente ao principal ator em palco, o ser humano. Em 1964 um experimento liderado

The Milgram's Experience

A experiência de Milgram: E=Experimentador, S=Sujeito, A=Ator

pelo psicólogo Stanley Milgram colocou um grupo de voluntários em uma sala em que do outro lado, separado por uma fina parede, um dos voluntários selecionado aleatoriamente era posicionado sentado e amarrado a cadeira. A cada pergunta feita pelo pesquisador ao homem, e que este errasse a resposta, o grupo deveria pressionar um botão que infringiria a ele um choque elétrico. No início os choques eram leves e rápidos, mas com o tempo se tornaram fortes e intensos –em paridade com os gritos do voluntário. Por fim, após um longo choque, o homem emudeceu e o mal estar tomou conta do ambiente. Naturalmente este era um experimento, e o homem, um ator de verdade, nunca levou qualquer choque. O importante na pesquisa foi a constatação de que o grupo perdia a sensação de responsabilidade –no caso, para com a punição-, já que a decisão tomada era do “grupo” e não do individuo. Um teste de controle mostrava que sendo uma decisão individual, os participantes não infringiam tal nível de choque elétrico ao pobre homem.

Free Vermeulen

Freek Vermeulen, autor de Business Exposed

O professor da London Business School e autor do livro Business Exposed, Freek Vermeulen, fala sobre a inclinação das pessoas em imitar o comportamento dos outros. De fato este talvez seja um dos nossos primeiros impulsos, e o responsável por aprendermos a falar, andar e… a tomar decisões. É fácil imaginar uma reunião para tomada de decisão onde o primeiro a se aventurar em opinar é seguido pelos demais, enquanto outro grupo simplesmente se omite. Alias, a omissão é explicada por Freek como uma inibição e não como um sinal de concordância; “quem cala consente”. O fato é que ninguém gosta de ser a minora, seja torcendo por um time de futebol ou durante uma decisão importante na Companhia. “A consequência disso é que, numa reunião, pode ocorrer de todos estarem divergindo, mas ninguém se manifestar por relutância“, afirma o professor.

Então o que fazer com a decisão compartilhada, agora que a endemoniamos? Algumas vezes é necessário derrubar paredes para construir alicerces. Então vamos saber extrair da decisão compartilhada o seu melhor e da melhor maneira, a fim de garantir que em um comitê de aprovação do projeto, ou na reunião de equipe para validação –e naturalmente aprovação- alcancemos o comprometimento e a maturidade superiores.

Norman Maier, psicólogo experimental americano, defende o método da decisão em grupo na prática do comando eficaz. Em seus estudos, Maier leva em consideração duas dimensões. A primeira é o peso social interno, e a segunda é o peso na eficiência organizacional. Criando uma matriz destas duas dimensões, poderemos encaixar cada decisão em um quartil. Maier concluiu que é possível diminuir sensivelmente os vícios da decisão compartilhada ao eleger um “animador profissional”.

Maier's Matrix

Matriz imaginária de Maier para modelo de decisão

Esta figura é responsável por manter elevado o nível da discussão, valorizando a esfera da informação e conduzindo de forma habilidosa à escolha de uma solução. O animador profissional tem lugar nas decisões críticas, onde o espaço para a manobra é reduzido, e o grupo não pode decidir além de determinados limites. Há mais um aspecto nesta forma de tomada de decisão, obter uma decisão que não é uma decisão. O animador manipula o grupo para uma decisão mais ou menos predeterminada, dando palavra à pessoa certa, suspendendo a reunião, ou declarando a reunião terminada no minuto oportuno. Habilidade é essencial para realizar tudo isto sem que os membros tenham percepção de manipulação enquanto se obtém o melhor do processo de resistência a mudanças, a “aceitação das consequências da decisão”.

Manhattan Connection guys

Comentaristas do programa Manhattan Connection. Lucas Mendes (ao centro) é exemplo de animador profissional de Maier

O modelo sugerido por Maier me faz lembrar muito o programa Manhattan Connection, exibido no canal pago Globo News. No ar a 19 anos, comentaristas políticos, econômicos e culturais debatem sobre diversos destaques da semana. Uma mesa de discussão por vezes caótica, mas que é habilmente coordenada pelo jornalista Lucas Mendes, que faz o papel de animador profissional trazendo o assunto e direcionando a discussão até obter (quase sempre) o resultado. Resultado que se pode imaginar de antemão ser o esperado.

Planejar a tomada de decisão compartilhada, e realizar o processo de uma forma menos ortodoxa, pode tornar fácil implementar um bom sistema decisório. O esforço despendido na atividade é recompensado com motivação, participação e comprometimento dos envolvidos na concretização prática da decisão.


O perigo da persistência de decisão na gestão de projetos

Recentemente estive conversando com um colega, durante um happy hour, sobre projetos bons que culminam em resultados ruins. A despeito de que em encontros de happy hour não se deveria falar de trabalho, a conversa em si rendeu algumas boas reflexões.

Se as pirâmides fossem software, as da frente seriam a versão trial

Desde a época em que cursava o colegial técnico em processamento de dados -ha longínquos treze anos atrás-, já via os números relativos a projetos de sistemas de informação serem motivo de chacota. Lembro-me que um dos meus professores da época realizava a comparação da engenharia de software com a engenharia civil, invariavelmente enaltecendo a capacidade de gestão e construção da civil em relação a de software. Pois bem, os engenheiros civis começaram construindo as pirâmides ha cinco mil anos atrás, nós mal começamos perfurando cartões a pouco mais de cinquenta anos. Historicamente, eles estão bem mais adiantados do que nós, pensava eu.

Retornando ao assunto, este meu colega comentava sobre um projeto do qual era o gerente, e que potencialmente representava uma importante evolução na Companhia, mas que por fim estava se transformando em um fracasso milionário. A minha insana curiosidade não deixou de se aguçar para entender, afinal, porque tamanha discrepância entre planejado e realizado.

O tal projeto, com orçamento de quase um milhão e meio de Reais, atendia quatro dos cinco clássicos motivos de iniciação: necessidade estratégica, demanda do mercado, solicitação do cliente e avanço tecnológico. Não se encaixando apenas no atendimento a requisitos legais. Sem querer discorrer de tantos outros detalhes, principalmente por motivos éticos, posso me limitar a dizer que o projeto objeto de nossa discussão era interessante e promissor. Mas então, o que falhou?

Chaos Report 2009

Segundo o Chaos Report de 2009 publicado por Standish Group, 32% dos projetos de TI obtiveram sucesso –dentro do prazo, orçamento, escopo e com qualidade (!). Em uma comparação com o relatório anterior publicado em 2006, o percentual caiu três pontos, quando era de 35%. Ainda assim, o cenário melhorou muito, pois na época em que eu cursava o colegial, o relatório de 1998 indicava 26% de sucesso.

Com certeza podemos apontar muitos motivos para que tantos projetos tenham falhado (se construíssemos pontes, imagine que 68% delas caíram). Aqui vamos apenas nos ater ao projeto do meu colega. De toda a triste história, o que me chamou atenção, e que poderia até ser deixado em segundo plano, foi a intervenção direta do Diretor de Informática durante o processo de seleção de fornecedores. Após definir as aquisições necessárias, e passar pelo ritual de requisição de propostas, a equipe do projeto classificou os fornecedores e identificou aquele que melhor atendia aos requisitos definidos no início do processo. Ainda que seja questionável, a decisão final sobre qual fornecedor seria contratado era do Diretor, e este decidiu pelo fornecedor com menor custo e maior risco (segundo os relatórios da equipe). É aqui que começa a minha particular análise, não para questionar a árvore decisória da companhia do meu colega –quem disse que é questionável? E sim, para traçar um paralelo a interessante teoria psicológica do “Efeito de congelamento”, fundamentada por Kurt Lewin depois da Segunda Guerra Mundial.

Kurt Lewin fundamentou a Teoria de Três Etapas

Após a decisão, pelo Diretor, de contratação do fornecedor menos apto, segundo a equipe de projeto, o trabalho de desenvolvimento do software teve início. Não demorou para que problemas de qualidade e prazo tivessem início, e num primeiro momento foram contornados dentro da gestão do projeto. Com o tempo e a insistência das ocorrências, os marcos do cronograma prosseguiam desrespeitados, e relatórios foram emitidos com soluções alternativas e seus cenários projetados definidos. Por fim, a equipe de gestão acionou diretamente o Diretor para que fosse tomada uma decisão em relação ao fornecedor. Na primeira incursão, a decisão foi pela manutenção do fornecedor, e um discreto pedido de atenção do mesmo. Ainda houve outras três ou quatro rodadas, onde o mesmo processo de identificação, criação de opções e tomada de decisão foi repetido, sempre com o resultado similar; a manutenção do fornecedor. Ou seria; a manutenção da decisão?

As pessoas tendem a aderir às suas próprias decisões, promovendo a manutenção do comprometimento com a primeira decisão, em uma escalada de decisões. Isto ajuda a explicar o motivo pelo qual o Diretor manteve sua decisão pelo fornecedor, mesmo tendo acesso a relatórios que o desaconselhavam. A decisão pela seleção do fornecedor foi livremente dele. Esta primeira decisão é o alicerce do efeito de “Escalada de comprometimento” (Barry M. Staw, 1976). Segundo a teoria psicológica, a decisão inicial congela o sistema de escolhas possíveis do individuo, fazendo com que ele mantenha o foco em comprometer-se com o comportamento que mais faz sentido à sua decisão. Afinal, este é o comportamento comum e esperado das pessoas, pois em uma sociedade organizada o que aconteceria se todos passassem a se comportar de uma maneira, após se comprometer com outra? Portanto, este efeito é um bloco básico da construção da personalidade.

Do mesmo modo que o processo de Efeito de congelamento explica a atitude do Diretor em manter sua decisão, também explica o motivo pelo qual a equipe de gerenciamento do projeto, após analisar o desempenho do fornecedor, foi capaz de buscar soluções e sugerir até mesmo a substituição do fornecedor: a decisão inicial não foi deles. Sem o comprometimento com a decisão, a equipe estava livre para utilizar de forma racional as informações obtidas. É especialmente interessante entender que este fenômeno psicológico existe e como ele funciona, pois assim podemos gerencia-lo e buscar formas de impedir seus efeitos perversos, explorando e maximizando suas virtudes.

Naturalmente o episódio do meu colega não é uma exceção, como os números do Chaos Report comprovam. Com mais certeza ainda não são todos os projetos que possuem problemas com fornecedores. Projetos de sistemas de informação possuem tantos pontos de atenção, que um gerente de projetos de TI deveria ser promovido a um deus (um pouco de chauvinismo). O que interessa extrair deste conto é a lição.

Assim como o Efeito de congelamento compreende a Escalada de comprometimento, também estão relacionados outros dois conceitos: a Despesa irreversível e a Armadilha.

Posso imaginar que em determinado momento, ao apresentar-se ao Diretor, a equipe de gerenciamento do projeto sugeriu a substituição do fornecedor. Este por sua vez deve ter argumentado –com mais ou menos emoção- que o projeto já havia despendido recursos financeiros com o tal fornecedor e, portanto, não seria prudente o substituir. Este é um exemplo do julgamento pela Despesa irreversível, o fenômeno que ocorre quando o individuo persiste na decisão porque investiu anteriormente, dinheiro, tempo, esforço, em detrimento de outras decisões potencialmente mais vantajosas.

Vale lembrar que o hipotético manual do bom gerenciamento de projetos diz que não se deve considerar, ao decidir pela continuidade do projeto, esforços já realizados (na norma contábil, estes são custos afundados). Portanto, por si só, um bom gerenciamento do projeto já deveria ser suficiente para evitar que o fenômeno da Despesa irreversível contaminasse a tomada de decisão.

E quanto aos marcos de cronograma, uma de suas funções não é a de servir como ponto de verificação para ajudar a controlar o projeto? Sim. Mas, talvez não foram utilizados de forma satisfatória. O último fenômeno, a Armadilha, pode ajudar a entender como melhorar o uso dos marcos.  Quem sabe no projeto do meu colega, este conceito poderia ter ajudado na correção do rumo, e garantido que o resultado final fosse o almejado.

Prompt to continue with the project

E agora?

Uma experiência realizada em 1979 por Joel Brockner, Myril C. Shaw e Jeffrey Z. Rubin, mostrou que jogadores expostos a oportunidade de decisão para continuar ou parar de apostar, perdiam menos quando eram obrigados a decidir por continuar. Por outro lado, aqueles que, na mesma oportunidade, apenas agiriam caso decidissem parar, perdiam mais.

O marco de cronograma geralmente funciona como no primeiro caso da experiência citada. Há um marco, onde a oportunidade de decisão ocorre. Caso não seja tomada uma enérgica decisão, o projeto continua por inércia. Assim como o apostador que perde mais, o projeto permanece consumindo mais recursos, ainda que esteja fora de controle. A lição aprendida entra aqui, pois bastaria mudar a forma como o marco do cronograma funciona, para que a Armadilha da decisão inicial seja controlada. Desse modo, em cada marco do projeto, se não houver uma decisão, o projeto então é interrompido. Radical? Talvez. Agora pense nos recursos economizados em contrapartida a um gerenciamento mais agressivo.

Nesta conversa de botequim com meu colega, e por consequência na reflexão do caso que ele apresentou, não esperava descobrir a pedra filosofal da gestão de projetos. Mas fiquei contente por termos entendido um pouco mais da psicologia humana, e como ela nos conduz de forma sutil e transparente.