ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

読んだ : Infrastructure As Code

インフラやっていくぞー、という気持ちで去年の中ごろに読んだ。

Infrastructure as Code ―クラウドにおけるサーバ管理の原則とプラクティス

Infrastructure as Code ―クラウドにおけるサーバ管理の原則とプラクティス

本書では最初 (第 1 部) に 「なぜ Infrastructure as Code が必要なのか」 「Infrastructure as Code とは何なのか、何を目指しているのか」 といった説明から始まり、Infrastructure as Code に関わるサービスやツールの紹介がなされる。 そして 2 部では、1 部で紹介されたツールなどを使ったサーバーの追加や変更といったインフラストラクチャの運用のパターンが紹介される。 最後の 3 部はプラクティスで、ソフトウェア工学のプラクティスを応用することや Infrastructure as Code のための組織といった部分の話がなされる。

自分は、Infrastructure as Code とはインフラ構成管理をコード化することで手順を再現できるようにしたり、バージョン管理できるようにしたり、自動化できるようにすること、というぐらいの理解しかない状態で読み始めたのだが、本書で説明される Infrastructure as Code はソフトウェア工学のプラクティスを応用するなど、もともと自分が想定していたものよりもさらに進んだものだった。 また、本書は 「なぜこういう考え方をするのか」 という思想的な部分も丁寧に説明しており、納得しやすい。 学びの多い良い本であった。

特に気になった内容のメモや感想

  • Infrastructure as Code の原則
    • 簡単に再現できるシステム
    • 使い捨てにできるシステム
    • 統一的なシステム
    • 反復できるシステム
    • 絶えず変化する設計
  • Infrastructure as Code の原則
    • 定義ファイルの利用
    • 自己記述システムとプロセス
    • あらゆるものをバージョン管理
    • 継続的テストシステム、プロセス
    • 一斉変更ではなく小刻みな変更
    • 継続的にサービスを利用可能状態に保つ
  • 「アンチフラジャイル」 という概念 : ストレスを受けたときに通常よりも強くなるシステム (インシデント発生時の対応として改良することをデフォルトの対応とする)
  • 「スタック」 の概念 : 一つの単位として定義・変更される、インフラストラクチャ要素の集合
    • スタックの単位で構造化していく : 単純な構成だとスタックへの分割の恩恵はないが、リソースの共有などをする場合には意味がある
    • スタック間の情報のやり取りに構成レジストリが役に立つ
  • システムの品質について、機能的な正しさの問題だと思われてしまうことが多いが、実際には変化を許すかどうかを決める鍵を握っている
    • 高品質システムは従来よりも簡単かつ安全に変更できる
  • 継続的なブランチのテストは継続的インテグレーションではない
    • 継続的インテグレーションとは、すべての作業がトランクで行われて、すべてのコミットがテストされることが保証される。 完全にチェックされた変更だけが本番システムに適用されることを保証するためには継続的デリバリーパイプラインを使う。
    • 思想としてはよいと思うが実践的にはレビュー等どうするのだ?? という気がする。 (機能を完全に実装する前の小さい変更の状態でブランチをマージしていく、ぐらいが実践的な気がする。)
  • 変更パイプライン : ソフトウェアのデプロイパイプラインに相当するもの (ソフトウェアのデプロイとは違うことを区別するために著者はこう呼んでいる)
  • 継続的デリバリーは継続的デプロイではない : 継続的デリバリー (CD) とは、すべての変更をすぐに本番に送り込める状態に高めること。 デプロイ判断を下したら後はツールがデプロイしていく (システムの稼働が技術的な判断になるのではなくビジネス上の判断になる)
  • インフラストラクチャの変更のテストでもソフトウェアのテストと同じく、低水準のものを多く、高水準のものを少なくする (テストピラミッド)
    • これに限らず、テストのプラクティスは結構ソフトウェアのテストと似ている部分が多いなーと感じた
  • リリースとデプロイを切り離すというプラクティス
    • 機能トグルとかゼロダウンタイム交換パターンとか
  • コンシューマ主導のコントラクト (CDC) テスト
    • コンシューマが提供するテストをプロバイダ側のパイプライン上で動かす
    • ソフトウェア開発のクライアントとサーバー間でも使えそう
  • ワークフローにガバナンスを組み込む
    • 承認などのフローも自動化してログの保持などをすることで、手での承認よりも良いものになる
  • ゼロダウンタイム変更のパターン
    • ブルー・グリーン交換 : ソフトウェアにおけるブルー・グリーンデプロイパターンをインフラストラクチャに応用したもの。 2 つのインスタンス群を切り替える
    • フェニックス交換 : ブルー・グリーン交換を進化させたもの。 常にインスタンス群を 2 つ用意しておくのではなく、必要になったときに新たに用意する
    • カナリア交換 : 全体を一気に切り替えるのではなく、システム全体のうちの一部ずつを新しいものに変えていく。 大規模システムでは上記は採用できないので、この方法になる (GoogleFacebook などで採用)
  • 企業が変化するニーズに対して信頼できる高品質のサービスで応えていくための組織面での原則
    • サービスの設計、実装、改良に対して継続的にアプローチしていくこと
    • 継続的にサービスをデリバリー、改良する権限をチームに与えること
    • 継続的にスピーディに変更をデリバリーしつつ、高い品質とコンプライアンスを保証すること
  • 効果測定。 目標と状況に基づいて役に立つものを選択
    • インフラチームが良く使っているのはリードタイム、平均修復時間 (MTTR)、平均故障間隔 (MTBF)、可用性、本物の可用性など
  • ユーザーに力を与える組織
    • ラクティス
      • セルフサービスモデル (使う人が作る)
      • Dev と Ops を (構築も運用も) 同じチーム : 運用時の問題から構築のチームが学習しづらい
      • 職能横断型チーム : 複数のプロジェクトの間でマルチタスクをこなす必要がなくなり、効率的に
        • このチームでは専門性の維持に課題があるが、「トライブ」 などのチーム横断型のコミュニティで対応
    • 職能分割モデルには落とし穴がある
      • 設計の細分化 : 設計と仕様が中央で作られて、実装のために様々なチームに分配される。 チームからは全体像が見えない
      • 厳格な日程管理 : 各チームが複数プロジェクトに関わることになるので、日程管理が重要になってくる
      • 長いリードタイム : チーム間の作業の一つ一つがオーバーヘッドを生む



