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

抽象データ型について学んだ

 抽象データ型について学んだ

Avatar for ryounasso

ryounasso

May 22, 2025
Tweet

More Decks by ryounasso

Other Decks in Programming

Transcript

  1. 抽象データ型とは • TYPES (型) • FUNCTIONS (関数) ◦ そ 抽象データ型に適用可能な操作

    • AXIOMS (公理) ◦ そ 抽象データ型が必ず満たす条件 • PRECONDITIONS (事前条件) ◦ 関数が正しく動作するために必要な前提条件 データ構造を公開した振る舞いの集合で表現する仕様記述 抽象データ型に基づいて実装することで、クライアントは内部実装を意識せず、 振る舞いに依存する形でシステムを構築することが可能になる
  2. • push(E item): スタック 一番上に要素を追加 • pop(): スタック 一番上 要素を取り出して削除

    • peek(): スタック 一番上 要素を参照(削除 しない) • empty(): スタックが空かどうかを確認 • Stack: 空 Stack を生成する 抽象データ型の例: Stack 本では例として Stack が取り上げられていた Stack は「後入れ先だし」 (LIFO: Last-In-First-Out) という特徴を持っている Java24 の Stack の操作をもとに、抽象データ型の仕様記述をみる https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/Stack.html
  3. 抽象データ型の例: Stack - TYPES - STACK[G] - FUNCTIONS - push:

    STACK[G] x G -> STACK[G] - peek: STACK[G] -/> G - pop: STACK[G] -/> STACK[G] - empty: STACK[G] -> BOOLEAN - Stack: STACK[G] これらの操作を用いて、先ほどの仕様記述を行うと以下の通り - AXIOMS - 任意 x:G, s:STACK[G]に対して 以下が成り立つ - 1. peek(push(s,x)) = x - 2. pop(push(s,x)) = s - 3. empty(Stack) - 4. not empty(push(s,x)) - PRECONDITIONS - peek(s: STACK[G]) require not empty(s) - pop(s: STACK[G]) require not empty(s)
  4. 抽象データ型の例: Stack AXIOMS 1 と 2 → LIFO を表現 こ

    特徴を表現する に使用してい る が FUNCTIONS で定義されて いる振る舞い み - AXIOMS - 任意 x:G, s:STACK[G]に対して 以下が成り立つ - 1. peek(push(s,x)) = x - 2. pop(push(s,x)) = s - 3. empty(new) - 4. not empty(push(s,x)) - PRECONDITIONS - peek(s: STACK[G]) require not empty(s) - pop(s: STACK[G]) require not empty(s) これがデータ構造を公開した振る舞い みで表現する使用記述である抽象データ型
  5. これを Java の実装に落とし込むと... 1. 作成する型 特徴を捉える (TYPES) 2. どんな操作を公開することで特徴を表現できるかを考え、interface に

    落とし込む (FUNCTIONS) 3. クライアントが定義する操作を通じてどんな結果が欲しい か、それを 実現するためにどんな条件を満たして欲しい かを考える (PRECONDITIONS) 4. 公開する振る舞いを用いて公理を考える (AXIOMS) こ 公理が作成する型 特徴を表現できているか確認する 5. 定義した内容に沿うように interface を実装する (interface がない場合や、2~4 を行き来することもあると思います)
  6. システムの拡張や保守コストの削減 ソフトウェア 保守コスト 17.6% が「データフォーマット 変更」と こと 例) アメリ か郵便番号

    桁数を5桁から9桁に変更する際に多く 変更が必要となり、 コスト 数億ドルに及んだ → 郵便番号が5桁という内部構造に依存する実装をしてしまっていたことが原因 郵便番号 特徴 、そ 番号から一意 住所が導かれることである クライアントが公開している振る舞いに依存することで、 今後 機能拡張や保守 際 対応コストを下げることができる
  7. より良いテストをかけるように 抽象データ型における公理 、そ クラス 特徴を表します。 それらが内部実装 変更によって壊れるとよくないです。 そ ためこ 公理を担保するため

    テストが必要であると判断できます。 こ ように、公理を明確にすることによって、何をテストするべきか 判断が行いやすく なり、テスト 過不足を避けやすくなります。 また、振る舞いに依存し、内部実装に依存しないテストを書きやすくなり、リファクタリン グに強いテストを書くことが可能になります。