# Lidar com preocupações paralelas

Copilot Chat pode ajudá-lo a evitar o código relacionado a uma preocupação diferente da principal preocupação do método ou função na qual o código está localizado.

Preocupações transversais são aspectos de um programa que afetam várias partes do sistema, como registro em log, segurança, validação de dados e tratamento de erros. Elas podem se espalhar por uma base de código, levando a desafios de duplicação e manutenção de código.

Copilot Chat pode ajudar a refatorar interesses transversais, sugerindo a implementação de práticas de Programação Orientada a Aspectos (AOP) ou o uso de decoradores e padrões de middleware para centralizar esses interesses de forma modular e de fácil manutenção.

## Cenário de exemplo

Imagine que você tem um projeto de Python que contém vários arquivos de serviço nos quais ocorre o registro em log. As informações que são registradas são definidas em cada um dos arquivos de serviço individuais. Se o aplicativo for modificado ou estendido no futuro, esse design poderá levar a inconsistência no conteúdo e no estilo das entradas de log. Você pode consolidar e centralizar o comportamento de registro de log para evitar sua distribuição em seu projeto.

Aqui estão três arquivos do nosso exemplo de projeto: o arquivo de ponto de entrada (`main.py`), o arquivo de configuração de mensagem de log (`logging_config.py`) e um dos arquivos de serviço (`order_service.py`). O arquivo de serviço de exemplo mostra como as informações de log são definidas em conjunto com a lógica de negócios de uma parte específica do aplicativo.

### main.py

```python
import logging
from logging_config import setup_logging
from payment_service import PaymentService
from order_service import OrderService
from shipping_service import ShippingService
from inventory_service import InventoryService
from notification_service import NotificationService

def main():
    setup_logging()
    payment_service = PaymentService()
    order_service = OrderService()
    shipping_service = ShippingService()
    inventory_service = InventoryService()
    notification_service = NotificationService()

    # Example usage
    payment_service.process_payment({"amount": 100, "currency": "USD"})
    order_service.place_order({"item": "Book", "quantity": 1})
    shipping_service.ship_order({"item": "Book", "quantity": 1})
    inventory_service.update_inventory("Book", -1)
    notification_service.send_notification("Order has been placed and shipped.")

if __name__ == "__main__":
    main()
```

### logging\_config.py

```python
import logging

def setup_logging():
    logging.basicConfig(level=logging.INFO,
                  format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
```

### order\_service.py

```python
import logging

class OrderService:
    def __init__(self):
        self.logger = logging.getLogger(__name__)

    def place_order(self, order):
        self.logger.info("Entering place_order method.")
        try:
            # In here would be the business logic for placing an order
            # ...
            self.logger.info("Order placed successfully.")
        except Exception as e:
            self.logger.error(f"Error in place_order method: {e}")
            raise
        finally:
            self.logger.info("Exiting place_order method.")
```

## Prompt de exemplo

Abra o espaço de trabalho do projeto em VS Code ou Visual Studio e insira o prompt a seguir na visualização Copilot Chat.

```copilot copy
@workspace Refactor this project by using AOP to avoid logging that has cross-cutting concerns
```

> \[!NOTE]
> O participante do chat em `@workspace` e VS Code fornece a Visual Studio o contexto sobre todo o código em seu workspace. Você pode usar `@workspace` quando quiser Copilot considerar a estrutura do seu projeto e como diferentes partes do código interagem. Se você estiver usando um IDE do JetBrains, use `@project` em vez de `@workspace`.

## Resposta de exemplo

Copilot responde da seguinte maneira.

> \[!NOTE] A resposta a seguir é um exemplo. Respostas do Copilot Chat são não determinísticas, portanto, você pode obter uma resposta diferente da mostrada aqui.

> Para refatorar esse projeto usando Programação Orientada a Aspectos (AOP) para lidar com o registro em log como uma preocupação transversal, você pode usar uma biblioteca como `aspectlib`. Veja como fazer isso:
>
> 1. Instale `aspectlib`:
>
>    `pip install aspectlib`
>
> 2. Crie um aspecto para registrar em log em um novo arquivo chamado `logging_aspect.py`:
>
>    ```python
>    import aspectlib
>    import logging
>
>    @aspectlib.Aspect(bind=True)
>    def log_method_call(cutpoint, *args, **kwargs):
>        logger = logging.getLogger()
>        method_name = cutpoint.__name__
>        logger.info(f"Entering method: {method_name}")
>        try:
>            result = yield aspectlib.Proceed
>            logger.info(f"Method {method_name} executed successfully.")
>            return result
>        except Exception as e:
>            logger.error(f"Error in method {method_name}: {e}")
>            raise
>        finally:
>            logger.info(f"Exiting method: {method_name}")
>    ```
>
> 3. Aplique o aspecto aos métodos de serviço em `main.py`:
>
>    ```python
>    import logging
>    from logging_config import setup_logging
>    from payment_service import PaymentService
>    from order_service import OrderService
>    from shipping_service import ShippingService
>    from inventory_service import InventoryService
>    from notification_service import NotificationService
>    from logging_aspect import log_method_call
>    import aspectlib
>
>    def main():
>        setup_logging()
>
>        # Apply logging aspect to service methods
>        aspectlib.weave(PaymentService.process_payment, log_method_call)
>        aspectlib.weave(OrderService.place_order, log_method_call)
>        aspectlib.weave(ShippingService.ship_order, log_method_call)
>        aspectlib.weave(InventoryService.update_inventory, log_method_call)
>        aspectlib.weave(NotificationService.send_notification, log_method_call)
>
>        payment_service = PaymentService()
>        order_service = OrderService()
>        shipping_service = ShippingService()
>        inventory_service = InventoryService()
>        notification_service = NotificationService()
>
>        # Example usage
>        payment_service.process_payment({"amount": 100, "currency": "USD"})
>        order_service.place_order({"item": "Book", "quantity": 1})
>        shipping_service.ship_order({"item": "Book", "quantity": 1})
>        inventory_service.update_inventory("Book", -1)
>        notification_service.send_notification("Order has been placed and shipped.")
>
>    if __name__ == "__main__":
>        main()
>    ```

Copilot em seguida, orienta você a remover o código de log de todas as classes de serviço e fornece o código dos arquivos revisados. Por exemplo, esta é a versão revisada de `order_service.py`:

```python
class OrderService:
    def place_order(self, order):
        # In here would be the business logic for placing an order
        # ...
        pass
```

Na versão refatorada do projeto, as mesmas operações de log são executadas, mas o código de log é centralizado em um só arquivo.

## Leitura adicional

* [Engenharia de prompts para o GitHub Copilot Chat](/pt/copilot/concepts/prompting/prompt-engineering)
* [Práticas recomendadas para usar GitHub Copilot](/pt/copilot/get-started/best-practices)