ウケた

読んだ : よくわかる Auto Layout — iOS レスポンシブデザインをマスター

同僚の iOS エンジニア氏に 「Auto Layout についてちゃんと学んでおくといいですよ」 って言われたので読んだ。

よくわかるAuto Layout  iOSレスポンシブデザインをマスター

よくわかるAuto Layout iOSレスポンシブデザインをマスター

著者によると下記のように書かれていて、わりと iOS アプリ開発の初心者向けっぽい。 まさに iOS アプリ開発初心者である自分にとって学びの多い良い本だった。

「よくわかるAuto Layout」はAuto Layoutとサイズクラスについて解説している書籍です。レイアウトの基礎を包括的に紹介し、後半では業務でよく使うパターンをまとめています。アマゾンの紹介文によると対象者は、

過去一度はXcodeを用いてアプリを作ったことがあるが、Auto Layoutとサイズクラスを用いたAdaptive Layoutと言われると、つい尻込みしてしまうアプリ開発者にぴったりの一冊です。

という感じになっています。基本的には、iOSアプリ開発初心者に向けて書いているので、"黒帯エンジニア"みたいな人には向きません。

「よくわかるAuto Layout」を執筆した話 - Jeffsuke is not a pen.

2016 年の本なので最新情報がない点だけは注意が必要そう。 (とはいえ Auto Layout の基礎を学ぶ上では問題なさそう。)

学んだこと

大量の学びがあった。

1 章 : Adaptive Layout をはじめる

  • 「Adaptivity」 というのは web でいうところのレスポンシブデザインみたいな感じ。 様々なサイズの画面などに適合するように UI デザインする
  • iOS 8 からトレイト (trait) という概念が導入された。 画面サイズなどの環境情報を抽象的なオブジェクトとして扱う概念

