programação orientada a aspectos com c# paulo borba e andré furtado centro de informática...

88
Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Upload: internet

Post on 17-Apr-2015

107 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Programação orientada a aspectos com C#

Paulo Borba e André FurtadoCentro de Informática

Universidade Federal de Pernambuco

Page 2: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Programação orientada a aspectos é...

uma nova técnica de programação

que oferece suporte à

modularização de crosscutting concerns

Page 3: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Ou seja, programação orientada a aspectos é...

uma nova técnica de programação

que oferece suporte à

modularização de “requisitos” que afetam várias

partes de uma aplicação

Page 4: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Persistência é um crosscutting concern

public class Conta { private string numero; private double saldo; public void Creditar(double valor) { this.saldo = this.saldo + valor; } public void Debitar(double valor) { if (valor > saldo) { throw new SaldoInsuficienteException)); } else { this.saldo = this.saldo - valor; } } public void Atualizar(Conta c) { this.numero = c.numero; this.saldo = c.saldo; } }

public class RepositorioContasAccess : RepositorioContas { public void Inserir(Conta conta) { string sql = "INSERT INTO Conta (NUMERO,SALDO) VALUES ('" + conta.Numero + "'," + conta.Saldo + ")"; OleDbCommand insertCommand = new OleDbCommand(sql,DBHandler.Connection,DBHandler.Transaction); insertCommand.ExecuteNonQuery(); } public void Atualizar(Conta conta) { string sql = "UPDATE Conta SET SALDO = (" + conta.Asldo + ") WHERE NUMERO = '" + conta.Numero + "'"; OleDbCommand updateCommand = new OleDbCommand(sql,DBHandler.Connection,DBHandler.Transaction); int linhasAfetadas; linhasAfetadas = updateCommand.ExecuteNonQuery(); if (linhasAfetadas == 0) { throw new ContaNaoEncontradaException(conta.Numero); } } }

public class CadastroContas { private RepositorioContas contas; public void Debitar(string numero, double valor) { Conta c = contas.Procurar(numero); c.Debitar(valor); contas.Atualizar(c); } public void Transferir(string numeroDe, string numeroPara, double valor) { Conta de = contas.Procurar(numeroDe); Conta para = contas.Procurar(numeroPara); de.Debitar(valor); para.Creditar(valor); contas.Atualizar(de); contas.Atualizar(para); } public double Saldo(string numero) { Conta c = contas.Procurar(numero); return c.Saldo; } }}

public class Banco { private CadastroContas contas; private Banco() { contas = new CadastroConta (new RepositorioContasAccess()); } public void Cadastrar(Conta conta) { Persistence.DBHandler.StartTransaction(); try { contas.Cadastrar(conta); Persistence.DBHandler.CommitTransaction(); } catch (System.Exception ex){ Persistence.DBHandler.RollBackTransaction(); throw ex; } } public void Transferir(string numeroDe, string numeroPara, double valor) { Persistence.DBHandler.StartTransaction(); try { contas.Transferir(numeroDe, numeroPara, valor); Persistence.DBHandler.CommitTransaction(); } catch (System.Exception ex){ Persistence.DBHandler.RollBackTransaction(); throw ex; } } }

public class DBHandler { private static OleDbConnection connection; public static OleDbConnection Connection { get { if (connection == null) { string dataSource = "BancoCS.mdb"; string strConexao = "Provider= Microsoft.Jet.OLEDB.4.0; " + "Data Source=" + dataSource; connection = new OleDbConnection(strConexao); } return connection; } } public static OleDbConnection GetOpenConnection() { Connection.Open(); return Connection; }

public static void StartTransaction() { Connection.Open(); transaction = Connection.BeginTransaction(); }

}

Código de persistência em vermelho…

Page 5: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Crosscutting concerns…

Afetam várias partes da aplicação São relativos à decomposição

dominante• via classes no caso de OO• via funcões no caso das linguagens

funcionais

Page 6: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Exemplos de crosscutting concerns Distribuição Controle de concorrência Tratamento de exceções Logging Debugging Variações em linhas de produtos de

software Suporte a eventos

Page 7: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Há várias técnicas para modularizacao Procedimentos Classes, herança e subtipos Padrões (arquitetura em camadas)

Aspectos

Foco em modularizar crosscutting concerns

Page 8: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

As técnicas de modularização...São complementares e ajudam a...

• Separar preocupações (separation of concerns)

• Aumentar extensibilidade • Facilitar reuso

Tudo isso vale para aspectos

(crosscutting concerns)

Page 9: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Sem aspectospublic class Conta { private string numero; private double saldo; public void Creditar(double valor) { this.saldo = this.saldo + valor; } public void Debitar(double valor) { if (valor > saldo) { throw new SaldoInsuficienteException)); } else { this.saldo = this.saldo - valor; } } public void Atualizar(Conta c) { this.numero = c.numero; this.saldo = c.saldo; } }

public class RepositorioContasAccess : RepositorioContas { public void Inserir(Conta conta) { string sql = "INSERT INTO Conta (NUMERO,SALDO) VALUES ('" + conta.Numero + "'," + conta.Saldo + ")"; OleDbCommand insertCommand = new OleDbCommand(sql,DBHandler.Connection,DBHandler.Transaction); insertCommand.ExecuteNonQuery(); } public void Atualizar(Conta conta) { string sql = "UPDATE Conta SET SALDO = (" + conta.Asldo + ") WHERE NUMERO = '" + conta.Numero + "'"; OleDbCommand updateCommand = new OleDbCommand(sql,DBHandler.Connection,DBHandler.Transaction); int linhasAfetadas; linhasAfetadas = updateCommand.ExecuteNonQuery(); if (linhasAfetadas == 0) { throw new ContaNaoEncontradaException(conta.Numero); } } }

