Skip to main content

Gérer les problèmes transversaux

Copilot Chat peut vous aider à éviter le code qui se rapporte à un problème autre que le problème principal de la méthode ou de la fonction dans laquelle se trouve le code.

Les problèmes transversaux sont des aspects d’un programme qui affectent plusieurs parties du système, tels que la journalisation, la sécurité, la validation des données et le traitement des erreurs. Ils peuvent être dispersés dans une base de code, ce qui entraîne une duplication du code et des problèmes de maintenance.

Copilot Chat peut aider à remanier les problèmes transversaux en suggérant la mise en œuvre de pratiques de programmation orientée aspects (AOP) ou en utilisant des décorateurs et des modèles d’intergiciels pour centraliser ces problèmes d’une manière modulaire et maintenable.

Exemple de scénario

Imaginez que vous ayez un projet Python qui contient plusieurs fichiers de service dans lesquels la journalisation se produit. Les informations qui sont journalisées sont définies dans chacun des fichiers de service individuels. Si l’application est modifiée ou étendue à l’avenir, cette conception pourrait entraîner des incohérences dans le contenu et le style des entrées de journal. Vous pouvez consolider et centraliser le comportement de journalisation afin d’éviter qu’il ne soit distribué à travers votre projet.

Voici trois fichiers de notre projet d’exemple : le fichier du point d’entrée (main.py), le fichier de configuration des messages de journalisation (logging_config.py) et l’un des fichiers de service (order_service.py). Le fichier de service de l’exemple montre comment les informations de journalisation sont définies parallèlement à la logique commerciale d’une partie particulière de l’application.

main.py

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

import logging

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

order_service.py

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.")

Exemples d’invite

Ouvrez l’espace de travail du projet dans VS Code ou Visual Studio et entrez le prompt suivant dans l’affichage Copilot Chat.

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

Note

Le participant au chat @workspace dans VS Code et Visual Studio fournit à Copilot le contexte de tout le code de votre espace de travail. Vous pouvez utiliser @workspace lorsque vous souhaitez que Copilot prenne en compte la structure de votre projet et la manière dont les différentes parties de votre code interagissent.

Exemple de réponse

Copilot répond comme suit.

Note

La réponse suivante est un exemple. Copilot Chat Les réponses ne sont pas déterministes, il est donc possible que vous obteniez une réponse différente de celle présentée ici.

Pour refactoriser ce projet à l’aide de la programmation orientée aspects (AOP) afin de gérer la journalisation comme un problème transversal, vous pouvez utiliser une bibliothèque telle que aspectlib. Voici comment procéder :

  1. Installez aspectlib :

    pip install aspectlib

  2. Créer un aspect pour la journalisation dans un nouveau fichier appelé logging_aspect.py :

    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. Appliquer l’aspect aux méthodes de service dans main.py :

    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 vous indique ensuite de supprimer le code de journalisation de toutes les classes de service et vous donne le code des fichiers révisés. Par exemple, voici la version révisée de order_service.py :

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

Dans la version refactorisée du projet, les mêmes opérations de journalisation sont effectuées, mais le code de journalisation est centralisé dans un seul fichier.

Pour aller plus loin