O que é esse idioma "Execute Around" (ou similar) sobre o qual tenho ouvido falar? Por que devo usá-lo e por que não desejo usá-lo?
java
language-agnostic
design-patterns
idioms
Tom Hawtin - linha de orientação
fonte
fonte
Respostas:
Basicamente, é o padrão em que você escreve um método para fazer as coisas sempre necessárias, por exemplo, alocação e limpeza de recursos e faz com que o chamador passe "o que queremos fazer com o recurso". Por exemplo:
O código de chamada não precisa se preocupar com o lado aberto / de limpeza - ele será tratado por
executeWithFile
.Isso foi francamente doloroso em Java porque os fechamentos eram muito prolixo, a partir das expressões lambda do Java 8 pode ser implementado como em muitas outras linguagens (por exemplo, expressões lambda C # ou Groovy), e esse caso especial é tratado desde o Java 7 com
try-with-resources
eAutoClosable
fluxos.Embora "alocar e limpar" seja o exemplo típico dado, existem muitos outros exemplos possíveis - manipulação de transações, registro em log, execução de algum código com mais privilégios etc. É basicamente um pouco como o padrão do método de modelo, mas sem herança.
fonte
O idioma Execute Around é usado quando você precisa fazer algo assim:
Para evitar repetir todo esse código redundante que é sempre executado "em torno de" suas tarefas reais, você deve criar uma classe que cuida dele automaticamente:
Esse idioma move todo o código redundante complicado para um único local e deixa o programa principal muito mais legível (e fácil de manter!)
Dê uma olhada nesta postagem para obter um exemplo de C # e neste artigo para um exemplo de C ++.
fonte
Um método Execute Around é o local onde você passa o código arbitrário para um método, que pode executar o código de instalação e / ou desmontagem e executar seu código no meio.
Java não é a linguagem na qual eu escolheria fazer isso. É mais elegante passar um fechamento (ou expressão lambda) como argumento. Embora objetos sejam sem dúvida equivalentes a fechamentos .
Parece-me que o método Execute Around é como Inversão de controle (injeção de dependência) que você pode variar ad hoc, toda vez que chama o método.
Mas também poderia ser interpretado como um exemplo de Control Coupling (dizendo a um método o que fazer por seu argumento, literalmente neste caso).
fonte
Vejo que você tem uma tag Java aqui, então usarei o Java como exemplo, mesmo que o padrão não seja específico da plataforma.
A idéia é que, às vezes, você tenha um código que sempre envolva o mesmo padrão antes de executar o código e depois de executá-lo. Um bom exemplo é o JDBC. Você sempre pega uma conexão e cria uma instrução (ou instrução preparada) antes de executar a consulta real e processar o conjunto de resultados e, em seguida, faz sempre a mesma limpeza no final - fechando a instrução e a conexão.
A idéia com executar ao redor é que é melhor se você puder fatorar o código padrão. Isso economiza sua digitação, mas o motivo é mais profundo. É o princípio de não repetir a si mesmo (DRY) aqui - você isola o código em um local, por isso, se houver um bug ou precisar alterá-lo ou apenas quiser entendê-lo, está tudo em um só lugar.
O que é um pouco complicado com esse tipo de fatoração é que você tem referências que as partes "antes" e "depois" precisam ver. No exemplo JDBC, isso incluiria a conexão e a instrução (preparada). Portanto, para lidar com isso, você "envolve" seu código de destino com o código padrão.
Você pode estar familiarizado com alguns casos comuns em Java. Um é o filtro de servlet. Outra é AOP em torno de conselhos. Um terceiro são as várias classes xxxTemplate na primavera. Em cada caso, você tem algum objeto wrapper no qual seu código "interessante" (digamos, a consulta JDBC e o processamento do conjunto de resultados) é injetado. O objeto wrapper faz a parte "antes", chama o código interessante e depois faz a parte "depois".
fonte
Veja também Code Sandwiches , que examina esse construto em muitas linguagens de programação e oferece algumas idéias interessantes de pesquisa. Com relação à questão específica de por que alguém pode usá-lo, o artigo acima oferece alguns exemplos concretos:
E depois:
O artigo não explora por que não usar esse idioma, mas descreve por que é fácil errar o idioma sem a ajuda no nível do idioma:
fonte
Vou tentar explicar, como faria com uma criança de quatro anos:
Exemplo 1
Papai Noel está vindo para a cidade. Seus elfos codificam o que quiserem pelas costas e, a menos que mudem, as coisas ficam um pouco repetitivas:
Ou isto:
.... ad nauseam um milhão de vezes com um milhão de presentes diferentes: observe que a única coisa diferente é a etapa 2. Se a segunda etapa é a única coisa diferente, por que o Papai Noel está duplicando o código, ou seja, por que ele está duplicando as etapas 1 e 3 um milhão de vezes? Um milhão de presentes significa que ele está repetindo desnecessariamente as etapas 1 e 3 um milhão de vezes.
Executar ajuda a resolver esse problema. e ajuda a eliminar o código. Os passos 1 e 3 são basicamente constantes, permitindo que o passo 2 seja a única parte que muda.
Exemplo 2
Se você ainda não entendeu, aqui está outro exemplo: pense em um sanduíche: o pão por fora é sempre o mesmo, mas o que está por dentro muda dependendo do tipo de sanduíche que você escolher (presunto, queijo, queijo, geléia, manteiga de amendoim etc). O pão está sempre do lado de fora e você não precisa repetir isso um bilhão de vezes para cada tipo de areia que estiver criando.
Agora, se você ler as explicações acima, talvez seja mais fácil entender. Espero que esta explicação tenha ajudado.
fonte
Isso me lembra o padrão de design da estratégia . Observe que o link que eu apontei inclui código Java para o padrão.
Obviamente, pode-se executar "Execute Around" criando código de inicialização e limpeza e passando apenas uma estratégia, que será sempre envolvida no código de inicialização e limpeza.
Como em qualquer técnica usada para reduzir a repetição de código, você não deve usá-la até ter pelo menos 2 casos em que precisar, talvez até 3 (à la o princípio YAGNI). Lembre-se de que a remoção da repetição do código reduz a manutenção (menos cópias de código significa menos tempo gasto na cópia de correções em cada cópia), mas também aumenta a manutenção (mais código total). Portanto, o custo desse truque é que você está adicionando mais código.
Esse tipo de técnica é útil para mais do que apenas inicialização e limpeza. Também é bom para quando você deseja facilitar a chamada de suas funções (por exemplo, você pode usá-lo em um assistente para que os botões "próximo" e "anterior" não precisem de instruções de caso gigantescas para decidir o que fazer para acessar). a página seguinte / anterior.
fonte
Se você deseja expressões idiomáticas, aqui está:
fonte