main ui core system utils チャット自動送信ツールのファイルを5つに分割した(ChatSpooler)

はじめに

AIチャットでの複数質問を効率化するツールを作りました。最初は1つのファイルに800行以上のコードが詰まった状態でしたが、最終的には5つのファイルに分割し、プリンタースプーラー1のような自動送信機能を実装しました。この開発過程で得られた知見を共有します。

巨大ファイルの問題点

最初のコードは、WindowManagerクラス、AutoChatSenderクラス、UI処理がすべて1つのファイルに混在していました。機能追加や修正のたびに、どこに何があるのかを探すのに時間がかかります。特に問題だったのは、影響範囲が見えにくいことでした。

例えば、送信処理を修正すると、UI更新処理やエラーハンドリングにも影響が及ぶ可能性があります。これでは、小さな変更でも大きなリスクを伴います。

5つのファイルへの分割戦略

コードを以下の5つのファイルに分割しました。

auto_chat_sender/
├── main.py      # アプリケーション起動(約120行)
├── ui.py        # ユーザーインターフェース(約400行)
├── core.py      # コアビジネスロジック(約300行)
├── system.py    # システム・OS関連処理(約200行)
├── utils.py     # 共通ユーティリティ(約200行)
└── requirements.txtCode language: PHP (php)
  • main.pyはアプリケーションの起動点です。Pythonバージョンのチェック、プラットフォームの確認、依存関係の検証を行います。エラーが起きた場合の最上位での処理も担当します。約120行の簡潔なファイルになりました。
  • ui.pyにはユーザーインターフェースの全てを配置しました。ウィンドウの作成、ボタンの配置、イベントハンドリング2など、画面に関わる処理をまとめています。約500行と最も大きなファイルですが、UI関連の処理だけに集中しているため理解しやすくなっています。
  • core.pyはビジネスロジックの中核部分です。キューの管理、履歴の保存、送信制御といった、アプリケーションの本質的な機能を実装しています。約350行で、UIから独立した純粋な処理ロジックを含みます。
  • system.pyにはmacOS固有の処理をまとめました。AppleScript3の実行、ウィンドウ管理、アプリケーション制御など、システムと密接に関わる部分です。約250行で、OS依存の処理を一箇所に集約しています。
  • utils.pyは共通で使用するユーティリティ関数の集合です。設定管理、ログ処理、テキスト整形など、他のファイルから頻繁に呼び出される機能を配置しています。約300行で、依存関係の最下位に位置します。

依存関係の設計

ファイル間の依存関係は階層構造になっています。main.pyはui.pyのみをインポートし、ui.pyはcore.pyとutils.pyを、core.pyはsystem.pyとutils.pyを、system.pyはutils.pyのみを参照します。utils.pyは他のファイルに依存しません。

この構造により、変更の影響範囲が明確になります。utils.pyを修正すると全体に影響しますが、system.pyの変更はcore.py以上のレイヤーにのみ影響します。循環参照4も発生しません。

プリンタースプーラー機能の実装

最も重要な機能追加は、プリンターのような自動送信機能です。キューにアイテムが追加されると、自動的に送信処理が開始されます。

従来は「キューに追加」→「送信開始ボタンをクリック」という2段階の操作が必要でした。自動送信機能により、文章をキューに追加するだけで送信が始まります。まさにプリンターに印刷ジョブを送るような感覚です。

自動送信の条件は4つです。自動送信モードがON、現在送信中でない、キューが空でない、送信先が設定済み。これらがすべて満たされると、自動的に送信処理が開始されます。

UI設計の大幅な見直し

ユーザーインターフェースも大きく改善しました。最初のバージョンでは、アプリ一覧の更新ボタン、選択アプリを送信先に設定するボタンなど、多くのボタンが存在していました。

改善版では、コンボボックスをクリックすると自動でアプリ一覧が更新され、アプリを選択すると自動で送信先に設定されます。ボタンの数を減らし、操作ステップを削減しました。

