[続開発プロセス#7] ここまでのビッグピクチャー

ここまでに説明したことを図解してみます。以下の通りです。要するに「通常の開発」とさほどの違いはありません。UI設計を独立させていることと、実装設計モデルという考え方が入っているだけです。

ちなみに、「こんなにたくさんのドキュメントを作れというのか?」という気になるかもしれませんが、メリハリは付けるべきであるし、開発のイテレーションでは更新しないというドキュメントも出てくるかもしれません。むしろ、どの成果物に力を入れるべきかを考えながら、さらにこれから深掘りしようと思います。

そういうわけで、皆さん、良いお年を!

[続開発プロセス#6] 実装部分の設計の大まかな方針

開発においては要求が最初に何らかの方法で記述される前提で話を進めます。前回のポストでは、要求から具体的な機能や必要なデータベース設計を検討するために、UIの設計を進めることを説明しました。制約された状況(フレームワークや開発ツールを適用した開発)では、UI開発がいろいろな意味で容易にできる状況が用意されているので、UIの設計はプロトタイプを開発したり、あるいはモックアップを作ることで、エンドユーザーによる確認ができることを示しました。そのUI設計や元になっている要求定義をもとにして、どのような仕組みが必要かをさらに検討できます。もちろん、機能や非機能という言い方もできるでしょうし、要件定義という言い方もできますが、UI設計によるビジュアルな側面の具体化とは別方向に、実装すべき機能を抽出するための設計のプロセスが必要です。もちろん、ここでも制約された状況において適用可能な方法を考えて行きます。なお、具体的なモデリング例などは追々紹介するので、まずは全体像を示します。

まず、一般には、要求定義などの初期段階で得られる情報を元にして、ビジネスモデルやあるいはドメインモデルと呼ばれるモデルが作られます。最初に作成できるモデルは、システム境界は曖昧か決まっていない状態のもので、システムを取り巻く業務全体がどのような要素とそれらの関連性を持つのかということを記述するものです。一般にはクラス図で書かれるものが多いと思われます。この段階では、対象とするビジネスドメインを整理し、理解するためのモデルとなります。また、その業務領域における概念を整理し、特定し、名前を確認する(あるいは名前を付ける)ということを行います。なお、用語としてのビジネスモデルは、別の意味にも捉えられるているので、この最初のモデルを「ドメインモデル」と呼ぶことにします。

ドメインモデルにおいては、「どうやって実装するか」ということをなるべく排除する方が良いでしょう。一番の目的は、業務全体をモデルとしてどのように今現在捉えられているかということを理解するためのモデルであるからです。開発者がどうしたいのかということはなく、あくまで、現状のスケッチであり、顧客が考えるシステムを取り巻くビジネス環境を表現したものです。用語については、極力、顧客が使っている用語を使うべきで、ここで用語の整理はまずしない方が良いでしょう。顧客が使っている帳票などから読み取る作業を通じて、1つのまとまった対象が何か、それらがどのような順序で登場し消えていくのか、そして、何を手がかりにその対象が結びついているのかなどをモデル化します。ここで、若干の矛盾点があってもモデルとし、その疑問点はメモ等で残し、どこかで解決を図ることにします。矛盾点は整理せず、現状やプランに矛盾と思われる箇所がある点をモデルとして表現することが肝心です。

この作業は、要求を抽出した段階でもできますが、UI設計の結果を反映させることまでは考えなくても良いでしょう。要求やそのための調査の結果を整理するという目的のためであって、このドメインモデルは最終的な着地点ではありません。UI設計に基づく結果は、実装のための設計にステップは進んでいるので、初期段階での理解をするためのドメインモデルは、要求を元にして作成することにします。

ドメインモデルやUI設計、そして要求を元にした要件定義、あるいは機能や非機能の整理をした結果が得られます。これを元に、具体的な設計を進めます。UI設計を行った結果、まず、システム境界はかなりはっきりするはずです。要求としていろいろ出ているとしても、対象とするシステム外部のことは、設計には含める必要はありません。ただ、別のシステムとして将来実現するというようなことがあれば、要求の記述を改めてそれを設計に含めるということになります。

具体的な設計とは、例えば、データベースのスキーマ(ER図)や、実装につなげるためのクラス図、シーケンス図、コミュニケーション図などで作成することになります。この段階のモデルは一般には「設計モデル」と呼ばれます。ここで、設計モデルは、開発環境の制約を考慮しないものをまずは作成します。最初から制約を考慮するのは手間もかかるし、また、様々な考慮すべきことや解決のための発想を阻害する可能性があります。つまり、まずは一般的な設計を目指すということです。データベース主体の設計では、ER図に相当する設計だけで済ませるかもしれませんが、プログラムを記述するような場合はコントローラに相当する部分の機能の抽出とモデリングもきちんと行うべきです。この段階では、デザインパターンやアーキテクチャパターンなどの様々なテクニックを駆使することも必要になります。

こうして設計モデルが確定が近くなると、実際に開発で利用する状況に合わせた設計モデルへと変化させます。このモデルを「実装設計モデル」と呼ぶことにします。設計モデルに対して、制約を適用したモデルへと発展させて作ります。例えば、モデルやコントロールのクラスを継承するような場合、詳細な設計が必要なのはコントロールそのものではなく、継承して追加する部分だけになります。設計モデルでは「必要な機能を持ったコントロール」が、実装設計モデルではフレームワークが提供する部分はむしろ割愛し「実装作業が必要な部分の記述に絞ったコントロール」として定義し、既存のクラスから単に継承等で記載するだけにします。もちろん、そうすることで、実装の作業をスムーズにすることを意図しています。FileMakerの場合は、ER図を記載した上で、リレーションシップに記述するオカレンスの図に発展させるのが、設計モデルと実装設計モデルの違いになります。いずれの場合でも、開発環境に合わせたパターンなどの設計ノウハウの適用が必要になります。この領域でのノウハウは、ともすると長年のノウハウといった俗人的な対応がよく見られますが、汎用的な開発と同様、パターン集の充実など、環境に合わせた開発ノウハウの標準化をしておくことで、スムーズに実装設計モデルを構築できるでしょう。

このように、設計においては、ドメインモデル→設計モデル→実装設計モデルといった段階を踏むことで、設計を進め、制約された状況でのモデルを構築することを提唱します。特に、設計段階で、どこで制約を適用するかということについては、設計の後の段階で行うがポイントになります。言い換えれば、ツールや環境を考えずに、まずは汎用的な設計をした上で、その設計を実際の環境に適合させることにより、ツールや環境ありきの限定された実装を避けることを意図しています。どの段階でも、モデルに落とし込むテクニックとしてはパターンがまずは挙げられますが、実装設計モデルへのパターンについてはなかなか用意されていないのが実情であり、そのパターン化を意識しながら作業することにもなるかもしれません。そして、ここで本当に欲しいのは最後の実装設計モデルであるとも言えるので、そうなれば設計モデル自体は時間をかけて仕上げるのではなく、不足がないようにすることを心がけてあまり詳細化しすぎない程度で終わらせておき、実装設計モデルに必要な部分だけの詳細化を進めると言った効率的な作業の段取りも考えられます。

Catalinaで使えなくなったRealtekのEthernetのドライバが出たけどダメだった話

私は、MacBookにNOVOOと書かれたEthernet端子付きのアダプタを自宅で使っているのですが、CatalinaになってEthernetが使えなくなりました。ドライバの問題なのは明らです。「システム情報」ではドライバそのものを認識しているのに対して、「ネットワーク」システム環境設定では赤いボールが見えていて、接続できません。もちろん、ケーブルはちゃんと接続してあります。

それで、どうやらCatalina対応版のドライバが出た模様です。Ver.1.0.20だそうです。とは言え、どうやらインストールが簡単ではないようです。そもそも、ドライバが動かなくなった理由は、おそらくはmacOSのセキュリティ要件が厳しくなったからと言うのもあると思われますが、その結果、機能拡張系は簡単にはインストールできない状態になったと思われます。そう言うわけでいろんな関門を潜り抜ける必要があるようです。

インストーラーの中のpkgファイルをダブルクリックして、まずはいきなり起動できません。署名はしてあり有効なもののようなのに、これが出るんですね。システム環境設定の「セキュリティとプライバシー」で「このまま開く」にしたら、もちろん起動してインストールはできます。

延々と待たされます。すると、インストーラーから「許可が必要になった」みたいなメッセージが出てきて、やはり「システム環境設定」のセキュリティとプライバシーを見ると、カギを解除しないといけませんが、みたこともない「いくつかのシステムソフトウェアの読み込みがブロックされました。」といったメッセージが出ています。「許可」をクリックします。

すると、ブロックされたソフトウェアがリストアップされるので、チェックを入れてOKをクリックしました。

この後待たされたのですが、最後の最後でエラーでインストールできないと言われました。えー。もう一度やったら成功したので再起動したのですが、やはり認識してくれません。「システム情報」上は以前と同じのようです。アップデートされていないとしか思えないです。

次に試したのはアンインストールです。ドライバのインストーラに、.commandファイルであるので、説明に従ってインストールして動かし、再起動してインストールしたのですが、再起動後にドライバがもはや見えない状態になっていました。

インストーラの文書を見ると、それでもダメならSIPをオフにしろと書いてあります。手順に従って、Command+R起動、csrutil disable、再起動してインストールしましたが、再起動後、「システム情報」にドライバ情報が登場しません。やはりダメです。

と言うことで、ダメでした。ググったのですが、できたと言う人もいればダメだと言う人もいると言う状況です。何か手順がいるのかも知れませんけど、macOSは順調にシステムに手を入れることを困難にしてセキュリティ確保を画策している模様です。

SwiftUIのビューをUIViewControllerに配置する

Xcode 11.2.1が最新版です。ちょっと思い立って、SwiftUIの画面ショットが必要になり、おなじみのAppleのチュートリアルを開いてみました。あれ?すでにこの通りにならない。半年くらい前に動きの悪いXcodeで必死に追っかけたチュートリアルですが、数ヶ月でその通りでなくなっています。手順通り、プロジェクトを作成する時にiOSのSingle View Appを選択すれば、その次に「Swift UI」のチェックボックスがあるはずなのですが、なくなっています。

快技庵 高橋政明@houheiさんに指摘いただきましたが、User Interfaceのところで、Storyboardではなく、SwiftUIを選択すると、以前のSwiftUIのチェックボックスを選択したのと同じ状態のプロジェクトが作れます。(2019-12-8 21:20)

仕方ないので、そのまま進みます。作ったプロジェクトにはSwiftUIのファイルはありません。この先、SwiftUIのビューを定義するにはどうするかと言うと、FileメニューのNewからFileを選択するなどして、ファイルの追加を行い、SwiftUI Viewの項目を選択して新たにファイルを作ります。この方法でファイルを開いた時、右側にプレビューのCanvasが出ないなら、EditorメニューのCanvasのチェックが入っているかを確認してください。

これで、SwiftUIのビューのコードファイルが用意されているので、作り込んでいくことはできます。なお、現状のXcodeでも、Target Device(プロジェクトアイコンを選択し、アプリケーションを選択して、Generalを選んだところで指定できる)にMacを選択したら、プレビューは動かなくなります。残念!

さて、本題は、こうして作ったアプリケーションを実際にRunさせても真っ白な画面しか出てこないです。つまり、SwiftUIはXcode上のキャンバスでないと動かないわけです。ちなみに、Appleのチュートリアルで作ったものは、ちゃんとRunしても画面に出てくるようになっているのですが、このプロジェクトは、Storyboardは使っていません。SceneDelegateクラスの最初の方に、UIWindowを生成し、UIHostingControllerを生成して、SwiftUIのViewをルートにしています。今後もしかしたら、この手法がメジャーになるのかも知れませんが、今はやはりStoryboardを中心にして作りたいと思いますよね(色々な意見はあるとは思いますが…)。

上記のチュートリアルのコードを見る限りは、UIViewControllerを継承したUIHostingControllerを使えばなんとかなりそうです。あれこれやってみて、こうすれば動くことがわかりました。元々使われているビューコントローラのViewControllerクラスをこのように書き直します。SwiftUIのビューは、既定の名前であるSwiftUIViewのままにしてあります。

import SwiftUI

class ViewController: UIHostingController<SwiftUIView> {

    required init?(coder: NSCoder) {
        super.init(coder: coder, rootView: SwiftUIView())
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}

要するにUIHostingControllerを継承しますが、このクラスにはジェネリックが記述されているの、そこにはViewを記述します。しかし、Viewはプロトコルなので、生成可能なクラスか構造体の名前を書く必要があります。ここでは、SwiftUIViewをそのままビューコントローラーのルートにするとして、そのクラス名を記載しました。

これだけではダメで、UIHostingController関するAppleのドキュメントを睨みます。ここで、init?(coder:rootView:)をオーバーライドしてうまくいくかなとあれこれいじっていたら、Xcodeのメッセージで「init?(coder:)を実装して、そこでスーパークラスのinit?(coder:rootView:)を呼び出しなさい」というのに出会いめでたく上記のようなコードにたどり着きました。もちろん、この初期化メソッドはStoryboardの定義に従って生成した時に初期化のために自動的に呼び出されるものです。StoryboardでViewControllerをインスタンス化する時に呼び出すコードの中で、ルートビューのインスタンスを作ります。これで、Runしたアプリケーションで、SwiftUIのビューが動くようになりました。

Storyboardは最初の状態から特に変更はしていません。View Controllerの直下のViewに対するCustom Classの設定でSwiftUIViewクラスを選択できるようになっていれば、上記のようなことは不要なように思うのですが、まだ、Xcodeはそこまで開発は進んでない模様です。SwiftUIのViewは選択できませんし、無理にキータイプして入れてもエラーになってビルドができません。もちろん、Canvasに見えるプレビューは、Storyboardの中では見えません。もうちょい先、つまり、SwiftUIのプレビューをmacOSをターゲットに入れても動くようになってからなのかなと思ったり。

Storyboardの編集機能をいじっていたら、Hositing View Controllerと言うのがあるのに気付きました。しかしながら、メッセージを見ると、その中にいれるSwiftUI Viewについては、プログラムで記述しろとなっているので、このページに書いてある方法でSwiftUIのViewを追加するのが、Xcode 11での方法になります。やはり、Storyboard上ではまだ全ての作業はできないと言うことです。(2019-12-15 10:05)

[続開発プロセス#5] UIの設計はプロトタイプあるいはモックで

UIの設計はどうするか? 設計の成果物は何にするのか? これは難しい問題であり、そう簡単には結論できません。特定の形式に決めてしまうと、それだけで「自分はできない」「自分は関係ない」という気持ちに強くさせると思います。ですが、設計と実装はどこかで線引きは必要です。その線引きも、会社、チーム、案件、顧客、まずはステークホルダーの集団ごとに違ってくると思われます。そして、設計中も、実装中も、要求との適合を判断するための基準は、UIから得られることは多いでしょう。UIだけということではないものの、システム全体像を形作るものがUIでもあることから、UI設計は独立して進めることになります。

ここで、UIの設計を、制約された状況(フレームワークやツールを使う前提での開発)において適用する場合、まずは、プロトタイプの構築を目指すべきと考えます。なぜなら、それらのツールは一般にUI構築が容易であり、変更も容易であることを謳っているからです。その仕組みを設計においても使わない手はありません。また、Webフレームワークであるなら、Webページのモックアップを作ることを行います。どの手法で、どこまで作り込むのかということは、ツールによっても違ってくるとは思います。ですが、ここでは「実環境である程度作る」ということが重要と考えます。

よく、ホワイトボードや紙を使って設計することがあります。ホワイトボードや紙を使うのは悪いことではありませんが、それらを設計の成果物とすることには、以下のような問題があると考えます。まず、ペンで記述するという自由さから、実装不可能なデザインをやってしまう可能性があります。プロトタイプやモックアップを作るのなら、少なくとも見かけの上では、実現不可能なことは実現できない時点で判別します。そして、やはり手書きの問題点は、書き漏れが多いということです。ホワイトボードや紙を使って、特にグループワークをしていると、話しながら書くので、話を聞いていれば意味がわかる線の塊も、単にその「線の塊」を見ただけではなんのことかわかりません。また、場所が足りないので、「…」となっていたり、書き損じがあるなど、最終的な成果物としては不完全です。つまり、ディスカッション等に費やした時間が後々に無駄になる可能性が高いのです。

では、Excelで清書しようということになるのですが、ずばり言ってそれは無駄です。Excelでグラフィクスを駆使する時間があるのなら、プロトタイプを作ってしまいましょう。また、HTMLでモックを組めば良いことです。わざわざExcelで作ることで、時間をかけるのは無駄です。証拠を残すだけのExcelワークほど無駄なものはありません。ホワイトボードや紙でのディスカッション結果や検討結果は、記憶が新しいうちに、プロトタイプやモックアップに展開し、そこで表現しきれないことは、要求として記述を残しておくのが良いでしょう。

プロトタイプやモックアップをUI設計の成果とする場合、大きなポイントは、それによって何を明確にするのかを、予め目星をつけるあるいはチームとして合意をしておくということがポイントになります。プロトタイプはうまく作りすぎると、クライアントは「もう出来上がったのですか!」と期待に胸を膨らませることになり、ボタンを押しても何も起きないことにかえって幻滅します。おそらく、ここで機能の実装をガッツリやることは、避けたいと思うところです。なぜなら、UI設計をしている段階ではまだまだ多くのことが決まっていないので、実装結果が無駄になる可能性があるからです。よって、プロトタイプもモックアップもともかく、労力がかからない範囲にしないと、かえって無駄な作業をしたことになります。

プロトタイプやモックアップにって明確にすべきことのまず一番重要なことは、「項目」となるべき要素の抽出です。UI画面に入力枠があって、そこに入力するということは、「項目」の1つです。また、一覧表を考えたとき、その列に表示すべき情報も「項目」です。これらは、明らかにデータベースのスキーマや、あるいは内部動作でのプロパティに直結するものであり、UIの上で必要なものを可能な限り余すところなく、UI設計上に記述できていれば、設計のレベルとしては成功だとみなせるでしょう。また、可能であれば、クライアントに協力してもらって、実際に入りそうなデータを入れてみます。もちろん、プロトタイプでは制約も多いですし、HTMLのモックだと自由度は少ないでしょう。それでも、例えば、それらをホワイトボードに写して、そこに手書きでもいいかと思います。具体的にデータをいれる場面にならないと実業務との関連性を判断できない人は多い、というか、ほとんどの人はそうです。抽象的なデザインのモックを見て判断できる人は、一般ユーザーではなくその道の人です。プロトタイプやモックアップでは、項目の抽出が目的であることを常に示しながら、クライアントに的確な判断ができる素地を整えるのが、UI設計のセッションには必要ということになります。

次に明確にすべきこと、あるいはできることとしては、その場面で必要な作業です。狭い意味では、どんなボタンをつけておくと良いのかということになりますが、言い換えればページやパネルなどに実装すべき機能を特定するということです。ここでは、いろいろなワークフローを想定してもらい、そのワークフローがスムーズに進むように、仕組みを追加すると言えばいいでしょうか? そうなると、開発側がプロトタイプやモックアップを紙芝居的に見せながら、不足する機能をピックアップするというセッションが可能になります。ただ、現実位はワークフローの抽出はなかなか大変です。当然、ドキュメントになっていて手順になっていれば、作業はスムーズですが、多くのクライアントは「時間がない」とか、「自分は全部知らない」などの言い訳をして、そうしたドキュメントは作ってくれません。開発側で要求抽出の結果から、不完全なワークフローの記述を作るなどの方策も考えられます。結果的にその場に来てもらって確認ということになることが多いとは思います。このセッションは恐らく達成率はあまり高くならないでしょうけど、要求を実現するための仕組みをUI設計に落とし込むためには、どうしてもワークフローとの関係を早い段階から明白にする必要があります。プロトタイプやモックアップを使えば、一定の範囲内では可能と考えられます。

プロトタイプやモックアップを作った後は、潔く捨てるのか、それとも、それを元に開発を進めるのか? これは非常に悩ましいところです。理想的には1からやり直すべきでしょうけど、結果的にはプロトタイプやモックアップをベースに開発は進むことになります。ここで注意したいのは、プロトタイプやモックアップに入れたけど、結果的に不要だった要素を確実に排除しておくことです。また、データベースを含むプロトタイプもFileMakerを使うような場合はあるかと思いますが、操作が簡単なら、データベース設計はやり直すのが良いと思われます。数回後に説明しますが、別途データベーススキーマの設計はすることになるので、結果的に1から作り直すことになるでしょう。ただ、プロトタイプやモックアップの完成後の扱いは、慎重に検討しましょう。また、作りかけの素材を元にする場合も、プロトタイプベースの開発と同様に、既存の開発物をどのように使うのかという問題は付き纏います。

macOSでJava8

そういう需要もあると思います。今、ある作業をしていて、Javaのバージョンが違うと怒られ、Java8のJDKが必要になりました。当然、Homebrewを使うのですが、いろいろなサイトで書かれている内容はその通りには行きません。今年の4月ごろの記事から事情がもう変わっている。この記事が当たりでした。ということで、次のコマンドでいけました。メッセージを見る限りはCaskにあるようです。

brew cask install adoptopenjdk/openjdk/adoptopenjdk8

あと、ほとんど自分用メモですが、以下のコマンドで、Javaのホームのパスが得られます。

/usr/libexec/java_home -v “1.8”

あるいは、以下のようにコマンドを入れて、環境変数のJAVA_HOMEを設定します。

JAVA_HOME=$(/usr/libexec/java_home -v “1.8”)

パスに含めるなら、このような感じです。

PATH=${JAVA_HOME}/bin:${PATH}

以上は一時的な環境変数の設定です。何か特定のことにだけ、Java8を使うのであれば、システムの環境変数は書き換えない方が便利ですね。