0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【公ド読】横断的関心事の処理

Posted at

【公式ドキュメントを読もうシリーズ】横断的関心事の処理

シリーズ概要

https://qiita.com/yasu_programming/items/cec66f9e8d5d571e9ce3

URL

https://docs.github.com/ja/copilot/copilot-chat-cookbook/refactoring-code/handling-cross-cutting-concerns

説明

アスペクト指向プログラミング (AOP)に沿ったリファクタリングをしてくれる。

下記のプロンプトで関心の分離をしてくれる。

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

所感

責務の分離ができているコードを見ると見やすいので、サクサク仕事が進むなあという感覚があるが、そういったリファクタリングをしてくれる。

アスペクト指向プログラミングという言葉を初めて知ったが、今までできていなかったので勉強になった。

ログ、セキュリティ、データ検証、エラー処理をそれぞれのビジネスロジック内に入れていたが、純粋なビジネスロジックだけを作成するという手法もあるんですね。

大規模開発とかだと使うのかもしれないですね。ロボットの組み立てっぽいというかパズルっぽい感じでプログラミングができそう。

AI君が出力した比較できるコードが下記の通りです。

従来のコード

def user_service():
    try:
        # ビジネスロジック
        result = process_user_data()
        return result
    except DatabaseError as e:
        logger.error(f"Database error: {e}")
        raise ServiceException("User processing failed")
    except ValidationError as e:
        logger.error(f"Validation error: {e}")
        raise ServiceException("Invalid user data")

def order_service():
    try:
        # ビジネスロジック
        result = process_order()
        return result
    except DatabaseError as e:
        logger.error(f"Database error: {e}")  # 重複コード
        raise ServiceException("Order processing failed")
    except ValidationError as e:
        logger.error(f"Validation error: {e}")  # 重複コード
        raise ServiceException("Invalid order data")

AOPを使用したコード

import functools
import logging
from typing import Dict, Type, Callable

logger = logging.getLogger(__name__)

class ServiceException(Exception):
    pass

class DatabaseError(Exception):
    pass

class ValidationError(Exception):
    pass

# エラーハンドリングのアスペクト
def error_handler(error_mappings: Dict[Type[Exception], str]):
    """エラー処理のデコレータ(アスペクト)"""
    def decorator(func: Callable):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                # 共通のエラー処理ロジック
                error_type = type(e)
                if error_type in error_mappings:
                    logger.error(f"{error_type.__name__}: {e}")
                    raise ServiceException(error_mappings[error_type])
                else:
                    logger.error(f"Unexpected error: {e}")
                    raise ServiceException("An unexpected error occurred")
        return wrapper
    return decorator

# ビジネスロジックからエラー処理を分離
@error_handler({
    DatabaseError: "User processing failed",
    ValidationError: "Invalid user data"
})
def user_service():
    # 純粋なビジネスロジックのみ
    return process_user_data()

@error_handler({
    DatabaseError: "Order processing failed", 
    ValidationError: "Invalid order data"
})
def order_service():
    # 純粋なビジネスロジックのみ
    return process_order()

def process_user_data():
    # 実際の処理
    pass

def process_order():
    # 実際の処理
    pass

単純なコード生成だけではなく、アーキテクチャの提案などもしてくれるので、初心者だけではなく、概念の具体化なども出来て良いなあと思いました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?