やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

GitHubアップローダをリファクタリングした

ソースコードが混沌としてきたから整理した。

成果物

GitHubGitHub.Upload.ByPython.Refactoring.201703101718

開発環境

前回まで

http://ytyaru.hatenablog.com/entry/2017/07/28/000000
http://ytyaru.hatenablog.com/entry/2017/07/29/000000
http://ytyaru.hatenablog.com/entry/2017/08/06/000000

今回

以下、前回までのコードのリファクタリングについて考えてみたログ。

ファイル

ファイル 説明
call.bash リポジトリ側に配置する。アップローダ呼出用スクリプト
up.py DBパスを動的に作成する。Main.pyを呼び出す。
Main.py アップローダCUI対話を実装する。
Data.py DB, 引数, キー値の取得を実装する。
Command.py gitコマンド、DB操作、WebAPIリクエスト、json操作を実装する。
Aggregate.py 集計を実装する。

Data.py

疑問

ほぼ引数値をそのまま返している。不要では?

解答

将来iniファイルなどデータまわりの事情が変化した時のラッパとして使いたい。どうなるか不透明なので今はこのままでいく。

Command.pyとAggregate.py

疑問

アプリケーションの機能を「コマンド」というのなら、Aggregateもコマンドの1つのはず。なぜAggregateだけ別ファイルなのか。

解答

おかしい。しかし、他のコマンドはすべてリポジトリ操作だが、Aggregateは違う。区別したいことは確か。

そこで、区別について考えてみる。

A. リポジトリ操作

  • CreateRepository()
  • ListupCommitTargetFiles()
    • git add -n .でcommit対象一覧表示
  • Add&Commit&Push()
    • git add .でステージングする
    • git commitでコミットする
    • git pushなどでプッシュする
  • DeleteRepository()
  • EditRepository()

B. リポジトリのIssue操作

未実装。

C. 集計

  • Show()
    • DBからデータを取得して集計し表示する

名前をつけてみる

  • Command.Repository
    • Create()
    • Delete()
    • Edit()
    • AddCommitPush()
    • ShowCommitFiles()
    • ShowDeleteRecords()
  • Command.Issue
    • Create()
    • Delete()
    • Edit()
  • Command.Aggregate
    • Show()

実装ファイルを分けたい

Command.Repository.Deleteなど機能毎に別クラス別ファイルにしたい。

Python的には1ファイル(モジュール)に複数classを入れるべきなのかもしれない。しかし、個人的には見づらくなるので嫌い。C#Javaのように1ファイル1classが好き。責任を明確に分離できる感がいい。読まねばならない部分を絞り込める。

  • Command.Repository
    • Creator
      • Create()
    • Deleter
      • Delete()
      • ShowDeleteRecords()
    • Editer
      • Edit()
    • Commiter
      • AddCommitPush()
      • ShowCommitFiles()

ファイル構成

  • src
    • Main.py
    • Data.py
    • Repository.py
    • Aggregate.py
    • Issue.py
    • command/
      • repository/
        • Creator.py
        • Deleter.py
        • Editer.py
        • Commiter.py
      • issue/
      • aggregate/
        • console/
          • Total.py
          • Today.py
          • Week.py
          • Month.py
          • Year.py
        • html/
          • some.py

repository/以外は未定なので適当。

import

Main.py

import Repository
import Aggregate

repo = Repository.Repository()
agg = Aggregate.Aggregate()

repo.Create()

Repository.py

import command.repository.Creator
import command.repository.Commiter
import command.repository.Deleter
import command.repository.Editor

creator = command.repository.Creator.Creator()

def Create():
    creator.Create()

Repository.pyは必要か?直接Main.pyから呼び出したほうが早い気もする。

たぶん以下でも同様。

from command.repository import Creator
from command.repository import Commiter
from command.repository import Deleter
from command.repository import Editor

creator = Creator.Creator()

def Create():
    creator.Create()

Pythonのimportは本当に面倒。package, module, classという概念に加え、import文の煩雑さが嫌。moduleのせいでCreator.Creator()が冗長に思える。1ファイル(module)1classの場合はすべてこうなってしまう。

だからといって以下のようにmoduleを省略すると、class名が重複してしまうリスクが高まる。たとえば他者が作ったライブラリと併用している場合、気づかぬうちにバッティングするとう事故も起こりうる。

from command.repository import *

所感

リファクタリングできてすっきりした。将来の機能拡張も実装しやすい状態になった。