2 章 : Auto Layout の基本概念

  • Auto Layout エンジンは制約式の連立方程式を解いてレイアウトを決定する
    • Auto Layout エンジンによる計算においては、各コンポーネントのフレームではなく外接矩形 (Alignment Rectangle) が用いられる
    • 制約式は Item1.Attribute1 = Multiplier * Item2.Attribute2 + Constant の形。 NSLayoutConstraint で表現される
      • Constant (制約定数) は制約生成後にも変更可能で、画面回転等に対応しやすい
      • 等号だけでなく不等号も可能
    • 制約には優先度がある
    • 参考 : Auto Layout Guide: Anatomy of a Constraint
  • Intrinsic Content Size は、view が保持する内容の固有のサイズ。 他の制約がない場合にはこのサイズが使われたりする
    • Content Hugging Priority と Content Compression Resistance Priority で伸び縮みの優先度が決められる
  • Auto Layout 以前には Autoresizing が使われていた。 Auto Layout にも影響する (NSAutoresizingMaskLayoutConstraint という制約になる)。 View をコードで生成するとデフォルトでは Autoresizing が Auto Layout の制約に変換されるので注意。 (UIView.translatesAutoresizingMaskIntoConstraints で変換されないように設定できる)

3 章 : UIViewController とレイアウトをサポートするクラス

  • 表示の階層構造 : スクリーン (UIScreen)、アプリのウィンドウ (UIWindow)、ビューコントローラ、ビューコントローラが持つビュー
  • アプリ起動時のルートビューコントローラの設定方法はストーリーボードを使うかどうかで異なる
  • レイアウトのライフサイクルは、制約の更新、フレームの更新、レンダリングの 3 ステップ
  • フレームとは??
  • View controller のライフサイクル : 読み込み、表示、レイアウト、非表示
  • UIWindow はウィンドウ。 キーボードとかもウィンドウ
  • アプリ内部でウィンドウの配列も取れる。 windowLevel で重なり順
  • ウィンドウサイズとスクリーンサイズは区別すること

4 章 : Storyboard と Auto Layout

  • アプリ起動時のストーリーボードをプログラムで指定もできる。 A/B テストとか。 AppDelegate で
  • ストーリーボードごとに Auto Layout の有効無効の設定ができる
  • 複数ビューに Spacing to nearest neighbor もできる
  • Equal Width などで 2 つのビューにサイズの制約をつけてそれ以外の幅の制約がない場合は大きい方の Intrinsic content size が使われる (Content Hugging Priority と Content Compression Resistance Priority だと後者のほうが通常は優先)
  • Align Panel でビュー間の並び方を決定。 定数も指定可能
  • Stack ボタン、本書の例とは変わってそう?
  • IB (Interface Builder) でビューを Control ドラッグすることでも制約追加できる。 Document Outline Control 上でも
  • IB でのビューのマージン表示 : Editor > Canvas > Show Layout Rectangles
  • IB 上で追加した制約は IBOutlet で参照できる
  • 制約に Identifier をつけることができて、エラーメッセージなどがわかりやすくなったりコードから参照できるようになったり
  • xib で独自ビューを作れる
  • iOS 8 以降の端末のみサポートであれば Xcode 7 で導入された Storyboard Reference で分割できる。 さもなければコードで分割
  • Bundle の概念とは? → アプリやフレームワーク、その他の種々のコンテンツなどを表すものらしい。

5 章 : コードと Auto Layout

  • 制約 (NSLayoutConstraint) をコード上で生成する方法は 3 つ。 普通にインスタンス化するのと、VFL (Visual Format Language) を用いる方法と、NSLayoutAnchor ファクトリークラスを用いる方法
  • VFL はアスキーアートみたいなやつ。 デバッグ中のエラーメッセージにも出てくるので一応形式は知っておくとよいとのこと
  • NSLayoutAnchor がおすすめ。 iOS 9.0 以降
  • 制約を作ったあとは有効化が必要。 iOS 7 以前のサポートが必要ならビューに追加する。 iOS 8 以降だけでいいなら制約の有効化を行う。 複数制約を有効化するための便利メソッドもある (NSLayoutConstraint.activateConstrains)
  • 制約の削除や編集もできる。 編集で制約定数を変更するほうが制約の削除と追加よりコストが低いらしい
  • iOS 9.0 以降では UILayoutGuide で空間を表現できる。 AndroidSpace っぽいけど、Space と違って view ではないらしい。 Xcode 7.3 時点では IB 上で生成できない (まじか)