public class CadastroContas { private RepositorioContas contas; public void Debitar(string numero, double valor) { Conta c = contas.Procurar(numero); c.Debitar(valor); contas.Atualizar(c); } public void Transferir(string numeroDe, string numeroPara, double valor) { Conta de = contas.Procurar(numeroDe); Conta para = contas.Procurar(numeroPara); de.Debitar(valor); para.Creditar(valor); contas.Atualizar(de); contas.Atualizar(para); } public double Saldo(string numero) { Conta c = contas.Procurar(numero); return c.Saldo; } }}

public class Banco { private CadastroContas contas; private Banco() { contas = new CadastroConta (new RepositorioContasAccess()); } public void Cadastrar(Conta conta) { Persistence.DBHandler.StartTransaction(); try { contas.Cadastrar(conta); Persistence.DBHandler.CommitTransaction(); } catch (System.Exception ex){ Persistence.DBHandler.RollBackTransaction(); throw ex; } } public void Transferir(string numeroDe, string numeroPara, double valor) { Persistence.DBHandler.StartTransaction(); try { contas.Transferir(numeroDe, numeroPara, valor); Persistence.DBHandler.CommitTransaction(); } catch (System.Exception ex){ Persistence.DBHandler.RollBackTransaction(); throw ex; } } }

public class DBHandler { private static OleDbConnection connection; public static OleDbConnection Connection { get { if (connection == null) { string dataSource = "BancoCS.mdb"; string strConexao = "Provider= Microsoft.Jet.OLEDB.4.0; " + "Data Source=" + dataSource; connection = new OleDbConnection(strConexao); } return connection; } } public static OleDbConnection GetOpenConnection() { Connection.Open(); return Connection; }

public static void StartTransaction() { Connection.Open(); transaction = Connection.BeginTransaction(); }

}

Page 10: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Com aspectospublic class Conta { private string numero; private double saldo; public void Creditar(double valor) { this.saldo = this.saldo + valor; } public void Debitar(double valor) { if (valor > saldo) { throw new SaldoInsuficienteException)); } else { this.saldo = this.saldo - valor; } } public void Atualizar(Conta c) { this.numero = c.numero; this.saldo = c.saldo; } }

public class RepositorioContasAccess : RepositorioContas { public void Inserir(Conta conta) { string sql = "INSERT INTO Conta (NUMERO,SALDO) VALUES ('" + conta.Numero + "'," + conta.Saldo + ")"; OleDbCommand insertCommand = new OleDbCommand(sql,DBHandler.Connection,DBHandler.Transaction); insertCommand.ExecuteNonQuery(); } public void Atualizar(Conta conta) { string sql = "UPDATE Conta SET SALDO = (" + conta.Asldo + ") WHERE NUMERO = '" + conta.Numero + "'"; OleDbCommand updateCommand = new OleDbCommand(sql,DBHandler.Connection,DBHandler.Transaction); int linhasAfetadas; linhasAfetadas = updateCommand.ExecuteNonQuery(); if (linhasAfetadas == 0) { throw new ContaNaoEncontradaException(conta.Numero); } } }

public class CadastroContas { private RepositorioContas contas; public void Debitar(string numero, double valor) { Conta c = contas.Procurar(numero); c.Debitar(valor);} public void Transferir(string numeroDe, string numeroPara, double valor) { Conta de = contas.Procurar(numeroDe); Conta para = contas.Procurar(numeroPara); de.Debitar(valor); para.Creditar(valor);} public double Saldo(string numero) { Conta c = contas.Procurar(numero); return c.Saldo; } }}

public class Banco { private CadastroContas contas; private Banco() { contas = new CadastroConta} public void Cadastrar(Conta conta) {contas.Cadastrar(conta);} public void Transferir(string numeroDe, string numeroPara, double valor) {contas.Transferir(numeroDe, numeroPara, valor);} }

public class DBHandler { private static OleDbConnection connection; public static OleDbConnection Connection { get { if (connection == null) { string dataSource = "BancoCS.mdb"; string strConexao = "Provider= Microsoft.Jet.OLEDB.4.0; " + "Data Source=" + dataSource; connection = new OleDbConnection(strConexao); } return connection; } } public static OleDbConnection GetOpenConnection() { Connection.Open(); return Connection; }

public static void StartTransaction() { Connection.Open(); transaction = Connection.BeginTransaction(); }

}

