Slide 1

Slide 1 text

2024-05-25 PyCon Kyusyu 2024 株式会社ZOZO
 ブランドソリューション開発本部 ZOZOMO部 FBZブロック
 杉田 尚弥 Copyright © ZOZO, Inc. 1 静的解析ツールの 刷新に向けた取り組み

Slide 2

Slide 2 text

© ZOZO, Inc. 株式会社ZOZO ブランドソリューション開発本部 ZOZOMO部 FBZブロック 🏢:2019年 株式会社アラタナに新卒入社   2020年 M&Aに伴い入社   現在はFulfillment by ZOZO(以降、FBZ)の開発・保守に従事 🛠:AWS / DevOps / Python / Go 👍:サウナ / 旅行 / アニメ鑑賞 杉田 尚弥 2

Slide 3

Slide 3 text

© ZOZO, Inc. https://zozo.jp/ 3 ● ファッションEC ● 1,500以上のショップ、9,000以上のブランドの取り扱い ● 常時102万点以上の商品アイテム数と毎日平均2,900点以上の新 着 商品を掲載(2024年3月末時点) ● ブランド古着のファッションゾーン「ZOZOUSED」や コスメ専門モール「ZOZOCOSME」、靴の専門モール 「ZOZOSHOES」、ラグジュアリー&デザイナーズゾーン 「ZOZOVILLA」を展開 ● 即日配送サービス ● ギフトラッピングサービス ● ツケ払い など

Slide 4

Slide 4 text

© ZOZO, Inc. 4 https://fbz.zozo.com/ ● ZOZOTOWN出店企業の自社ECのフルフィルメント支援サービス ● 自社EC運営のための撮影・採寸・梱包・配送などの各種フルフィルメント 業務を、ZOZOの物流拠点「ZOZOBASE」が受託 ● 設備投資・人件費・在庫保管料などの負担なしで、自社ECの運営が可能 ● 各販売チャネル(自社EC・店舗・ZOZOTOWN)の在庫連携が可能。 これにより、商品欠品による販売機会の損失を最小化

Slide 5

Slide 5 text

© ZOZO, Inc. ZOZOTOWNと自社ECの在庫を一元化 5 FBZ APIのサービス概要
 5 
 
 
 
 
 
 
 
 ZOZOBASE
 (物流拠点)
 自社カート
 システム
 FBZ API
 商品在庫データ連携 データ連携 ZOZO
 TOWN
 出荷 入荷

Slide 6

Slide 6 text

© ZOZO, Inc. 6 FBZ APIの技術構成
 


Slide 7

Slide 7 text

© ZOZO, Inc. 7 ● なぜ静的解析を行っているのか ● FBZにおける静的解析の仕組みが抱えていた課題 ● 課題に向けた取り組みと結果 ● まとめ 󰢏 今日話すこと

Slide 8

Slide 8 text

© ZOZO, Inc. ● なぜ静的解析を行っているのか ● FBZにおける静的解析の仕組みが抱えていた課題 ● 課題に向けた取り組みと結果 ● まとめ 8 今日話すこと

Slide 9

Slide 9 text

© ZOZO, Inc. 9 ● コード品質の向上・維持 ○ コーディング規約の遵守 ■ コードスタイルを統一できる ■ 可読性の向上 ○ バグや脆弱性の早期発見 ■ セキュリティ的に脆弱となりえるコードを指摘 ● 本来やりたいことに集中できる ○ 細かなコードの書き方に迷わなくなる ○ レビューの効率化 ■ コードの書き方や誤字脱字など指摘をせずに済む なぜ静的解析を行うのか

Slide 10

Slide 10 text

© ZOZO, Inc. 静的解析ツールや仕組み化によって、 開発・保守をしやすくする 10

Slide 11

Slide 11 text

© ZOZO, Inc. 11 ここまで話したのは あくまで 理想

Slide 12

Slide 12 text

