diff --git a/.vitepress/config.mjs b/.vitepress/config.mjs index 30901a80..70762c32 100644 --- a/.vitepress/config.mjs +++ b/.vitepress/config.mjs @@ -66,27 +66,6 @@ const links = { link: "/documents/forGitBranch/git_branch_standards.html", }, ], - "/documents/forMarkdown/": [ - { text: "Introduction", link: "/documents/forMarkdown/" }, - { - text: "Markdown設計ドキュメント規約", - link: "/documents/forMarkdown/markdown_design_document.html", - }, - ], - "/documents/forSlack/": [ - { text: "Introduction", link: "/documents/forSlack/" }, - { - text: "Slack利用ガイドライン", - link: "/documents/forSlack/slack_usage_guidelines.html", - }, - ], - "/documents/forCodeReview/": [ - { text: "Introduction", link: "/documents/forCodeReview/" }, - { - text: "Slack利用ガイドライン", - link: "/documents/forCodeReview/code_review.html", - }, - ], }; /** diff --git a/build-resources-with-pandoc.sh b/build-resources-with-pandoc.sh index 2b431418..8f13920a 100644 --- a/build-resources-with-pandoc.sh +++ b/build-resources-with-pandoc.sh @@ -72,21 +72,3 @@ cd ${ROOT_DIR}/documents/forGitBranch pandoc ./git_branch_standards.md -s --self-contained --number-sections --toc -t html5 -c ${CSS_PATH} -o ${RESOURCES_DIR}/Gitブランチフロー規約.html pandoc ./git_branch_standards.md --toc --reference-doc=${STYLE_DOCX_PATH} -s -o ${RESOURCES_DIR}/Gitブランチフロー規約.docx - -# Markdown -cd ${ROOT_DIR}/documents/forMarkdown - -pandoc ./markdown_design_document.md -s --self-contained --number-sections --toc -t html5 -c ${CSS_PATH} -o ${RESOURCES_DIR}/Markdown設計ドキュメント規約.html -pandoc ./markdown_design_document.md --toc --reference-doc=${STYLE_DOCX_PATH} -s -o ${RESOURCES_DIR}/Markdown設計ドキュメント規約.docx - -# Slack -cd ${ROOT_DIR}/documents/forSlack - -pandoc ./slack_usage_guidelines.md -s --self-contained --number-sections --toc -t html5 -c ${CSS_PATH} -o ${RESOURCES_DIR}/Slack利用ガイドライン.html -pandoc ./slack_usage_guidelines.md --toc --reference-doc=${STYLE_DOCX_PATH} -s -o ${RESOURCES_DIR}/Slack利用ガイドライン.docx - -# コードレビュー -cd ${ROOT_DIR}/documents/forCodeReview - -pandoc ./code_review.md -s --self-contained --number-sections --toc -t html5 -c ${CSS_PATH} -o ${RESOURCES_DIR}/コードレビューガイドライン.html -pandoc ./code_review.md --toc --reference-doc=${STYLE_DOCX_PATH} -s -o ${RESOURCES_DIR}/コードレビューガイドライン.docx diff --git a/documents/forCodeReview/code_review.md b/documents/forCodeReview/code_review.md deleted file mode 100644 index b2aca875..00000000 --- a/documents/forCodeReview/code_review.md +++ /dev/null @@ -1,633 +0,0 @@ ---- -sidebarDepth: 4 -title: コードレビューガイドライン -author: フューチャー株式会社 -head: - - - meta - - name: keywords - content: コードレビュー ---- - - - -本規約は、世の中のシステム開発プロジェクトのために無償で提供致します。 -ただし、掲載内容および利用に際して発生した問題、それに伴う損害については、フューチャー株式会社は一切の責務を負わないものとします。 -また、掲載している情報は予告なく変更することがございますので、あらかじめご了承下さい。 - -# はじめに - -[プログラマが知るべき97のこと](https://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/) の14個目に「コードレビュー」について記述がある。コードレビューの目的は「コードの質を上げ、欠陥を減らすため」だけではなく、「チーム全員に同じ知識を共有させること、またコーディングにおいて全員が守るべきガイドラインを確立すること」が大切だとある。そして「 レビューを楽しいものにすること」がおそらく最も有効だとある。 - -コードレビューを楽しい場にするためにも、レビュアー/レビュイ が同じ方向性を向くことが重要である。同時に、人によってコメントなどの表現が揺れ、それにより認識齟齬があると楽しむ以前の問題であるため、守るべきルールも存在するはずである。このガイドラインは推奨する行動と、守るべきルールの両方を定義し、コードレビューをより有意義で学びが多く、生産性と品質を高める場とすることを目指す。 - -- 参考: [コードレビューとは | GitLab](https://about.gitlab.com/ja-jp/topics/version-control/what-is-code-review/) にも似た旨の記載がある - -# 定義 - -- レビュアー: レビューを行う側の担当者 -- レビュイー: レビューを依頼する側の担当者。プルリクエストを起票する開発者でもある -- プルリクエスト: GitLabではマージリクエストともいうが、本規約ではプルリクエストに統一して呼称する - -# 適用範囲 - -GitHubやGitLabなどのサービスを利用した、コーディングについてのレビューのみを対象とする。 - -プロジェクト計画によっては、開発プロセスを複数の「フェーズ」に分割し、各フェーズの終了時点で「フェーズレビュー」を挟むようなケースも考えられるが、それらは対象外とする。 - -# 免責事項 - -::: warning 有志で作成したドキュメントである - -- フューチャーアーキテクトには多様なプロジェクトが存在し、それぞれの状況に合わせて工夫された開発プロセスや高度な開発支援環境が存在する。本規約はフューチャーアーキテクトの全ての部署/プロジェクトで適用されているわけではなく、有志が観点を持ち寄って新たに整理したものである -- 相容れない部分があればその領域を書き換えて利用することを想定している - -::: - -# 前提条件 - -## 利用するGitブランチ戦略 - -[Gitブランチフロー規約 \> ブランチ戦略の選定](https://future-architect.github.io/coding-standards/documents/forGitBranch/git_branch_standards.html#%E3%83%95%E3%82%99%E3%83%A9%E3%83%B3%E3%83%81%E6%88%A6%E7%95%A5%E3%81%AE%E9%81%B8%E5%AE%9A) にある、以下の2パターンのいずれかを利用しているとする。 - -- `Lite GitLab Flow` -- `GitLab Flow` - -そのため当然であるが、全ての機能開発や不具合修正に、`feature` ブランチを使用したプルリクエストを経由してマージする方針を取る。その他の `feature` ブランチから `develop` ブランチへのマージ方法などもGitブランチフローに記載した推奨事項に則る。 - -## 事前設定(GitHub) - -[Gitブランチフロー規約](https://future-architect.github.io/coding-standards/documents/forGitBranch/git_branch_standards.html#git-config%E6%8E%A8%E5%A5%A8%E8%A8%AD%E5%AE%9A) に則った設定を実施する。例えば、ブランチ保護やレビューの設定には以下の内容がある。できるかぎり自動化やテンプレートを用意することで、個々人が考慮すべきことを減らすことで運用負荷を下げ、規則を形骸化にせず実効性を上げることを基本姿勢とする。 - -| 設定項目 | 設定例 | 説明 | -| :-------------------------------------------------------------------------------------------------------------------------------------------------- | :----- | :---------------------------------------------------------------------------------- | -| Require a pull request before merging | ✔ | プルリクエストを必須とする | -| Require approvals | 1 | 1名以上の承認を必須とする | -| Require status checks to pass before merging | ✔ | CIの成功をマージ条件とする | -| [CODEOWNERS](https://docs.github.com/ja/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) | (省略) | 重要ファイル(例えば、ddl.sqlやopenapi.yamlなど)は承認が必須なレビュアーを指定する | -| [linguist-generated=true](https://docs.github.com/ja/repositories/working-with-files/managing-files/customizing-how-changed-files-appear-on-github) | (省略) | ツールなどによる生成ファイルの差分を非表示にする .gitattributesの設定 | - -## 機械的なチェックが可能な場合はCIに寄せる方針としている - -コードレビューのやり取りで、「コードフォーマットされていない」 「リンターを通していない」といった指摘は不毛である。そのため、CIでそれらを実行し、パスしているという前提条件を作ることが重要である。それにより、レビュアーは人間が本来見るべき点に集中できるためである。 - -例えば、下表のような内容はフォーマッタやリンターに寄せることができる可能性が高い。 - -| 自動化可能だと考えられる指摘例 | ツール例 | -| :----------------------------- | :----------------------------------------------------------------------- | -| 使われていないメソッドや関数 | Pythonの場合、Flake8 など | -| デッドコード | Pythonの場合、Vultureなど | -| デバック用のログの残骸 | JSの場合は、ESLint(console.logの検知など)。 Pythonの場合は、Pylintなど | -| 不適切なレイヤーに対するimport | Pythonの場合、import-linterなど | -| //TODO コメントが残っている | JSでは、eslint-plugin-no-inline-commentsなど | - -## CIによるレビューコメント連携を行う - -Linterなどの検知結果をreviewdogなどと連携することで、形式的な指摘はツール側に寄せる。それにより開発者個人個人のやり取りを減らし、本当に集中すべき事項に時間を割くこととする。 - -## プルリクエストテンプレートでチェックリストを設ける - -プルリクエストにチェックリストを追加し、レビュー依頼前にセルフチェックする運用を採用するチームも多い。チェックリストが多すぎると形骸化するため、項目は具体的にする(例: 設計ドキュメントを同時に直したか?など)とともに、必要最低限の項目に留め、チームの成熟度に応じて適時見直す運用とする。 - -参考: [リポジトリ用のプルリクエストテンプレートの作成 \- GitHub Docs](https://docs.github.com/ja/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository) - -## チームで合意した開発規約が存在し遵守しつつ育てる - -「[Javaコーディング規約](https://future-architect.github.io/coding-standards/documents/forJava/Java%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E8%A6%8F%E7%B4%84.html)」 「[SQLコーディング規約](https://future-architect.github.io/coding-standards/documents/forSQL/SQL%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E8%A6%8F%E7%B4%84%EF%BC%88PostgreSQL%EF%BC%89.html)」 「[AWSインフラ命名規約](https://future-architect.github.io/coding-standards/documents/forAWSResource/AWS%E3%82%A4%E3%83%B3%E3%83%95%E3%83%A9%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E5%91%BD%E5%90%8D%E8%A6%8F%E7%B4%84.html)」 「[OpenAPI Specification 3.0.3規約](https://future-architect.github.io/coding-standards/documents/forOpenAPISpecification/OpenAPI_Specification_3.0.3.html)」など、チームで守るべきと合意形成されたコーディング規約や命名ルールが存在することを前提とする。また、これらに記載された内容をチームで改善し続ける運用とする。 - -# レビュー観点 - -「フォーマッタやリンター」などのツールをCIと組み合わせることで、レビュアーが見るべき領域を減らすことができる。また、「チームで合意された開発規約」をレビュイが遵守できれば、ツールがカバーできない領域に対してもレビュアーの負担減に繋がる。 - -| 大分類 | 中分類 | 小分類 | レビュイーが気にすべきか | レビュアーが見るべきか | -| :--------------- | :----------------- | :--------------------- | :---------------------------------------- | :-------------------------------------------------------------------- | -| 開発規約に記載済 | ツールでカバー可能 | | ⚠️ツール補助あり | 不要 | -| | ツールでカバー不可 | | ✅️規約を準拠しているか確認する必要がある | ✅️規約を準拠しているか確認する必要がある | -| 開発規約に未記載 | 規約に記載可能 | | ⚠️Yesだが、難しい場合が多い | ✅️言語化して開発規約に追加すべき | -| | 規約に記載不可 | 機能要件の充足 | ✅️ | ✅️ | -| | | 文脈依存が強く汎化不可 | ⚠️Yesだが、難しい場合が多い | ✅️個別の命名や、他に類似の実装パターンがない場合は個別に見るしかない | - -レビュー観点は、開発しているプロダクトの性質、開発体制、採用技術で大きく変動するためここで詳細は述べない。 - -基本的には、チームで合意形成された開発規約(参考: [開発アーキテクチャドキュメント](https://jisou-programmer.beproud.jp/%E5%AE%9F%E8%A3%85%E3%81%AE%E9%80%B2%E3%82%81%E6%96%B9/39-%E9%96%8B%E7%99%BA%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88.html))やツール(リンターやフォーマッタ)を充実させる方向に寄せるべきである。以下に、開発規約にはどのような内容を記載すべきかを以下に参考情報としてまとめる。 - -``` -# 開発ガイドライン(例) - -## 仕様確認 - -- 開発の入力情報となる、設計ドキュメント、チケットなどの前提が正しいかどうかの確認は開発者が行う -- もし、入力情報が疑わしい場合は開発者自身が有識者に確認、必要に応じてチケットを起票して、ドキュメント修正を行うか、修正依頼を行う - -## 機能要件 - -フロントエンド: - -- 設計書通りの見た目となっているか確認する -- 必須/任意、Readonlyなど表示仕様は適切か確認する -- 表示項目の編集仕様(時刻など)は他機能と整合性が取れているか確認する - -バックエンド: - -- 環境によって変わる値がハードコードになっていないか - -## 性能観点 - -SQL: -- N+1クエリはなるべく避けるようにする -- アプリケーション側でジョインしてはならない -- SQLの検索条件で、パーティションキーの指定が抜けていないように注意する - -## 可用性 - -- 外部API呼び出し時などでタイムアウトは設定されているか -- 外部API呼び出し時に、リトライ設定は行っているか - -## 可読性 -- [命名規則](https://java-standard.example.com) に従う -- コードコメントは、JavaDoc形式(Markdown)をなるべく使用する - -## ログ -- loggerはxxxを利用すること -- ループ内で大量に呼び出される場合は、debugログであっても性能劣化懸念があるため不可とする - -## テスト - -- カバレッジはCO 90%程度が目安 -- バックエンドについては、デシジョンテーブル(決定表)からテストケースを作成する -``` - -関連: [コードレビューの観点 | google-eng-practices-ja](https://fujiharuka.github.io/google-eng-practices-ja/ja/review/reviewer/looking-for.html) - -# レビュイーの推奨行動 - -## 重要な変更の場合、方向性を事前にレビュアー陣と合意形成しておく - -実装する内容が、設計書に基づく新規機能の改修や、不具合改修でチケットに原因分析や対応方針が明記されている場合は、チーム内で改めて対応方針のすり合わせを行う必要はない。 - -考慮の残がありかつ、すでに稼働済みの機能の挙動変更を行う場合や、原因が特定されていない不具合修正の場合は、以下の内容をチームで合意形成してから実装に入った方が、認識齟齬や手戻りを減らせ、レビュイー/レビュアー双方の負荷を下げることができる - -- (不具合対応の場合) - - 事象 - - 業務影響 - - システム影響 - - 原因分析 - - 対応方針 - - この変更に伴う影響範囲(分割リリースを行うかどうか) -- (既存機能の挙動変更) - - 変更理由(顧客要望)が何か - - 対応方針 - - この変更に伴う影響範囲(分割リリースを行うかどうか) - -::: tip スキーマファイルは事前にレビューしておくと手戻りを防ぎやすい -「WebAPIのスキーマ定義」や「DBスキーマ定義」など、システム構成要素の境界となるようなスキーマファイルの変更は、システムに対する影響度が大きいためレビュアーとしても設計を妥協しにくい。また、これらのファイルに指摘が入ると、ほぼ必然的にアプリケーションコードも修正することになるため、手戻りも大きくなる。これら境界となるようなファイルは先行して、Draftプルリクエストでレビュアーに確認してもらってから作業する工夫は有効である。また、そのような開発ルールにするチームも多い。 -::: - -参考: [Design Doc でチームを跨いだ開発を円滑に行う \- 一休.com Developers Blog](https://user-first.ikyu.co.jp/entry/2024/12/09/143648) - -## プルリクエストの単位を小さくする - -複数の改修内容が単一のプルリクエストに含まれており、変更内容が多い(20ファイル以上などの)場合、レビュアーの負荷が高くなってしまう。コミットを意味のある粒度に保ちつつ細かくするか、プルリクエストの粒度を細かくするかの2通りの対応が考えられる。 - -本規約の推奨は以下。 - -- プルリクエストの単位を小さくする - -::: tip 大きな変更の場合、目的別にプルリクエストを分ける -プルリクエストの粒度を細かくすることで、レビュアーの負荷を下げることができる。例えば、ある機能改修を行う際に、リファクタリングを行ってから作業をおこないたい場合は、リファクタリングのみを行うプルリクエストと、機能追加を行うプルリクエストを分けることがあげられる。なお、ローカル変数の名称を変更すると言った小さな変更は、わざわざプルリクエストを分ける必要はない。 -::: - -## コミットメッセージはこだわらなくても良い - -[commitlint](https://commitlint.js.org/) を適用し、レビュー負荷軽減のためコミットメッセージの統制を図るという考え方も存在する。 - -本規約の推奨は以下。 - -- コミットメッセージは開発者の裁量に任せる - - 「wip」や「リファクタリング」など荒くても良い -- コミットメッセージより、プルリクエストのタイトルに気を配る - -理由は以下。 - -- プルリクエストの単位を小さくする前提であるため、コミットの粒度やメッセージを気にすることによるメリットが小さい -- Gitブランチ規約から、最終的にスカッシュマージするため重要度が下がる - -## プルリクエストのタイトルにプレフィックスを入れる - -プルリクエストのタイトルに命名規則をもたせることで、レビュアーの負荷軽減に繋げることができる。また、履歴からのトラッキングが容易になる。 - -本規約の推奨は以下。 - -- タイトルは `{type}: {subject}` や `{type}: {feature_id}: {subject}` という構成に従う -- type は下表のいずれかを選択し、複数該当する場合はより上位にあるものを選ぶ - -| type | 説明 | -| :------- | :------------------------- | -| feat | 新機能の追加 | -| mod | 機能変更(仕様変更) | -| fix | バグの修正 | -| refactor | リファクタリング | -| docs | ドキュメンテーションの更新 | - -::: tip ラベルとの使い分け -プルリクエストの[ラベル](https://docs.github.com/ja/issues/using-labels-and-milestones-to-track-work/managing-labels)でも同じ意図を持たせることができるが、レビュアーにとっての視認性を重視するため、重複した内容であってもタイトルにプレフィックスを含ませる。 - -関連: [Gitブランチフロー規約 \> ラベル](https://future-architect.github.io/coding-standards/documents/forGitBranch/git_branch_standards.html#%E3%83%A9%E3%83%98%E3%82%99%E3%83%AB%E8%A6%8F%E5%89%87) -::: - -## 差分(diff)を極小化することにこだわりすぎない - -レビュー負荷軽減や、影響度の極小化の観点から、なるべく差分を小さくすることを志向した改修を行うべきか迷う場面がある。 - -本規約の推奨は以下。 - -- あるべき変更を最優先とし、その後でレビュー負荷軽減のため差分を小さくできないか考える - - リファクタリングなど、可読性/保守性を上げる改善は継続する必要がある - - 差分を小さくするために、コードベースの改善活動を止めるのは本末転倒である(良いモノを作るためにコードレビューをしている面がある) -- 必要に応じて、プルリクエストの分割を検討する - -## ファイルの移動やリネームと同時に大きく編集しない - -リファクタリングや構成の整理で、ファイルの移動やリネームを行う場面は多々ある。 - -本規約の推奨は以下。 - -- ファイルの移動やリネームと同時に、ファイル自体を大きく変更しない - - gitの同一ファイル判定が狂い、ファイルの削除+ファイルの新規作成となり、該当ファイルの変更履歴が消える可能性があるため - - レビュアーにとって、新規ファイル扱いになると、本当の差分がどれか画面上は分からず、確認コストが上がってしまうため -- どうしても同一プルリクエストでファイルのリネームと編集を行う必要がある場合は、以下の対応をする - - `git mv` で操作してからファイルを変更する - - ファイルの移動やリネームで、`git commit` し、その後にファイルの変更を行う - -## 作業途中のプルリクエストはDraftにする - -何かしらの理由で、マージされたくない作業途中の状態で、プルリクエストを作成したい場合がある。例えば、作業途中の内容を部分的にメンバーに確認してもらいたい場面や、セルフチェックが完了前に別タスクを行う必要が出た場合などがある。誤ってレビューやマージされたくない - -本規約の推奨は以下。 - -- GitHubにおいて、プルリクエストの[ドラフトステータス](https://docs.github.com/ja/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request)機能を利用して、誤操作を防ぐ - - 誤認識、誤操作による作業を防ぐ - - プルリクエストが滞留している状況で、レビュー待ちなのか作業中なのかが区別して可視化できるようにし、開発状況をマネージャーが把握しやすくするため - -::: tip Draftプルリクエストの早期作成のススメ -作業途中であっても、早期にDraftプルリクエストを作成することで、作業の可視化/透明性に繋げることができる。他にも開発者が作業を再開しやすくなるなどメリットが大きいため、ローカルでの開発作業が完了する前の段階でDraftプルリクエストを利用することを推奨する。 -::: - -## プルリクエスト本文にチケット番号や関連情報を貼る - -トレーサビリティのため、チケット番号(のURL)や、設計検討したドキュメントのリンクや、議論スレッドのURLなどを、チケット本文に記載することで、後からトレース可能にする。チリツモであるがチームの開発生産性を上げることに繋がるため。 - -## チケット番号があるのであれば、プルリクエスト本文に重複記載は不要 - -作業目的(どういった要望/不具合に対する対応か)などは、作業チケットに記載されているのであれば、プルリクエスト本文での記述は不要である。 -なお、サマリ事項だけ転記するなど、詳細な運用ルールは各チームごとに決めて良い。 - -## ローカルでの動作確認ログなど、長くなる場合はMarkdownの折りたたみを利用する - -GitHubでは `
` タグで[折りたたんだセクション](https://docs.github.com/ja/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections)が作成可能である。例えば、単体テストケース化できないような動作確認を行い、かつ動作検証ログをエビデンスとして貼り付けるような場面では、折りたたんだセクションを活用することで、本文を簡潔に保つことができる。 - -::: tip スラッシュコマンドを利用する -[スラッシュコマンド](https://docs.github.com/ja/issues/tracking-your-work-with-issues/using-issues/about-slash-commands)を用いることで、簡単に折りたたみできる詳細領域を挿入できる。入力時に \`/\` を押すとメニューが表示されるため、「Details」を選択する。 -::: - -## 画像をエビデンスとして貼るべきかどうか - -[2023年5月9日のアップデート](https://github.blog/changelog/2023-05-09-more-secure-private-attachments/)で、ライベートリポジトリのプルリクエストなどにアップロードされたファイルの閲覧に、認証が必須となった(それまではURLを知っていれば無認証でアクセスができてしまっていた)。 - -本規約の推奨は以下。 - -- フロントエンドなど画面開発の場合は、作成/修正後の画像(必要に応じてGIF動画)を貼ることを推奨する -- スタックトレースなどは、検索性を考えてテキストで貼ることを推奨する - -なお、GIF動画を作成するには、以下の記事で紹介されているツールの利用者も多い。 - -- [Future社員が使っているWindows便利ツール(新人さん向け) | フューチャー技術ブログ](https://future-architect.github.io/articles/20220107a/#ScreenToGif) - -## Files changedで余計なファイルがコミットされていないか確認する - -ジュニアメンバー/シニアメンバー問わず、特に新規参画した当初は新しい環境に慣れるのに手一杯で、誤った操作をしがちである。よくあるミスに、余分なファイルをコミットに含めてしまうことがある。 - -本規約の推奨は以下。 - -- レビュー依頼前に、プルリクエスト画面の `Files changed` タブを開き、対象のファイルが想定通りか確認する - -このように、 `Files changed` を見ると、ローカルのエディタで見るのとは違ったセルフレビューの効果があるため、レビュアーになった気持ちで変更内容を確認することも推奨する。 - -## Files changedで特に見て欲しいポイントを補足する - -プルリクエストで、特に念入りに確認して欲しいポイントや、リファクタリングなど複数のコミットが混ざり、メインの改修ポイントがわかりにくくなってしまう場合がある。後者はコミットごとにレビューすれば解決するケースもあるが、featureブランチはスカッシュマージするチームでは、必ずしもきれいなコミットを求めないケースも多い。 - -本規約の推奨は以下。 - -- 特に注力してレビューして欲しいポイントがあれば、`Files changed` でセルフコメントを付ける - -::: warning 以下の場合は、セルフコメントは非推奨である。 - -- 意図がわかりにくい実装の補足や、背景情報などは、プルリクエスト上のコメントではなく、設計ドキュメントや、コードコメントに記載する。それにより保守運用性を高めることができる -- 「PJの実装ガイドライン・ルールから敢えて外れる実装を選択している」場合は、コードコメントに記載すべきである - -意図や背景情報をレビュアーに強調したい場合は、コードコメントに対して「実装意図はコードコメントに記載」などセルフコメントすると良い。 - -::: - -## Assigneesは自分を設定する - -プルリクエストのAssigneesは基本的にはレビュイー本人にする。もし、作成したプルリクエストを別の担当者に引き継ぐときは、Assigneesも変更する。これにより、最終的にどの開発者がどのような作業をしたか可視化しやすくなる。 - -Assigneesで指定された人が、そのプルリクエストの責任を持つ。つまり、マージさせるかクローズさせるか最終的に意思決定されるよう、推進する必要がある。 - -## Reviewersはレビュー依頼時はブランクでも良い - -Reviewersに設定することで、レビュアー側が自分がアサインされていることに気が付きやすくするメリットや、後からどれくらいレビューしたか把握しやすくできる。 - -本規約の推奨は以下。 - -- レビュアーが確定している場合は、レビュー依頼時に予め必要な数のReviewersに設定しておく -- チームのだれがレビューするか不明な場合は、ブランクにする(候補者を片っ端からReviewersに設定しない) -- CODEOWNERSで指定したファイルを編集したなどで、自明であればオーナーをReviewersに追加しておく - -## CIの成功を確認する - -ローカルでLinterやテストが通っていると、プルリクエスト作成後、すぐにレビュー依頼を行いたくなる。しかし、何かしらの理由でレビュアーが確認した際にCIによるチェックが失敗している場面もよく見る。 - -本規約の推奨は以下。 - -- レビュー依頼を出す前にCIが通っていることを確認する - -理由は以下。 - -- レビュアーとして、最初のフィードバックは「CIが落ちているので修正して欲しい」となり、余計なやり取りのホップが発生するだけであるため - -## レビュー依頼時にURLを貼る - -プルリクエストのタイトルや、\#511などの番号だけで依頼を出すのではなく、URLをSlackなどチャットに貼ることを推奨する。 - -理由は以下。 - -- 齟齬を生じさせない依頼が可能となる -- 後々、該当のプルリクエストのURLでSlackなどチャット検索が可能とするため - - 前提条件など、Slackのスレッド上で確認しているやり取りの有無を確認したい場面がある - -## レビュー依頼はメンションを飛ばす - -コードレビュー待ちは他作業が捗らないことが多いし、別作業に移ったとしても集中したタイミングでレビューフィードバックがあり、集中が途切れることもしばしばある。 - -本規約の推奨は以下。 - -- チャット上でのレビュー依頼はメンションを飛ばす - - なるべく早くレビューしてもらうことで、待機時間を最小化する - - レビュー可能なタイミングの回答をもらい、別タスクに着手するかの計画に活かす -- メンションは、自チームが必要最小限所属する、Slackでいうユーザーグループを利用することが好ましい - -## Markdown記法を活用する - -Markdown記法を活用することで、Descriptionやレビューコメントを視覚的に整理し、意図を明確に伝えることを推奨します。 - -特に、見出しやコードブロックやリストを使用することで、よりわかりやすいコメントを提供する事ができる。 - -- [基本的な書き方とフォーマットの構文 \- GitHub Docs](https://docs.github.com/ja/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax) - -## マージはレビュイーが実施する - -[Gitブランチフロー規約](https://future-architect.github.io/coding-standards/documents/forGitBranch/git_branch_standards.html#%E3%83%9E%E3%83%BC%E3%82%B7%E3%82%99%E3%81%AF%E3%81%9F%E3%82%99%E3%82%8C%E3%81%8B%E3%82%99%E8%A1%8C%E3%81%86%E3%81%B8%E3%82%99%E3%81%8D%E3%81%8B)で記載された推奨ルールに従う。チームの自律性と生産性を重視するのであれば、レビュイーがマージすべきである。 - -信頼関係が構築できていれば、以下のようなやり取りが可能となり、スピード感が上がるためである。 - -- 「コメントはしたけど承認(Approve)したので、随時対応してマージしてOKです」 -- 「Conflictだけ対応したら、マージしちゃってください」 - -何かしらの理由でレビュアーの関与度を増やす必要がある場合は、レビュアーがマージする。 - -# レビュアーの推奨行動 - -## グラウンドルール - -**レビューはコミュニケーションである。コメント記載時には相手への敬意を忘れないこと。** - -特にレビュアー側はその責務上、指摘コメントを多く行う役割であり、より一層の配慮(上下関係を作らないやりとり)が求められる。 - -レビューは作成者を詰問する場ではなく、より良いものをチーム一丸となって作るという考えが重要である。 - -- 参考: [プルリクエストを見る時、出す時に重要なマインドセット \- NRIネットコムBlog](https://tech.nri-net.com/entry/important_mindset_for_pull_requests) - -## レビュー依頼へのリアクションはできるだけ即レス - -本規約の推奨は以下。 - -- コードレビューの対応優先度を上げる -- もし、利害関係者との会議中など、即座に対応することがが難しい場合は、いつごろ確認するかのコメントを記載したり、代理でレビュー可能な人に依頼する - -理由は以下。 - -- レビュアーが気がついていないのか、気がついているが忙しくて対応できないかで、レビュイーがリマインドを送るかどうかの行動に影響があるため -- レビュイーの作業見積もりに影響するため(レビュイーとして待機すべきか、他の作業を着手すべきか迷ったり、どれくらいで開発作業がクローズできそうかといった作業計画にも影響するため) - -::: tip コードレビューの優先度を上げる - -チーム開発において、レビュー待ちでの待機時間を最小化することでチームでの生産性を最大化できるとされる。 - -- 参考: [どうして手を動かすよりもチーム内のコードレビューを優先するべきなのか \- Speaker Deck](https://speakerdeck.com/okashoi/dousiteshou-wodong-kasuyorimotimunei-nokodorebiyuwoyou-xian-surubekinanoka) - -::: - -## Reviewersを自分に設定する - -プルリクエストに対して、レビューを実際に行う場合はReviewersに自分を選択する。以下の理由がある。 - -- 後からどのプルリクエストに対してレビューを実施したか、トレース/可視化しやすくする -- 他のレビュアーが、◯◯さんが見るなら終わってからレビューを行う/スキップするという判断材料を提供する - -## hotfixの場合はマージ先のブランチを確認する - -通常のプルリクエストであれば、featureブランチはデフォルトブランチ(多くはdevelopブランチ)がデフォルトで選択されるため、間違えは少ない。一方でhotfixブランチの場合は、main、developの2ブランチにマージ先がありえるため間違えやすい。 - -特に慣れていないメンバーの場合は作業ミスも多発しやすいため、最初にマージ先のブランチが正しいか確認するクセを付けると良い。 - -::: tip 複数のdevelopブランチがある場合も間違えやすい -複数のリリースバージョンを並行して開発する場合、一時的に develop、develop2 と複数のアップストリームを保つ場合がある。このケースは特にマージ先を間違えやすいため注意する。 -::: - -## 「Start a review」と「Add single comment」の使い分け - -GitHubでのコードレビューは、`Start a review` を行うと `Submit review` しない限り、レビューコメントが自分以外のメンバーが参照できない。 - -`Add single comment` の場合は投稿が即参照可能となる。 - -本規約の推奨は以下。 - -- なるべく早くレビュイーにフィードバックを返すことを重視し、 `Add single comment` の利用を推奨する - -理由は以下。 - -- レビュイーとして、今レビューをしてもらっていると気付くことができ、心理的に楽になる -- コメントを貰った部分の疑問点を即返信しレビュアーにフィードバックしたり、随時修正できる - -## 暗黙知を形式知にする - -レビュー対象の変更内容が、機能上は問題なくても、他の実装方針と揺れている場合が存在する。 - -本規約の推奨は以下。 - -- レビュイーに「機能上は問題ないが、保守性/可読性の観点から、他の設計方針に合わせてほしい」といった旨のフィードバックを行う -- 開発規約にその設計方針が未記載の場合は、レビュアーが追記する(Linterに追加できれば理想である)。追記内容のレビュアーに、先ほどのレビュイーを含めることが望ましい - -暗黙知を形式期にすることで、チームの方針が明文化され、透明性のある運営に繋げることができる。新規参画者にとってのオンボーディング負荷が下がり、戦力化が早まるメリットがある。 - -## レビューコメントにラベルを追加する - -レビューコメントにはラベル(プレフィックス)をつけることを推奨する。レビューコメントの意図を明確にすることで、開発者間の非同期的なコミュニケーションを円滑にし、作業効率を向上させる。 - -以下にプレフィックスを利用した例を示す。 - -| プレフィクス | 説明 | 例 | -| :----------- | :------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------- | -| LGTM | Look Good To Me(良さげです) | \[LGTM\] 責務分解が明瞭で、良い実装です!💯 | -| ASK | 質問 | \[ASK\] この実装意図が理解できず、どうして必要なのか教えてもらえますか❓️🤔 | -| Q | ASKと同じ意味 | \[Q\] 同上 | -| MUST | 必須 | \[MUST\] ソート処理が漏れているため、順序が不正になってしまう可能性があります! | -| SHOULD | 提案 | \[SHOULD\] 愚直なループではなく、□□□の書き方の方が可読性および性能が良いです。書き換えを検討してください。 | -| IMO | In My Opinion(自分ならこうしますが、どうでしょうか?) | \[IMO\] スコープの広さの割に変数名が短いため、 \`name\` ではなく \` pre_ordered_product_name\` などが良いかと思いました | -| NITS | Nitpick(枝葉ですが直して欲しい) | \[NITS\] この変数名は、単数形よりも複数形 \`users\` または \`usersList\` が適しているかと思います。 | - -それぞれの定義は以下。特に「ASK(Q)」と「MUST」はレビューコメントが解決しないと、プルリクエストの承認を行うべきではない。 - -| 分類 | プレフィクス | 承認のために解決が必須 | レビュイーの対応 | -| :------- | :----------- | :--------------------- | :--------------------------------------------------------------------------------------------------------------------------------------- | -| 礼賛 | LGTM | | リアクション不要 | -| 質問 | ASK | ✅️ | 回答が必須 | -| | Q | ✅️ | 同上 | -| 修正依頼 | MUST | ✅️ | 対応しない場合はコメントバックまたは、コード変更の対応が必須 | -| | SHOULD | | 対応しない場合はコメントバックまたは、コード変更をできる限り実施する。対応見送りの場合は、チケット起票および、次リリースまでの対応が目安 | -| **提案** | IMO | | 絵文字リアクションやコメントバックが推奨だが、対応の是非はレビュイーが判断する | -| | NITS | | 同上 | - -参考: [コード品質向上のテクニック:第51回 確信的な質問 | LINEヤフー](https://techblog.lycorp.co.jp/ja/20241121icq) にも、レビューアの「要求」であるのにもかかわらず、単なる「質問」にも読み取れてしまうミスコミュニケーションの例があり、 コードレビューにおいては要求と質問は明確に区別できるように書かれるべき とある。 - -## 適度なユーモアを取り入れる - -心理的安全性を担保しつつレビューを楽しい場とするためには、ポジティブな絵文字(🚀✨️💯)を使うとともに、レビューコメントに適度にユーモアを入れると良い。 - -以下に例を示す。 - -- 「このチューニングが入ると操作性がチート並に爆速になって、お客様も喜んでくれそうですね🐆💨」 -- 「さすがに年齢設定の上限が1000になっているのは、エルフの世界くらいだと思うので150くらいまでにしておきましょうよ🧝」 - -## 指摘内容は具体的であればあるだけ良い - -レビューコメントで「可読性が低いです」 といったコメントは、レビュイーが受け取るとどのように修正して良いか判断ができず、次のアクションに繋がりにくいため不毛である。そのため、面倒であっても、どのように直して欲しいか、できる限り具体的に指示する方が建設的である。 - -本規約の推奨は以下。 - -- 「可読性が低いです」 「{任意の非機能要件}を満たしていません」といったコメントで終始せず、具体的にどの部分を、どのように修正して欲しいかをフィードバックする -- もし、修正する部分を(教育目的などで)レビュイーに考えてほしい場合は、その旨をコメントに追記する。レビュアーのお気持ちあてゲームにしないこと - -## 出典があれば追記できるとベター - -指摘内容の補足情報があれば追加するとベターである。例えば、「◯◯の観点で、このコードは△△の懸念があるため、□□□になるように修正をお願いします。公式ブログの{URL}にも記載があり、参考にできると思います。」といった形式である。 - -レビュイーが自分で調べれば事足りる場合もあるが、レビュアー側が出典を示すことで納得感が増す。また、誤った記事(過去のバージョンの記事や、見当違いの記事)を読んでしまい空回ってしまうことも、探す手間も減る。 - -## 指摘内容を論理的に説明できないのであれば、コメントすべきではない - -「なんとなく汚いです」は指摘ではない。悪いコードだと感じたのであれば、相手が納得できるように論理的に説明する。論理的に説明できないのであれば、指摘をすべきではない。 - -- 引用: [デキるプログラマだけが知っているコードレビュー7つの秘訣 | PPT](https://www.slideshare.net/rootmoon/7-37892729) p26 - -## なるべく1度のレビューで指摘し切る - -レビュイーからすると、レビューの「依頼1→指摘1→対応1→確認依頼1→別の指摘2→対応2→確認依頼2→別の指摘3→…」と、依頼のたびに指摘をもらうとタスクの予実管理も作業見積もりも建てられずストレスである(ムービング・ゴールポストである)。 - -本規約の推奨は以下。 - -- できるかぎり最初のレビューで、指摘事項を出し切る -- もし、2回目以降のレビューで追加要素に気がついた場合は、「\[imo\] 1度目の指摘で見逃してしまってすいません。この部分ですが、~の観点のため修正してもらいたく。」などと非を認めつつ、コメントする - -## 本筋から離れるコードコメントやREADMEのtypoなどはsuggestにする - -プルリクエスト上のコメントで、レビュイーに対して直接変更内容を提案を行うことができる[Suggested changes](https://docs.github.com/ja/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/incorporating-feedback-in-your-pull-request)という機能がある。 - -本規約の推奨は以下。 - -- 可能であればできる限り、Suggested changes形式を利用する。特にtypo、ドキュメントの言い回しや表現の訂正は、直接的に変更を指示しないと、やり取りのホップ数が増える傾向にあり、非生産的である -- 新規参画者やジュニアメンバー向けに、教育目的で自分で編集させたいと考える場合もあるが、何度かSuggested chagnesでフィードバックして直らなかったなど、限定的な場面で行う - -Suggested changesを使わないほうが良い場合もある。 - -- 変数名のリネーム(一箇所だけ変更してもビルドエラーになり、その後のリファクタリングが余計に面倒であるため) -- 上記のリネームの例のように、リンターやテストに影響を与えるものは、レビューコメントという形でコメントする方が良い - -参考: [君は GitHub の Suggested change を知っているか? \- BASEプロダクトチームブログ](https://devblog.thebase.in/entry/2018/12/02/130657) - -## nits(WANT以下)のコメントだけであれば、先にapproveする - -対応が必須ではない、いわゆるnitsな指摘事項だけの場合がある。 - -この場合の推奨は以下。 - -- さきにapproveしてから、「コメント部分を適時対応してマージして下さい」と伝える - - レビュイーの心理的負荷の軽減(レビュイーの裁量が増し信頼感が作れる) - - 余分なコミュニケーションが減り、スピード感が上がる -- 先にapproveすることにより、nitsであるがその対応可否をまったく検討せず、セルフマージするようなメンバーがいた場合は、nitsだけであったも、対応状況を見極めてからapproveしても良い - - つまり、初回、2回目は信頼してapproveすべきである - -## レビュアーはローカル環境で動作確認をすべきか - -レビュー対象のリモートブランチを、ローカル環境にてテストなど動作確認すべきか迷う場合がある。レビュアーがローカルで動作検証を行うと、おそらく品質は高まるはずだが、レビュイーとの作業重複でもあるため工数は非常に高くなり、費用対効果は必ずしも良いと言えない。 - -本規約の推奨は以下。 - -- レビュアーはローカル環境での動作確認はしなくても良い - - もちろん、しても良いがMUSTではない - - CIで単体テストが成功/失敗しているかは確認できずはずである - - どのように品質を担保するかはテスト戦略に依存させるべきである(その後のデプロイメント環境での結合テスト、システムテスト、性能テスト、障害テストなどに含まれるはずである) - -## 疑問点は臆せず質問する - -レビュアーは意図が掴みきれない部分があった場合は、そのままにせず理解できるように務める必要がある。分かったふりをすると、後でその部分が火を噴くことが多いからである。また、「チーム全員が同じ知識を共有する」というコードレビューの意図からすると、レビュイーだけ分かっていればよいという状態は不健全である。レビュイーがリーダー(テックリード)であっても臆する必要はないし、レビュイーが自分より若手であったとしても、自分が調べても分からないことを聞くことは恥ではないので、堂々と教えてもらう。 - -本規約の推奨は以下。 - -- 不明点が少ない場合は、レビューコメントで質問する -- 不明点が多い場合は、同期的なコミュニケーション(リモート会議。SlackのハドルやGoogle Meet)で確認する。やり取りのホップ数をなるべく減らすことを意識する -- リモート会議を行う場合は、レビュアー側から時間や枠を調整する - -## 自信がない場合は、有識者にディスパッチする - -レビュアーという立場だからといって、必ずしも開発チームが利用する全技術スタックや、開発プロダクトの過去の経緯に精通している訳ではない。それでも、自信が無い領域についてコードレビューを求められるケースも多々ある。 - -本規約の推奨は以下。 - -- 自分に自信がない領域については、レビュアーが無理せず有識者にディスパッチする体制にする - - 分からないことは恥ではない。それより、知ったかぶりで手違いが発生する方がチームにとってのリスクである -- 業務要件/機能要件が不明確であれば、プロダクトリーダー(業務担当者)に移譲する。非機能面で自信が無ければ、アーキテクトに移譲する。チーム規模によっては恒常的にこれら2つの役割のレビュアーで分担してレビュー方式も考えられる - -## ジュニアメンバーに対して大量の指摘がある場合にどうするか - -対象領域のスキル不足などが原因で、レビュー事項が大量にある場合に対応をどうすべきか迷う場合がある。 - -本規約の推奨は以下。 - -- 50でも100でも指摘事項があるのであれば、全てコメントを付ける - - 最初に全量を提示することで、レビュイーに対して作業見積もりを可能とさせる。逆に最初にコメント領域を絞ると、ムービング・ゴールポストである -- 指摘事項が多い場合、レビュイーが落胆してしまう懸念があるため、特に新規参画者で信頼構築ができていない場合は、コードレビューとは別にケアする - - 指摘事項が多くても問題ない旨を、チャット上でフィードバックする - - 指摘事項の背景情報(開発規約や、採用技術)について説明する会議をセッテイングする(適度に同期的なコミュニケーションを取る) - - ペアプロで指摘内容を修正する -- 可能であれば、Suggested changesを用いて、レビュイーの負荷を下げる工夫を取る - -なお、類似の指摘がある場合に、省略するかどうか判断に迷う場面もある。これについては以下を推奨する。 - -- 「ある1点だけ取り上げて、横展開をお願いします」は機能しないため、該当箇所を全てコメントする - - そのプルリクエスト内でレビュイーがキャッチアップしきれない可能性があるため、レビュアー側で補助した方がベター - - 横展開が漏れることが多く、余計なやり取りが発生し、レビュアー・レビュイーともにストレスになることが多いため - -## レビュー終了の連絡 - -レビュー終了した場合、レビューが終わった旨をプルリクエスト上でメンションをつけてコメントしたり、Slackなどのチャットで通知することで、レビュアーに対応を促すことができる。「Add single comment」の場合は、レビュー終了の切れ目が分からないためである。 - -本規約の推奨は以下。 - -- Slackでのメンション付きでレビュー終了の旨のコメントする - -理由は以下。 - -- 普段利用しているチャットツールの方がレビュイーが気がつく確率が高いため diff --git a/documents/forCodeReview/index.md b/documents/forCodeReview/index.md deleted file mode 100644 index 6938f6d2..00000000 --- a/documents/forCodeReview/index.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -sidebarDepth: 4 -author: フューチャー株式会社 -layout: home -hero: - name: コードレビュー
ガイドライン - tagline: Future Enterprise Standards for Code Review - actions: - - theme: brand - text: コードレビューガイドライン - link: ./code_review.md ---- - -# コードレビューガイドライン - -チーム開発する上で必要となる、コードレビューのガイドラインです。 - -- [コードレビューガイドライン](code_review.md) - -次のリンクから単一ファイル版を取得できます。 - -- [Markdown](https://github.com/future-architect/coding-standards/blob/master/documents/forCodeReview/code_review.md) -- [HTML(Single File)](https://github.com/future-architect/coding-standards/blob/gh-pages/resources/コードレビューガイドライン.html) ([ブラウザで見る](https://future-architect.github.io/coding-standards/resources/コードレビューガイドライン.html)) -- [Word](https://github.com/future-architect/coding-standards/raw/gh-pages/resources/コードレビューガイドライン.docx) - -ファイルは[Pandoc]を利用して作成しています。 - -[pandoc]: https://pandoc.org/ diff --git "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIM01/index.md" "b/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIM01/index.md" deleted file mode 100644 index 6d0ec71e..00000000 --- "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIM01/index.md" +++ /dev/null @@ -1,49 +0,0 @@ -# [UIM01] ログイン - - - -## 概要 - -機能目的: - -- ログインや会員登録導線を提供する - -機能概要: - -- ログイン処理 -- 会員登録への導線 - -## イベント概要 - -| No | イベント名 | イベント分類 | 処理説明 | -| --- | ------------ | ------------ | -------- | -| 1 | 初期表示 | 初期表示 | | -| 2 | ログインする | ボタン押下 | | -| 3 | 会員登録 | ボタン押下 | | - -## イベント詳細 - -### 1. 初期表示 - -モーダルを起動。初期パラメータは無し。 - -### 2. ログインする - -利用API: - -| ID | URL | Parameter | -| ------ | ----------- | ---------------------- | -| API001 | POST /login | 入力フォームの値を取得 | - -画面表示制御: - -- HTTPステータスが400系 - - 「IDまたはパスワードが異なります」を表示 -- HTTPステータスが500系 - - メッセージID(MSG_BIZ_111)表示 -- HTTPステータスが200 - - [UIS02](../UIS02/index.md)に遷移 - -### 3. 会員登録 - -... diff --git "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIM02/index.md" "b/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIM02/index.md" deleted file mode 100644 index d56b5cd1..00000000 --- "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIM02/index.md" +++ /dev/null @@ -1,48 +0,0 @@ -# [UIM02] トレーナー検索 - - - -## 概要 - -機能目的: - -- パーソナルトレーナーを検索する - -機能概要: - -- 行きつけのジムの絞り込み -- 店舗名の検索 -- トレーニング時間/予算の絞り込み -- トレーニングコースの絞り込み - -## イベント概要 - -| No | イベント名 | イベント分類 | 処理説明 | -| --- | ---------- | ------------ | -------- | -| 1 | 初期表示 | 初期表示 | | -| 2 | 検索 | ボタン押下 | | - -## イベント詳細 - -### 1. 初期表示 - -モーダルを起動。初期パラメータは無し。 - -### 2. 検索 - -利用API: - -| ID | URL | Parameter | -| ------ | ------------- | -------------------------------------------------- | -| API007 | GET /trainers | モーダルに指定された値をクエリパラメータに設定する | - -画面表示制御: - -- 入力チェック - - favorite_gym_name, store_nameが未設定の場合は、フロントエンド側でチェックし「行きつけのジム名・店舗名は必須項目です」と表示する -- 応答が0件の場合 - - 「条件に一致するコーチは存在しませんでした」と表示する -- HTTPステータスが200以外 - - メッセージID(MSG_BIZ_111)表示 -- HTTPステータスが200 - - [UIS03](../UIS03/index.md)に遷移 diff --git "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIM03/index.md" "b/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIM03/index.md" deleted file mode 100644 index 27772a51..00000000 --- "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIM03/index.md" +++ /dev/null @@ -1,57 +0,0 @@ -# [UIM03] カレンダー予約 - - - -## 概要 - -機能目的: - -- トレーニーやパーソナルトレーナの空き時間を表示し、予約を行えるようにする - -機能概要: - -- 本日以降の週間カレンダーを表示する -- すでに予約済みの時間がわかるようにする - -## イベント概要 - -| No | イベント名 | イベント分類 | 処理説明 | -| --- | ---------- | ------------------------------ | ------------------------------------------------------------------ | -| 1 | 初期表示 | 初期表示 | 指定されたトレーナーと、ログイン中のトレーニーのスケジュールを表示 | -| 2 | 日時設定 | カレンダーを選択 | ドラッグ&ドロップで範囲指定 | -| 3 | 日時指定 | 設定された日時で予約を指定する | | - -## イベント詳細 - -### 1. 初期表示 - -起動パラメータ: - -| Name | Value | Memo | -| ---------- | ----------------------------- | ---- | -| trainer_id | {"trainer_id":""} | | -| trainee_id | {"trainee_id":""} | | - -利用API: - -| ID | URL | Parameter | -| ------ | ----------------------------------- | -------------------- | -| API011 | GET /trainers/{trainer_id}/schedule | 初期パラメータを設定 | -| API013 | GET /bookings/{trainee_id} | 初期パラメータを設定 | - -画面表示制御: - -- API011 - - 0件の場合は何もしない - - 1件以上存在した場合は、カレンダーには「ブロック」と表示する -- API026 - - 0件の場合は何もしない - - 1件以上存在した場合は、カレンダーに「予約あり」と表示する - -### 2. 日時設定 - -選択された日付がカレンダーに追加される。 - -### 3. 日時指定 - -[UIM04](../UIM04/index.md) を起動する。 diff --git "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIM04/index.md" "b/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIM04/index.md" deleted file mode 100644 index ec63fc21..00000000 --- "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIM04/index.md" +++ /dev/null @@ -1,48 +0,0 @@ -# [UIM04] 決済 - - - -## 概要 - -機能目的: - -- トレーニング予約内容を表示し、決済によって確定する - -機能概要: - -- トレーニングのコース/日時/料金を表示 -- クレジット決済に必要な項目の入力 -- 決済の確定 - -## イベント概要 - -| No | イベント名 | イベント分類 | 処理説明 | -| --- | -------------- | ------------ | ------------ | -| 1 | 初期表示 | 初期表示 | | -| 2 | 日時指定に戻る | ボタン押下 | UIM003に遷移 | -| 2 | 決済する | ボタン押下 | | - -## イベント詳細 - -### 1. 初期表示 - -起動パラメータ: - -| Name | Value | Memo | -| ---------- | ----------------------------- | ---- | -| trainer_id | {"trainer_id":""} | | -| menu_id | {"menu_id":""} | | - -利用API: - -| ID | URL | Parameter | -| ------ | ------------------------ | -------------------- | -| APIxxx | トレーニングメニュー取得 | 初期パラメータを設定 | - -### 2. 日時指定に戻る - -[UIM03](../UIM03/index.md)に遷移 - -### 3. 決済 - -... diff --git "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIS01/index.md" "b/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIS01/index.md" deleted file mode 100644 index 93f49b26..00000000 --- "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIS01/index.md" +++ /dev/null @@ -1,63 +0,0 @@ -# [UIS01] トップページ - - - -## 概要 - -機能目的: - -- トップページ - -機能概要: - -- ログインへの導線 -- パーソナルトレーナーの検索への導線 - -## イベント概要 - -| No | イベント名 | イベント分類 | 処理説明 | -| --- | ------------------ | ------------ | ---------------------------------------------------------------------- | -| 1 | 初期表示 | 初期表示 | ログイン済みである場合、「会員登録/ログイン」が「マイページ」に変わる | -| 2 | トレーナーを探す | ボタン押下 | パーソナルトレーナー検索モーダル起動 | -| 3 | 会員登録/ログイン | ボタン押下 | ログインモーダル起動 | - -## イベント詳細 - -### 1. 初期表示 - -起動パラメータ: - -| Name | Value | Memo | -| --------- | ----------------------- | ------------ | -| userState | {"user_id":""} | ログイン状態 | - -初期表示イベント: - -- ログイン済み判定 - -利用API: - -| ID | URL | Parameter | -| ------- | ------------------------- | ---------------------------- | -| API-005 | GET /profile/{trainee_id} | trainee_id=userState.user_id | - -画面表示制御: - -- HTTPステータスが500系 - - 何もしない(無視で良い)、初期表示のまま -- HTTPステータスが400系 - - 未ログインとして、初期表示のまま -- HTTPステータスが200 - - すでにログイン中と判断し、(画面表示制御1)へ - -画面表示制御1: - -- 「会員登録/ログイン」表示を、サムネイル画像(thumbnail_url)に書き換える - -### 2. トレーナーを探す - -[UIM002](../UIM02/index.md) 呼び出し - -### 3. 会員登録/ログイン - -[UIM001](../UIM01/index.md) 呼び出し diff --git "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIS02/index.md" "b/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIS02/index.md" deleted file mode 100644 index f5d4f208..00000000 --- "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIS02/index.md" +++ /dev/null @@ -1,105 +0,0 @@ -# [UIS02] マイページ - - - -## 概要 - -機能目的: - -- トレーニーのマイページを表示し、受講予定・受講済みのトレーニング一覧を表示する - -機能概要: - -- 受講状況の表示 -- パーソナルトレーナーの検索への導線 - -## イベント概要 - -| No | イベント名 | イベント分類 | 処理説明 | -| --- | ---------------- | ------------ | ------------------------------------------------------------ | -| 1 | 初期表示 | 初期表示 | 初期検索条件に従いAPIを実行し、履歴表示する | -| 2 | トレーナーを探す | ボタン押下 | パーソナルトレーナー検索モーダル起動 | -| 3 | 受講完了確認 | ボタン押下 | 予約済みトレーニングを受講完了に切り替えるためのモーダル起動 | -| 4 | 受講完了 | ボタン押下 | 予約済みトレーニングを完了済みのトレーニングに更新 | - -## イベント詳細 - -### 1. 初期表示 - -起動パラメータ: - -| Name | Value | Memo | -| --------- | ----------------------- | ------------ | -| userState | {"user_id":""} | ログイン状態 | - -初期表示イベント: - -- マイページ表示 - -利用API: - -| ID | URL | Parameter | -| ------- | ------------------------- | ---------------------------- | -| API-005 | GET /profile/{trainee_id} | trainee_id=userState.user_id | - -画面表示制御: - -- HTTPステータスが500系 - - メッセージID(MSG_BIZ_111)表示 -- HTTPステータスが400系 - - トップページにリダイレクト - -利用API: - -| ID | URL | Parameter | -| ------ | -------------------------- | ---------------------------- | -| API013 | GET /bookings/{trainee_id} | trainee_id=userState.user_id | - -画面表示制御: - -- 起動条件 - - API016が有効な場合 -- HTTPステータスが200以外 - - メッセージID(MSG_BIZ_111)表示 - -### 2. トレーナーを探す - -[UIM002](../UIM02/index.md) を起動。 - -### 3. 受講完了確認 - -「`${トレーニングメニュー}` は完了しましたか?」ダイアログを表示する。 - -キャンセルの場合は閉じる。 - -### 4. 受講完了 - -「`${トレーニングメニュー}` は完了しましたか?」ダイアログがOKの場合。 - -利用API: - -| ID | URL | Parameter | -| ------ | -------------------------------- | ---------------------------- | -| API016 | PUT /booking/{booking_id}/status | 選択されたトレーニング予約ID | - -画面表示制御: - -- クリック可否判定 - - 予約済み+現在時間<=受講時間になっている場合に、クリック可能とする -- HTTPステータスが200以外 - - メッセージID(MSG_BIZ_111)表示 -- HTTPステータスが200 - - 次のAPIを呼び出し - -利用API: - -| ID | URL | Parameter | -| ------- | -------------------------- | ---------------------------- | -| API-012 | GET /bookings/{trainee_id} | trainee_id=userState.user_id | - -画面表示制御: - -- 起動条件 - - API016が有効な場合 -- HTTPステータスが200以外 - - メッセージID(MSG_BIZ_111)表示 diff --git "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIS03/index.md" "b/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIS03/index.md" deleted file mode 100644 index 7344e0de..00000000 --- "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIS03/index.md" +++ /dev/null @@ -1,50 +0,0 @@ -# [UIS03] トレーナー一覧 - - - -## 概要 - -機能目的: - -- 検索条件に一致する順にパーソナルトレーナーを表示する - -機能概要: - -- パーソナルトレーナーの一覧表示 -- パーソナルトレーナーの再検索を指定可能とする -- 興味が湧いたパーソナルトレーナーについて、詳細画面への導線 - -## イベント概要 - -| No | イベント名 | イベント分類 | 処理説明 | -| --- | -------------- | ------------ | --------------------------------------- | -| 1 | 初期表示 | 初期表示 | 検索条件に従いAPIを実行し、一覧表示する | -| 2 | トレーナー詳細 | ボタン押下 | UIS04に遷移 | -| 3 | トレーナー検索 | ボタン押下 | 入力された条件で検索 | - -## イベント詳細 - -### 1. 初期表示 - -利用API: - -| ID | URL | Parameter | -| ------ | ------------- | ------------------------------------------------------------------- | -| API007 | GET /trainers | favorite_gym_nameなど、各クエリパラメータ指定されたパラメータを設定 | - -画面表示制御: - -- HTTPステータスが200以外 - - メッセージID(MSG_BIZ_111)表示 -- 応答結果が0件の場合 - - 「条件に一致するパーソナルトレーナーが見つかりませんでした。」を表示する -- 応答結果が1件以上の場合 - - リスト表示する(ページングは不要。応答順に最大100件表示する) - -### 2. トレーナー詳細 - -[UIS04](../UIS04/index.md)に遷移 - -### 3. トレーナー検索 - -初期表示と同等の処理を実行する。 diff --git "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIS04/index.md" "b/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIS04/index.md" deleted file mode 100644 index 270a3c54..00000000 --- "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/UIS04/index.md" +++ /dev/null @@ -1,78 +0,0 @@ -# [UIS04] トレーナー詳細 - - - -## 概要 - -機能目的: - -- パーソナルトレーナーが提供するトレーニング一覧を表示する - -機能概要: - -- パーソナルトレーナー情報を表示 -- トレーニング一覧を表示する - -## イベント概要 - -| No | イベント名 | イベント分類 | 処理説明 | -| --- | ---------------------- | ------------ | ------------------------------------------- | -| 1 | 初期表示 | 初期表示 | 初期検索条件に従いAPIを実行し、履歴表示する | -| 2 | トレーニングコース決定 | ボタン押下 | 予約のためカレンダーモーダルを起動 | - -## イベント詳細 - -### 1. 初期表示 - -起動パラメータ: - -| Name | Value | Memo | -| ---------- | ----------------------------- | ---- | -| trainer_id | {"trainer_id":""} | | - -利用API: - -| ID | URL | Parameter | -| ------ | ---------------------------------- | -------------------- | -| API009 | GET /trainers/{trainer_id}/profile | 起動パラメータを設定 | - -画面表示制御: - -- HTTPステータスが200以外 - - メッセージID(MSG_BIZ_111)表示 -- HTTPステータスが200 - - プロフィールを更新 - - API008を呼び出し - -利用API: - -| ID | URL | Parameter | -| ------ | -------------------------------- | -------------------- | -| API008 | GET /trainers/{trainer_id}/menus | 起動パラメータを設定 | - -画面表示制御: - -- HTTPステータスが200以外 - - メッセージID(MSG_BIZ_111)表示 -- HTTPステータスが200 - - メニューを一覧表示 - - 0件の場合は「現在、提供できるメニューが存在しません。」と表示 - - API010を呼び出し - -利用API: - -| ID | URL | Parameter | -| ------ | ------------------------------ | -------------------- | -| API010 | /trainers/{trainer_id}/reviews | 起動パラメータを設定 | - -画面表示制御: - -- HTTPステータスが200以外 - - メッセージID(MSG_BIZ_111)表示 -- HTTPステータスが200 - - 0件の場合は、「レビューがありません」を表示する - - 1件以上存在する場合は、最大5件まで表示する - -### 2. トレーニングコース決定 - -[UIM03](../UIM03/index.md) を起動する。 diff --git "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/index.md" "b/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/index.md" deleted file mode 100644 index 187b5776..00000000 --- "a/documents/forMarkdown/future_muscle_partner/docs/01_\347\224\273\351\235\242/index.md" +++ /dev/null @@ -1,21 +0,0 @@ -# 画面 - -- [Figma URL](https://www.figma.com/design/kLgdi4xdGRpQudMEoZYwvq/%E3%80%90FMP%E3%80%91Future-Muscle-Partner_%E7%94%BB%E9%9D%A2%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3?node-id=0-1&t=WUJH1mSc5HgzhHcH-1) - -## 標準画面 - -| ID | 論理名 | 備考 | -| ------------------------- | -------------- | ---- | -| [UIS01](./UIS01/index.md) | トップページ | | -| [UIS02](./UIS02/index.md) | マイページ | | -| [UIS03](./UIS03/index.md) | トレーナー一覧 | | -| [UIS04](./UIS04/index.md) | トレーナー詳細 | | - -## モーダル画面 - -| ID | 論理名 | 備考 | -| ------------------------- | -------------- | ---- | -| [UIM01](./UIM01/index.md) | ログイン | | -| [UIM02](./UIM02/index.md) | トレーナー検索 | | -| [UIM03](./UIM03/index.md) | カレンダー予約 | | -| [UIM04](./UIM04/index.md) | 決済 | | diff --git a/documents/forMarkdown/future_muscle_partner/docs/02_WebAPI/index.md b/documents/forMarkdown/future_muscle_partner/docs/02_WebAPI/index.md deleted file mode 100644 index dd34c9d0..00000000 --- a/documents/forMarkdown/future_muscle_partner/docs/02_WebAPI/index.md +++ /dev/null @@ -1,3 +0,0 @@ -## Web API - -[openapi.yaml](openapi.yaml) diff --git a/documents/forMarkdown/future_muscle_partner/docs/02_WebAPI/openapi.yaml b/documents/forMarkdown/future_muscle_partner/docs/02_WebAPI/openapi.yaml deleted file mode 100644 index b6b4be05..00000000 --- a/documents/forMarkdown/future_muscle_partner/docs/02_WebAPI/openapi.yaml +++ /dev/null @@ -1,1373 +0,0 @@ -openapi: 3.0.3 -info: - title: Future Muscle Partner API - description: パーソナルトレーナーのマッチングサービスAPI - version: 1.0.0 -tags: - - name: account - description: アカウント管理 - - name: profile - description: プロフィール - - name: trainer - description: パーソナルトレーナー - - name: booking - description: 予約 - - name: review - description: レビュー - - name: payment - description: 決済 - - name: provider - description: パーソナルトレーニング提供者 -security: - - Bearer: [] -paths: - /login: - post: - tags: - - account - summary: API001 ログイン - operationId: login - security: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/LoginRequest" - responses: - "200": - description: ログインに成功しました。 - "400": - $ref: "#/components/responses/BadRequest" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /logout: - post: - tags: - - account - summary: API002 ログアウト - operationId: logout - security: [] - responses: - "200": - description: ログアウトに成功しました。 - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthorized" - "403": - $ref: "#/components/responses/Forbidden" - "404": - $ref: "#/components/responses/NotFound" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /signup: - post: - tags: - - account - summary: API003 会員登録 - operationId: signup - security: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/SignupRequest" - responses: - "200": - description: 会員登録に成功しました。 - "400": - $ref: "#/components/responses/BadRequest" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /account: - delete: - tags: - - account - summary: API004 会員退会 - operationId: deleteAccount - responses: - "200": - description: 会員退会に成功しました。 - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthorized" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /profile/{trainee_id}: - get: - tags: - - profile - summary: API005 プロフィール表示 - operationId: getUserProfile - responses: - "200": - description: プロフィールの取得に成功しました。 - content: - application/json: - schema: - $ref: "#/components/schemas/Profile" - "401": - $ref: "#/components/responses/Unauthorized" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - put: - tags: - - profile - summary: API006 プロフィール更新 - operationId: putUserProfile - parameters: - - name: trainee_id - in: path - description: トレーニーID - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/ProfileRequest" - responses: - "200": - description: プロフィールの更新に成功しました。 - "401": - $ref: "#/components/responses/Unauthorized" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /trainers: - get: - tags: - - trainer - summary: API007 パーソナルトレーナー検索 - operationId: searchTrainers - security: [] - parameters: - - name: favorite_gym_name - in: query - description: 行きつけのジム名 - required: true - schema: - type: string - - name: store_name - in: query - description: 店舗名 - required: true - schema: - type: string - - name: training_start_at - in: query - description: トレーニング開始 - schema: - type: string - - name: training_end_at - in: query - description: トレーニング終了時間 - schema: - type: string - - name: budget - in: query - description: 予算 - schema: - type: number - format: integer - - name: training_menu_typ - in: query - description: トレーニングメニュー区分 - schema: - type: number - format: integer - enum: [1, 2, 3] - responses: - "200": - description: トレーナーの検索結果を取得しました。 - content: - application/json: - schema: - $ref: "#/components/schemas/Trainers" - "400": - $ref: "#/components/responses/BadRequest" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /trainers/{trainer_id}/menus: - get: - tags: - - trainer - summary: API008 トレーニングメニュー取得 - operationId: getTrainingMenu - security: [] - parameters: - - name: trainer_id - in: path - description: トレーナーのID - required: true - schema: - type: string - responses: - "200": - description: トレーニングメニューを取得しました。 - content: - application/json: - schema: - $ref: "#/components/schemas/TrainingMenus" - "400": - $ref: "#/components/responses/BadRequest" - "404": - $ref: "#/components/responses/NotFound" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - - /trainers/{trainer_id}/profile: - get: - tags: - - trainer - summary: API009 トレーナープロフィール取得 - operationId: getTrainerProfile - security: [] - parameters: - - name: trainer_id - in: path - description: トレーナーのID - required: true - schema: - type: string - responses: - "200": - description: トレーナープロフィールを取得しました。 - content: - application/json: - schema: - $ref: "#/components/schemas/Trainer" - "400": - $ref: "#/components/responses/BadRequest" - "404": - $ref: "#/components/responses/NotFound" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /trainers/{trainer_id}/reviews: - get: - tags: - - trainer - summary: API010 トレーナー口コミ取得 - operationId: getTrainerReviews - security: [] - parameters: - - name: trainer_id - in: path - description: トレーナーのID - required: true - schema: - type: string - responses: - "200": - description: トレーナーの口コミを取得しました。 - content: - application/json: - schema: - $ref: "#/components/schemas/Reviews" - "400": - $ref: "#/components/responses/BadRequest" - "404": - $ref: "#/components/responses/NotFound" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /trainers/{trainer_id}/schedule: - get: - tags: - - trainer - summary: API011 トレーナースケジュール取得 - operationId: getTrainerSchedule - security: [] - parameters: - - name: trainer_id - in: path - description: トレーナーのID - required: true - schema: - type: string - responses: - "200": - description: トレーナーのスケジュールを取得しました。 - content: - application/json: - schema: - $ref: "#/components/schemas/TrainerSchedules" - "400": - $ref: "#/components/responses/BadRequest" - "404": - $ref: "#/components/responses/NotFound" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /bookings: - post: - tags: - - booking - summary: API012 トレーニング予約(仮登録) - operationId: bookTraining - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/BookingRequest" - responses: - "200": - description: 予約が仮登録されました。 - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthorized" - "409": - $ref: "#/components/responses/Conflict" - "422": - $ref: "#/components/responses/UnprocessableEntity" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /bookings/{trainee_id}: - get: - tags: - - booking - summary: API013 予約済みトレーニング取得 - operationId: getBookings - parameters: - - name: trainee_id - in: path - description: トレーニーID - required: true - schema: - type: string - - name: start_at - in: query - description: 開始日時 - schema: - type: string - - name: end_at - in: query - description: 終了日時 - schema: - type: string - responses: - "200": - description: ユーザーの予約情報を取得しました。 - content: - application/json: - schema: - $ref: "#/components/schemas/Bookings" - "401": - $ref: "#/components/responses/Unauthorized" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /bookings/{booking_id}: - delete: - tags: - - booking - summary: API014 トレーニング予約削除 - operationId: deleteBooking - parameters: - - name: booking_id - in: path - description: 予約ID - required: true - schema: - type: string - responses: - "200": - description: 予約が削除されました。 - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthorized" - "404": - $ref: "#/components/responses/NotFound" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /bookings/{booking_id}/confirm: - post: - tags: - - booking - summary: API015 トレーニング予約(本登録) - operationId: confirmBooking - parameters: - - name: booking_id - in: path - description: 予約ID - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/BookingConfirmationRequest" - responses: - "200": - description: 予約が本登録されました。 - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthorized" - "409": - $ref: "#/components/responses/Conflict" - "422": - $ref: "#/components/responses/UnprocessableEntity" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /booking/{booking_id}/status: - put: - tags: - - booking - summary: API016 トレーニング受講ステータス変更 - operationId: updateTrainingStatus - parameters: - - name: booking_id - in: path - description: 予約ID - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/TrainingStatusUpdateRequest" - responses: - "200": - description: ステータスが更新されました。 - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthorized" - "404": - $ref: "#/components/responses/NotFound" - "409": - $ref: "#/components/responses/Conflict" - "422": - $ref: "#/components/responses/UnprocessableEntity" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /payment: - post: - tags: - - payment - summary: API017 決済 - operationId: makePayment - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/PaymentRequest" - responses: - "200": - description: 決済が完了しました。 - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthorized" - "409": - $ref: "#/components/responses/Conflict" - "422": - $ref: "#/components/responses/UnprocessableEntity" - "500": - $ref: "#/components/responses/InternalServer" - "503": - $ref: "#/components/responses/ServiceUnavailable" - /reviews: - post: - tags: - - review - summary: API018 口コミ登録 - operationId: postReview - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/ReviewRequest" - responses: - "200": - description: 口コミ登録成功 - /reviews/{review_id}: - put: - tags: - - review - summary: API019 口コミ修正 - operationId: putReview - parameters: - - name: review_id - in: path - description: レビューID - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/ReviewUpdateRequest" - responses: - "200": - description: 口コミ修正成功 - delete: - tags: - - review - summary: API020 口コミ削除 - operationId: deleteReview - parameters: - - name: review_id - in: path - description: 口コミID - required: true - schema: - type: string - responses: - "200": - description: 口コミ削除成功 - /trainer: - post: - tags: - - provider - summary: API021 トレーナー登録 - operationId: postTrainer - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/Trainer" - responses: - "200": - description: トレーナー登録成功 - put: - tags: - - provider - summary: API022 トレーナー属性更新 - operationId: putTrainer - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/Trainer" - responses: - "200": - description: トレーナー属性更新成功 - /training-menus: - post: - tags: - - provider - summary: API023 トレーニングメニュー登録 - operationId: postTrainingMenu - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/TrainingMenu" - responses: - "200": - description: トレーニングメニュー登録成功 - /training-menus/{menu_id}: - put: - tags: - - provider - summary: API024 トレーニングメニュー更新 - operationId: putTrainingMenu - parameters: - - name: menu_id - in: path - description: メニューID - required: true - schema: - type: integer - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/TrainingMenu" - responses: - "200": - description: トレーニングメニュー更新成功 - delete: - tags: - - provider - summary: API025 トレーニングメニュー削除 - operationId: deleteTrainingMenu - parameters: - - name: menu_id - in: path - description: メニューID - required: true - schema: - type: integer - responses: - "200": - description: トレーニングメニュー削除成功 - -components: - schemas: - ProblemDetailError: - description: A Problem Details object (RFC 9457) - type: object - properties: - title: - type: string - description: A short summary of the problem type. Written in English and readable for engineers (usually not suited for non technical stakeholders and not localized). - example: Service Unavailable - status: - type: integer - format: int32 - description: The HTTP status code generated by the origin server for this occurrence of the problem. - minimum: 400 - maximum: 600 - exclusiveMaximum: true - example: 503 - detail: - type: string - description: A human-readable explanation specific to this occurrence of the problem - example: - title: Description of the type of problem that occurred - status: 400 # HTTP response status, appropriate for the problem type - detail: Description of specific occurrence of the problem - - LoginRequest: - type: object - properties: - email: - type: string - format: email - description: メールアドレス - password: - type: string - format: password - description: パスワード - SignupRequest: - type: object - properties: - email: - type: string - format: email - description: メールアドレス - password: - type: string - format: password - description: パスワード - name: - type: string - description: 名前 - ProfileRequest: - type: object - properties: - trainee_name: - type: string - description: トレーニー名 - display_name: - type: string - description: 表示名 - self_introduction: - type: string - description: 自己紹介 - PaymentRequest: - type: object - properties: - amount: - type: number - format: double - description: 支払金額 - method: - type: string - description: 支払方法 - BookingRequest: - type: object - properties: - menu_id: - type: string - description: トレーニングメニューのID - booking_status_typ: - type: string - enum: ["0"] - description: | - 予約ステータス区分 - 0: 仮登録 - trainee_id: - type: string - description: トレーニーID - training_start_at: - type: string - format: date - description: トレーニング開始日時 - training_end_at: - type: string - format: date - description: トレーニング終了日時 - BookingConfirmationRequest: - type: object - properties: - booking_status_typ: - type: string - enum: ["1"] - description: | - 予約ステータス区分 - 1: 本登録 - TrainingStatusUpdateRequest: - type: object - properties: - booking_status_typ: - type: string - enum: ["2", "3"] - description: | - 予約ステータス区分 - 2: 受講中 - 3: 受講済み - ReviewRequest: - type: object - properties: - trainer_id: - type: string - description: トレーナーID - trainee_id: - type: string - description: トレー二ーID - comment: - type: string - description: レビューコメント - ReviewUpdateRequest: - type: object - properties: - review_id: - type: string - description: レビューID - comment: - type: string - description: レビューコメント - Profile: - type: object - properties: - trainee_id: - type: string - description: トレーニーID - trainee_name: - type: string - description: トレーニー名 - display_name: - type: string - description: 表示名 - self_introduction: - type: string - description: 自己紹介 - thumbnail_url: - type: string - description: サムネイル画像URL - Bookings: - type: object - properties: - bokkings: - type: array - items: - $ref: "#/components/schemas/Booking" - Booking: - type: object - properties: - booking_id: - type: string - description: 予約ID - menu_id: - type: string - description: トレーニングメニューのID - trainer_id: - type: string - description: トレーナーのID - display_order: - type: string - description: 表示順序 - menu_name: - type: string - description: メニュー名 - menu_description: - type: string - description: メニュー説明 - required_time: - type: integer - description: 所要時間 - price: - type: integer - description: 料金 - start_at: - type: string - format: date - description: 開始日時 - end_at: - type: string - format: date - description: 終了日時 - training_start_at: - type: string - format: date - description: トレーニング開始日時 - training_end_at: - type: string - format: date - description: トレーニング終了日時 - Trainers: - type: object - properties: - count: - type: integer - description: 検索件数 - items: - type: array - items: - $ref: "#/components/schemas/Trainer" - Trainer: - type: object - properties: - trainer_id: - type: string - description: トレーナーID - trainer_name: - type: string - description: トレーナー名 - unit_price: - type: integer - description: 単価 - business_start_at: - type: string - format: date - description: 営業開始時間 - business_end_at: - type: string - format: date - description: 営業終了時間 - public_mail_addr: - type: string - format: email - description: 公開メールアドレス - public_tel: - type: string - description: 公開電話番号 - store_name: - type: string - description: 店舗名 - gym_name: - type: string - description: ジム名 - star_count: - type: number - format: float - description: 星の数 - TrainerSchedules: - type: object - properties: - count: - type: integer - description: 検索件数 - items: - type: array - items: - $ref: "#/components/schemas/TrainerSchedule" - TrainerSchedule: - type: object - properties: - trainer_id: - type: string - description: トレーナーID - trainer_name: - type: string - description: トレーナー名 - date: - type: string - format: date - description: 日付け - booking_typ_0000: - type: string - enum: ["0", "1"] - description: | - 予約区分 00:00-00:30 - 0: 未予約 - 1: 予約済み - booking_typ_0030: - type: string - enum: ["0", "1"] - description: | - 予約区分 00:30-01:00 - 0: 未予約 - 1: 予約済み - booking_typ_0100: - type: string - enum: ["0", "1"] - description: | - 予約区分 01:00-01:30 - 0: 未予約 - 1: 予約済み - booking_typ_0130: - type: string - enum: ["0", "1"] - description: | - 予約区分 01:30-02:00 - 0: 未予約 - 1: 予約済み - booking_typ_0200: - type: string - enum: ["0", "1"] - description: | - 予約区分 02:00-02:30 - 0: 未予約 - 1: 予約済み - booking_typ_0230: - type: string - enum: ["0", "1"] - description: | - 予約区分 02:30-03:00 - 0: 未予約 - 1: 予約済み - booking_typ_0300: - type: string - description: | - 予約区分 03:00-03:30 - 0: 未予約 - 1: 予約済み - booking_typ_0330: - type: string - enum: ["0", "1"] - description: | - 予約区分 03:30-04:00 - 0: 未予約 - 1: 予約済み - booking_typ_0400: - type: string - enum: ["0", "1"] - description: | - 予約区分 04:00-04:30 - 0: 未予約 - 1: 予約済み - booking_typ_0430: - type: string - enum: ["0", "1"] - description: | - 予約区分 04:30-05:00 - 0: 未予約 - 1: 予約済み - booking_typ_0500: - type: string - enum: ["0", "1"] - description: | - 予約区分 05:00-05:30 - 0: 未予約 - 1: 予約済み - booking_typ_0530: - type: string - enum: ["0", "1"] - description: | - 予約区分 05:30-06:00 - 0: 未予約 - 1: 予約済み - booking_typ_0600: - type: string - description: | - 予約区分 06:00-06:30 - 0: 未予約 - 1: 予約済み - booking_typ_0630: - type: string - enum: ["0", "1"] - description: | - 予約区分 06:30-07:00 - 0: 未予約 - 1: 予約済み - booking_typ_0700: - type: string - enum: ["0", "1"] - description: | - 予約区分 07:00-07:30 - 0: 未予約 - 1: 予約済み - booking_typ_0730: - type: string - enum: ["0", "1"] - description: | - 予約区分 07:30-08:00 - 0: 未予約 - 1: 予約済み - booking_typ_0800: - type: string - enum: ["0", "1"] - description: | - 予約区分 08:00-08:30 - 0: 未予約 - 1: 予約済み - booking_typ_0830: - type: string - enum: ["0", "1"] - description: | - 予約区分 08:30-09:00 - 0: 未予約 - 1: 予約済み - booking_typ_0900: - type: string - enum: ["0", "1"] - description: | - 予約区分 09:00-09:30 - 0: 未予約 - 1: 予約済み - booking_typ_0930: - type: string - enum: ["0", "1"] - description: | - 予約区分 09:30-10:00 - 0: 未予約 - 1: 予約済み - booking_typ_1000: - type: string - enum: ["0", "1"] - description: | - 予約区分 10:00-10:30 - 0: 未予約 - 1: 予約済み - booking_typ_1030: - type: string - enum: ["0", "1"] - description: | - 予約区分 10:30-11:00 - 0: 未予約 - 1: 予約済み - booking_typ_1100: - type: string - enum: ["0", "1"] - description: | - 予約区分 11:00-11:30 - 0: 未予約 - 1: 予約済み - booking_typ_1130: - type: string - enum: ["0", "1"] - description: | - 予約区分 11:30-12:00 - 0: 未予約 - 1: 予約済み - booking_typ_1200: - type: string - enum: ["0", "1"] - description: | - 予約区分 12:00-12:30 - 0: 未予約 - 1: 予約済み - booking_typ_1230: - type: string - enum: ["0", "1"] - description: | - 予約区分 12:30-13:00 - 0: 未予約 - 1: 予約済み - booking_typ_1300: - type: string - enum: ["0", "1"] - description: | - 予約区分 13:00-13:30 - 0: 未予約 - 1: 予約済み - booking_typ_1330: - type: string - enum: ["0", "1"] - description: | - 予約区分 13:30-14:00 - 0: 未予約 - 1: 予約済み - booking_typ_1400: - type: string - enum: ["0", "1"] - description: | - 予約区分 14:00-14:30 - 0: 未予約 - 1: 予約済み - booking_typ_1430: - type: string - enum: ["0", "1"] - description: | - 予約区分 14:30-15:00 - 0: 未予約 - 1: 予約済み - booking_typ_1500: - type: string - enum: ["0", "1"] - description: | - 予約区分 15:00-15:30 - 0: 未予約 - 1: 予約済み - booking_typ_1530: - type: string - enum: ["0", "1"] - description: | - 予約区分 15:30-16:00 - 0: 未予約 - 1: 予約済み - booking_typ_1600: - type: string - enum: ["0", "1"] - description: | - 予約区分 16:00-16:30 - 0: 未予約 - 1: 予約済み - booking_typ_1630: - type: string - enum: ["0", "1"] - description: | - 予約区分 16:30-17:00 - 0: 未予約 - 1: 予約済み - booking_typ_1700: - type: string - enum: ["0", "1"] - description: | - 予約区分 17:00-17:30 - 0: 未予約 - 1: 予約済み - booking_typ_1730: - type: string - enum: ["0", "1"] - description: | - 予約区分 17:30-18:00 - 0: 未予約 - 1: 予約済み - booking_typ_1800: - type: string - enum: ["0", "1"] - description: | - 予約区分 18:00-18:30 - 0: 未予約 - 1: 予約済み - booking_typ_1830: - type: string - enum: ["0", "1"] - description: | - 予約区分 18:30-19:00 - 0: 未予約 - 1: 予約済み - booking_typ_1900: - type: string - enum: ["0", "1"] - description: | - 予約区分 19:00-19:30 - 0: 未予約 - 1: 予約済み - booking_typ_1930: - type: string - description: | - 予約区分 19:30-20:00 - 0: 未予約 - 1: 予約済み - booking_typ_2000: - type: string - enum: ["0", "1"] - description: | - 予約区分 20:00-20:30 - 0: 未予約 - 1: 予約済み - booking_typ_2030: - type: string - enum: ["0", "1"] - description: | - 予約区分 20:30-21:00 - 0: 未予約 - 1: 予約済み - booking_typ_2100: - type: string - enum: ["0", "1"] - description: | - 予約区分 21:00-21:30 - 0: 未予約 - 1: 予約済み - booking_typ_2130: - type: string - enum: ["0", "1"] - description: | - 予約区分 21:30-22:00 - 0: 未予約 - 1: 予約済み - booking_typ_2200: - type: string - enum: ["0", "1"] - description: | - 予約区分 22:00-22:30 - 0: 未予約 - 1: 予約済み - booking_typ_2230: - type: string - enum: ["0", "1"] - description: | - 予約区分 22:30-23:00 - 0: 未予約 - 1: 予約済み - booking_typ_2300: - type: string - enum: ["0", "1"] - description: | - 予約区分 23:00-23:30 - 0: 未予約 - 1: 予約済み - booking_typ_2330: - type: string - enum: ["0", "1"] - description: | - 予約区分 23:30-24:00 - 0: 未予約 - 1: 予約済み - TrainingMenus: - type: object - properties: - count: - type: integer - description: 検索件数 - items: - type: array - items: - $ref: "#/components/schemas/TrainingMenu" - TrainingMenu: - type: object - properties: - menu_id: - type: string - trainer_id: - type: string - description: トレーナーID - display_order: - type: string - description: 表示順序 - menu_name: - type: string - description: メニュー名 - menu_description: - type: string - description: メニュー説明 - required_time: - type: integer - description: 所要時間 - price: - type: integer - description: 料金 - Reviews: - type: object - properties: - count: - type: integer - description: 検索件数 - items: - type: array - items: - $ref: "#/components/schemas/Review" - Review: - type: object - properties: - review_id: - type: string - description: レビューID - display_name: - type: string - description: トレーニーの表示名 - trainer_name: - type: string - description: トレーナー名 - comment: - type: string - description: レビューコメント - posted_at: - type: string - format: date - description: 投稿日時 - star_count: - type: number - format: float - description: 星の数 - responses: - BadRequest: - description: 400 Bad Request - content: - application/json: - schema: - $ref: "#/components/schemas/ProblemDetailError" - Unauthorized: - description: 401 Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/ProblemDetailError" - Forbidden: - description: 403 Forbidden - content: - application/json: - schema: - $ref: "#/components/schemas/ProblemDetailError" - NotFound: - description: 404 Not Found - content: - application/json: - schema: - $ref: "#/components/schemas/ProblemDetailError" - Conflict: - description: 409 Conflict - content: - application/json: - schema: - $ref: "#/components/schemas/ProblemDetailError" - UnprocessableEntity: - description: 422 Unprocessable Content - content: - application/json: - schema: - $ref: "#/components/schemas/ProblemDetailError" - InternalServer: - description: 500 Internal Server - content: - application/json: - schema: - $ref: "#/components/schemas/ProblemDetailError" - ServiceUnavailable: - description: 503 Service Unavailable - content: - application/json: - schema: - $ref: "#/components/schemas/ProblemDetailError" - securitySchemes: - Bearer: - type: http - scheme: bearer - bearerFormat: JWT - description: "Bearer トークン認証" diff --git "a/documents/forMarkdown/future_muscle_partner/docs/03_\343\203\207\343\203\274\343\202\277/index.md" "b/documents/forMarkdown/future_muscle_partner/docs/03_\343\203\207\343\203\274\343\202\277/index.md" deleted file mode 100644 index 1d2d0ff2..00000000 --- "a/documents/forMarkdown/future_muscle_partner/docs/03_\343\203\207\343\203\274\343\202\277/index.md" +++ /dev/null @@ -1,5 +0,0 @@ -# テーブル一覧 - -[A5:SQL Mk-2](https://a5m2.mmatsubara.com/) で管理している。 - -- [erd.a5er](https://github.com/future-architect/coding-standards/raw/gh-pages/example-resources/erd.a5er) を参照 diff --git a/documents/forMarkdown/future_muscle_partner/docs/README.md b/documents/forMarkdown/future_muscle_partner/docs/README.md deleted file mode 100644 index 3bb2564e..00000000 --- a/documents/forMarkdown/future_muscle_partner/docs/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# docs - -設計ドキュメントを管理する。 - -## フォルダ階層 - -```sh -docs -├── 01_画面 # Figma、画面アクション -├── 02_WebAPI # openapi.yaml、API処理設計 -├── 03_データ # erd.a5er(ERD)、区分値 -├── ... -└── README.md -``` - -## 設計書 - -- [01\_画面](./01_画面/index.md) -- [02_WebAPI](./02_WebAPI/index.md) -- [03\_データ](./03_データ/index.md) - -## コード体系 - -機能IDのコード体系は以下に従う。 - -| 種別 | 種別 | 例 | 備考 | -| ---- | ---------------- | ------------ | ---------------------- | -| UIS | 通常画面 | UIS01、UIS02 | UI Standard から | -| UIM | モーダル画面 | UIM01、UIM02 | UI Mordal から | -| API | Web API | API01、API02 | | -| IFS | システムI/F 送信 | IFS01、IFS02 | InterFace Send から | -| IFR | システムI/F 受信 | IFR01、IFR02 | InterFace Receive から | -| BAT | バッチ | BAT01、BAT02 | BATch から | -| RPT | 帳票 | RPT01、RPT02 | RePorT から | - -コード体系について補足: - -- UISであれば、 `UIS(0[1-9]{1}|[0-9]{2}` といったフォーマットに従うこと -- Future Muscle Partnerのプロダクト規模であれば、機能数が爆発しないという想定で2桁とする - - 万が一あぶれた場合、16進数と見なしてA~Fを導入する拡張を行う - -機能IDの採番について注意点: - -- 採番後の変更は許可しない -- 連番とする(数字部分に新しい体系を作らない) - -## 画面設計書の記載方針 - -- Web API の応答項目が、画面項目のどこにマッピングすべきかという情報は、多くの業務画面で重要である - - 理由は、類似名称の項目がWeb API応答項目にも画面項目多く、紐づけの認識の齟齬が生じやすいからである -- future muscle partnerにおいては、項目数は多くなくFigmaを見れば自明であるため、画面項目定義を省略する diff --git a/documents/forMarkdown/future_muscle_partner/docs/future_muscle_partner_abstract.png b/documents/forMarkdown/future_muscle_partner/docs/future_muscle_partner_abstract.png deleted file mode 100644 index 2f816600..00000000 Binary files a/documents/forMarkdown/future_muscle_partner/docs/future_muscle_partner_abstract.png and /dev/null differ diff --git a/documents/forMarkdown/future_muscle_partner/index.md b/documents/forMarkdown/future_muscle_partner/index.md deleted file mode 100644 index 08606944..00000000 --- a/documents/forMarkdown/future_muscle_partner/index.md +++ /dev/null @@ -1,36 +0,0 @@ -# Future Muscle Partner - -「いきつけのジムでパーソナルトレーニングを受けよう」のFuture Muscle Partnerのリポジトリ。 - -## サービスコンセプト - -パーソナルトレーナーを身近なものにして、質が高く安全で楽しいフィットネス体験を提供する。 - -![アプリを通してトレーニがトレーナに予約し、トレーニングを実施するフロー](docs/future_muscle_partner_abstract.png) - -サービス概要: - -- アプリ上でジム公認のトレーナーを検索&予約し、いきつけのジムでトレーニングを受けることができる - -主なアクターとメリット: - -- トレーニー - - 自分が通っているジムでパーソナル受けられる - - トレーナーの得意分野ごとにトレーナーを使い分けられる -- パーソナルトレーニー - - 24H型ジムでサービスを提供できる - - いつ/誰に/どんなメニューでトレーニングしたかを管理できる - -## フォルダ階層 - -```sh -. -├── backend # バックエンド系のコード -├── docs # 設計書 -├── frontend # フロントエンド系のコード -├── infra # インフラ系のコード -``` - -## 設計書 - -[docs](docs/README.md) を参照。 diff --git a/documents/forMarkdown/index.md b/documents/forMarkdown/index.md deleted file mode 100644 index ab02e19b..00000000 --- a/documents/forMarkdown/index.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -sidebarDepth: 4 -author: フューチャー株式会社 -layout: home -hero: - name: "Markdown設計ドキュメント規約" - tagline: Future Enterprise Markdown Design Document Standards - actions: - - theme: brand - text: Markdown設計ドキュメント規約 - link: ./markdown_design_document.md ---- - -# Markdown設計ドキュメント規約 - -Markdown ベースの設計ドキュメントの規約をまとめる。 - -- [Markdown設計ドキュメント規約](markdown_design_document.md) - -次のリンクから単一ファイル版を取得できます。 - -- [Markdown](https://github.com/future-architect/coding-standards/blob/master/documents/forMarkdown/markdown_design_document.md) -- [HTML(Single File)](https://github.com/future-architect/coding-standards/blob/gh-pages/resources/Markdown設計ドキュメント規約.html) ([ブラウザで見る](https://future-architect.github.io/coding-standards/resources/Markdown設計ドキュメント規約.html)) -- [Word](https://github.com/future-architect/coding-standards/raw/gh-pages/resources/Markdown設計ドキュメント規約.docx) - -ファイルは[Pandoc]を利用して作成しています。 - -[pandoc]: https://pandoc.org/ diff --git a/documents/forMarkdown/markdown_design_document.md b/documents/forMarkdown/markdown_design_document.md deleted file mode 100644 index 429e742d..00000000 --- a/documents/forMarkdown/markdown_design_document.md +++ /dev/null @@ -1,478 +0,0 @@ ---- -sidebarDepth: 4 -title: Markdown設計ドキュメント規約 -author: フューチャー株式会社 -head: - - - meta - - name: keywords - content: Slack ---- - - - -本規約は、世の中のシステム開発プロジェクトのために無償で提供致します。 -ただし、掲載内容および利用に際して発生した問題、それに伴う損害については、フューチャー株式会社は一切の責務を負わないものとします。 -また、掲載している情報は予告なく変更することがございますので、あらかじめご了承下さい。 - -# はじめに - -Markdown ベースの設計ドキュメントの規約をまとめる。 - -システム開発にて利用する設計ドキュメントを Markdown ベースにすることで、コーディングと同じ慣れたツールを用いて、Git によるバージョン管理、レビュープロセス、CI/CD などに自動化(静的解析、自動生成)を行いやすくし、ドキュメントを陳腐化させず、俊敏な設計開発を目指す。 - -Markdown に限った話では無いが、どういった内容を設計書に記載すべきかは悩むポイントは多い。 - -本規約では、アプリケーションの種別ごとに記載すべき内容と、それをどのような Markdown の構造で記載するかを規約化し、各チームで悩む余地を減らし、注力すべきことに集中できる環境を提供することを目的とする。 - -# 前提 - -本規約は以下の前提で作成されている - -- チーム/プロジェクトが 3 ~ 10 名程度の規模 -- Git(GitHub, GitLab)で管理され、コードと設計書が同一リポジトリで管理される -- システム開発で必要なアプリケーション開発 - -# 免責事項 - -::: warning 有志で作成したドキュメントである - -- フューチャーアーキテクトには多様なプロジェクトが存在し、それぞれの状況に合わせて工夫された運営方針が存在する。本規約はフューチャーアーキテクトの全ての部署/プロジェクトで利用されているわけではなく、有志が観点を持ち寄って新たに整理したものである。相容れない部分があればその領域を書き換えて利用することを想定している - -::: - -# 本規約で紹介する設計ドキュメントの位置付け - -設計ドキュメントは様々な前提条件/制約/経緯で作成され、Excel/Word/パワーポイントなどのファイル形式で作成することが多い。 - -本規約はそれらを否定するものではなく、様々な利害関係者の要求に応え洗練され続けた上記の設計ドキュメントのテンプレートには、強く敬意を表する。 - -一方で、設計ドキュメントを精緻に管理していく優先度より、プロダクト開発の効率とビジネスピードをより重視する場合もあり、それらの開発チームでは設計ドキュメントが存在さえない、あっても設計書が実装と乖離しているなどの問題が世間で課題提起されることも多い。 - -本規約では、後者のプロダクト開発の効率性を重視し、設計ドキュメントが開発以外の観点から求められない場合において、必要最低限必要だと思われるレベルの記載のサンプルを提供する。 - -また、設計ドキュメントのファイル形式に制約は無いという前提に立つため、設計ドキュメントの陳腐化を防ぐのに有効だと思われる、テキストベース(Markdown)でGit管理するという思想を採用する。 - -本規約で紹介した各設計ドキュメントの記載内容を参考にしつつ、各開発チームにおいて必要な情報を追加/削除して利用するという、テンプレートとしての利用を想定する。 - -# テキストベースにおける設計書の注意点 - -特に扱いで留意すべき点として、列数が多い表形式で設計ドキュメントを記載するケースがある。 - -Markdownで表を記載することは可能ですが、列数が多い場合は保守性が非常に低くなり、git diffを用いた差分が見れるメリットも下がる。 - -例えば、1つの画面の利用項目数が数十以上になり得る場合は、Excelなどのファイル形式を利用することを推奨する。 - -# フォルダ階層の推奨 - -リポジトリ直下に `docs` フォルダを作成し、その配下に設計ドキュメントとなる Markdown ファイルを配備する。 - -次はバックエンド、フロントエンド、インフラのコードをモノリポで管理している例である。 - -```sh -. -├── backend # バックエンド系のコード -├── docs -├── frontend # フロントエンド系のコード -├── infrastructure # インフラ系のコード -``` - -`docs` 配下は以下のルールにしたがった構造を取る。 - -- `01_`、`02_` といったプレフィックスを持つ -- 番号には体系をもたせず、必要になったタイミングでインクリメントさせる -- オンボーディングコストを抑えるため、なるべく先頭に新規参画者が欲する情報を配備する - -構成例を次にあげる。 - -```sh -docs -├── 01_キャッチアップ # ドメイン知識など抑えておくべき前提知識 -├── 02_環境構築 # -├── 03_開発規約 # GitFlowなど、リリース方式、CI/CD周り -├── 04_ユーザーストーリー -├── 05_UI設計 # Figmaのパスなど -├── 06_画面設計書 -├── 07_API設計書 # OpenAPIのパス+各BL設計 -├── 08_データモデル # ERD, テーブル定義 -├── 09_IF設計書 # I/F定義+受信/送信BL設計 -├── 10_バッチ設計書 # タイマー、イベント起動の非同期処理のBL設計 -├── 11_インフラ設計 # 監視、キャパシティサイジング、コスト -├── ... -└── README.md -``` - -# システム構成図 - -図は基本的に変更差分がGitと相性が良い、PlantUML(またはMermaid.js)で作成すること。PlantUMLの場合、テーマは `toy` を指定すること。 - -```plantuml -@startuml -!theme toy - -participant Participant as Foo -note over Foo: Event -actor Actor as Foo1 -boundary Boundary as Foo2 -control Control as Foo3 -entity Entity as Foo4 -database Database as Foo5 -collections Collections as Foo6 -queue Queue as Foo7 -Foo -> Foo1 : To actor -Foo -> Foo2 : To boundary -Foo -> Foo3 : To control -Foo -> Foo4 : To entity -Foo -> Foo5 : To database -Foo -> Foo6 : To collections -Foo -> Foo7: To queue - -@enduml -``` - -システム構成図などは上記では対応しにくいことが多いため、diagrams.net(draw.io)で作成する。 - -diagrams.netの場合は、拡張子は以下のいずれかで作成する。 - -- `.drawio.png` -- `.drawio.jpg` -- `.drawio.svg` - -# フロントエンド - -以下の方針を取る。 - -- Figmaを用いて、画面遷移、画面表示項目を定義する -- Markdown設計書には、Figmaで判断可能な見た目の情報は **記載しない** -- Markdown設計書には、Web APIの呼び出しやイベントの定義、パラメータの受け渡し、バリデーションロジックなどを定義する。 - -[サンプル設計書](./future_muscle_partner/index.md)を参考にする。 - -# バックエンド - -## テーブル定義書 - -[A5:SQL Mk-2](https://a5m2.mmatsubara.com/)を用い、`erd.a5er` という名称で管理する。 - -以下の情報の管理は `erd.a5er` で行えないため、別で定義する。 - -- 保持期限 -- 個人情報有無 - -## 区分値 - -設計書サンプルを以下に示す。 - -::: tip 区分値設計書サンプル - -```md -# ENUM01 ユーザー権限 - -## 区分値概要 - -- 目的: 画面のモードの切り替えに利用する -- 物理名: user permission level -- 型: string -- スコープ: frontend, backend -- マスターテーブル: m_user_role - -## 区分値定義 - -| 論理名 | 物理名 | 値 | バージョン | コメント | -| ------------------ | --------------- | --- | ---------- | -------- | -| ゲスト | guest | 01 | 1 | | -| 未認証ユーザー | unauthenticated | 02 | 1 | | -| 登録ユーザー | user | 03 | 1 | | -| プレミアムユーザー | premium_user | 04 | 2 | | -| 開発者 | developer | 05 | 0 | | -| テスター | tester | 06 | 0 | | -| 管理者 | administrator | 07 | 0 | | -``` - -::: - -## メッセージ定義 - -::: tip メッセージ定義サンプル - -```md -## メッセージ定義 - -| 識別子 | レベル | ステータス | メッセージ | コメント | -| ------ | ------ | ---------- | ------------------------------------------ | ---------------------------- | -| 10001 | E | 400 | ユーザー名またはパスワードが間違っています | ログイン画面で発生 | -| 10002 | W | | 文字数オーバーです | ログイン画面で発生 | -| 10003 | E | 500 | {domain}は無効なユーザードメインです | ユーザーの所属が異なっている | -| 10004 | F | 500 | EntraIDに接続できません | ログインのバックエンドで発生 | -``` - -::: - -## Web API 設計書 - -API 定義書は `openapi.yaml` で記載すること。 - -詳細は[OpenAPI Specification 3.0.3規約](https://future-architect.github.io/coding-standards/documents/forOpenAPISpecification/OpenAPI_Specification_3.0.3.html) を参考にする。 - -## プログラム設計書(バッチ、非同期タスクなど) - -::: tip プログラム設計書サンプル - -````md -# BAT01 xxx 計算 - -## 処理概要 - -- xxx(なぜこれが必要なのか) -- xxx受信の後続処理で起動し、xxx計算を行いxxxトランに登録する(処理の概略) - -## 処理シーケンス - -```plantuml -@startuml -!theme toy - -participant システム -database DB - -note over システム: 各種インプット取得 - -システム -> DB: 業務日付取得 [日付マスタ] -システム -> DB: 計算対象抽出xxx\n[xxx受信管理トラン]\n[xxx受信ワーク]\n[xxxマスタ]\n[yyyマスタ]\n[zzzマスタ] -システム -> システム: 支払い差し引き金額計算(※ビジネスロジック1) -システム -> DB: 登録\n[xxxトラン] -システム -> DB: 更新\n[xxx予測ワーク] - -@enduml -``` - -## ビジネスロジック - -### ビジネスロジック1 - -```txt -支払金額 = 受信ワーク.商品コード * xxx * xxx - yyyy - -IF xxx 区分 - 支払金額 = 支払金額 * 支払い係数 + (支払金額 - 前回発注金額)/2 -END -``` - -## DB 項目 - -### 取得 - -- xxxマスタ.支払い金額 -- xxxマスタ.特定商品区分 -- yyyマスタ.新古品フラグ -- zzzマスタ.前回発注金額 - -抽出条件: - -- xxx受信管理トラン.業務日付 = 業務日付 -- xxx受信管理トラン.処理連番 = xxx受信管理トラン の最新の処理連番 - -### 登録 - -- xxxトラン.会社コード = xxx -- xxxトラン.処理日付 = xxx -- xxxトラン.xxx区分 = xxx -- xxxトラン.支払金額 = ビジネスロジック1計算結果 - -### 更新 - -xxx 予測ワーク: - -- xxx 予測ワーク.優先度 -- xxx 予測ワーク.処理予定日 -```` - -::: - -## プログラム設計書(Web API) - -Web APIについても、プログラム設計書(バッチ、非同期タスクなど)と同様に機能ID単位で作成する。 - -ただし、Web APIにおいては `openapi.yaml` と重複する部分で自明な内容(例えば、リクエストパラメータの定義や、レスポンス項目)については、重複するため記載を省略する。 - -もし、検索APIで複数のテーブルを参照して結果を応答する場合に、項目の由来を示すため、下表のような形式を定義すること。 - -### Web API応答例 - -| Parameter | Description | Settings | Note | -| --------------- | ------------- | ------------- | ---- | -| last_name | 氏名 (姓) | m_user | | -| first_name | 氏名 (名) | m_user | | -| last_name_kana | 氏名カナ (姓) | m_user | | -| first_name_kana | 氏名カナ (名) | m_user | | -| date_of_birth | 生年月日 | m_user_detail | | -| gender_type | 性別区分 | m_user_detail | | -| tel | 電話番号 | m_user_detail | | -| occupation_type | 職業区分 | m_user_detail | | -| zipcode | 郵便番号 | m_user_detail | | - -※Descriptionは `openapi.yaml` 側の `description` で記載済みであれば、省略すること -※Noteは何かしら加工処理により生み出された項目であれば、計算ロジックを記載する - -## I/F 定義書 - -I/F 定義書は、システム間の連携について定義と、その受信/配信処理の設計書です。 - -システム I/F は連携先の対向システムが存在するため、認識齟齬が無いように、どのようなプロトコル・項目であるかを定義する必要がある。 - -::: tip I/F設計書サンプル - -````md -# IF01 設備有効開始受信 - -設備有効開始の取り込みを行う。 - -## 対向システム - -| 連携元 | 連携先 | -| ---------- | ------ | -| A システム | Future | - -## 環境情報 - -### Input - -| Item | Value | -| ---------------- | ---------------------------------------------- | -| 連携 S3 バケット | `${env}-example-import` | -| プレフィックス | `activate/year=${yyyy}/month=${MM}/day=${dd}/` | -| ファイル名 | `${yyyy}-${mm}-${dd}-${hh}-${MM}-${SS}.csv` | -| 保持期限 | 3 年 | - -### Output - -| Item | Value | -| ---------------- | ---------------------------------------------- | -| 連携 S3 バケット | `${env}-example-import` | -| プレフィックス | `activate/year=${yyyy}/month=${MM}/day=${dd}/` | -| ファイル名 | `${yyyy}-${mm}-${dd}-${hh}-${MM}-${SS}.csv` | -| 保持期限 | 3 年 | - -## 連携元定義 - -| Category | Item | Value | Memo | -| -------- | ----------------------------------- | --------- | -------------------- | -| Protocol | 連携方式(ファイル/API/ストリーム) | ファイル | | -| | 連携タイミング(随時/定時) | 定時 | | -| | 頻度 | 1 回/日 | | -| | 起動時間 | **16:00** | | -| | 処理完了期限 | **16:00** | | -| | 未着チェック(なし/WARN/ERROR) | WARN | | -| | 全件/差分 | 差分 | | -| | 0 件時連携 | あり | | -| Format | ファイル種別 | **CSV** | | -| | レイアウト | RFC 8259 | | -| | 文字コード | UTF-8 | | -| | 改行コード | LF | | -| | 圧縮 | - | | -| | 暗号化 | - | | -| | ヘッダ行 | あり | | -| | 項目順 | 固定 | 項目順は入れ替え不可 | -| | 機密情報 | - | | - -### 項目定義 - -| Name | Physical Name | Type | Length | Precision | Enum | Format | Sensitive | Example | Memo | -| ---------- | --------------- | ------ | ------ | --------- | ---- | ---------- | --------- | ---------- | ---- | -| 会社コード | company_cd | string | 5 | - | - | - | - | 00001 | | -| 設備コード | device_cd | string | 8 | - | - | - | - | 00000052 | | -| 有効開始日 | activation_date | string | 10 | - | - | YYYY-MM-DD | - | 2022-10-16 | [^1] | - -[^1]: 現在日以降である必要があるが、受信ではテスト観点で過去日も許容する - -#### サンプル - -```csv -company_cd,device_cd,activation_date -12121,00000052,2022-03-01 -12121,00000053,2022-03-30 -``` - -## 連携先定義 - -| Category | Item | Value | Memo | -| -------- | ----------------------------------- | --------- | -------------------- | -| Protocol | 連携方式(ファイル/API/ストリーム) | ファイル | | -| | 連携タイミング(随時/定時) | 定時 | | -| | 頻度 | 1 回/日 | | -| | 起動時間 | **16:00** | | -| | 処理完了期限 | **16:00** | | -| | 未着チェック(なし/WARN/ERROR) | WARN | | -| | 全件/差分 | 差分 | | -| | 0 件時連携 | あり | | -| Format | ファイル種別 | **CSV** | | -| | レイアウト | RFC 8259 | | -| | 文字コード | UTF-8 | | -| | 改行コード | LF | | -| | 圧縮 | - | | -| | 暗号化 | - | | -| | ヘッダ行 | あり | | -| | 項目順 | 固定 | 項目順は入れ替え不可 | -| | 機密情報 | - | | - -## 処理概要 - -- ファイル定義に則ったバリデーションを実施 -- 次の項目変換定義に従い加工し、出力先テーブルに Merge する -- 受信完了後、 Completed: YYYY-MM-DDTHH:MI:SS.SSS のタグを追加する - -## 処理シーケンス - -```plantuml -@startuml -!theme toy - -participant システム -participant S3 -database DB - -システム -> DB: 処理日付取得\n[日付管理] -システム -> S3: 対象ファイルの存在チェック -alt ファイルが存在しなかった場合 - システム -> システム: 処理終了して、次の処理を待機 -end -システム -> DB: シーケンスの取得\n[シーケンスオブジェクト] -システム -> DB: 1.実行開始レコード追加\n[IF受信管理] -システム -> S3: 対象ファイルを取得 -システム -> DB: 対象マスタのTruncate -システム -> DB: ファイル連携処理 -システム -> システム: 連携件数確認 -システム -> S3: 処理済対象ファイルを格納 -システム -> DB: 2.実行終了状態の更新\n[IF受信管理] -@enduml -``` - -## DB 項目 - -### 参照 - -なし - -### 登録 - -リストワークに以下のカラムでレコードを登録する - -- xxx ワーク.会社コード -- xxx ワーク.処理日付 -- xxx ワーク.yyy 区分 - -### 更新 - -なし - -## ビジネスロジック - -特記事項なし - -## エラー処理 - -| Pattern | Description | recovery | -| ------------------ | ------------------------------------------ | -------------------------------------- | -| フォーマットエラー | 連携元から提供されているデータ形式が想定外 | 連携元またはIFの処理内容の修正と再実行 | -```` - -::: diff --git a/documents/forSlack/index.md b/documents/forSlack/index.md deleted file mode 100644 index d23f2db9..00000000 --- a/documents/forSlack/index.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -sidebarDepth: 4 -author: フューチャー株式会社 -layout: home -hero: - name: "Slack利用ガイドライン" - tagline: Slack Usage Guidelines - actions: - - theme: brand - text: Slack利用ガイドライン - link: ./slack_usage_guidelines.md ---- - -# Slack利用ガイドライン - -チーム開発する上で必要となるGitブランチフローの規約です。 - -- [Slack利用ガイドライン](slack_usage_guidelines.md) - -次のリンクから単一ファイル版を取得できます。 - -- [Markdown](https://github.com/future-architect/coding-standards/blob/master/documents/forSlack/slack_usage_guidelines.md) -- [HTML(Single File)](https://github.com/future-architect/coding-standards/blob/gh-pages/resources/Slack利用ガイドライン.html) ([ブラウザで見る](https://future-architect.github.io/coding-standards/resources/Slack利用ガイドライン.html)) -- [Word](https://github.com/future-architect/coding-standards/raw/gh-pages/resources/Slack利用ガイドライン.docx) - -ファイルは[Pandoc]を利用して作成しています。 - -[pandoc]: https://pandoc.org/ diff --git a/documents/forSlack/slack_usage_guidelines.md b/documents/forSlack/slack_usage_guidelines.md deleted file mode 100644 index 44c2217d..00000000 --- a/documents/forSlack/slack_usage_guidelines.md +++ /dev/null @@ -1,390 +0,0 @@ ---- -sidebarDepth: 4 -title: Slack利用ガイドライン -author: フューチャー株式会社 -head: - - - meta - - name: keywords - content: Slack ---- - - - -本規約は、世の中のシステム開発プロジェクトのために無償で提供致します。 -ただし、掲載内容および利用に際して発生した問題、それに伴う損害については、フューチャー株式会社は一切の責務を負わないものとします。 -また、掲載している情報は予告なく変更することがございますので、あらかじめご了承下さい。 - -# はじめに - -リモートワーク/ハイブリッドワーク前提の業務において、チャットなどの非同期コミュニケーションを円滑に進めることは、業務効率を向上させるだけではなく、従業員全員の満足度を向上させ、より良い職場づくりに繋げることができる。 - -また、ユーザーの様々な要望に応えるため、現代のチャットサービスは豊富な機能が提供されている。しかし、各ユーザーの考え方/利用者の感覚が千差万別であるため、ある人によって問題ないとされる行動が、別の人にとっては良くない受け取り方をされることも多い。例えば次のような対立が考えられる。 - -- 必要最低限の簡潔なメッセージを送る方が効率的だ/文面が冷たくならないように絵文字や感嘆符(!)を使うべきだ -- 質問はDMで行うべき/チャンネルで行うべき -- times(分報)チャンネルを活用すべき/ノイズなので個人のメモに閉じるべき - -これら運用方法は利用者の所属する部署やチームごとに自然と決めていくことが多いが、複数のチャンネルで異なった運用方針である場合に混乱をきたすことがしばしばである。また、トレードオフを理解せずに、メールのコミュニケーションモデルを引きずった方針を取ってしまうこともある。異なる文化圏のチームから移籍した時に、ハレーションが起きるケースも多い。 - -本ガイドラインはSlackを対象に利用方針についてのベースとなる規約を設け、Slackを用いてより良いコミュニケーションを促進することを目的とする。 - -# 適用範囲 - -- 「はじめに」章で述べた、一般ユーザー視点での利活用を中心とする -- 次のような特に管理者が関心を持つ事項については対象外とする - - パスワードポリシー/多要素認証の強制 - - 社外メンバー招待/ゲストレベルの調整 - - 監査 - -# 免責事項 - -::: warning 有志で作成したドキュメントである - -- フューチャーアーキテクトには多様なプロジェクトが存在し、それぞれの状況に合わせて工夫された運営方針が存在する。本規約はフューチャーアーキテクトの全ての部署/プロジェクトで利用されているわけではなく、有志が観点を持ち寄って新たに整理したものである。相容れない部分があればその領域を書き換えて利用することを想定している -- 自社のセキュリティポリシーや外部サービス利用ポリシーがある場合は、そちらを優先すること -- Slack Enterprise Grid/Google Workspaceを利用しているため、それらの機能を前提にしている記述がある - -::: - -# 管理者向け推奨設定 - -## Workspace Access - -チーム、プロジェクトでの利用の場合は リクエスト制(`By Request`) もしくは招待性( `Invite Only`)の設定を推奨する。 - -## デフォルトチャンネル - -通常ワークスペースにメンバーを追加した際には `#general` へ自動参加するが、他にもメンバー全員に参加して欲しいチャンネルがある場合にはデフォルトチャンネルを追加する。 - -::: tip 💡ユーザグループに対してもデフォルトチャンネルを設定できるため、用途に応じて使い分けると良い。 -::: - -## 表示名ガイドライン - -ワークスペースごとにガイドラインを設定することを推奨する。後述の表示名設定や、その他チームコミュニケーションにおけるルールを設定する。表示名のガイドラインを設定する権限があるのは、ワークスペースのオーナーだけなので注意する。 - -## ワークスペースの管理者 - -ワークスペース内に複数のチームが混在する場合、それぞれのチームごとに管理者権限保持者を設定すること。 - -理由: - -- 管理者権限を持った人しか実行できないオペレーションがあった際、チーム内で解決できる状態を作っておくことが望ましいため - -# ユーザ向け推奨設定 - -## アカウントアイコンを設定する - -デフォルトのアイコン利用は極力避け、アカウント登録時に各自のアイコン画像を積極的に登録する - -理由: - -- チャットコミュニケーションにおいて、個人識別におけるアイコン画像の有用性が高いため - -また、GitHub/GitLab、Google Workspace、その他利用サービスも同様のアイコンを利用することで、個人を識別しやすくなる。 - -## 検索性の高い氏名(Full name)を設定する - -表示名(Display name) もしくは氏名(Full name) にて、ローマ字及び漢字(無ければカタカナ)でのフルネームを登録すること。表示名はチームごとに記載文化や書き方が異なるケースが多いので、本ガイドラインでは氏名に記載することを推奨する。例えば「未来 太郎」の場合、「Taro Mirai (未来 太郎)」という記載を推奨する。 - -理由: - -- Slackではアカウント名のインクリメンタルサーチが強力である。その際、ローマ字でも漢字でもサジェストされる状態にすることでユーザビリティの向上が期待できるため。 - -## ユーザーグループの推奨 - -ユーザーグループの利用を推奨する。ゲストユーザーは追加できないため、もしチャンネルに該当するメンバーが在籍する場合は、その旨をメンバー全員が理解しコミュニケーションから除外してしまわないように注意すること。 - -::: tip 💡ユーザーグループを作成できない状態の回避策 -ユーザーグループを作成できない状態(メンバーがワークスペース間にまたがっている場合等)の時、メンション先の対象者全員が個別に自分のSlack設定\>Notification\>My Keywordsに「@○○チーム」と予約語を登録することで、擬似的にグループメンションが可能である -::: - -# チャンネル命名規則 - -## 外部組織メンバーが在籍するチャンネルの命名 - -Slack コネクト等でチャンネル内に社外のメンバーが含まれる場合には、チャンネル名の先頭に `---ext` をつける - -理由: - -- 全社的に統一的なプレフィックスを定義することで、外部とのコミュニケーションにて予期しないミスが発生してしまうことを防ぐ目的がある。例えば、内部の進行について相談する発言を、取引先メンバーが在籍するチャンネルに誤投稿してしまう事態を避けるため -- チャンネルはセクションという単位でグルーピング可能となり、従来のように、用途や組織を表現するプレフィックスで並び順を制御する必然性が薄れた - -# 投稿内容ポリシー - -## 敬称は不要 - -敬称は省略して、 `@mano メッセージ内容` といった形式でコメントすること。もし、どうしても敬称を付けて欲しい場合、表示名をさん付けにするハックも存在するため、受信者側で調整する。 - -理由: - -- コミュニケーションを迅速・シンプルにするため - -## 絵文字や感嘆符を活用する - -積極的に活用することを推奨する。テキストコミュニケーションは、画像や音声が伝わらない分、冷たく捉えられがちである。特にリーダーなど上位のポジションにいる場合は、メンバーに威圧的に捉えられないように配慮するのが好ましい。 - -「では、Aの方針でよろしくお願いします!」「では、Aの方針でよろしくお願いします:ganbatte:」 など付けることで、不機嫌でないことがわかり、心理的安全性が保たれる。 - -積極的にカスタム絵文字を追加することを推奨する。チーム内でしか通用しない(例えば内輪ネタのような)カスタム絵文字であっても気軽に追加して良い。 - -理由: - -- より良いコミュニケーション手段を模索すること自体が、コミュニケーションを活性化させ、価値を向上させるため - - なお、当然ながら他人の名誉を毀損するなど、社会人/プロフェッショナルとしてふさわしくない内容は登録しないこと - -## 絵文字リアクションによる積極応答 - -非同期のコミュニケーションにおいて発信者が気になる点として、「投稿内容を見てくれたのかどうか」がある。特に確認依頼については見ていればOKで、回答は急がないケースは想像以上に多い。 -こういった場面では、::後で確認します:: といった絵文字リアクションを付けることで解決するため、積極的に活用する。 - -また、参加者が多いチャンネルでの発信は勇気がいることなので、コミュニケーションを活性化させるためにも絵文字リアクションを積極的に行い推奨/礼賛することが望ましい。 - -::: warning ⚠️「〇〇してほしい」「〇〇について教えてほしい」(相談セクション)への対応は絵文字リアクションだけで済まさない -「投稿内容を見てくれたのかどうか」ではなく、「投稿内容を理解して次のアクションをとってくれるのか」を知りたい場面も多い。 -そのような場面では、絵文字リアクションのみで済まさず、対応可否をコメントでフィードバックする必要がある。 -::: - -## DMはなるべく避ける - -基本的には、DMよりチャンネルでのやり取りを推奨する。チャンネルであっても、より参加人数が多い(よりオープンな)チャンネルでのやり取りを推奨する。 - -理由: - -- 重複した質問を防ぐため -- 質問事項がチーム/組織に共有されることで、全体の効率が上がるため -- 後から類似の困りごとを持ったメンバーが、キーワード検索で見つけやすくするため - -DMの利用を推奨するケース: - -- 人事相談、機密事項を含む場合(「機密情報の流出に注意する」章を参照) -- 限られたメンバーのみに、ファイル共有をしたい場合 -- 後から検索させる意味がないやり取り(「最近元気?」と同期に投げる場合など) - -## timesの推奨 - -timesとは、分報や作業スレッドとも呼ばれ、今取り組んでいることや困っていることを投稿することを指す。 - -本規約の推奨は次のとおり: - -- timesの利用を推奨する -- メンバーごとのtimesチャンネルではなく、スレッドでの利用を推奨する -- timesスレッドは、他のメンバーは参照しても参照しなくてもどちらでも良い - -理由: - -- スレッド単位であれば、本チャンネル側のノイズになることはない。参加メンバーが多い場合は、times専用のチャンネルを作成すれば良い -- メンバーごとの times チャンネルは、チャンネルが必要以上に増えるので推奨しない -- 必要に応じて、作業状況を本人に確認(ポーリング)しなくても把握することができる -- ハマったことや調べたことが、後々キーワード検索で見つかり、新規参画者の助けになることも多い - -::: warning ⚠️timesスレッドの注意 -times内とはいえ、他の人が不快になるような発言や不適切な利用は避ける(チームメンバーが閲覧可能であることを忘れない) -::: - -::: tip timesスレッドでのやり取りにこだわりすぎない - -- timesスレッドのコメント数は100以上になることもあり、途中で他メンバーに相談事などでメンションを飛ばすと、呼ばれたメンバーには「該当のスレッドの全コメントをチェックしたほうが良いのか」といった迷いが生じる。そのため、times内ではなく相談は別メッセージに切り出して行うことを推奨する -- なお、timesの投稿を読んで欲しいときは、timesスレッドでメンションしても良い -- timesのメンションを受けたユーザーが、その後の投稿の通知を受け取りたくない場合は、そのスレッドの通知を切ることで対応する - -::: - -::: tip スレッドのフォローは適当なタイミングで外す(外してもらう) -timesスレッドでメンションされると、その後にもスレッド内の投稿がメンション先のユーザーに通知が飛び続けてしまうのではないか?という懸念がある。 - -- 該当スレッドの必要に応じてフォローを外せば良いので、上記観点でメンションを行う/行わないの判断は行わなくても良い -- 前述の通り、timesのコメントを(全て)読んで欲しい否かでスレッド内でメンションするかどうかを決める - -::: - -## メッセージ(スレッドのトップ)は具体的に書く - -チャンネルのメッセージ(スレッド先頭の投稿)では、話題を端的に表現する。ただし、返信スレッドの中を確認しないと内容が分からないようなメッセージ(タイトル)は非推奨とする。 - -| | メッセージ(スレッド先頭の投稿) | -| :--------- | :--------------------------------------------------------------------------------------------------------------------- | -| ✅推奨例 | @mirai チケット \#4191 foo bar failed のビルドエラーの解消についての相談です。スタックトレースはスレッド内に記載します | -| ❌非推奨例 | レビュー依頼 | - -なお、メンションはメッセージ(スレッド先頭)に付けるか、返信スレッド内に付けるかは任意とする。 - -参考: - -- [Slackで要件を書かずに「質問があります。詳細はスレッドに記載」をやめたほうがいい理由 \- CARTA TECH BLOG](https://techblog.cartaholdings.co.jp/entry/better_slack_communication) -- [リモートワーク時代を生き抜くAI・機械学習チームの働き方 \- エムスリーテックブログ](https://www.m3tech.blog/entry/2024/12/07/110000) - -## メッセージのURLを活用する - -Slackは本来、フロー情報向けのツールである。しかしこれをWikiなどのストック情報向けツールに転記する労力は高く、運用が形骸化しがちである。そのため、例えばあるスレッドで設計方針について議論したのであれば、そのスレッドのURLをコピーして、作業チケットやWikiなどに記載し、トレース可能にするような運用にするチームも良く聞く。本規約もスレッドURLの活用を推奨する。 - -なお、決定事項の経緯や議論内容を数年経過したのちに確認することもしばしば発生する。そのため議論があればスレッドを利用し、かつ同一スレッドで複数のテーマを混ぜないことが望ましい。関連議論がいくつかのスレッドに分かれる場合、相互に関連スレッドのURLを投稿しておくと良い。 - -::: tip 💡Slackにおける情報ストック機能 -Canvas、ブックマーク、ピン留め機能を活用することで、Slack内にてストック情報を取り扱うことも可能である。PJで利用している課題管理サービスのURLを共有したい場合にはブックマーク、PJメンバーに都度参照して欲しい特定のメッセージがある場合にはピン留め、情報量が多く章立てて整理をしたい場合にはCanvas、などといった形でユースケースに合わせて使い分ける。 -::: - -## Also send to channelは乱発しない - -Also send to channel を利用することで、スレッド内の投稿をチャンネルのタイムライン側に重複投稿ができる。 - -本規約の推奨は以下の通り: - -- 過去のスレッドでやり取りを再開した場合に、チャンネルに在籍するメンバーに通知する目的で用いる -- スレッド内で重要な決定事項に至った場合は、メンバーに周知する目的で用いる -- スレッド内のやり取りを細かくAlso send to channelすると、スレッドを用いる意味が薄れるので、利用頻度は抑えるように意識する - -## 広めの通知に注意する - -### `@channel` - -緊急時を除き、原則利用を禁止する。 - -理由: - -- `@channel` はSlackを見ていないユーザにも通知が飛ぶため、休暇中のメンバー等にも影響がある。受取側で制御すべきという考えもあるが、システム障害対応など優先度の高い問い合わせのために、あえてOFFにしていないメンバーも存在することを考えると、なるべく利用を避けた方が無難である - -利用して良い場合: - -- システム障害時など、重大かつ緊急度が高い場合は `@channel` を使っても良い - -### `@here` - -メールのCCに似た意図で `@here` を使うことは禁止とする。 - -推奨ケース - -```txt -@真野 @村田 ○○の件ですが\~ -``` - -NG(メールのCC的な形で `@here` を追加) - -```txt -@真野 @村田 @here ○○の件ですが -``` - -理由: - -- メールのCC的な参考情報であれば、`@here` を付けずに、チャンネルの未読通知で後で見ることができるため -- 真に必要ではないときに通知が飛ぶことが常態化すると、`@here` の緊急性やアクションを求める意味合いが弱まり、真に必要なときに読み飛ばされてしまう可能性が上がるため(「狼少年」現象) - -利用して良い場合: - -- 全員にアクションを促す連絡事項を行う場合。例えば、チーム全体イベントへの出欠可否を確認する連絡など - -## メンション範囲は適切に - -### 過剰なメンションの抑制 - -原則、レビュー依頼や確認依頼など、行動してほしい時にメンションを付けるものとする。「@mirai ありがとうございます!」「@mirai 承知しました!」等の挨拶にメンションを付けると、通知が来てノイズになるため非推奨とする。メンションを付けず「ありがとうございます!」とすると良い。 - -::: tip 💡情報提供依頼系など善意やり取りはきちんとフィードバックする -情報提供依頼はSlackと親和性が良いタスクである。この際、情報提供の依頼者は、回答してもらった人に対して、:+1: 絵文字だけのリアクションを取る場合があるが、フィードバック付きでコメントを返すことが望ましい。情報提供者としても、その情報が役立ったのか、またそうでないかの関心は強いためである。 -もし、フィードバックが難しい場合や、スレッド投稿数をなるべく減らしたいなどの意図がある場合は、複数のリアクションを返し感謝の意を強調すると良い。 👍️🎉☺\[神\] のようなイメージである。 -::: - -### メンションの宛先をできる限り絞り込む - -単なる周知目的ではなく行動を促したい相手に絞ること。お見合いになってボールが浮いてしまう可能性がある。「@mirai @mano @murata @ozawa @tanimura AWSの設定で確認したいのですが~」などと広すぎる場合は、宛先メンバーは自分よりもっと詳しい人がいるかも知れないので、回答すべきかどうか逡巡してしまう。できれば1、2名に宛先を絞り、宛先メンバーから別の有識者メンバーにディスパッチしてもらう運用を考えると良い。 - -## 予約投稿を活用する - -特にリーダーからメンバーに対して、深夜(22:00-6:00など)や休日など業務時間外の投稿は原則禁止とし、予約投稿を推奨する。 - -理由: - -- 仕事とプライベートにメリハリを持たせることで、成果の向上を期待できるため -- (システム障害等)緊急時の依頼と混同してしまうため。次回出勤時の対応で良いものと区別すること -- Slackのアップデートにより、チャンネル投稿に閉じずスレッド投稿へも予約投稿が可能となった - -::: tip 💡受け取り側で制御する方針 -システム障害時などの緊急時は電話連絡とし、メンションに対する即対応を求めない取り決めを行うのであれば、受け取り側で通知時間を設定し、送る側は送信時間に気を遣わない運用も可とする。ただし、時間外に通知を受け翌営業日に対応しようと考えたが翌営業日には忘れているような場合、受け取り側で通知を受けた時点でリマインダーを仕込んだり、アクティビティ \> @メンション を定期的に確認するような工夫をする。 -::: - -## 不在の表明 - -表示名に不在情報を記載(例:`@sato_11/8休`)しておくことを推奨する。受信側が不在時に緊急性の低い通知を防げたり、送信側が即レスを期待しなくて済む。不在情報がGoogleカレンダーなど別のスケジュールアプリで管理されていたとしても、Slackでの依頼時に気付けるため。 - -::: tip 💡ステータス機能で「休暇中🏝️」にすればよいのではないか -ステータス機能でもチームメンバーに不在であるという状態を表明できる。しかし、次の観点で表示名での表明を推奨する。 - -- いつから、いつまで休暇なのかステータスでは不明である - - 期間が分かれば、予約投稿で休暇明けに投稿するなどのアクションがすぐ取れる -- 休暇だけでなく出張中などの情報も提示できる - - 例えば、海外出張なので時差があることが分かれば、チームメンバーにどれくらいでレスポンスが来そうか予想ができるようになる -- ステータス変更に気が付きにくい - - メンションを付けて投稿する時に常時表示されるわけではないので、ステータスは見過ごされる可能性が高い - -::: - -## 可読性を上げるための書式設定 - -箇条書き、太字、引用などの装飾は、積極的に活用する。文章を構造化することで、読み手にとっての負荷が軽減されるため。Slackの書式以外にも、【すみかっこ】等の記号を使うことでセクションを表現することも同時に推奨する。 - -## エラーメッセージの画像添付非推奨、テキストスニペットの推奨 - -有識者にスタックトレースなどのエラー内容を画像添付して問い合わせることは原則として非推奨とし、テキストで共有することを推奨する。また、共有内容が長文の場合にはテキストスニペット使用が好ましい。 - -理由: - -- 相談相手も裏取りとしてスタックトレースの内容を検索することが多々あるため -- 後から同様の困り事を持った人が、キーワード検索で見つけにくくなるため -- 長いログをそのまま貼り付けるとスレッドを広く埋め尽くしてしまうが、テキストスニペットを使えば1投稿あたりのデフォルト表示域を制限できる - -次の場合は、スクリーンショットなどの画像で共有しても良い。 - -- コピーできないエラー表示など、テキストでの情報提供が難しい場合 -- (相談相手が、コピー範囲などを独自判断で狭められることを防ぐなどの理由で)スクリーンショットでの共有を希望する場合 - -::: tip 💡テキストスニペット利用時は、タイトル(ファイル名)に拡張子をつける -Slackはテキストスニペットに設定されたタイトルをそのままファイル名としてダウンロードするよう動作する。この際拡張子が設定されていないとSlack内でそのままファイルを開くことができなくなってしまう。 -::: - -## 機密情報の流出に注意する - -営業情報、個人情報、人事情報など機密情報は、「最小権限の原則」に従い、なるべく宛先を狭めるべきである。センシティブなやり取りを行う場合は、参加者を絞ったプライベートチャンネル/DMグループの活用を推奨する。 - -:::tip 💡メッセージ通知にも気をつける -画面投影やWebミーティングでの画面共有時、意図しないメッセージ通知が見えてしまう事がある。Slackの通知設定にて次に示す設定を施すことで防ぐことが可能なので活用すると良い。 - -- 通知自体をOFFにする -- 通知はOFFにしないが、メッセージ内容は非表示にする - ::: - -## ファイルの共有に注意する - -Slackのファイル共有は便利であるが、ファイルのオーナー(作成者)とチャンネルにメンバー追加できる担当者が必ずしも1:1ではない。そのため次の運用が望ましい。 - -推奨する運用: - -- Google Driveなどにファイルをアップロードする -- Google Drive側で適切な権限に絞り込む - -理由: - -- Google Drive側で権限設定が可能 -- Slack上にアップロードされたファイルが、別のチャンネルに再アップロードされて収集がつかなくなるといったケースを防ぎ、統制を図るため - -該当しないケース: - -- 社外勉強会の登壇資料など、一般に「公開済み/公開予定 」のファイルはアップロードして良い - -Google DriveのURL共有時プレビュー表示について: - -- 表紙がプレビューされるが、次の理由により問題ないという立場を取る。 - - プレビュー表示されるのは1枚目(1シート目)であり、通常は表紙ページが見られるのみ - - ファイルが存在すること自体は知られて良い(チャンネルに投稿しているため)と考えられる - - なにか問題があれば、プレビュー表示を行わない操作がSlack上で可能である - -## プライベートチャンネルの投稿に対する引用 - -プライベートチャンネルの投稿コメントを、別のチャンネルにURL引用で投稿すると、該当チャンネルの権限を有していないユーザーにも参照権限を与えてしまう。引用時にはセンシティブな内容が含まれていないか確認するよう注意する。 - -# さいごに - -本ガイドラインの策定にあたっては、すでにインターネットに公開されているSlack利用ガイドラインや記事等も参照させていただいた。本ガイドラインが皆様のSlack活用をより快適にする一助となれば幸いである。 - -参考: - -- [メルカリ社内Slack利用ガイドラインを一挙公開しました〜!!\#メルカリな日々 | mercan (メルカン)](https://careers.mercari.com/mercan/articles/23325/) [mercari-Slack-guidelines/Slack_Guidelines_Ja.md at master](https://github.com/mercari/mercari-slack-guidelines/blob/master/Slack_Guidelines_Ja.md)