public class Conta { private string numero; private double saldo; public void Creditar(double valor) { this.saldo = this.saldo + valor; } public void Debitar(double valor) {

public class Conta { private string numero;; } public void Debitar(double valor) {

Código base

do sistema

Código do aspecto

de persistência

com OleDb

Page 11: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Roteiro

Problemas com implementações OO

Conceitos de OA e Eos Soluções baseadas em aspectos AspectC# e LOOM.NET Conclusões

Page 12: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Projeto OO ruim

G D COMUNICAÇÃO I D NEGÓCIO S

Problema: entrelaçamento de código comdiferentes propósitos

Page 13: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Projeto OO bom, em camadas

Interface com o usuário(GUI)

Comunicação

Negócio

Dados

Page 14: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Melhor, em camadas com PDC (sem interfaces)

CadastroClientes

cadastrar()

<<coleção de negócio>>

CadastroLogins

efeturaLogin()

<<coleção de negócio>>

Servidor do Banco

cadastrarCliente()cadastrarConta()efetuarLogin()

<<fachada de negócio>>

CadastroContas

cadastrar()descadastrar()procurar()creditar()transferir()atualizar()selecionarSaldosMenorQue()

<<coleção de negócio>>

RepositorioContasArray

inserir()retirar()procurar()atualizar()selecionarSaldosMenorQue()

<<coleção de dados>>

Conta[]

Conta

creditar()debitar()transferir()equals()atualizar()

<<classe básica de negócio>>

Camada de negócio

Camada dedados

Page 15: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Boa modularização sem persistência, distribuição, ...

public class Conta { private string numero; private double saldo; public void Creditar(double valor) { this.saldo = this.saldo + valor; } public void Debitar(double valor) { if (valor > saldo) { throw new SaldoInsuficienteException)); } else { this.saldo = this.saldo - valor; } } public void Atualizar(Conta c) { this.numero = c.numero; this.saldo = c.saldo; } }

public class CadastroContas { private RepositorioContas contas; public void Debitar(string numero, double valor) { Conta c = contas.Procurar(numero); c.Debitar(valor);} public void Transferir(string numeroDe, string numeroPara, double valor) { Conta de = contas.Procurar(numeroDe); Conta para = contas.Procurar(numeroPara); de.Debitar(valor); para.Creditar(valor);} public double Saldo(string numero) { Conta c = contas.Procurar(numero); return c.Saldo; } }}

