- 技術 💻
実装とは?意味・設計との違いを割引計算のコードとテストで解説
結論
IT でいう実装とは、設計で決めた内容を、実際に動くプログラム(コード)にして組み込むことです。設計が「何を・どう作るか」を決める作業なら、実装はそれを「作って、動くことを確かめる」作業です。
この記事でわかること
- 実装の意味と、設計・開発・コーディングとの違い
- 設計書の1行→コード→テストを割引計算で追った実物
- 境界値・小数・implements で実際に出たエラー原文
「実装」は、IT の仕事で毎日のように使われる言葉です。会議では「この機能は来週実装します」、コードでは「このクラスはインターフェースを実装しています」、ニュースでは「AI の社会実装」と、場面によって指すものが少しずつ違います。この記事では、まず意味をはっきりさせ、そのあと小さな機能を1つ、設計書からコードとテストまで実際に作って、実装という作業の中身を見ていきます。
flowchart TD
R[要件定義<br>何を作るか] --> B[基本設計<br>画面・機能の外側]
B --> D[詳細設計<br>処理の中身・ルール]
D --> I[実装<br>コードを書く・単体テスト]
I --> T[結合テスト・システムテスト]
T --> U[受け入れテスト・リリース]
I -. 設計の疑問を質問 .-> D
T -. 不具合を直す .-> I
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| 実装とは(意味) | 設計を、動くプログラムにして組み込むこと。英語は implementation | 実装とは?IT での意味 |
| 実装と設計の違い | 設計は「何を・どう作るか」を決める。実装は決めたとおりに作って確かめる | 実装と設計の違い |
| 実装と開発の違い | 開発は要件定義からリリースまでの全体。実装はその中の「作る」工程 | 実装と開発・コーディングの違い |
| 実装とコーディングの違い | コーディングはコードを書く行為。実装は単体テスト・レビューまで含むことが多い | 実装と開発・コーディングの違い |
| 実装工程で作るもの | ソースコード・単体テスト・テスト結果・レビュー記録・変更履歴 | 実装工程で作るもの |
| インターフェースを実装する | 決められたメソッドを、クラスの中で中身つきで書くこと(Java の implements) | インターフェースを実装する |
| 実装でよくある間違い | 「以上」と「より大きい」の取り違え・切り捨ての対象違い・小数のずれ | 実装でよくあるつまずき |
| AI に実装させるときの注意 | 先にテストを用意し、生成されたコードを読んでからテストで確かめる | AIで実装するときの注意 |
確認環境:Ubuntu 24.04.5 LTS の上で、架空の機能「F-012 注文金額の割引計算」の詳細設計(6行)を書き、Python 3.13.18 で実装して、pytest 9.2.0 と coverage 7.17.0(pytest-cov 7.1.0、分岐カバレッジ)で単体テストを流しました。わざと4種類の誤り(境界値・切り捨ての対象・設計の読み違い・丸め方)を入れたコードでもテストを流し、失敗の原文を取っています。小数のずれは 1〜100,000円の全金額で数えました。インターフェースの実装は OpenJDK 21.0.12.1 の javac と java で、コンパイルエラーの原文も含めて確かめています。静的チェックは ruff 0.16.9、変更履歴は git 2.43.0(手元のリポジトリだけ。外部には送っていません)です。用語の意味は辞書(コトバンク収録のデジタル大辞泉ほか)、Java の決まりは Java 言語仕様(Java SE 21)と Oracle の Java Tutorials、小数の扱いは Python 公式ドキュメント、工程の枠組みは IPA の公開ページで確かめました。図は mermaid-cli 11.16.0 で描画を確かめています(確認日 2026年10月29日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「実装とは?意味・設計との違いを割引計算のコードとテストで解説」
実装とは?IT での意味を一言で
この節では、「実装」という言葉の意味と、英語・言い換えの言葉が分かります。
実装とは、仕様や設計で決めた機能を、実際に動く形にしてシステムに組み込むことです。ソフトウェアでは「設計に沿ってプログラムを書き、動くことを確かめる」作業を指します。辞書では次のように説明されています。
1 装置などを構成する部品を、実際に取り付けること。2 コンピューターのハードウエアやソフトウエアに新たな機能を組み込むこと。インプリメント。インプリメンテーション。
(デジタル大辞泉「実装」より、コトバンク掲載)
英語では implement(動詞)・implementation(名詞)です。開発の会話では「インプリ」と略されることもあります。「実装する」「実装済み」「未実装」「実装予定」のように使い、それぞれ「作る」「作り終わって動く」「まだ作っていない」「作る予定」という意味になります。
上の数字は、この記事で実際に作った小さな機能のものです。設計書の6行が、コード17行とテスト31行(テストケース14件)になりました。実装は「コードを書く」だけでなく、それが設計どおりに動くことを確かめるところまでが仕事だと分かります。
IT 以外の「実装」
- 電子部品の実装:プリント基板に部品をはんだ付けなどで取り付けること。「表面実装(SMT)」「実装基板」のように使います。辞書の1つ目の意味はこちらです。
- 社会実装:研究や技術を、実際の社会・暮らしの中で使われる形にすること。「AI の社会実装」「自動運転の社会実装」のように使います。
- 実装する(政策・制度):決めた制度を実際に運用し始める意味で使われることもあります。
どれも「決めたものを、実際に使える形にして組み込む」という点で共通しています。以下は IT(ソフトウェア)の実装を扱います。
実装と設計の違い
この節では、設計と実装がそれぞれ何を決め、何を作るのかの違いが分かります。
設計は「何を・どう作るか」を文章や図で決める作業、実装はそれをプログラムにして動かし、決めたとおりに動くことを確かめる作業です。家づくりにたとえると、設計は図面を引くこと、実装は図面どおりに家を建てることです。
設計(決める)
入力・出力・計算のルールを文章や表で決める
成果物は設計書(基本設計書・詳細設計書)
誤りは「書いてあることが要件と違う」形で出る
実装(作って確かめる)
決めたルールをコードにし、テストで確かめる
成果物はソースコード・単体テスト・テスト結果
誤りは「設計と動きが違う」形で出る
実際には、設計書にすべてが書かれているわけではありません。今回の割引計算でも、設計書には「1円未満を切り捨てる」とありましたが、「割引額を切り捨てるのか、支払額を切り捨てるのか」で結果が1円変わります(あとの節で実際に1円・499円のずれが出ます)。こうした「設計に書かれていない細部」をどう扱うかは、実装する人の判断に任されがちです。
- 書かれていない細部は、自分で決めずに設計者に聞く:聞いた内容と答えは、設計書に書き足してもらうか、チケットに残します。
- 決めた解釈はテストに書く:「999円・SILVER なら950円」というテストがあれば、解釈がコードに固定され、後から読む人にも伝わります。
- コードに設計書の番号を残す:
# 設計 4(以上)のように書くと、どの行がどの決まりに対応するかを追えます。
設計書の書き方そのものは、関連記事「詳細設計書の書き方|基本設計との違いと記入例」で扱っています。
実装と開発・コーディング・プログラミングの違い
この節では、実装と似た言葉(開発・コーディング・プログラミング・製造・構築)の違いが分かります。
範囲の広い順に、開発 > 実装 > コーディングです。開発は要件定義からリリースまでの全体、実装はその中の「作って確かめる」工程、コーディングはその中の「コードを書く」行為を指します。ただし会社やチームによって使い方が違い、「開発」と「実装」をほぼ同じ意味で使うこともあります。
| 言葉 | 指す範囲 | 使い方の例 |
|---|---|---|
| 開発 | 要件定義・設計・実装・テスト・リリースの全体 | 「新しい会員サイトを開発する」 |
| 実装 | 設計をコードにし、単体テスト・レビューまで行う工程 | 「割引計算を実装した。単体テストも通っている」 |
| コーディング | ソースコードを書く行為そのもの | 「コーディング規約に沿って書く」 |
| プログラミング | プログラムを考えて書くこと全般(学習・趣味も含む) | 「プログラミングを学ぶ」 |
| 製造・構築 | 工程表で実装工程を指す呼び名(会社により違う) | 「製造工程は来月から」 |
工程表で「製造」「PG(プログラミング)」「CD(コーディング)」と書かれている工程は、多くの場合「実装」と同じ作業を指します。新しいチームに入ったときは、工程表の言葉が何を含むのか(単体テストまで含むか)を最初に確かめておくと、作業の抜けを防げます。プログラミングそのものの意味と仕組みは、関連記事「プログラミングとは|意味・仕組み・言語の種類を3言語の実行で解説」で扱っています。
開発工程のどこが実装か(V字モデルとの関係)
この節では、開発の流れの中で実装がどこにあり、前後の工程とどうつながるかが分かります。
実装は、詳細設計のあと、結合テストの前にある工程です。ウォーターフォール型の開発では、要件定義→基本設計→詳細設計→実装(コーディングと単体テスト)→結合テスト→システムテスト→受け入れテストの順に進みます。冒頭の図のとおり、実装中に設計の疑問が出れば詳細設計に戻って確かめ、後のテストで不具合が見つかれば実装に戻って直します。
V字モデルでは、左側の設計の各段階と、右側のテストの各段階が対になります。実装は V の底にあり、詳細設計で決めたことを確かめるのが単体テストです。工程とテストの対応は、関連記事「V字モデルとは?設計とテストの工程対応表とW字モデルとの違い」で扱っています。
| 開発の進め方 | 実装のタイミング | 実装の単位 |
|---|---|---|
| ウォーターフォール | 詳細設計が終わってから、まとめて実装する | 機能・画面ごと(数週間〜数か月) |
| アジャイル(スクラム等) | 短い期間(スプリント)ごとに設計・実装・テストを繰り返す | ユーザーストーリーごと(数日) |
| テスト駆動開発(TDD) | 先にテストを書き、それが通るように実装する | テスト1件ごと(数分〜数十分) |
工程の名前や区切りは、標準の枠組みでも整理されています。IPA(情報処理推進機構)の「共通フレーム2013」は、ソフトウェアのライフサイクルで必要な作業を規定した共通の枠組みで、国際規格 ISO/IEC 12207(JIS X 0160)をもとにしています。実際の工程の呼び名は案件ごとの工程表で決まるので、上の表は目安として読みます。
設計書の1行が実装になるまで(割引計算の例)
この節では、詳細設計の文章が実際のコードにどう対応するかが、実物で分かります。
実装の第一歩は、設計書の1行ずつを「コードのどこに書くか」「テストで何を確かめるか」に分けることです。ここでは、架空の通販サイトの機能「F-012 注文金額の割引計算」を題材にします。詳細設計書の抜粋は次の6行です。
## F-012 注文金額の割引計算(詳細設計書より抜粋)
1. 入力:小計(円・整数・0以上)、会員ランク(GENERAL / SILVER / GOLD / PLATINUM)、クーポン有無
2. ランク割引率:GENERAL 0%、SILVER 5%、GOLD 10%、PLATINUM 20%
3. ランク割引額は「小計 × 割引率」の1円未満を切り捨てる
4. クーポンは、ランク割引後の金額が3,000円以上のときだけ500円引く
5. 支払額は0円未満にしない
6. 小計が負、またはランクが一覧に無いときは ValueError(E-012-01/E-012-02)
これを Python で実装したのが次のコードです。各行のコメントに、対応する設計の番号を書いています。
"""F-012 注文金額の割引計算(設計書 F-012 の 1〜6 に対応)"""
RATE_PERCENT = {"GENERAL": 0, "SILVER": 5, "GOLD": 10, "PLATINUM": 20} # 設計 2
COUPON_AMOUNT = 500
COUPON_THRESHOLD = 3000
def calc_payment(subtotal: int, rank: str, has_coupon: bool = False) -> int:
if subtotal < 0: # 設計 6
raise ValueError("E-012-01: subtotal must be >= 0")
if rank not in RATE_PERCENT: # 設計 6
raise ValueError(f"E-012-02: unknown rank {rank!r}")
rank_discount = subtotal * RATE_PERCENT[rank] // 100 # 設計 3(整数で切り捨て)
amount = subtotal - rank_discount
if has_coupon and amount >= COUPON_THRESHOLD: # 設計 4(以上)
amount -= COUPON_AMOUNT
return max(amount, 0) # 設計 5
設計の1行とコード・テストの対応を表にすると、次のようになります。この「対応が全部埋まっているか」が、実装が終わったかどうかの目安になります。
| 設計 | コード | 確かめるテスト |
|---|---|---|
| 2 ランク割引率 | RATE_PERCENT の辞書 |
10,000円で4ランクそれぞれ |
| 3 割引額を切り捨て | subtotal * 率 // 100(整数で計算) |
999円・SILVER→950円、5円・PLATINUM→4円 |
| 4 3,000円以上で500円引く | amount >= COUPON_THRESHOLD |
3,000円→2,500円、2,999円→2,999円、3,200円・GOLD→2,880円 |
| 5 0円未満にしない | max(amount, 0) |
0円→0円 |
| 6 入力の誤り | raise ValueError("E-012-0x") |
小計 -1、ランク "gold"(小文字) |
flowchart TD
S["設計書の1行<br>3,000円以上で500円引く"] --> C["コード<br>amount >= 3000"]
S --> T["テスト<br>3,000円・2,999円"]
C --> R{テストは通る?}
T --> R
R -->|いいえ| F[コードか<br>設計の読みを直す]
F --> R
R -->|はい| V[レビュー・コミット]
この順番で考えると、設計の1行が「コードの1か所」と「テストの数件」に分かれ、どこまで作ったかが目に見えます。実装中に「3,000円ちょうどは対象?」のような疑問が出たら、設計の言葉(以上・未満・超える)を確かめ、決まった答えをテストに書きます。
単体テストで実装を確かめる(pytest の実行結果)
この節では、実装したコードが設計どおりかを、単体テストでどう確かめるかが実行結果で分かります。
単体テストは、実装した関数やクラスを1つずつ取り出して、決めた入力に決めた出力を返すかを確かめるテストです。実装工程の中で、コードを書いた人が自分で書いて流すのが一般的です。今回のテストは次のとおりです。
import pytest
from discount import calc_payment
@pytest.mark.parametrize("subtotal, rank, coupon, expected", [
(10000, "GENERAL", False, 10000),
(10000, "SILVER", False, 9500),
(10000, "GOLD", False, 9000),
(10000, "PLATINUM", False, 8000),
(999, "SILVER", False, 950), # 49.95円 → 49円引き(切り捨て)
(5, "PLATINUM", False, 4), # 1円引き
(3000, "GENERAL", True, 2500), # 境界:ちょうど3,000円はクーポン対象
(2999, "GENERAL", True, 2999), # 境界:1円足りない
(3334, "GOLD", True, 2501), # 割引後 3,001円 → 対象
(3333, "GOLD", True, 3000 - 500), # 割引後 3,000円 → 対象(333円引き)
(3200, "GOLD", True, 2880), # 小計は3,000円以上だが割引後は2,880円 → 対象外
(0, "GOLD", True, 0), # 0円
])
def test_calc_payment(subtotal, rank, coupon, expected):
assert calc_payment(subtotal, rank, coupon) == expected
def test_negative_subtotal():
with pytest.raises(ValueError, match="E-012-01"):
calc_payment(-1, "GOLD")
def test_unknown_rank():
with pytest.raises(ValueError, match="E-012-02"):
calc_payment(1000, "gold")
実行すると、14件すべてが成功しました。
============================= test session starts ==============================
platform linux -- Python 3.13.18, pytest-9.2.0, pluggy-1.7.0 -- .venv/bin/python
rootdir: ~/f012
plugins: cov-7.1.0
collecting ... collected 14 items
test_discount.py::test_calc_payment[10000-GENERAL-False-10000] PASSED [ 7%]
test_discount.py::test_calc_payment[10000-SILVER-False-9500] PASSED [ 14%]
test_discount.py::test_calc_payment[10000-GOLD-False-9000] PASSED [ 21%]
test_discount.py::test_calc_payment[10000-PLATINUM-False-8000] PASSED [ 28%]
test_discount.py::test_calc_payment[999-SILVER-False-950] PASSED [ 35%]
test_discount.py::test_calc_payment[5-PLATINUM-False-4] PASSED [ 42%]
test_discount.py::test_calc_payment[3000-GENERAL-True-2500] PASSED [ 50%]
test_discount.py::test_calc_payment[2999-GENERAL-True-2999] PASSED [ 57%]
test_discount.py::test_calc_payment[3334-GOLD-True-2501] PASSED [ 64%]
test_discount.py::test_calc_payment[3333-GOLD-True-2500] PASSED [ 71%]
test_discount.py::test_calc_payment[3200-GOLD-True-2880] PASSED [ 78%]
test_discount.py::test_calc_payment[0-GOLD-True-0] PASSED [ 85%]
test_discount.py::test_negative_subtotal PASSED [ 92%]
test_discount.py::test_unknown_rank PASSED [100%]
============================== 14 passed in 0.03s ==============================
どの行と分岐をテストが通ったかを、カバレッジ(テストが通ったコードの割合)で見た結果です。--cov-branch を付けると、if の「真」「偽」の両方を通ったかも数えます。
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.18-final-0 _______________
Name Stmts Miss Branch BrPart Cover Missing
---------------------------------------------------------
discount.py 13 0 6 0 100%
---------------------------------------------------------
TOTAL 13 0 6 0 100%
14 passed in 0.04s
1テストは設計の言葉から作る
「以上」とあれば、ちょうどの値(3,000円)と1つ手前(2,999円)の両方を入れる。コードを見て作ると、コードの誤りをそのまま写してしまう。
2誤りの入力もテストする
マイナスの小計・小文字の "gold" のように、設計にあるエラーの条件も1件ずつ確かめる。エラーコードまで照合すると取り違えに気づける。
3速いので何度でも流せる
14件で0.03〜0.04秒だった。直すたびに全件を流しても待ち時間がほとんど無い。
単体テストと結合テストの違いや、pytest の書き方は、関連記事「単体テストと結合テストの違い|pytestの実例と実行結果で比較」で扱っています。
実装でよくあるつまずき:設計の読み違いと境界値
この節では、実装で起きやすい間違いが、実際にテストが失敗した原文つきで分かります。
実装の間違いの多くは、文法の誤りではなく「設計の読み違い」と「境界の扱い」です。どれもコードとしては正しく動くので、実行してもエラーは出ません。テストで期待値と比べて初めて分かります。手元で、正しいコードに1か所ずつ誤りを入れて、同じ14件のテストを流しました。
| 入れた誤り | 変えた1行 | テストの結果 |
|---|---|---|
| A:「以上」を「より大きい」にした | amount > COUPON_THRESHOLD |
2件失敗(3,000円ちょうど) |
| B:支払額のほうを切り捨てた | int(subtotal * (1 - 率 / 100)) |
3件失敗(1円ずれ→クーポン判定も変わる) |
| C:割引前の小計でクーポンを判定した | subtotal >= COUPON_THRESHOLD |
1件失敗(500円の差) |
| D:切り捨てを四捨五入にした | round(subtotal * 率 / 100) |
1件失敗(1円の差) |
A:境界値(以上・より大きい)の取り違え
......F..F.... [100%]
=================================== FAILURES ===================================
E AssertionError: assert 3000 == 2500
+ where 3000 = calc_payment(3000, 'GENERAL', True)
test_discount.py:21: AssertionError: assert 3000 == 2500
E AssertionError: assert 3000 == 2500
+ where 3000 = calc_payment(3333, 'GOLD', True)
test_discount.py:21: AssertionError: assert 3000 == 2500
=========================== short test summary info ============================
FAILED test_discount.py::test_calc_payment[3000-GENERAL-True-2500] - Assertio...
FAILED test_discount.py::test_calc_payment[3333-GOLD-True-2500] - AssertionEr...
2 failed, 12 passed in 0.03s
3,000円ちょうどのときにクーポンが効かず、3,000円のままになりました。境界のテスト(3,000円と2,999円)が無ければ、この誤りは見つかりません。実際に、境界の3件を消したテストで同じ誤りのコードを流すと、全件成功し、カバレッジも100%のままでした。
Name Stmts Miss Branch BrPart Cover Missing
---------------------------------------------------------
discount.py 13 0 6 0 100%
---------------------------------------------------------
TOTAL 13 0 6 0 100%
11 passed in 0.04s
カバレッジ100%は「全部の行と分岐を通った」という意味で、「正しい」という意味ではありません。境界の値を選んでテストに入れることが、カバレッジの数字より大切です。
B:切り捨ての対象の取り違え(1円が499円の差になる)
....F...FF.... [100%]
=================================== FAILURES ===================================
E AssertionError: assert 949 == 950
+ where 949 = calc_payment(999, 'SILVER', False)
test_discount.py:21: AssertionError: assert 949 == 950
E AssertionError: assert 2500 == 2501
+ where 2500 = calc_payment(3334, 'GOLD', True)
test_discount.py:21: AssertionError: assert 2500 == 2501
E AssertionError: assert 2999 == 2500
+ where 2999 = calc_payment(3333, 'GOLD', True)
test_discount.py:21: AssertionError: assert 2999 == 2500
=========================== short test summary info ============================
FAILED test_discount.py::test_calc_payment[999-SILVER-False-950] - AssertionE...
FAILED test_discount.py::test_calc_payment[3334-GOLD-True-2501] - AssertionEr...
FAILED test_discount.py::test_calc_payment[3333-GOLD-True-2500] - AssertionEr...
3 failed, 11 passed in 0.04s
3,333円・GOLD では、正しくは割引額333円(333.3円の切り捨て)で3,000円になり、クーポンが効いて2,500円です。支払額を切り捨てると 3,333 × 0.9 = 2,999.7 → 2,999円になり、3,000円に1円届かずクーポンが効かないため、結果は2,999円と、正しい金額との差が499円になりました。設計書の「1円未満を切り捨てる」が何に掛かるかを確かめなかったことが原因です。
C:設計の読み違い(どの時点の金額で判定するか)
..........F... [100%]
=================================== FAILURES ===================================
E AssertionError: assert 2380 == 2880
+ where 2380 = calc_payment(3200, 'GOLD', True)
test_discount.py:21: AssertionError: assert 2380 == 2880
=========================== short test summary info ============================
FAILED test_discount.py::test_calc_payment[3200-GOLD-True-2880] - AssertionEr...
1 failed, 13 passed in 0.02s
設計は「ランク割引後の金額が3,000円以上」でした。小計3,200円・GOLD は割引後2,880円で対象外ですが、割引前の3,200円で判定したため500円引かれました。テストに「小計は3,000円以上だが割引後は届かない」ケースを入れていたので見つかりました。
D:丸め方の取り違え
....F......... [100%]
=================================== FAILURES ===================================
E AssertionError: assert 949 == 950
+ where 949 = calc_payment(999, 'SILVER', False)
test_discount.py:21: AssertionError: assert 949 == 950
=========================== short test summary info ============================
FAILED test_discount.py::test_calc_payment[999-SILVER-False-950] - AssertionE...
1 failed, 13 passed in 0.01s
999円・SILVER の割引額は49.95円で、切り捨てなら49円、四捨五入なら50円です。Python の round() は「偶数への丸め」をするので、round(2.5) は 2 になる点にも注意が要ります(手元で round(2.5)→2、round(0.5)→0 でした)。金額の丸め方は設計書で必ず決めてもらいます。
よくあるエラー/つまずき一覧(原文つき)
| 出たもの(原文) | 意味 | 確かめ方・直し方 |
|---|---|---|
AssertionError: assert 3000 == 2500 |
結果が期待値と違う(実装か期待値のどちらかが誤り) | 設計の文言に戻り、どちらが正しいかを決めてから直す |
UnboundLocalError: cannot access local variable 'rate' ... |
if の片方でしか変数に値を入れていない | すべての分岐で値を決める。ランク一覧の外の入力をテストする |
F401 `math` imported but unused(ruff) |
使っていない import が残っている | 静的チェックを実装の手順に入れる |
error: CouponDiscount is not abstract and does not override abstract method discount(int) ... |
インターフェースのメソッドを実装していない | メソッド名・引数の型をインターフェースと合わせる |
error: method does not override or implement a method from a supertype |
@Override を付けたメソッドの名前が違う | 綴りを直す(@Override が誤りを教えてくれた) |
TypeError: Can't instantiate abstract class ... |
Python の抽象基底クラスのメソッドを実装していない | 抽象メソッドと同じ名前で定義する |
| 1円だけずれる(エラーは出ない) | 小数(float)で金額を計算した | 整数か Decimal で計算する(次の節) |
表の UnboundLocalError と ruff の出力は、次の小さなコードで実際に出したものです。ruff は使っていない import を見つけましたが、「SILVER のときに rate が決まらない」誤りは静的チェックでは出ず、実行して初めて分かりました。静的チェックとテストは役割が違うので、両方を使います。
import math
def calc(subtotal, rank):
if rank == "GOLD":
rate = 10
return subtotal * rate // 100
$ ruff check --isolated lint_demo.py
F401 [*] `math` imported but unused
--> lint_demo.py:1:8
|
1 | import math
| ^^^^
help: Remove unused import: `math`
|
- import math
1 |
|
Found 1 error.
[*] 1 fixable with the `--fix` option.
$ python3 -c "from lint_demo import calc; calc(1000, 'SILVER')"
Traceback (most recent call last):
File "<string>", line 1, in <module>
from lint_demo import calc; calc(1000, 'SILVER')
~~~~^^^^^^^^^^^^^^^^
File "lint_demo.py", line 7, in calc
return subtotal * rate // 100
^^^^
UnboundLocalError: cannot access local variable 'rate' where it is not associated with a value
金額の実装で起きる小数のずれ
この節では、金額や割合の計算を実装するとき、小数(浮動小数点数)で1円ずれる理由と避け方が分かります。
コンピューターの小数(float)は、0.07 や 0.1 のような10進の小数を正確には表せません。Python の公式ドキュメントにも、次のように書かれています。
Unfortunately, most decimal fractions cannot be represented exactly as binary fractions.
(大意:残念ながら、ほとんどの10進の小数は2進の小数として正確には表せません。Python ドキュメント「Floating-Point Arithmetic: Issues and Limitations」)
手元で、7%引き・30%引きなどを float で計算して切り捨て、整数だけで計算した正しい値と比べました。
from decimal import Decimal, ROUND_DOWN
print("1 - 0.07 =", 1 - 0.07)
print("500 * (1-0.07) =", 500 * (1 - 0.07))
print("int(...) =", int(500 * (1 - 0.07)), "(正しくは 465)")
print("90 * 0.7 =", 90 * 0.7)
print("0.1 + 0.2 =", 0.1 + 0.2)
for pct in (5, 7, 10, 20, 30):
bad = sum(1 for x in range(1, 100001)
if int(x * (1 - pct / 100)) != x * (100 - pct) // 100)
print(f"{pct}%引き: 1〜100,000円のうち float で1円ずれる金額 {bad} 件")
print("Decimal:", (Decimal(500) * (1 - Decimal("0.07"))).quantize(Decimal("1"), rounding=ROUND_DOWN))
print("整数 :", 500 * (100 - 7) // 100)
1 - 0.07 = 0.9299999999999999
500 * (1-0.07) = 464.99999999999994
int(...) = 464 (正しくは 465)
90 * 0.7 = 62.99999999999999
0.1 + 0.2 = 0.30000000000000004
5%引き: 1〜100,000円のうち float で1円ずれる金額 0 件
7%引き: 1〜100,000円のうち float で1円ずれる金額 239 件
10%引き: 1〜100,000円のうち float で1円ずれる金額 0 件
20%引き: 1〜100,000円のうち float で1円ずれる金額 0 件
30%引き: 1〜100,000円のうち float で1円ずれる金額 2336 件
Decimal: 465
整数 : 465
500円の7%引きは465円のはずが、float では464.99999999999994になり、切り捨てると464円になりました。1〜100,000円の全金額で数えると、7%引きで239件、30%引きで2,336件が1円ずれました。5%・10%・20%ではずれは出ませんでしたが、これは「たまたま」なので、率が変わったときに急に1円ずれ始めます。
金額・割合の計算の実装
int(price * (1 - 0.07)) のように float で掛けてから切り捨てる。テストした率では合っても、別の率でずれるprice * 7 // 100 と計算する。小数が要るなら Decimal を文字列から作り、丸め方を明示するJava なら BigDecimal、JavaScript なら整数(銭・円単位)で計算するのが基本
「インターフェースを実装する」の意味(Java の implements)
この節では、プログラミング言語でいう「インターフェースを実装する」の意味が、Java の実行例とエラー原文で分かります。
「インターフェースを実装する」とは、インターフェースで名前と引数だけ決められたメソッドを、クラスの中で中身つきで書くことです。Java では implements というキーワードを使います。Oracle の Java Tutorials は次のように説明しています。
To declare a class that implements an interface, you include an implements clause in the class declaration.
(大意:インターフェースを実装するクラスを宣言するには、クラスの宣言に implements 句を書きます。Oracle「Implementing an Interface」)
割引計算を「割引のしかた(ポリシー)」として部品に分け、インターフェースで形をそろえた例です。
public interface DiscountPolicy {
/** 小計(円)から割引額(円)を返す。1円未満は切り捨て。 */
int discount(int subtotal);
}
public class RankDiscount implements DiscountPolicy {
private final int percent;
public RankDiscount(int percent) {
this.percent = percent;
}
@Override
public int discount(int subtotal) {
return subtotal * percent / 100;
}
}
public class CouponDiscount implements DiscountPolicy {
@Override
public int discount(int subtotal) {
return subtotal >= 3000 ? 500 : 0;
}
}
import java.util.List;
public class Main {
public static void main(String[] args) {
int subtotal = 3333;
int amount = subtotal;
List<DiscountPolicy> policies = List.of(new RankDiscount(10), new CouponDiscount());
for (DiscountPolicy p : policies) {
int d = p.discount(amount);
amount -= d;
System.out.printf("%-15s -%4d円 → %5d円%n", p.getClass().getSimpleName(), d, amount);
}
}
}
$ javac -d out *.java
$ java -Dstdout.encoding=UTF-8 -cp out Main
RankDiscount - 333円 → 3000円
CouponDiscount - 500円 → 2500円
Main は「DiscountPolicy を実装しているもの」のリストを順に呼ぶだけで、中身がランク割引かクーポンかを知りません。インターフェースは「呼ぶ側との約束」、implements したクラスは「約束を守る中身」です。新しい割引(たとえば誕生月割引)を足すときも、DiscountPolicy を実装したクラスを1つ増やすだけで、Main は変えずに済みます。
実装し忘れたときのコンパイルエラー
メソッドの名前を discount ではなく calc にしてしまった場合です。
public class CouponDiscount implements DiscountPolicy {
public int calc(int subtotal) { // 名前を discount にし忘れた
return subtotal >= 3000 ? 500 : 0;
}
}
CouponDiscount.java:1: error: CouponDiscount is not abstract and does not override abstract method discount(int) in DiscountPolicy
public class CouponDiscount implements DiscountPolicy {
^
1 error
Java 言語仕様(8.1.5)は、abstract でないクラスは、インターフェースの抽象メソッドをすべて実装しなければならないと定めています。実装の漏れは、実行する前のコンパイルで止まります。@Override を付けておくと、名前の打ち間違いも見つけてくれます。
CouponDiscount.java:5: error: method does not override or implement a method from a supertype
@Override
^
1 error
Python でインターフェースに近いもの
Python には implements はありませんが、抽象基底クラス(abc モジュール)で同じことができます。実装を忘れると、インスタンスを作る時点でエラーになりました。
from abc import ABC, abstractmethod
class DiscountPolicy(ABC):
@abstractmethod
def discount(self, subtotal: int) -> int: ...
class CouponDiscount(DiscountPolicy):
def calc(self, subtotal: int) -> int:
return 500 if subtotal >= 3000 else 0
CouponDiscount()
TypeError: Can't instantiate abstract class CouponDiscount without an implementation for abstract method 'discount'
Java と違い、Python ではコンパイルの段階ではなく、実行してインスタンスを作った時点で分かります。インターフェースと抽象クラスの使い分けは、関連記事「Javaインターフェースと抽象クラスの違い|比較表と使い分け」で扱っています。
「実装する」の使い分けと実装の種類
この節では、「実装する」が会話の中で何を指しているかの見分け方と、実装の種類が分かります。
「実装する」の目的語が「機能」「インターフェース」「仕様」のどれかで、意味が変わります。
機能を実装する
「割引計算を実装する」。設計に沿ってコードを書き、テストで確かめ、使える状態にする。
いちばんよく使う意味
インターフェースを実装する
「DiscountPolicy を実装する」。決められたメソッドを中身つきで書く。Java の implements。
プログラミング言語の用語
仕様を実装する
「HTTP/3 を実装したサーバー」。標準の仕様書に書かれた動きを、製品やライブラリで実現する。
規格・標準の話で使う
アルゴリズムを実装する
「二分探索を実装する」。考え方(手順)を、特定の言語のコードにする。
学習・面接でよく出る
実装の種類(新規・追加・改修・再実装)
| 種類 | 内容 | 気をつけること |
|---|---|---|
| 新規実装 | まだ無い機能を一から作る | 設計に無い細部(丸め・境界)を早めに質問する |
| 追加実装 | 動いているシステムに機能を足す | 既存のテストを全件流し、壊していないか確かめる |
| 改修 | 既存の機能の動きを変える | 変える前の動きをテストで固定してから直す |
| 再実装(作り直し) | 同じ機能を別の言語・構成で作り直す | 以前の版と同じ入力で同じ出力になるかを比べる |
「実装依存」と「参照実装」
同じ仕様でも、作る人や製品によって細かな動きが違うことがあり、これを「実装依存」と呼びます。たとえば、ある言語の仕様が「結果は決めない」としている部分は、処理系ごとに結果が違ってよい、という意味です。仕様の動きを確かめるための見本として作られたものを「参照実装(リファレンス実装)」と呼びます。今回の割引計算でも、Python 版と Java 版で同じ入力(3,333円・GOLD・クーポンあり)を与え、どちらも2,500円になることを確かめました。複数の実装の結果を突き合わせるのは、作り直しや移行のときにも使える方法です。
実装工程で作るもの(成果物と完了の目安)
この節では、実装工程で何を作り、どうなったら「実装完了」と言えるのかが分かります。
実装工程の成果物は、ソースコードだけではありません。単体テストのコードと結果、レビューの記録、変更履歴(コミット)がそろって、初めて次の工程(結合テスト)に渡せます。
| 成果物 | 今回の実物 | 何のためにあるか |
|---|---|---|
| ソースコード | discount.py(17行) | 設計を動く形にしたもの |
| 単体テストのコード | test_discount.py(14件) | 設計どおりかを何度でも確かめる |
| 単体テストの結果 | 14 passed・分岐カバレッジ100% | 確かめた事実を残す |
| レビュー記録 | 指摘と対応(例:「以上」の境界テストを足した) | 別の人の目で読み違いを見つける |
| 変更履歴 | git のコミット(設計番号つき) | いつ・何を・なぜ変えたかを追う |
手元のリポジトリにコミットした記録です(外部には送っていません)。コミットのメッセージに設計書の番号を入れると、後から「F-012 の変更」を検索できます。
$ git log --stat
31e7831 F-012 割引計算を実装(設計 1〜6、単体テスト14件)
design.md | 7 +++++++
discount.py | 17 +++++++++++++++++
test_discount.py | 31 +++++++++++++++++++++++++++++++
3 files changed, 55 insertions(+)
「実装完了」の基準は、チームで先に決めておきます。次は今回の機能で使った確認項目です。
- 1設計の全項目にコードとテストが対応している設計・コード・テストの対応表に空欄が無い
- 2単体テストが全件成功している境界の値(ちょうど・1つ手前)とエラーの入力を含む
- 3静的チェックで指摘が無いruff・Checkstyle などチームで決めた道具とルールで
- 4レビューを受け、指摘に対応した指摘と対応の内容を記録に残す
- 5設計への質問と答えが残っている設計書に反映されたか、チケットに記録がある
仕様の変更が実装の途中で入ったときは、口頭で受けずに、変更の内容・影響する範囲・期日を書面(チケット)で確かめてから直します。変更前のテストを残しておくと、どのテストの期待値を変えたかが差分で分かります。
実装の進め方(手順と判断表)
この節では、1つの機能を実装するときの手順と、迷ったときの判断の目安が分かります。
実装は「設計を読む→疑問を聞く→テストを考える→書く→確かめる→見てもらう→残す」の順に進めると、やり直しが減ります。今回の割引計算も、この順で作りました。
設計書を読み、入力・出力・ルールを書き出す
設計の1行ずつに番号を付け、「入力の範囲」「境界の言葉(以上・未満)」「丸め方」に線を引く。
書かれていない細部を質問する
「切り捨ては割引額か支払額か」「クーポンは割引前か後か」のように、2通りに読めるところを設計者に確かめ、答えを記録する。
テストケースを先に考える
通常の値・境界(ちょうど・1つ手前)・0・エラーの入力を表にする。コードを見る前に作ると、思い込みが入りにくい。
コードを書く
コーディング規約に沿い、設計の番号をコメントに残す。金額は整数で計算する。
静的チェックと単体テストを流す
ruff などで書き方の誤りを、テストで動きの誤りを見つける。両方が通るまで直す。
レビューを受け、コミットする
設計との対応表・テスト結果を添えて読んでもらう。指摘を直したら、設計番号つきのメッセージでコミットする。
実装で迷ったときの判断表
| 迷う場面 | 判断 | 理由 |
|---|---|---|
| 設計に書かれていない細部がある | 自分で決めずに質問し、答えをテストにする | 読み違い(誤り B・C)は動いてしまうので気づきにくい |
| 設計が誤っていると思う | 設計どおりに作る前に、根拠を添えて相談する | 黙って直すと、設計書とコードがずれる |
| 金額・割合を計算する | 整数か Decimal。float を使わない | 7%引きで1〜100,000円のうち239件が1円ずれた |
| カバレッジは100%だが不安 | 境界の値がテストにあるかを見る | 境界の誤りがあっても100%・全件成功だった |
| 同じ処理が何種類もある | インターフェースで形をそろえる | 種類を足しても呼ぶ側を変えずに済む |
| 期日に間に合わない | テストを削らず、作る範囲を相談する | テストの無いコードは、後の工程で手戻りが大きい |
- 1設計の言葉を読む → 境界・丸め・判定の時点を確かめる以上・未満・切り捨て・割引後
- 22通りに読める → 質問して記録するチケット・設計書の更新
- 3決まった解釈 → テストに書くちょうど・1つ手前・0・誤りの入力
- 4テストが通る → レビュー・コミット設計番号を残す
AIで実装するときの注意(生成→読む→テスト)
この節では、生成AI にコードを書かせて実装するときに、何を人が確かめるべきかが分かります。
AI にコードを書かせても、実装の責任(設計どおりかを確かめること)は人に残ります。AI が書いたコードも、上で入れた誤り A〜D と同じ形で間違える可能性があり、どれも実行してエラーにならない種類の誤りです。そのため、手順は「生成→読む→テスト」の順にします。
AI に割引計算を書かせるとき
コードとテストを同じ AI に作らせると、同じ読み違いが両方に入りやすい
- 設計とテストは人が持つ:AI に渡すのは「設計書の該当行」と「人が決めた期待値のテスト」。テストが失敗したら、AI の出力を直させるか自分で直します。
- 読めないコードは取り込まない:説明できない行がある状態でレビューに出すと、指摘に答えられません。
- 機密を渡さない:設計書や顧客データを外部の AI サービスに貼る前に、社内の利用ルールを確かめます。
- 小さく頼む:機能をまとめて頼まず、関数1つ・テスト数件の単位で頼むと、読む量と確かめる量が釣り合います。
AI に任せて書き進めるやり方と、そのリスクの抑え方は、関連記事「バイブコーディングとは?やり方と注意点、リスク対策チェック表」で扱っています。
よくある質問
Q. 実装とは簡単に言うと何ですか? A. 設計で決めたことを、実際に動くプログラムにして組み込むことです。ソフトウェア開発では、コードを書き、単体テストで設計どおりに動くことを確かめるまでを指すことが多いです。
Q. 実装と設計の違いは何ですか? A. 設計は「何を・どう作るか」を文章や図で決める作業で、成果物は設計書です。実装はそれをコードにして動かし、確かめる作業で、成果物はソースコードと単体テストです。
Q. 実装と開発は同じ意味ですか? A. 厳密には違います。開発は要件定義からリリースまでの全体、実装はその中の「作る」工程です。ただ、会話では「この機能を開発する」「実装する」がほぼ同じ意味で使われることもあります。
Q. 実装とコーディングの違いは何ですか? A. コーディングはソースコードを書く行為そのもの、実装はコーディングに加えて単体テスト・レビューまでを含む工程として使われることが多いです。
Q. 「実装済み」「未実装」とはどういう意味ですか? A. 実装済みは「作り終わって動く状態」、未実装は「まだ作っていない(使えない)状態」です。製品のドキュメントでは「この機能は未実装」のように、まだ使えない機能を示すのに使われます。
Q. 「インターフェースを実装する」とはどういう意味ですか? A. インターフェースで名前と引数だけ決められたメソッドを、クラスの中で中身つきで書くことです。Java では implements を使い、実装し忘れるとコンパイルエラーになります。
Q. 実装工程で作るものは何ですか? A. ソースコード、単体テストのコードと結果、レビューの記録、変更履歴(コミット)です。チームによっては単体テスト仕様書や成績書も作ります。
Q. 実装工程でよくある間違いは何ですか? A. 「以上」と「より大きい」の取り違え、切り捨ての対象や丸め方の取り違え、判定に使う金額の時点の読み違い、小数(float)での金額計算です。どれも実行してエラーにならないので、境界の値を入れたテストで見つけます。
Q. カバレッジが100%なら実装は正しいですか? A. いいえ。手元では、境界の誤りがあるコードでも、境界のテストを抜くと全件成功・分岐カバレッジ100%になりました。カバレッジは「通った割合」で、正しさは期待値を入れたテストで確かめます。
Q. 初学者は実装の何から練習するとよいですか? A. 小さな機能(割引計算・日付の計算など)を、設計を自分で数行書く→テストを先に考える→コードを書く→テストを流す、の順で作るのがおすすめです。設計と実装とテストのつながりを一度に体験できます。
Q. AI に実装させてもよいですか? A. 使えますが、設計どおりかを確かめる責任は人に残ります。設計書の該当行と人が作ったテストを渡し、生成されたコードを読んでからテストを流して取り込みます。
Q. 社会実装とは何ですか? A. 研究や技術を、実際の社会や暮らしの中で使われる形にすることです。IT の実装と同じく「決めたもの・作ったものを、実際に使える形にする」という意味です。
まとめ
- 実装とは、設計で決めた内容を動くプログラムにして組み込むこと。英語は implementation。コードを書き、単体テストで確かめるまでを含むことが多い。
- 設計は「何を・どう作るか」を決め、実装は「作って確かめる」。範囲は開発 > 実装 > コーディング。
- 設計の6行は、コード17行・テスト14件になった。設計・コード・テストの対応表が埋まることが完了の目安。
- 境界・切り捨ての対象・判定の時点・丸め方の誤りは、実行してもエラーにならない。境界の誤りは、境界のテストを抜くとカバレッジ100%・全件成功のまま残った。金額は float で計算しない(7%引きで239件が1円ずれた)。
- 「インターフェースを実装する」は、決められたメソッドを中身つきで書くこと。Java では実装漏れがコンパイルエラーで止まる。AI で実装するときも、設計とテストは人が持つ。
次に読むとよい記事です。設計書の種類と工程ごとの成果物は関連記事「詳細設計書の書き方|基本設計との違いと記入例」で、単体テストの書き方は関連記事「単体テストと結合テストの違い|pytestの実例と実行結果で比較」で扱っています。
参考・出典
確認日はいずれも 2026年10月29日です。
- コトバンク「実装」(デジタル大辞泉・精選版 日本国語大辞典・IT用語がわかる辞典):https://kotobank.jp/word/%E5%AE%9F%E8%A3%85-4256
- IPA「エンタプライズ系事業/ライフサイクルプロセス」(共通フレーム2013の概要):https://www.ipa.go.jp/archive/digital/iot-en-ci/process/ent02-a.html
- Oracle「The Java Tutorials: Implementing an Interface」:https://docs.oracle.com/javase/tutorial/java/IandI/usinginterface.html
- Oracle「The Java Language Specification, Java SE 21 Edition」8.1.1.1 abstract Classes・8.1.5 Superinterfaces:https://docs.oracle.com/javase/specs/jls/se21/html/jls-8.html
- Python「Floating-Point Arithmetic: Issues and Limitations」:https://docs.python.org/3/tutorial/floatingpoint.html
- Python「decimal — Decimal fixed-point and floating-point arithmetic」:https://docs.python.org/3/library/decimal.html
- Python「abc — Abstract Base Classes」:https://docs.python.org/3/library/abc.html
- pytest「How to parametrize fixtures and test functions」:https://docs.pytest.org/en/stable/how-to/parametrize.html
- Coverage.py「Branch coverage measurement」:https://coverage.readthedocs.io/en/latest/branch.html
- Ruff「Rules」:https://docs.astral.sh/ruff/rules/
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「実装とは?意味・設計との違いを割引計算のコードとテストで解説」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。