Tags:
create new tag
, view all tags

Feature Oriented Programming (FOP)

FOP estende o design orientado a objetos por meio de mecanismos de modularização e composição de features. De acordo com a documentação apresentada na suite de ferramentas AHEAD, uma implementação de FOP, features correspondem às unidades incrementais do programa e que encapsulam fragmentos espalhados por diferentes classes. O mecanismo de composição de FOP, em certo grau, é semelhante ao de Mixins.

Implementação de Variações usando AHEAD

Esse exemplo consiste em adaptar o avaliador de expressões de acordo com:

  • 1 - o tipo da expressão (int ou double).
  • 2 - suporte opcional a geração de uma representação String das expressões.
  • 3 - suporte alternativo a expressões básicas (soma e subtração) ou avançadas (que inclui divisão e multiplicação)

Um modelo AHEAD consiste em um diretório raiz. Nesse caso, criamos um diretório "EPL". O mecanismo de composição de AHEAD consiste em adicionar incrementos (features) a uma versão base da aplicação. Tanto a aplicação base quanto as features são definidas em sub-diretórios. Para esse exemplo, criamos a seguinte estrutura de diretórios:

EPL 
 + Base
 + Int    
 + Double
 + Extended
 + Print       

Versão Base

No diretório base, são criados os artefatos comuns a linha de produtos. Note que artefatos AHEAD possuem a extensão ".jak". Para a definição base do produto, os artefatos são classes e interfaces java.

Base/Expression.jak

public interface Expression {
   
   public Value eval();

}

Base/Value.jak

public class Value implements Expression {
   
   public Value eval() {
      return this;
   }

}

Base/BinaryExpression.jak

public abstract class BinaryExp implements Expression {

   protected Expression left;

   protected Expression right;

   protected String operator;

   public BinaryExp(Expression left, Expression right, String operator) {
      this.left = left;
      this.right = right;
      this.operator = operator;
   }

   public Expression getLeft() {
      return left;
   }

   public Expression getRight() {
      return right;
   }

   public String getOperator() {
      return operator;
   }
}

Base/AddExpression.jak

public class AddExp extends BinaryExp {
   
   public AddExp(Expression left, Expression right) {
      super(left, right, "+");
   }
   
   public Value eval() {
      return new Value(left.eval().getValue() + right.eval().getValue());
   }
}

Base/SubExpression.jak

public class SubExp extends BinaryExp {
   
   public SubExp(Expression left, Expression right) {
      super(left, right, "-");
   }
   
   public Value eval() {
      return new Value(left.eval().getValue() - right.eval().getValue());
   }

}

Features Int e Double

As features Int e Double basicamente refinam a classe Value, configurando corretamente o tipo da propriedade value. Noque que, nesses casos, não definimos novas classes ou interfaces. Os incrementos, ou features, são implementados com "refinamentos" das classes e/ou das interfaces existentes.

Int/Value.jak

refines class Value {

   protected int value;
   
   public Value(int value) {
      this.value = value;
   }
   
   public int getValue() {
      return this.value;
   }
   
}

Double/Value.jak

refines class Value {

   protected double value;
   
   public Value(double value) {
      this.value = value;
   }
   
   public double getValue() {
      return this.value;
   }
   
}

Feature Extended (suporte a multiplicação e divisão)

A definição da feature Extended segue um princípio semelhante, por outro lado, apenas definimos classes para suportar as expressões de multiplicação e divisão.

Extended/MultExp.jak

public class MultExp extends BinaryExp {
   
   public MultExp(Expression left, Expression right) {
      super(left, right, "*");
   }
   
   public Value eval() {
      return new Value(left.eval().getValue() * right.eval().getValue());
   }

}

Extended/DivisionExp.jak

public class DivisionExp extends BinaryExp {
   
   public DivisionExp(Expression left, Expression right) {
      super(left, right, "/");
   }
   
   public Value eval() {
      return new Value(left.eval().getValue() / right.eval().getValue());
   }

}

Feature Print

Finalmente, definimos a feature Print refinando a inteface Expression e as classe Value e BinaryExpression.

Print/Expression.jak

refines interface Expression  {

   public String print();

}

Print/Value.jak

refines class Value {

   public String print() {
      return "" + value;
   }
   
}

Print/BinaryExp.jak

refines class BinaryExp  {

   public String print() {
      return left.print() + operator + right.print();
   }

}

Processo de Composição

AHEAD diponibiliza um conjunto de ferramentas para fazer a composição de programas. A documentação é bem detalhada, e o processo de configuração não chega a ser traumático (mesmo no Windows, que requer a ferramenta Cygwin). Importante destacar que a versão mais nova também requer Java 1.6 em diante.

Por exemplo, para fazer a geração de um avaliador de expressões com a configuração (Base + Int + Print), executamos a seguinte seqüencia de comandos:

EPL $ composer --target=out Base Int Print
EPL $ cd out
EPL / out $ jak2java *.jak

Pronto, com isso geramos um conjunto de classes chave que corresponde a definição do produto (Base + Int + Print). Se desejarmos o produto (Base + Double + Extended + Print), basta alterar a chamada do composer para: *composer --target=out Base Double Extended Print.

Existem outros recursos da suite AHEAD que não foram cobertos nesse exemplo.

-- RodrigoBonifacio - 29 Aug 2008

Topic revision: r1 - 2008-08-29 - RodrigoBonifacio
 
This site is powered by the TWiki collaboration platformCopyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback

mersin escort bayan adana escort bayan izmit escort ankara escort bursa escort