© ZOZO, Inc. 現実 には、 開発・保守に悪影響を及ぼす事態が発生 12

Slide 13

Slide 13 text

© ZOZO, Inc. ● なぜ静的解析を行っているのか ● FBZにおける静的解析の仕組みが抱えていた課題 ● 課題に向けた取り組みと結果 ● まとめ 13 今日話すこと

Slide 14

Slide 14 text

© ZOZO, Inc. 1. 検査観点やルールを管理するための設定ファイルの管理が大変に 2. アプリケーションコードに対する静的解析の待ち時間が増えてきた 3. 静的解析が適用されていないコードが存在した 14 抱えていた課題

Slide 15

Slide 15 text

© ZOZO, Inc. 15 課題1. 設定ファイルの管理が困難 ツール名 指定可能な設定ファイル isort .isort.cfg, pyproject.toml Flake8 setup.cfg, .flake8, (pyproject.toml) yapf setup.cfg, .style.yapf, pyproject.toml mypy mypy.ini, .mypy.ini, pyproject.toml, setup.cfg, ~/.config/mypy/config ● FBZでは複数の静的解析ツールを利用 ○ ツール毎で設定ファイルが統一できていなかった ○ 一定の前提知識が必要となるため、メンテナンスできる人が限られていた

Slide 16

Slide 16 text

© ZOZO, Inc. 16 課題1. 設定ファイルの管理が困難 ● 共通する設定ファイルもあるが・・・ ○ pyproject.tomlで統一できそう!? ○ FBZで使っていたバージョンでは未サポートのものが多かった ツール名 指定可能な設定ファイル isort .isort.cfg, pyproject.toml Flake8 setup.cfg, .flake8, (pyproject.toml) yapf setup.cfg, .style.yapf, pyproject.toml mypy mypy.ini, .mypy.ini, pyproject.toml, setup.cfg, ~/.config/mypy/config 画像引用元:https://github.com/csachs/pyproject-flake8

Slide 17

Slide 17 text

© ZOZO, Inc. 種別 名前 役割・特徴 Formatter isort importの順番を修正 Linter Flake8 シンタックスチェック 複数の静的解析ツールのラッパー ● PyFlakes・・・・エラー検出 ● pycodestyle・・ PEP8のスタイル規則の一部をチェック ● McCabe・・・・複雑度のチェック 17 課題2. Pythonの静的解析に時間がかかっていた ● いくつかの静的解析ツールを開発初期から導入 ○ コード量に比例して静的解析に時間がかかるようになってきた ○ 以下、ボトルネックになっていた主な静的解析ツール

Slide 18

Slide 18 text

© ZOZO, Inc. 18 課題2. Pythonの静的解析に時間がかかっていた ● 検査対象のコード量 ○ ファイル数:およそ3,000ファイル(内、Pythonは1,800ファイル) ○ コード行数:およそ61万行(内、Pythonは26万行) $ cloc . --vcs=git github.com/AlDanial/cloc v 1.96 T=5.57 s (586.1 files/s, 122123.5 lines/s) ---------------------------------------------------------------------------------- Language files blank comment code ---------------------------------------------------------------------------------- Python 1781 46494 14391 264744 … ---------------------------------------------------------------------------------- SUM: 3265 53412 16833 610065 ----------------------------------------------------------------------------------

Slide 19

Slide 19 text

© ZOZO, Inc. 19 課題2. Pythonの静的解析に時間がかかっていた 各ツールの実行時間 $ time isort --recursive . 4.01s user 2.13s system 70% cpu 8.768 total $ time flake8 . 26.06s user 0.57s system 96% cpu 27.565 total ● 実行毎に最大 30秒 程度 (差分ファイルに適用していたため、実際はもう少し短い) ● 実行している箇所は以下の通り ○ Git hooks pre-commit ○ CI(GitHub Actions)のワークフロー

Slide 20

Slide 20 text

© ZOZO, Inc. ● サービスローンチ後しばらくの間、自動実行する仕組みが整備できていなかった ● 静的解析ツールの実行を開発者自身に委ねていた ○ Makefileに実行する内容は記述されていた ○ 開発者が意識的に実行する必要があった 20 課題3. 静的解析の適用がされていないコードが存在した

Slide 21

Slide 21 text

© ZOZO, Inc. ● なぜ静的解析を行っているのか ● FBZにおける静的解析の仕組みが抱えていた課題 ● 課題に向けた取り組みと結果 ● まとめ 21 今日話すこと

Slide 22

Slide 22 text

© ZOZO, Inc. 1. 検査観点やルールを管理するための設定ファイルの管理が大変 → 他ツールへの移行 2. アプリケーションコードに対する静的解析の待ち時間が増えてきた → 他ツールへの移行 3. 静的解析が適用されていないコードが存在した → エディタの設定の共通化 → 開発プロセスに自動実行する仕組みを入れる 22 対応方針

Slide 23

Slide 23 text

© ZOZO, Inc. 23 1. 検査観点やルールを管理するための設定ファイルの管理が大変 → 他ツールへの移行 2. アプリケーションコードに対する静的解析の待ち時間が増えてきた → 他ツールへの移行 3. 静的解析が適用されていないコードが存在した → エディタの設定の共通化 → 開発プロセスに自動実行する仕組みを入れる 対応方針

Slide 24

Slide 24 text

© ZOZO, Inc. 24 選ばれたのは「Ruff」でした 画像引用元:https://astral.sh/ruff ● Ruffの概要 ○ Rust製のPython Linter ○ リリースは2022年8月末(現在バージョン0.4.4) ● 選定理由 ○ 高いパフォーマンス ○ ルールが充実している ○ 開発が活発で将来性が見込める

Slide 25

Slide 25 text

© ZOZO, Inc. 25 Ruffの特徴 引用元:https://docs.astral.sh/ruff

Slide 26

Slide 26 text

© ZOZO, Inc. 26 Ruffの特徴 引用元:https://docs.astral.sh/ruff 求めていた内容が 網羅されている!

Slide 27

Slide 27 text

© ZOZO, Inc. ● インストールは各種方法をサポート ○ pip ○ brew ○ ...etc ● 適用するルールを指定 ○ 開発しながら徐々に調整でも可 ○ 移行を支援するツールも存在 27 # for pip $ pip install ruff # for macOS Homebrew $ brew install ruff Ruffのセットアップ [tool.ruff] exclude = ["node_modules", "venv"] target-version = "py39" [tool.ruff.lint] select = ["E4", "E7", "E9", "F"] [tool.ruff.format] quote-style = "double" 引用元:https://docs.astral.sh/ruff/installation/

Slide 28

Slide 28 text

© ZOZO, Inc. 28 $ pip install flake8-to-ruff Ruffのセットアップ(Flake8の移行) $ flake8-to-ruff path/to/setup.cfg $ flake8-to-ruff path/to/tox.ini $ flake8-to-ruff path/to/.flake8 ● Flake8の設定をpyproject.tomlに変換するツール ○ flake8-to-ruff ● 移行前に使っていた設定ファイルのパスを指定 ○ setup.cfg ○ tox.ini ○ .flake8 引用元:https://pypi.org/project/flake8-to-ruff/

Slide 29

Slide 29 text

© ZOZO, Inc. 29 設定ファイルをpyproject.tomlに一元化 [tool.ruff] [tool.ruff.isort] [tool.ruff.flake8-quotes] [tool.mypy] [tool.black] ● 既存ルールからそのまま移行できた ○ flake8 ○ isort ○ mypy ○ black ● その他、Python関連のツールの設定も移行 ○ pytest ○ OpenAPIのモデル生成 ○ ...etc [tool.pytest.ini_options] [tool.datamodel-codegen] (基本的に)このファイルを確認すれば各種設定が分かるように!

Slide 30

Slide 30 text

© ZOZO, Inc. 30 圧倒的なパフォーマンス ● 公式によるベンチマークを抜粋 ○ Lint・Formatterともに他ツールと比較して10〜100倍高速 画像引用元:https://astral.sh/ruff

Slide 31

Slide 31 text

© ZOZO, Inc. 31 待ち時間がかかっていたのは過去の話 $ time ruff --fix . 1.21s user 0.41s system 106% cpu 1.519 total ● FBZのコードで試した結果 ○ 36秒 → 1.5秒 ● 開発中の待ち時間が減った ○ 開発に集中できるようになった $ time isort --recursive . 4.01s user 2.13s system 70% cpu 8.768 total $ time flake8 . 26.06s user 0.57s system 96% cpu 27.565 total 20倍以上の高速化を実現

Slide 32

Slide 32 text

© ZOZO, Inc. 32 対応方針 1. 検査観点やルールを管理するための設定ファイルの管理が大変 → 他ツールへの移行 2. アプリケーションコードに対する静的解析の待ち時間が増えてきた → 他ツールへの移行 3. 静的解析が適用されていないコードが存在した → エディタの設定を共通化 → 開発プロセスに自動実行する仕組みを入れる

Slide 33

Slide 33 text

© ZOZO, Inc. 33 エディタの設定を共通化 // .vscode/extensions.json { "recommendations": [ "ms-python.python", "ms-python.black-formatter", "charliermarsh.ruff", "ms-python.mypy-type-checker" ] } // .vscode/settings.json { "[python]": { "editor.defaultFormatter": "charliermarsh.ruff", "editor.codeActionsOnSave": { "source.fixAll.ruff": "explicit", "source.organizeImports.ruff": "explicit" }, "editor.formatOnSave": true }, "ruff.path": [ "${workspaceFolder}/.venv/bin/ruff" ], } ● Visual Studio Codeの場合 ○ 設定と拡張機能の管理ファイルを作成 ○ commit対象に含めることで、チーム内で共有できる

Slide 34

Slide 34 text

© ZOZO, Inc. 34 開発プロセスに自動実行する仕組みを入れる(pre-commit) ● pre-commit ○ Gitのpre-commitフックスクリプトを管理するフレームワーク ○ Python製(Python以外のプロダクトでも導入可) ○ 実行するスクリプトを自作することも可能 画像引用元:https://pre-commit.com/

Slide 35

Slide 35 text

© ZOZO, Inc. 35 pre-commitの定義 repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: - id: check-toml - id: check-yaml - id: detect-private-key - id: detect-aws-credentials - repo: https://github.com/charliermarsh/ruff-pre-commit rev: v0.0.262 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix, --config, pyproject.toml] - repo: https://github.com/crate-ci/typos rev: v1.16.11 hooks: - id: typos

Slide 36

Slide 36 text

© ZOZO, Inc. 36 開発プロセスに自動実行する仕組みを入れる(CI) ● GitHub Actions ○ 静的解析ツールをはじめとしたチェックを行う ○ ツールに指摘された場合はマージできないようにすると安心 name: Lint Check on: pull_request: paths: - '**/*.py' jobs: run-lint: runs-on: ubuntu-latest name: Lint steps: # 各種セットアップ・インストール # ... - name: Run Ruff run: | ruff --fix . --output-format=github

Slide 37

Slide 37 text

© ZOZO, Inc. ● Ruffを導入した結果 ○ アプリケーションコードに対する静的解析の時間が20倍高速化 ■ 開発中の待ち時間が激減して開発体験が良くなった ○ 乱立していた設定ファイルを集約できた ■ 認知負荷が軽減された ● ツールのインストールだけで終わらない ○ 開発プロセスへ組み込むまでがワンセット ■ Git hookやCI、エディタの統合など ■ 実行時間と相談して実行させるツールとタイミングは調整する 37 まとめ

Slide 38

Slide 38 text

No content