6 章 : 実装基本パターン

  • 親ビューに対する割合で幅や高さを指定できる。 Multiplier で。
  • Android でいうところの Space みたいなものは UIView を透明にする (または上に書いた UILayoutGuide)
    • 透明にするほうがパフォーマンス悪いから背景色決まってるなら背景色指定の方が良いらしい
  • View を削除したり、一時的に非表示にして後から戻すというような処理 (本書ではトルツメ) は難しい
    • View を削除するとその view に関連する制約も削除されるため
  • UIScrollView の内容サイズも Auto Layout で指定する (さもなければコードで指定する必要がある)
  • 上述のとおり、AutoresizingMask が制約に変換されないようにした方が (暗黙的に制約が追加されて混乱する、ということがないので) 良い場合が多いが、xib ファイルにレイアウトがカプセル化された view を UITableCellView に追加する場合などは Autoresizing を有効にしておくと便利っぽい (そうすると親 view のサイズに自動的に合うようになるので)
  • UIStackView は、view を縦か横に一列に並べる view。 制約を自分で追加せずとも自動で Auto Layout してくれるので便利 (Android でいうところの LinearLayout っぽい感じ)

7 章 : 実装応用パターン集

  • UITableView のセルの高さを指定する方法は 3 つ。 固定の高さを与える方法と、セルごとに計算する方法と、Self-Sizing Cells を使う方法 (iOS 8 以降)。
  • オフスクリーンでのレイアウトの際に UILabel のサイズを見るには preferredMaxLayoutWidth を設定する必要がある
  • テーブルのスクロール領域全体の高さ計算が最初に実行されるので、セル数が多い場合はパフォーマンスに問題が起こりうる。 iOS 7 以降だと estimatedRowHeight で対処できる
  • Dynamic Type、ユーザー設定に合わせてフォントのサイズを変更する仕組み
  • キーボード表示時に表示中の内容がキーボードに隠れないようにするには独自処理が必要
  • 画面回転への対応は、iOS 8.0 以降とそれより前で方法が異なる
    • 回転時のレイアウト変更は制約の有効化と無効化でやるのが (制約の追加と削除よりも) パフォーマンス的には良い
    • UIViewControllerTransitionCoordinator.animateAlongsideTransition に制約の変更を記述することで、画面回転のアニメーションと同期して動くようになるらしい

8 章 : Auto Layout をデバッグする

  • デバッグに用いることができる Auto Layout の情報は : IB キャンバスおよび Document Outline Control 上と Issue Navigator 上と実行時のコンソール (この章では主にコンソールの話)
  • 曖昧なレイアウトかどうかは hasAmbiguousLayout で確認できる。 exerciseAmbiguityInLayout でランダムにフレームを変更できる
  • ドキュメント化されていない便利なメソッドもある
  • 制約の衝突はコンソールログを確認。 UIViewAlertForUnsatisfiableConstraints のシンボリックブレークポイントでも捉えられる
  • 制約に Identifier を追加するのと、軸やビューごとに制約を確認する
  • ビューデバッガーが Xcode 6 で追加されてる。 制約の表示もできる

9 章 : サイズクラスとトレイトコレクション

  • トレイトコレクション。 ミュータブルなので最適な値を持つ?? みたいなことが書かれていたがミュータブルという表現がよくわからない。 (例えばアプリのウィンドウがスクリーンよりも小さい場合に、UIScreen が持つトレイトコレクションのサイズクラスは Regular だけど UIWindow が持つトレイトコレクションのサイズクラスは Compact になる、みたいなことかなーと思っている。 が、あってるかどうかは不明)
  • 画面回転
  • IB においてサイズクラスに応じたレイアウトが可能

感想

Auto Layout はもちろんのこと、view の階層構造や view のレンダリングのライフサイクル周りなどについても学ぶことができて、非常に良い本だった。

初心者ながらに 「iOS の view 周りについて必読の一冊なのではないか」 と思った。

関連

読んだ : これからつくる iPhone アプリ開発入門 — Swift ではじめるプログラミングの第一歩

何故か iOS アプリ開発に関わることになったので iOS アプリ開発について学んでいる。

とりあえず

の 2 つを読んで基礎の基礎だけおさえたところで本書を読んだ。

新たに学んだこと

Foundation フレームワーク周り

UIKit フレームワーク周り

その他フレームワーク周り

本書で出てきたフレームワーク

Swift 言語周り

その他 iOS アプリ周り

  • 重なっている view の z 軸方向の重なり順を Interface Builder (IB) 上で変更するにはドキュメントアウトライン上での前後の位置を変えればよい
    • オブジェクトを選択して、メニューの Editor > Arrange > Send to Front などで変更することも可能
  • Xcode でパラメータ情報を見るにはカーソルを当てて Option キー
  • App Transport Security で通信のセキュリティ周りが規定される
    • NSAppTransportSecurity キー
    • 参考 : Cocoa Keys
    • iOS 10 でデフォルト設定が変わったらしい

関連して調べたこと

そもそもフレームワークとは?

共有リソース *1 を保持する構造化されたディレクトリ (バンドル) のことらしい。

A framework is a hierarchical directory that encapsulates shared resources, such as a dynamic shared library, nib files, image files, localized strings, header files, and reference documentation in a single package. Multiple applications can use all of these resources simultaneously. The system loads them into memory as needed and shares the one copy of the resource among all applications whenever possible.

What are Frameworks?

A framework is a bundle (a structured directory) that contains a dynamic shared library along with associated resources, such as nib files, image files, and header files. When you develop an application, your project links to one or more frameworks. For example, iPhone application projects link by default to the Foundation, UIKit, and Core Graphics frameworks.

Framework

感想

かなり丁寧に Xcode 上での操作手順などの説明が書かれていて、iOS 開発以外も含めてプログラミング自体の初心者向けという感じ。 とりあえず最初の一歩としては良さそう。 開発経験者でも、iOS が初めてなら本書をばーっと読んで一通り学ぶという使い方はできそう。 (とはいえ古いので今だと他に良い本もありそう。)

一方でソースコードに微妙なところがあったり *2、デリゲートの説明とかクロージャの説明とかが微妙だったりするのは気になった。

*1:ダイナミックシェアードライブラリや nib ファイル、画像ファイル、ローカライズされた文字列やヘッダファイル、リファレンスドキュメントなど。

*2:AVAudioPlayerの使い方」 のソースコードはまさに本書のもので、AVAudioPlayer の初期化処理がちょっと謎な気がする。

読んだ : JUnit 実践入門 〜 体系的に学ぶユニットテストの技法

JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)

JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)

既に JUnit 5 が出ているし今更感はある (本書は JUnit 4 を題材にしている) けど、テストの全体的な話も学べるかなって思って読んだ。 JUnit 4 の話もありつつテスト全般に関する知見も書かれているので、(類書も少ないので) 読む機会がある人はさらっと読んでみるといいかもしれない。

新しく学んだこと

テスト全般

  • テストフィクスチャ (test fixtures) : テストの対象やテストの入力値や検証用の値、外部リソースなどの実行環境やテストの実行前に必要なオブジェクトの操作などのこと。
    • 狭義にはテストデータだけを指して 「テストフィクスチャ」 と呼ぶこともあるらしい。
  • 振舞駆動開発 (behavior driven development; BDD) : ソフトウェアの相互作用に着目してソフトウェアがどのように振る舞うかを定義することを起点とした開発技法
    • テスト駆動開発と似ている部分もあるが、ソフトウェア全体がテスト対象で、ユースケースシナリオのシナリオの粒度でシステムをテストするという違いがある。
    • 語彙として、Given (前提) / When (条件) / Then (ならば) というものが使われる。 それぞれテスト駆動開発の arrange (set up) / act (exercise) / assert (verify) に対応する。

JUnit 4 について

読んだ : ユースケース駆動開発実践ガイド

ユースケース駆動開発実践ガイド (OOP Foundations)

ユースケース駆動開発実践ガイド (OOP Foundations)

ユースケースを出発点とする開発プロセスを学びたかったので読んだ。 ちなみにこの書籍が言っている 「ユースケース」 というのは Ivar Jacobson (イヴァー・ヤコブソン) によるものであり、Uncle Bob の Clean Architecture が言う 「ユースケース」 と (基本的には) 同じものである *1

結論から言うと、本書は個人的に学びの多いものであった。 私は 「DDD を実際の開発プロセスにどう取り込んでいくと良いか?」 「Clean Architecture でいうところの UseCases 層のメソッドって具体的にどういう粒度で書くことになるのか?」 といったところを知りたかったのだが、非常に参考になった。 また、ちゃんとした要求定義・要件定義などの経験がなく *2 て、要求定義を含んだ開発プロセスについても学びたかったので、その点を学ぶことができたのも良かった。

古い本ではあるが、開発プロセスを概念的に理解するという目的であれば現代でも十分に通用するものだと感じる。 不要な内容もそれなりにある *3 が、そこはいい感じに飛ばして読むと良いだろう。

内容 : 開発プロセス概要

本書で述べられている開発プロセスICONIX プロセスと呼ばれるものである。 大まかな流れは以下のようになる。

f:id:nobuoka:20190217132851p:plain
ICONIX プロセス

要求定義から始まり、実装・テストまで静的モデルと動的モデルをブラッシュアップしながら進めていく。 全体の流れを説明すると下記のようになる。

  1. 要求定義
    • 機能要求 : システムができることの定義。 プロジェクトの組織化によって開発チームが機能要求の抽出に加わるのか、顧客やビジネス分析者が機能要求を開発チームに伝えるのかが決まる。
    • ドメインモデリング : 問題領域からユビキタス言語を定義し、単語間の関連を表現する。
    • 振る舞い要求 : 紙芝居から始めて、アクター (ユーザー) とシステムがどう対話するかをユースケースとして記述する。
    • 要求レビュー : ユースケース記述が顧客の要望に応えているかレビューする。 ユースケースごとに行っても良い。
  2. 分析・予備設計レビュー : 個別のイテレーションごとに (= ユースケースの小さな単位で) 下記を行う。
  3. 詳細設計
    • シーケンス図の作成
    • ドメインオブジェクトに振る舞いを追加して、クラスモデルに昇華
    • 詳細設計レビュー
  4. 実装
    • コーディングと単体テスト
    • 統合テストとシナリオテスト

ICONIX プロセスの特徴はロバストネス分析にあるらしく、ロバストネス分析により 「ユースケースとシーケンス図の間のギャップが大きく、ユースケースとシーケンス図がうまく対応付けられていない」 という状況が起こることを避けられるらしい。

ユースケースについて

Jacobson の 「ユースケース」 と言っても、いろいろ流儀があるらしい。 本書では、ユースケースの記述として下記を重要と言っている。

  • イベントとその応答として、アクター (ユーザー) とシステムの対話を記述すること。 すなわち、ユーザーがどういう操作をするのかだけでなく、システムの挙動も記述する。
  • UI についても考慮する。 GUI プロトタイプや画面モックアップを使用する。
  • ドメインモデル中の言葉や、画面のようなバウンダリクラスの名前を使って記述する。
  • 代替コース (「雨の日」 のシナリオ) (バリデーションエラー時のシステムの応答など) を忘れないようにする。
  • ユースケース記述は叙述的にする。 要求自体をユースケース記述に含めたりはしない。 (要求は別に管理し、要求を満たすようにユースケースを記述すれば良い。)

思ったことなど

アジャイルなプロセスに適用できるのか?

本書ではできると書かれている。 私自身の実感としても可能だと感じた。

上流工程でのモデリングを、コーディングの前に少しだけ (1 回にひとつのユースケースに対してだけ) 行うのか、すべてのユースケースをコーディング前にモデリングするのかの判断は、あなたに任されてい ます。 ICONIX プロセスを利用する場合、プロジェクトに応じてアジャイルに行う (短いイテレーションによって、短期間で連続的にリリースする) ことも、ウォーターフォール的に行う (まずすべての要求を記述し、設計を行い、それからコードを書く) ことも可能です。

ユースケース駆動開発とドメイン駆動設計 (DDD)

ユースケース駆動開発」 と聞くと DDD とは全然違う概念のように思うが、実際のところはドメインモデリングをするし、動的モデルをユースケース記述からブラッシュアップしていくのにあわせて静的モデル (ドメインモデル) をブラッシュアップするという開発プロセスなので、ある意味 DDD (の一部?) を包含しているように思う。 DDD で難しいのは 「ドメインオブジェクトにどういう振る舞いを割り当てるのか」 というところ *4 だと私は思っているのだが、ICONIX プロセスではユースケース記述中に出てくる動詞がドメインオブジェクトの振る舞いの候補となるので、DDD をやりやすいと感じた。

つまり、ドメインモデルを使う側 (ユースケース側) の記述をもとにドメインモデルに振る舞いを割り当てられるわけである。 さらに言うと、そうすることでアプリケーション上のユースケースのステップに相当する処理がユースケース記述に近いものになり、実装を理解しやすくなるという利点もある。

ドキュメントを書くべきなのか?

ICONIX プロセスではドキュメント (ユースケース記述やドメインモデル、ロバストネス図やシーケンス図など) をしっかりと作り、コードの変更に合わせてドキュメントを更新していくという教えになっている。 個人的には、ユースケース記述とユビキタス言語についてはドキュメント化はした方が良くて (= 非開発者とも共有するため)、それ以外の設計用のドキュメントについては開発チームの練度によるかなーという気はする。 ユースケース記述とユビキタス言語から直接設計・実装に入れる場合も多々ありそうなので、必要に応じてで良さそう。 ロバストネス図やシーケンス図をしっかりと書くことでユースケースドメインモデルのブラッシュアップに効くというのはわかるので、それを明示されたモデル上でやるのか、頭の中でやるのか、実際のコード上でやるのか、みたいな話になりそう。

Clean Architecture でいう UseCases との関係

冒頭でも述べた通り、Clean Architecture におけるユースケースも Jacobson のユースケースがもとになっている。 『Clean Architecture 達人に学ぶソフトウェアの構造と設計』 には、ユースケースについて 『ユーザーとエンティティのインタラクションを支配するアプリケーション固有のルールを記述したものである』 と書かれており、基本的には本書のユースケースと同じものを表している思って良いだろう。 ただ、ユースケースの例を見るとシステムの挙動しか表していなかったり、『ユースケースは、ユーザーインターフェイスについては記述していない』 と書かれていたりして、やや差異はあるようだ。 ここら辺はユースケースの書き方の流儀の違いなどによるものだと思われる。

UseCases 層の実装として、『ユースケースはオブジェクトである。アプリケーション固有のビジネスルールを実装した関数を1つ以上持っている。』 と書かれている。 これをそのまま受け取ると、1 ユースケースに対して 1 つの UseCase クラスを用意し、ユースケース記述におけるシステムの応答のステップのひとまとまりを 1 メソッドとして実装する (ユースケースに複数の応答がある場合などは複数メソッドを定義する) という感じになりそう?

とはいえ Android だと非同期処理とか画面遷移とかで 1 ユースケースを 1 クラスで実装するのは設計的にやりにくい気もするので、「UseCases 層のメソッドはユースケース記述の粒度で実装する」 ぐらいの感じで設計すれば良さそう。

ユースケース記述に技術的な内容を含めて良いか

例えば 「キャッシュ」 の扱いなど。 個人的にはユーザーから検知できるものであればユースケースに含めるべきなきはしている。

例えばブラウザでスーパーリロードするとキャッシュがあっても再読み込みする、みたいな場合、ユーザーからキャッシュの存在が見えるわけなので、ユースケース記述に含めるべきな気がする。 キャッシュの有無がユーザーから見える挙動に全く影響を与えない、本当にパフォーマンスのためだけのキャッシュだったらユースケースに含めない方が良さそう。

関連

目線合わせシートとユースケース記述

うちのチームでは、新機能開発などの施策を行う際にデザイナの人が 「目線合わせシート」 というものを作ってくれている。

UI のプロトタイプやユーザーの行動などがまとめられている。 うちのチームでユースケースを使うとしたら、目線合わせシートをもとにユースケースを抜き出してユースケース記述をしていく、という感じにするのが良さそう。

*1:書籍 『Clean Architecture 達人に学ぶソフトウェアの構造と設計』 において、「ユースケース」 が Ivar Jacobson によるものであることが述べられている。

*2:Web 業界だと明確な要求定義がないことが多いように思う。

*3:UML についてだったり、モデリングツールの使い方だったりの説明などがある。

*4:戦略的には境界付けられたコンテキストをどう分けるかというところが一番難しいと思っているけど、ここでは戦術的な話をしている。