Graph Q L開発における効率的なコード分割

GraphQL 開発における効率的なコード分割と ChatGPT 活用のベストプラクティス #

【目的】 #

GraphQL API を Flask + Graphene で開発する際に、

  • 人間開発者にとって保守性・拡張性が高く
  • ChatGPT にとっても理解しやすく相談しやすい コード構成と運用方法をまとめたノウハウです。

【基本方針】 #

◆ 本番コード:機能ごとにファイルを分離 #

  • mutations/ ディレクトリに、Mutation ごとにファイルを分割
  • queries/ ディレクトリに、Query ごとにファイルを分割
  • 各ファイル内に関連する InputType / ObjectType も同時に定義

◆ ChatGPT に相談するとき:該当処理を 1 ファイルにまとめる #

  • types.py のような型共通ファイルは使わず、Mutation と Type をその場にまとめて貼る
  • 関連する型定義を明示的に含めることで、AI が完全に理解しやすくなる

【ディレクトリ構成例】 #

graphql_schema/
├── __init__.py
├── schema.py              # Schema(query=..., mutation=...) の統合定義
├── utils.py               # 共通処理(put_item, DynamoDB処理など)
├── mutations/
│   ├── __init__.py        # Mutation統合クラス
│   ├── order.py           # placeOrder + 型定義
│   ├── reservation.py     # reservation + 型定義
│   └── ...
├── queries/
│   ├── __init__.py        # Query統合クラス
│   ├── status.py          # hello やステータス系のクエリ
│   └── ...

【Mutation / Query のベストプラクティス】 #

◆ Mutation ファイルの例(mutations/order.py#

from graphene import Mutation, String, Int, List, InputObjectType, ObjectType
from graphql_schema.utils import put_item, get_japanese_current_time
from boto3.dynamodb.types import TypeSerializer
import uuid

# --- InputType ---
class OrderItemInput(InputObjectType):
    itemId = String(required=True)
    name = String(required=True)
    quantity = Int(required=True)
    price = Int()

class OrderInput(InputObjectType):
    tableId = String(required=True)
    printerMAC = String(required=True)
    items = List(OrderItemInput, required=True)

# --- OutputType ---
class OrderResponse(ObjectType):
    jobToken = String()
    status = String()
    timestamp = String()

# --- Mutation定義 ---
class PlaceOrder(Mutation):
    class Arguments:
        orderInput = OrderInput(required=True)
    Output = OrderResponse

    def mutate(self, info, orderInput):
        serializer = TypeSerializer()
        job_data = {
            "printerMAC": serializer.serialize(orderInput["printerMAC"])["S"],
            "tableId": serializer.serialize(orderInput["tableId"])["S"],
            "items": serializer.serialize(orderInput["items"])["L"],
        }
        job_token = str(uuid.uuid4())
        put_item(
            printerMac=orderInput["printerMAC"],
            jobToken=job_token,
            mediaTypes=["application/vnd.star.starprnt"],
            jobBody=job_data,
            printType="Order"
        )
        return OrderResponse(
            jobToken=job_token,
            status="confirmed",
            timestamp=get_japanese_current_time()
        )

◆ Query ファイルの例(queries/status.py#

from graphene import ObjectType, String

class StatusQuery(ObjectType):
    hello = String(default_value="Hello from print system")

◆ 統合ファイル(mutations/init.py) #

from graphene import ObjectType
from .order import PlaceOrder
from .reservation import Reservation
# ... 他のMutation

class Mutation(ObjectType):
    placeOrder = PlaceOrder.Field()
    reservation = Reservation.Field()

◆ 統合ファイル(queries/init.py) #

from graphene import ObjectType
from .status import StatusQuery
# ... 他のQuery

class Query(StatusQuery, ObjectType):
    pass

【ChatGPT に相談するときの Tips】 #

◆ その Mutation/Query に関する型・処理を1 ファイルで渡す #

class OrderInput(InputObjectType):
    ...

class PlaceOrder(Mutation):
    ...

class Mutation(ObjectType):
    placeOrder = PlaceOrder.Field()

schema = Schema(mutation=Mutation)

◆ “types.py"などの共通化は ChatGPT には不搬所 #

  • ChatGPT は"その場に書かれていない型"の内容は文脈から類推するしかない
  • 型定義を明示的に書いた方が確実

【まとめ】 #

  • 本番コードでは機能単位でファイルを分割して保守性を高める
  • ChatGPT に相談する際は、対象の Mutation や Query に関する型・処理を 1 ファイルにまとめて提示する
  • この設計方針なら、開発効率と AI 活用の両方で最適化が可能