🧐
python アプリケーション開発中、 git submodule で取り込んだパッケージ内の依存解決に躓いた
問題
- 複数のアプリケーションで共通のビジネスルールを利用したい
- ビジネスルールを公開したくはない
- 個人開発なのでチーム開発ほどのコストをかけたくない
- pythonのアプリケーションである
- どうするか?
対応
共通のビジネスルールを切り出す。
それを単一のprivate repositoryとして管理する。
このrepositoryをsubmoduleとして取り込む。
取り込むことは簡単にできた。
だが、取り込んだパッケージの作りが悪く、そのまま使うことができなかった。
具体的には、取り込んだパッケージ内での依存解決ができない状態になった。
共通ビジネスルールパッケージのディレクトリ構造は下記のようになっていた。
├─domains
│ ├─bar
│ └─foo
また、fooはbarに依存している。
下記の類の依存がある。
# domains/bar/domain.py
class Domain:
def __init__(self, prefix: str):
self.__prefix = prefix
def dummy(self) -> str:
return "{}: bar".format(self.__prefix)
# domains/foo/domain.py
from domains.bar.domain import Domain as Bar
class Domain:
def __init__(self, bar: Bar):
self.__bar = bar
def dummy(self):
print("foo, {}".format(self.__bar.dummy()))
あるアプリケーションでgit submoduleを使ってパッケージを取り込んだところ、下記の構造になった。
├─py_hoge_domain
│ └─domains
│ ├─bar
│ └─foo
py_hoge_domainは、共通ビジネスルールのパッケージ名。
この状態で下記を実行すると、エラーになる。
if __name__ == '__main__':
from py_hoge_domain.domains.bar.domain import Domain as Bar
from py_hoge_domain.domains.foo.domain import Domain as Foo
Foo(Bar("sandbox")).dummy()
ModuleNotFoundError: No module named 'domains'
なので、相対パスでimportする形に変更した。
from ..bar.domain import Domain as Bar
上の Foo(Bar("sandbox")).dummy()
を実行したところ、
foo, sandbox: bar
と、期待通りの出力が出た。
問題は解消された。
但し、pycharmでは警告が出ている。
domains下に __init__.py
を配置すると警告が解消した。
余談
- ビジネスルールといっても、現状稼いでいる処理ではない
- monorepoを検討したが、その保守にかかるコストに見合わない気がした
-
git+ssh
でパッケージとして取り込むことを試したが、requirementsに含めることができなさそうなので選択しなかった- requirementsに含められないと保守コストが上がるので
- しばらく触らない期間があった場合に思い出すコストが比較的かかりそう
- 参考
- requirementsに含められないと保守コストが上がるので
- 何となくbestな解決策ではない気もする。他の良い方法があるかもしれない
- 現状捉えられている問題
- 相対パスでのimportだと理解容易性が悪くなるというデメリットがある
- 現状捉えられている問題
Discussion