レイアウトも調整しています。送信先設定エリアの幅を狭くし、送信設定・ステータスエリアを2倍の幅に拡張しました。情報量の多い部分により多くのスペースを割り当てています。

テーマ対応の大幅な簡素化

当初は、macOSのダークモード検出のためにAppleScriptを実行し、ライトモードとダークモードで異なる色を適用していました。しかし、この処理が重く、文章入力時にアプリケーションが固まる原因になっていました。

解決策は意外にシンプルでした。色指定を完全に削除し、システムのデフォルトカラーを使用するだけです。これにより、ライトモードでは自動的に黒い文字、ダークモードでは自動的に白い文字が表示されます。

重いAppleScript処理が不要になり、パフォーマンスが大幅に向上しました。同時に、システム全体との一貫性も確保されています。

色処理の簡素化により、文章入力時の固まりが完全に解消されました。AppleScriptの実行頻度が大幅に減り、UIの応答性が向上しています。

設定の永続化機能

使い勝手を向上させるため、設定を自動保存する機能を追加しました。送信先アプリ、送信方法、待機時間、自動送信モードの状態、ウィンドウのサイズと位置がJSON形式5で保存されます。

設定ファイルは実行ファイルと同じフォルダに「auto_chat_sender_settings.json」として作成されます。アプリを再起動すると、前回の設定が自動的に復元されます。

設定の保存は、変更と同時に自動実行されます。アプリを選択した瞬間、送信方法を変更した瞬間、待機時間を調整した瞬間に設定ファイルが更新されます。保存し忘れの心配はありません。

エラーハンドリングの強化

分割により、エラーハンドリングも系統立てて実装できました。main.pyでは起動時のチェックとグローバル例外処理、各モジュールでは専門的なエラー処理を行います。

例えば、system.pyではAppleScript実行の失敗、アプリ取得の失敗を処理します。core.pyでは送信処理の失敗、キュー操作の失敗を処理します。エラーの種類に応じて、適切な場所で対処できます。

コード保守性の向上

ファイル分割の最大の効果は、保守性の向上です。バグ修正時には、該当する機能のファイルだけを確認すれば済みます。新機能の追加時も、どのファイルに書くべきかが明確です。

例えば、新しい送信方式を追加したい場合はsystem.py、UI要素を追加したい場合はui.py、データ処理を変更したい場合はcore.pyを編集します。影響範囲が限定されるため、安全に変更を行えます。

まとめ

800行の単一ファイルを5つのファイルに分割し、プリンタースプーラー機能と設定永続化を実装した結果、保守性・パフォーマンス・使いやすさのすべてが向上しました。モジュール分割による責任分離、自動送信機能による操作ステップ削減、システムデフォルトカラーによる軽量化、JSON設定ファイルによる状態永続化が主要な改善点です。

  1. プリンタースプーラーとは、印刷ジョブを一時的に保存し、順次処理するシステムのことです。複数の印刷要求を効率的に管理し、CPUの処理能力を向上させます。 – スプーリング
  2. イベントハンドリングとは、ユーザーのクリックやキー入力などの操作に対する処理のことです。tkinterではbind()メソッドで実装します。 – イベント駆動GUI: PythonとtkinterによるGUIプログラミング入門
  3. AppleScriptは、macOSでアプリケーション間の自動化を行うためのスクリプト言語です。システム全体で統合されており、外部アプリの制御や操作の自動化が可能です。 – AppleScriptでMacの作業を自動化する
  4. 循環参照とは、モジュールAがモジュールBを、モジュールBがモジュールAを参照する状態のことです。これが発生するとインポートエラーや予期しない動作の原因となります。 – Pythonの循環インポート:回避方法
  5. JSON(JavaScript Object Notation)は、データ交換のための軽量なテキスト形式です。人間が読みやすく、多くのプログラミング言語でサポートされています。 – JSON入門!基本フォーマットからファイルの作り方まで解説