public class RepositorioContasArray : RepositorioContas { private Conta[] contas; private int indice; public RepositorioContasArray() { contas = new Conta[100]; indice = 0; } public void Inserir(Conta conta) { contas[indice] = conta; indice = indice + 1; } public void Atualizar(Conta conta) { int i = GetIndice(conta.Numero); if (i == indice) { throw new ContaNaoEncontradaException(conta.Numero); } else { contas[i].Atualizar(conta); } }

public class Programa { [STAThread] public static void Main(string[] args) { Banco fachada = Banco.GetInstance(); Programa.menu(fachada); } public static void menu(Banco fachada) { string numero = null; double valor = 0.0; Conta conta = null; int opcao = 1; while (opcao != 0) { try { System.Console.Out.WriteLine("Aperte <Enter> para continuar"); Util.Util.waitEnter(); System.Console.Out.WriteLine("\n\n\n\n\n\n\n"); System.Console.Out.WriteLine("Escolha uma das alternativas abaixo:"); System.Console.Out.WriteLine("1 - Cadastrar Conta"); System.Console.Out.WriteLine("2 - Creditar"); System.Console.Out.WriteLine("3 - Debitar"); System.Console.Out.WriteLine("4 - Transferir"); System.Console.Out.WriteLine("5 - Ver Saldo"); System.Console.Out.WriteLine("0 - Sair"); opcao = Util.Util.readInt(); switch (opcao) {

public class Banco { private CadastroContas contas; private Banco() { contas = new CadastroConta (new RepositorioContasAccess()); } public void Cadastrar(Conta conta) {contas.Cadastrar(conta);} public void Transferir(string numeroDe, string numeroPara, double valor) {contas.Transferir(numeroDe, numeroPara, valor);} }

Interface

Negócio Dados

Page 16: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Mas temos problemas com persistência via OleDb

public class Conta { private string numero; private double saldo; public void Creditar(double valor) { this.saldo = this.saldo + valor; } public void Debitar(double valor) { if (valor > saldo) { throw new SaldoInsuficienteException)); } else { this.saldo = this.saldo - valor; } } public void Atualizar(Conta c) { this.numero = c.numero; this.saldo = c.saldo; } }

public class RepositorioContasAccess : RepositorioContas { public void Inserir(Conta conta) { string sql = "INSERT INTO Conta (NUMERO,SALDO) VALUES ('" + conta.Numero + "'," + conta.Saldo + ")"; OleDbCommand insertCommand = new OleDbCommand(sql,DBHandler.Connection,DBHandler.Transaction); insertCommand.ExecuteNonQuery(); } public void Atualizar(Conta conta) { string sql = "UPDATE Conta SET SALDO = (" + conta.Asldo + ") WHERE NUMERO = '" + conta.Numero + "'"; OleDbCommand updateCommand = new OleDbCommand(sql,DBHandler.Connection,DBHandler.Transaction); int linhasAfetadas; linhasAfetadas = updateCommand.ExecuteNonQuery(); if (linhasAfetadas == 0) { throw new ContaNaoEncontradaException(conta.Numero); } } }

public class CadastroContas { private RepositorioContas contas; public void Debitar(string numero, double valor) { Conta c = contas.Procurar(numero); c.Debitar(valor); contas.Atualizar(c); } public void Transferir(string numeroDe, string numeroPara, double valor) { Conta de = contas.Procurar(numeroDe); Conta para = contas.Procurar(numeroPara); de.Debitar(valor); para.Creditar(valor); contas.Atualizar(de); contas.Atualizar(para); } public double Saldo(string numero) { Conta c = contas.Procurar(numero); return c.Saldo; } }}

public class Banco { private CadastroContas contas; private Banco() { contas = new CadastroConta (new RepositorioContasAccess()); } public void Cadastrar(Conta conta) { Persistence.DBHandler.StartTransaction(); try { contas.Cadastrar(conta); Persistence.DBHandler.CommitTransaction(); } catch (System.Exception ex){ Persistence.DBHandler.RollBackTransaction(); throw ex; } } public void Transferir(string numeroDe, string numeroPara, double valor) { Persistence.DBHandler.StartTransaction(); try { contas.Transferir(numeroDe, numeroPara, valor); Persistence.DBHandler.CommitTransaction(); } catch (System.Exception ex){ Persistence.DBHandler.RollBackTransaction(); throw ex; } } }

public class DBHandler { private static OleDbConnection connection; public static OleDbConnection Connection { get { if (connection == null) { string dataSource = "BancoCS.mdb"; string strConexao = "Provider= Microsoft.Jet.OLEDB.4.0; " + "Data Source=" + dataSource; connection = new OleDbConnection(strConexao); } return connection; } }

public static OleDbConnection GetOpenConnection() { Connection.Open(); return Connection; }

public static void StartTransaction() { Connection.Open(); transaction = Connection.BeginTransaction(); }

}

Código OleDb em vermelho…

Page 17: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Problemas com implementação OO

public class CadastroContas { private RepositorioContas contas; public void Debitar(string numero, double valor) { Conta c = contas.Procurar(numero); c.Debitar(valor); contas.Atualizar(c); } public void Transferir(string numeroDe, string numeroPara, double valor) { Conta de = contas.Procurar(numeroDe); Conta para = contas.Procurar(numeroPara); de.Debitar(valor); para.Creditar(valor); contas.Atualizar(de); contas.Atualizar(para); } public double Saldo(string numero) { Conta c = contas.Procurar(numero); return c.Saldo; } }}

public class Banco { private CadastroContas contas; private Banco() { contas = new CadastroConta (new RepositorioContasAccess()); } public void Cadastrar(Conta conta) { Persistence.DBHandler.StartTransaction(); try { contas.Cadastrar(conta); Persistence.DBHandler.CommitTransaction(); } catch (System.Exception ex){ Persistence.DBHandler.RollBackTransaction(); throw ex; } } public void Transferir(string numeroDe, string numeroPara, double valor) { Persistence.DBHandler.StartTransaction(); try { contas.Transferir(numeroDe, numeroPara, valor); Persistence.DBHandler.CommitTransaction(); } catch (System.Exception ex){ Persistence.DBHandler.RollBackTransaction(); throw ex; } } }

public class DBHandler { private static OleDbConnection connection; public static OleDbConnection Connection { get { if (connection == null) { string dataSource = "BancoCS.mdb"; string strConexao = "Provider= Microsoft.Jet.OLEDB.4.0; " + "Data Source=" + dataSource; connection = new OleDbConnection(strConexao); } return connection; } }

public static OleDbConnection GetOpenConnection() { Connection.Open(); return Connection; }

public static void StartTransaction() { Connection.Open(); transaction = Connection.BeginTransaction(); }

}

Espalhamento de código(scattering)

Entrelaçamento de código(tangling)

Page 18: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Persistência na fachadapublic class Banco { private CadastroContas contas;... public void Cadastrar(Conta conta) { try {Pers.DBHandler.StartTransaction(); contas.Cadastrar(conta); ... Pers.DBHandler.CommitTransaction(); } catch (System.Exception ex){ Pers.DBHandler.RollBackTransaction();... } }... Código de negócio misturado

com transações (não pode ficar na coleção de dados)

Page 19: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Persistência na coleção de negóciopublic class CadastroContas { private RepositorioContas contas;... public void Creditar(string numero, double valor) { Conta c = contas.Procurar(numero); c.Creditar(valor); contas.Atualizar(c); }... Sincronização de

estados entre objetos e tabelas (registros)

Page 20: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Problemas e conseqüências Código de persistência misturado

com código de negócio Código de persistência aparece em

várias classes Código difícil de manter e reusar

• mudanças na tecnologia de persistência serão invasivas

Page 21: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Implementação OApublic class Conta { private string numero; private double saldo; public void Creditar(double valor) { this.saldo = this.saldo + valor; } public void Debitar(double valor) { if (valor > saldo) { throw new SaldoInsuficienteException)); } else { this.saldo = this.saldo - valor; } } public void Atualizar(Conta c) { this.numero = c.numero; this.saldo = c.saldo; } }

public class RepositorioContasAccess : RepositorioContas { public void Inserir(Conta conta) { string sql = "INSERT INTO Conta (NUMERO,SALDO) VALUES ('" + conta.Numero + "'," + conta.Saldo + ")"; OleDbCommand insertCommand = new OleDbCommand(sql,DBHandler.Connection,DBHandler.Transaction); insertCommand.ExecuteNonQuery(); } public void Atualizar(Conta conta) { string sql = "UPDATE Conta SET SALDO = (" + conta.Asldo + ") WHERE NUMERO = '" + conta.Numero + "'"; OleDbCommand updateCommand = new OleDbCommand(sql,DBHandler.Connection,DBHandler.Transaction); int linhasAfetadas; linhasAfetadas = updateCommand.ExecuteNonQuery(); if (linhasAfetadas == 0) { throw new ContaNaoEncontradaException(conta.Numero); } } }

public class CadastroContas { private RepositorioContas contas; public void Debitar(string numero, double valor) { Conta c = contas.Procurar(numero); c.Debitar(valor);} public void Transferir(string numeroDe, string numeroPara, double valor) { Conta de = contas.Procurar(numeroDe); Conta para = contas.Procurar(numeroPara); de.Debitar(valor); para.Creditar(valor);} public double Saldo(string numero) { Conta c = contas.Procurar(numero); return c.Saldo; } }}

public class Banco { private CadastroContas contas; private Banco() { contas = new CadastroConta} public void Cadastrar(Conta conta) {contas.Cadastrar(conta);} public void Transferir(string numeroDe, string numeroPara, double valor) {contas.Transferir(numeroDe, numeroPara, valor);} }

public class DBHandler { private static OleDbConnection connection; public static OleDbConnection Connection { get { if (connection == null) { string dataSource = "BancoCS.mdb"; string strConexao = "Provider= Microsoft.Jet.OLEDB.4.0; " + "Data Source=" + dataSource; connection = new OleDbConnection(strConexao); } return connection; } } public static OleDbConnection GetOpenConnection() { Connection.Open(); return Connection; }

public static void StartTransaction() { Connection.Open(); transaction = Connection.BeginTransaction(); }

}

public class Conta { private string numero; private double saldo; public void Creditar(double valor) { this.saldo = this.saldo + valor; } public void Debitar(double valor) {

public class Conta { private string numero;; } public void Debitar(double valor) {

Código base

do sistema

Código do aspecto

de persistência

com OleDb

Page 22: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Conseqüências Melhor modularidade, reuso e

extensibidade• mais unidades de código• mudanças na base podem causar

impacto nos aspectos Separation of concerns

• relação entre os aspectos e o resto do sistema nem sempre é clara

Normalmente menos linhas de código

modularidade?

Page 23: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Weaving é usado para… Compor a base do sistema com os

aspectos

A B

Tecnologia de distribução

Sistema original chamadas locais entre A e B

Sistema distribuído chamadas remotas entre A e B

WeaverProcesso decomposição

Aspectos dedistribuição

A B

Page 24: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Composição nos join points

object A

object B

and returns or throws

a method is called

dispatch

dispatch

a method is called

and returns or throwsa method executes

and returnsor throws

a method executesand returns or throws

Comportamento pode ser alterado nos join points…

Fonte: AspectJ Programming Guide

Page 25: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Pointcuts especificam join points Identificam joint points de um

sistema• chamadas e execuções de métodos (e

construtores)• acessos a atributos• tratamento de exceções• inicialização estática e dinâmica

Composição de joint points • &&, || e !

Page 26: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Identificando chamadas de métodos

pointcut writeCall():

call(public void any.Write(string));

com argumento

string

método Write de qualquer

classe

identifica chamadas

de …

nome do pointcut

Page 27: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Advice especifica comportamento extra nos join points Define código adicional que deve

ser executado…• before• after

—after returning—after throwing

• ou around

join points

Page 28: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Alterando o comportamento de chamadas de métodos

after(): writeCall() && within(HelloWorld)

{

System.Console.Write(“ AOP World");

}

após...

qualquer chamada a Write dentro de

HelloWorld

a ação especificada será

executada

Page 29: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspectos agrupam pointcuts, advices, propriedades, etc.aspect HelloAOPWorld {

pointcut writeCall():

call(public void any.Write(string));

after():

writeCall() && within(HelloWorld) {

System.Console.Write(“ AOP World!");

}

}

Page 30: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Hello AOP World!

public class HelloWorld {

public static void Main(string[] args) {

System.Console.Write(“Hello");

}

} Chamada afetada pelo advice, caso

HelloAOPWorld tenha sido composto

com HelloWorld

Page 31: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto de persistência, advicespublic aspect PersistenceAspect {

before(): TransMethods() {

Pers.DBHandler.StartTransaction();

}

after() returning(): TransMethods() {

Pers.DBHandler.CommitTransaction();

}

after() throwing(): TransMethods() {

Pers.DBHandler.RollBackTransaction();

}...

Page 32: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Além de dynamic crosscutting com advice… Temos também static

crosscutting• alterar relação de subtipo• adicionar membros a classes

Inter-typedeclarations

Page 33: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto de persistência, pointcut

pointcut TransMethods():

execution(public any Trans.any(..));

private interface Trans {

public void Cadastrar(Conta conta);...

}

declare parents: Banco:Trans;

altera a hierarquia

de tipos

interface local

ao aspecto

call versus execution

Page 34: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto de persistência, pointcut, alternativa

pointcut TransMethods():

execution(public any Banco.Cadastrar(..)) ||

execution(public any Banco.Creditar(..)) ||

execution(public any Banco.Debitar(..)) ||

...

Page 35: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Declaração entre tipos no aspecto de distribuição

public SaldoInsuficienteException.new(

...SerializationInfo info,

...StreamingContext context):

base(info,context) {

numero = info.GetString("numero");

saldo = info.GetDouble("saldo");

}

Introduz construtor na classe indicada

Page 36: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Banco com controle de concorrência básico

public class Conta { private string numero; private double saldo;Private long timestamp; public void Creditar(double valor) { this.saldo = this.saldo + valor; } public void Debitar(double valor) { if (valor > saldo) { throw new SaldoInsuficienteException)); } else { this.saldo = this.saldo - valor; } } public void Atualizar(Conta c) { this.numero = c.numero; this.saldo = c.saldo;this.timestamp = c.timestamp; } }

public class CadastroContas { private RepositorioContas contas; public void Debitar(string numero, double valor) { lock(this) { Conta c = contas.Procurar(numero); c.Debitar(valor);}} public void Transferir(string numeroDe, string numeroPara, double valor) {lock(this) { Conta de = contas.Procurar(numeroDe); Conta para = contas.Procurar(numeroPara); de.Debitar(valor); para.Creditar(valor);}} public double Saldo(string numero) { Conta c = contas.Procurar(numero); return c.Saldo; } }}

public class RepositorioContasArray : RepositorioContas { private Conta[] contas; private int indice; public RepositorioContasArray() { contas = new Conta[100]; indice = 0; } public void Inserir(Conta conta) { contas[indice] = conta; indice = indice + 1; } public void Atualizar(Conta conta) { int i = GetIndice(conta.Numero); if (i == indice) { throw new ContaNaoEncontradaException(conta.Numero); } else { if (conta.Timestamp == contas[I].Timestamp) { contas[i].Atualizar(conta);Conta.incTimestamp();} else {………….}} } }

public class Banco { private CadastroContas contas; private Banco() { contas = new CadastroConta (new RepositorioContasAccess()); } public void Cadastrar(Conta conta) {contas.Cadastrar(conta);} public void Transferir(string numeroDe, string numeroPara, double valor) {contas.Transferir(numeroDe, numeroPara, valor);} }

Dados

Negócio Concorrência

Page 37: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Controle de concorrência na coleção de negócio

public void Debitar(string n, double v) { lock(this) {... Conta c = contas.Procurar(n); ... c.Debitar(v); }}... Controle de concorrência para

evitar interferências indesejadas

entre os métodos da fachada

Page 38: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Controle de concorrência na coleção de dadospublic void Atualizar(Conta conta) { ... c = contas[i]; if (conta.Timestamp == c.Timestamp) { c.Atualizar(conta); c.UpdateTimestamp(); } else {...}

}... Controle de concorrência para

evitar manipulação de versões

desatualizadas de objetos

Page 39: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Controle de concorrência na classe básicapublic class Conta { private double saldo;... private long timestamp; public void Atualizar(Conta c) { this.saldo = c.saldo;... this.timestamp = c.timestamp; }... }

Controle otimista de concorrência

Page 40: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Os pointcuts podem expor o contexto dos join points Informações disponíveis nos join

points• argumentos de métodos• objetos responsáveis pela execução• objetos alvo• variáveis de instância

Page 41: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto de concorrência, pointcut

public aspect ConcurrencyAspect {

pointcut ConcurrentMethods(object t):

((call(void CadContas.Cadastrar(Conta))

&& target(t)) || ...

);

Informação exposta

Associação de t com o alvo da chamada de

método

Page 42: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto de concorrência, adviceObject around(Object t):

ConcurrentMethods(t) {

Object obj;

lock (t) {

obj = proceed(t);

}

return obj;

}

O corpo do around

poderá usar a informação

exposta

A execução do join point

interceptado deve

continuar

Page 43: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto de persistência, outro advice

void around(Banco b):

fset(CadastroContas Banco.contas) &&

execution(private Banco.new()) && this(b) {

b.contas = new CadastroContas(

new RepositorioContasAccess());

}

atribuições à variável de instância ou

estática

Associação de b com o objeto sendo inicializado

Page 44: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Quebra de encapsulamento

void around(Banco b):

fset(CadastroContas Banco.contas) &&

execution(private Banco.new()) && this(b) {

b.contas = new CadastroContas(

new RepositorioContasAccess());

}

Variável de instância privada! Aspecto deve ser definido como privileged

Page 45: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Banco remoto com .NET Remoting

[System.Serializable()]public class Conta { private string numero; private double saldo; public void Creditar(double valor) { this.saldo = this.saldo + valor; } public void Debitar(double valor) { if (valor > saldo) { throw new SaldoInsuficienteException)); } else { this.saldo = this.saldo - valor; } } public void Atualizar(Conta c) { this.numero = c.numero; this.saldo = c.saldo; } }

public class RepositorioContasArray : RepositorioContas { private Conta[] contas; private int indice; public RepositorioContasArray() { contas = new Conta[100]; indice = 0; } public void Inserir(Conta conta) { contas[indice] = conta; indice = indice + 1; } public void Atualizar(Conta conta) { int i = GetIndice(conta.Numero); if (i == indice) { throw new ContaNaoEncontradaException(conta.Numero); } else { contas[i].Atualizar(conta); } }

public class Programa { [STAThread] public static void Main(string[] args) { Banco fachada; try { TcpChannel chan = new TcpChannel(); (Banco)Activator.GetObject(typeof(Fachada.Banco),System.Console.WriteLine("Could not locate server"); } else { Programa.menu(fachada); } } catch (Exception e) {System.Console.WriteLine("The error was: " + e.Message); } } public static void menu(Banco fachada) { string numero = null;while (opcao != 0) { try { System.Console.Out.WriteLine("Aperte <Enter> para continuar"); Util.Util.waitEnter(); System.Console.Out.WriteLine("\n\n\n\n\n\n\n");System.Console.Out.WriteLine("2 - Creditar"); …} catch (Exception exception) { System.Console.Out.WriteLine(exception.Message); }

public class Banco: System.MarshalByRefObject { private CadastroContas contas; private Banco() { contas = new CadastroConta (new RepositorioContasAccess()); } public void Cadastrar(Conta conta) {contas.Cadastrar(conta);} public void Transferir(string numeroDe, string numeroPara, double valor) {contas.Transferir(numeroDe, numeroPara, valor);} }

public class CadastroContas { private RepositorioContas contas; public void Debitar(string numero, double valor) { Conta c = contas.Procurar(numero); c.Debitar(valor); contas.Atualizar(c); } public void Transferir(string numeroDe, string numeroPara, double valor) { Conta de = contas.Procurar(numeroDe); Conta para = contas.Procurar(numeroPara); de.Debitar(valor); para.Creditar(valor); contas.Atualizar(de); contas.Atualizar(para); } public double Saldo(string numero) { Conta c = contas.Procurar(numero); return c.Saldo; } }}

public class ServerInit {

public static void Main(string[] args) {

try {

TcpChannel chan = new TcpChannel(8085);

ChannelServices.RegisterChannel(chan);

RemotingConfiguration.RegisterWellKnownServiceType

(Type.GetType("Fachada.Banco"),

} catch (Exception e) {

Console.WriteLine("An error has happened:");

Console.WriteLine(e.Message);

}

}

[System.Serializable()]

public class ContaJaCadastradaException :

System.Exception {

public string Numero {

get { return numero;

} }

private string numero;

public ContaJaCadastradaException(numero;

}

public ContaJaCadastradaExceptionnumero =

info.GetString("numero");

}

public override void GetObjectData(base.

GetObjectData(info,context);

info.AddValue("numero", numero,typeo

f(string));

}}

Interface

Negócio

Distribuição

Dados

Page 46: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Distribuição na interface com o usuário

public static void Main(string[] args) { Banco fachada; try {... fachada = (Banco) Activator.GetObject( typeof(Fachada.Banco), "tcp://localhost:8085/BancoRemoto"); ... Programa.menu(fachada); } catch...}

serviço de

lookup

Page 47: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Distribuição na fachada

public class Banco: System.MarshalByRefObject {

private CadastroContas contas;private static Banco banco;

Supertipo de qualquer servidor

Manipulação de objetos por valor

versus por referência

Page 48: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Distribuição na classe básica e exceções

[System.Serializable()]public class Conta {

private double saldo;...}[System.Serializable()]

public class ContaNaoEncontradaException

: System.Exception {...}

Possibilita a passagem de objetos por valor

Page 49: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto de distribuição, servidorpublic aspect DistributionAspectServer {

declare parents:

Banco:System.MarshalByRefObject;

}

Temos dois aspectos apenas por questões de

implantação

Page 50: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto de distribuição, cliente

aspect DistributionAspectClient {

declare class attributes:

(Conta || SaldoInsuficienteException)

[System.Serializable()];

...

Acrescenta atributos a uma classe

Page 51: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto de distribuiçãovoid around():

execution(...void Programa.Main(string[])) {

Banco fachada;

try {...

fachada = (Banco) Activator.GetObject(

typeof(Fachada.Banco),

"tcp://localhost:8085/BancoRemoto");

...Programa.menu(fachada);

} catch...

}

Page 52: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

O aspecto de sincronização de estado é... Útil tanto para persistência quanto

para distribuição Dividido em duas partes:

• registro de objetos modificados (sujos)

• atualização dos objetos modificados

Page 53: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Registro de objetos modificados

pointcut localUpdate(Conta c):

this(CadContas) && target(c) &&

(call(any Conta.Creditar(..)) || ...;

private ArrayList dirtyObjects = ...;

after(Conta c) returning(): localUpdate(c) {

dirtyObjects.add(c);

}

Quaisquer argumentos

Page 54: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Atualização dos objetos modificadospointcut localExecution(CadContas cad):

if(HasDirtyObjects()) && this(cad) &&

execution(public any any(..));

after(CadContas cad) returning():

localExecution(cad) {

foreach (Conta c in dirtyObjects) {

cad.Contas.Atualizar(c);

}

}

Page 55: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto de sincronização de estado

privileged aspect StateSynchronization

percflow(execution(any Banco.any(..))) {

RepositorioContas CadastroContas.Contas {

get {

return this.contas;

}

}

publics omitidos...

Para evitar interferências

no atributo do aspectoAdiciona propriedade

Page 56: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Instâncias de aspectos

default, apenas uma instância, aspecto estático

percflow, uma instância para cada fluxo de um joint point

pertarget, uma instância para cada alvo de um joint point

pertthis percflowbelow

Page 57: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

cflow(<pointcut>)• todos os join points no fluxo de controle do

<pointcut> cflowbelow(<pointcut>)

• todos os join points no fluxo de controle do <pointcut>, exceto o inicial

fget(<signature>) • todos os join points dos acessos às variáveis

com assinatura <signature>

Outros pointcut designators

Page 58: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

withincode(<method>) • todos os join points do código que aparece

dentro de um método initialization(<constructor>)

• todos os join points de inicialização com uma dada assinatura

args(<Type or Id, ...>)• todos os join points com argumentos dos

tipos especificados

Mais pointcut designators

Page 59: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

NomeAspecto.aspectOf() • retorna a instância de um

determinado aspecto, útil para acesso a membros do aspecto

declare precedence: <TypeList> • define a precedência entre

aspectos que afetam um mesmo join point

Mais construções de Eos

Page 60: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Advices só para instâncias específicas instancelevel

• modificador de advice e aspecto• advice ou aspecto só afetará

instâncias registradas pelos métodos abaixo

addObject removeObject

Page 61: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Selecionando instâncias

Fonte: Eos distribution

public aspect Trace {

public void Select(Bit bit) {

addObject(bit);

}

after():execution(public any any.any()) {

Console.WriteLine("In any method");

}

instancelevel after():

execution(public bool Bit.Get()) {

Console.WriteLine(“A selective advice");

}...

Page 62: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Sincronização entre conjuntos, aspecto

Fonte: Eos distribution

public instancelevel aspect Bijection {

bool busy;

Set A;

Set B;

public void Relate(Set A, Set B) {

addObject(A); addObject(B);

this.A = A; this.B = B;

}

Page 63: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Sincronização entre conjuntos, advice

after():execution(public bool Set.Insert()) {

...r = (bool) thisJoinPoint.getReturnValue();

if(r) {

Set set = (Set) thisJoinPoint.getTarget();

object[] args = thisJoinPoint.getArgs();

Element e = (Element)arguments[0];

if (set == this.A) B.Insert(e);

else A.Insert(e);

}

}...

Fonte: Eos distribution

Page 64: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Sincronização entre conjuntos, inicialização

Fonte: Eos distribution

public static void Main (string[] argument) {

Set A = new Set();

Set B = new Set();

Bijection bj = new Bijection();

bj.Relate(A,B);

Element A1 = new Element("A1");

A.Insert(A1);

Element B1 = new Element("B1");

B.Insert(B1);...

}

Page 65: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Acessando mais informações dos join pointsAlém das informações expostas pelos pointcuts, é possível acessar mais sobre os join points usando referências especiais:

•thisJoinPoint

•thisJoinPointStaticPart

Page 66: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Métodos das referências especiais

thisJoinPoint

getArgs()

getTarget()

getReturnValue()

thisJoinPointStaticPart

getSignature()

Page 67: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Debugging ou logging simplespublic aspect LoggingAspect {

before(): execution(public any any.any(..)) {

System.Console.Write("A method from..." +

thisJoinPoint.getTarget() + " is about" +

“ to be executed. Its signature is " +

thisJoinPointStaticPart.getSignature());

}

Page 68: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto de desenvolvimento versus produção

after(): execution(public any any.any(..)) {

System.Console.Write("Now the method" +

... + " has finished"); ...

System.Console.Write("The return value was “

+ thisJoinPoint.getReturnValue());

}

Page 69: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Abordagens para aspectos com C# Eos

• baseada em uma extensão de C# com novos recursos linguísticos

AspectC#• baseada em XMLs que descrevem

como classes C# devem ser compostas LOOM.NET

• baseada em API e atributos C# que descrevem como classes C# devem ser compostas

Page 70: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Orientação a aspectos é...

Quantificação (quantification)• uma parte do programa tem efeito em

várias outras• o aspecto afeta várias classes e outros

aspectos Mudanças não invasivas

(obliviouness)• uma parte A do programa tem efeito

sobre uma B sem precisar alterar o código de B

Page 71: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

AspectC#

Advices disponíveis: before, after e around

Acesso reflexivo ao contexto do join point

Falta quantificação

Page 72: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

AspectC#, localização da base e dos aspectos

<Aspect>

<TargetBase>c:\...</TargetBase>

<AspectBase>c:\...</AspectBase>

Page 73: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

AspectC#, definição do aspecto (advice)...

<Aspect-Method>

<Name>AspectoSincronizacao</Name>

<Namespace>Contas</Namespace>

<Class>AspectoSincronizacao</Class>

<Method>Sincronizar()</Method>

</Aspect-Method>

Page 74: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

AspectC#, definição da classe afetada (pointcut)...<Target>

<Namespace>Contas</Namespace>

<Class>CadContas</Class>

<Method>

<Name>Cadastrar()</Name>

<Type>before</Type>

<Aspect-Name>AspectoSincronizacao

</Aspect-Name></Method></Target></Aspect>

Page 75: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

LOOM.NET

Advices disponíveis: before, after e instead (around) • proceed(context)

Aspectos são classes que herdam de Aspect

Suporte a quantificação (wildcards) É invasiva

Page 76: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

LOOM.NET, invasãopublic class HelloWorld {

public virtual void SayHello() {

System.Console.WriteLine("Hello World");

}

public virtual void SayBye() {

System.Console.WriteLine("Bye World");

}

}Métodos afetados têm

que ser virtual

Page 77: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

LOOM.NET, aspecto

public class LoggingAspect:Aspect {

[Call(Invoke.After)]

public void SayBye() {

System.Console.Write("SayBye! <-");

}...Corpo do método é o

corpo do advice; atributo e nome do método são o pointcut e tipo do advice

Page 78: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

LOOM.NET, quantificação

[Call(Invoke.Before,Alias="Say*")]

public void Say() {

System.Console.Write(“-> SayHello!");

}

Nome do método deixa de contribuir para o

pointcut

Page 79: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

LOOM.NET, mais invasãoclass MainClass {

[STAThread]

public static void Main(string[] args) {

HelloWorld h = (HelloWorld)

Weaver.CreateInstance(

typeof(HelloWorld),

null,new LoggingAspect());

h.SayHello();...

}...

Page 80: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

AOP ou um bom projeto OO?

Decorator ou Adapter

Page 81: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Com padrões (adapter ou decorator)… Escrevemos mais código A ligação entre o adaptador e o

objeto adaptado• é explicita e invasiva• não altera o comportamento de

chamadas internas para o objeto adaptado

• não tem acesso ao objeto fonte (source)

• pode ser modificado dinamicamente

Page 82: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Reuso e extensibilidade de aspectos via padrões e frameworks Tag interface

• como na interface Trans do aspecto de transações

Glue aspects• advices invocando serviços auxiliares

Template pointcut• com aspectos abstratos

Page 83: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto abstrato para persistênciapublic abstract aspect APersistenceAspect {

abstract pointcut TransactionalMethods();

before(): TransactionalMethods() {

Pers.DBHandler.StartTransaction();

}...

}

Page 84: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspecto concreto para persistência

public aspect PersistenceAspect:

APersistenceAspect {

private interface Trans {

public void Cadastrar(Conta conta);...

}

declare parents: Banco:Trans;

override pointcut TransactionalMethods():

execution(public any Trans.any(..));

}

Page 85: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspectos, pontos positivos Útil para implementar crosscutting

concerns Modularidade, reuso, e

extensibilidade de software Produtividade Separação na implementação e

testes (plug-in/out)

Page 86: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Aspectos, pontos negativos Modularidade relativa

• falta noção de interface Dependência entre classes e

aspectos • sensível a refactorings

Necessidade de refactorings para expor join points

É essencial usar IDE Conflitos entre aspectos

Page 87: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Tópicos de pesquisa

Orientação a aspectos modular• entendimento das partes leva ao

entendimento do todo; não é preciso expandir...

Novos joint points Processo de desenvolvimento Linhas de produtos de software

Page 88: Programação orientada a aspectos com C# Paulo Borba e André Furtado Centro de Informática Universidade Federal de Pernambuco

Referências

Ver roteiro de exercícios ... [email protected]