AX Dev Warehouse

Um blog dedicado ao desenvolvimento de soluções em Microsoft Dynamics AX
posts - 41, comments - 18, trackbacks - 0

Utilizando maps para reaproveitamento de código

 

O Dynamics AX tem um objeto não muito comum em linguagens OO, mas que permite mapear suas Tables com um funcionamento semelhante ao de uma interface. Vou mostrar um exemplo simples como aplicar esta funcionalidade.

A SalesTable, que contém as ordens de venda, e a PurchTable, que contém as ordens de compra, têm alguns campos em comum e podem ter algumas funcionalidades em comum. Por isto existe no sistema um Map, chamado SalesPurchTable, que mapeia alguns campos destas tabelas e pode ser usado em métodos cuja regra de negócio é comum as duas tabelas.

Como é possível ver na imagem um Map é composto de campos, grupos de campos, métodos e mappings. Estes mapeiam cada campo do Map ao campo correspondente da tabela. Você pode perceber que o map SalesPurchTable mapeia não só a SalesTable e PurchTable, mas também SalesBasket, SalesQuotationBasket e SalesQuotationTable.

Uma forma interessante de utilizar o Map é evitar a duplicação de código, quando existe uma funcionalidade igual, ou muito parecida, mas que usam diferentes tabelas.

O código de exemplo abaixo implementa uma classe e um método printOrderDetails. O método recebe como parâmetro um map SalesPurchTable. O método é bem simples, imprime alguns campos da ordem. O importante é que ele pode receber tanto objetos do tipo SalesTable como do tipo PurchTable que o seu comportamento será igual.

static void printOrderDetails(SalesPurchTable _table)
{;

    print _table.SalesPurchId;
    print _table.OrderAccount;
    print _table.CashDisc;
    
    pause;
}

O job abaixo executa o nosso método passando um SalesTable e em seguida um PurchTable e o comportamento é igual.

static void Job11(Args _args)
{
    SalesTable salesTable;
    PurchTable purchTable;
    ;

    //Trocar o parâmetro para uma id de Sales Order válido
    salesTable = SalesTable::find('000004'); 
    //Trocar o parâmetro para uma id de Purchase Order válido
    purchTable = PurchTable::find('000001'); 
    
    MapSample::printOrderDetails(salesTable);
    MapSample::printOrderDetails(purchTable);
}

Quem conhece um pouco mais de X++ sabe que posso obter um resultado semelhante com o tipo common, pois ele aceita qualquer objeto. Mas a solução utilizando Map tem uma grande vantagem: Ela é Type safe. Veja na imagem abaixo o que acontece se tento passar um objeto do tipo SalesLine para o método. Ocorre um erro em tempo de compilação, pois não existe mapping de SalesLine para SalesPurchTable. Utilizando o common este mesmo erro ocorreria em tempo de execução, o que é muito pior.

Se durante a execução do código você precise saber qual tipo da tabela recebida ainda assim é possível, como você pode ver no código abaixo.

O que você NÃO deve fazer é criar um método que recebe um map, mas no final das contas tem um comportamento completamente distinto para cada tipo de tabela. Neste caso o seu método fica muito grande, com muitas responsabilidades e confuso para os outros desenvolvedores lerem.

static void printOrderDetails(SalesPurchTable _table)
{;

    switch (_table.TableId)
    {
        case TableNum(SalesTable):
            print "Sales Order";
            break;
            
        case TableNum(PurchTable):
            print "Purchase Order";
            break;
            
        default:
            print "Order";
            break;
    }

    print _table.SalesPurchId;
    print _table.OrderAccount;
    print _table.CashDisc;
    
    pause;
}

Print | posted on Thursday, May 24, 2007 5:22 PM | Filed Under [ X++ ]

Powered by: