Upgrade to Pro — share decks privately, control downloads, hide ads and more …

静的解析ツールの刷新に向けた取り組み

 静的解析ツールの刷新に向けた取り組み

naoya_s

May 26, 2024
Tweet

More Decks by naoya_s

Other Decks in Technology

Transcript

  1. © ZOZO, Inc. 株式会社ZOZO ブランドソリューション開発本部 ZOZOMO部 FBZブロック 🏢:2019年 株式会社アラタナに新卒入社   2020年

    M&Aに伴い入社   現在はFulfillment by ZOZO(以降、FBZ)の開発・保守に従事 🛠:AWS / DevOps / Python / Go 👍:サウナ / 旅行 / アニメ鑑賞 杉田 尚弥 2
  2. © ZOZO, Inc. https://zozo.jp/ 3 • ファッションEC • 1,500以上のショップ、9,000以上のブランドの取り扱い •

    常時102万点以上の商品アイテム数と毎日平均2,900点以上の新 着 商品を掲載(2024年3月末時点) • ブランド古着のファッションゾーン「ZOZOUSED」や コスメ専門モール「ZOZOCOSME」、靴の専門モール 「ZOZOSHOES」、ラグジュアリー&デザイナーズゾーン 「ZOZOVILLA」を展開 • 即日配送サービス • ギフトラッピングサービス • ツケ払い など
  3. © ZOZO, Inc. 4 https://fbz.zozo.com/ • ZOZOTOWN出店企業の自社ECのフルフィルメント支援サービス • 自社EC運営のための撮影・採寸・梱包・配送などの各種フルフィルメント 業務を、ZOZOの物流拠点「ZOZOBASE」が受託

    • 設備投資・人件費・在庫保管料などの負担なしで、自社ECの運営が可能 • 各販売チャネル(自社EC・店舗・ZOZOTOWN)の在庫連携が可能。 これにより、商品欠品による販売機会の損失を最小化
  4. © ZOZO, Inc. ZOZOTOWNと自社ECの在庫を一元化 5 FBZ APIのサービス概要
 5 
 


    
 
 
 
 
 
 ZOZOBASE
 (物流拠点)
 自社カート
 システム
 FBZ API
 商品在庫データ連携 データ連携 ZOZO
 TOWN
 出荷 入荷
  5. © ZOZO, Inc. 9 • コード品質の向上・維持 ◦ コーディング規約の遵守 ▪ コードスタイルを統一できる

    ▪ 可読性の向上 ◦ バグや脆弱性の早期発見 ▪ セキュリティ的に脆弱となりえるコードを指摘 • 本来やりたいことに集中できる ◦ 細かなコードの書き方に迷わなくなる ◦ レビューの効率化 ▪ コードの書き方や誤字脱字など指摘をせずに済む なぜ静的解析を行うのか
  6. © 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では複数の静的解析ツールを利用 ◦ ツール毎で設定ファイルが統一できていなかった ◦ 一定の前提知識が必要となるため、メンテナンスできる人が限られていた
  7. © 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
  8. © ZOZO, Inc. 種別 名前 役割・特徴 Formatter isort importの順番を修正 Linter

    Flake8 シンタックスチェック 複数の静的解析ツールのラッパー • PyFlakes・・・・エラー検出 • pycodestyle・・ PEP8のスタイル規則の一部をチェック • McCabe・・・・複雑度のチェック 17 課題2. Pythonの静的解析に時間がかかっていた • いくつかの静的解析ツールを開発初期から導入 ◦ コード量に比例して静的解析に時間がかかるようになってきた ◦ 以下、ボトルネックになっていた主な静的解析ツール
  9. © 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 ----------------------------------------------------------------------------------
  10. © 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)のワークフロー
  11. © ZOZO, Inc. 1. 検査観点やルールを管理するための設定ファイルの管理が大変 → 他ツールへの移行 2. アプリケーションコードに対する静的解析の待ち時間が増えてきた →

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

    → 他ツールへの移行 3. 静的解析が適用されていないコードが存在した → エディタの設定の共通化 → 開発プロセスに自動実行する仕組みを入れる 対応方針
  13. © ZOZO, Inc. 24 選ばれたのは「Ruff」でした 画像引用元:https://astral.sh/ruff • Ruffの概要 ◦ Rust製のPython

    Linter ◦ リリースは2022年8月末(現在バージョン0.4.4) • 選定理由 ◦ 高いパフォーマンス ◦ ルールが充実している ◦ 開発が活発で将来性が見込める
  14. © 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/
  15. © 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/
  16. © 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] (基本的に)このファイルを確認すれば各種設定が分かるように!
  17. © 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倍以上の高速化を実現
  18. © ZOZO, Inc. 32 対応方針 1. 検査観点やルールを管理するための設定ファイルの管理が大変 → 他ツールへの移行 2.

    アプリケーションコードに対する静的解析の待ち時間が増えてきた → 他ツールへの移行 3. 静的解析が適用されていないコードが存在した → エディタの設定を共通化 → 開発プロセスに自動実行する仕組みを入れる
  19. © 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対象に含めることで、チーム内で共有できる
  20. © ZOZO, Inc. 34 開発プロセスに自動実行する仕組みを入れる(pre-commit) • pre-commit ◦ Gitのpre-commitフックスクリプトを管理するフレームワーク ◦

    Python製(Python以外のプロダクトでも導入可) ◦ 実行するスクリプトを自作することも可能 画像引用元:https://pre-commit.com/
  21. © 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
  22. © 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
  23. © ZOZO, Inc. • Ruffを導入した結果 ◦ アプリケーションコードに対する静的解析の時間が20倍高速化 ▪ 開発中の待ち時間が激減して開発体験が良くなった ◦

    乱立していた設定ファイルを集約できた ▪ 認知負荷が軽減された • ツールのインストールだけで終わらない ◦ 開発プロセスへ組み込むまでがワンセット ▪ Git hookやCI、エディタの統合など ▪ 実行時間と相談して実行させるツールとタイミングは調整する 37 まとめ