[続開発プロセス#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を使うのであれば、システムの環境変数は書き換えない方が便利ですね。

[続開発プロセス#4] どこにフォーカスするか

制約された状況での開発プロセスとして、どこにフォーカスするかをまずは示しておきます。開発において、「要求」が最初にあり、それに応じて「設計」「実装」と進む点はもちろん外せません。ここで、重点をおきたい「設計」については、(1)ユーザーインタフェース設計と、(2)内部動作設計の2つに分離して考えます。古くからの言い方だと、外部設計、内部設計に相当し、呼び方としてはそれでいいとは思いますが、ポイントはUIとそれ以外に分離します。(2)は何かいい言葉が見つかったら変えます。

ここで、全体的なデザインやUXはどうなるということが気になるところですが、もちろん、UXはUIとは切っても切れない間柄ではあるものの、本来はUXの検討事項は要求に還元されるのではないかとも言えます。ユーザーの体験は「実現したいこと」であり、どう実現するかと言うことではないのです。

一方、ドメイン知識などはどうでしょう? これは、要求を明確化するための素地と考えます。ビジネスモデルは、要求を明確化したものとも言えます。このように、初期段階の難しいプロセスは、実は要求の定義に帰着します。そうなると、やはり要求は無視できないということになりますが、ここでは現在の様々な開発現場の状況をそのまま取り込むことを考えます。要求分析はしないわけではないですし、軽視するつもりもありません。しかしながら、現実に要求が固まった状況で開発に取り掛かれることは皆無であり、開発途中で要求は変化し、追加され、また物によってはなくなります。開発プロセスの中で、要求までフィードバックして、再検討することは多々あるという状況です。また、派生開発では、謎の実装があってもそれら全部に要求をマッピングすることはせずに進める場合もあるでしょう。時間がないというより、本当に分からないこともあり、影響がないなら無視と判断するのは効率を基準にすれば正しいと言えます。

制約された開発環境の多くは、そうした仕様変更への対処に強いことが特徴として言えます。変更後の実装変更作業が、相対的に軽いと言えるでしょう。そのために制約があるものの、その制約を理解した上で最短のタスクを動かせば、短時間で巻き返しが可能です。そこが大きな特徴であることは明白なのですが、スクラッチな開発の話ばかりが強調されている気もします。

要求自体をどのように扱うかと言う点については、ここで検討する開発プロセスでは、結果的に「通常通り」と言う結論になり、そこから先のプロセスを考えることにします。ただ、制約された開発環境で発生する要求上の問題もある程度は見通しがあるのですが、まずは、その後の工程についての検討から進めたいと考えます。いずれにしても、何らかの方法で、要求を集めてドキュメントにしなければなりません。インタビューの記録や議事録でもいいのですが、それは一次情報なのでそこから整理した要求定義を作文しておくのは、後々のための知識蓄積には必要な作業だと言えます。

ただし、要求定義の段階で、要求抽出をしながらも、設計の検討を始めることで、設計そのものに要求を明確に反映させることも可能です。ただ、設計したらそこに全ての要求が記述されたも同然とはいえません。しかしながら、ある程度の明白な要求は、UI設計をすることでそこに込めることも可能です。UI設計を進めながら要求を検討することで、要求として書き残すことが少なくなるとは言えますが、一方で「書かなくても良い」「書くべき」という判断が難しいところです。

要求が絡むと問題が難しくなりがちですし、そのドキュメンテーションの基準も曖昧な物になりがちではありませんが、最初に要求を追求することは必須であることを指摘しておきます。

[続開発プロセス#3] 『もはや開発をしている場合ではない』

システム開発と言えば、プログラミングが作業の主体で、プログラマがたくさん関わるというイメージが世間的には強いかもしれません。しかしながら、スクラッチから作るような開発タスクでさえ、プログラマよりもデザインや調整等で動く人の方が数多く関わる状況かと思います。まず、全体の傾向として、プログラミングもしくはコーディングは年々縮小していると言って良いでしょう。その1つの大きな要因は、開発環境としてソフトウェアの再利用が年々洗練化され、高まっているということがあります。

つまり、フレームワークの利用は当たり前の時代からさらに進んで、ERPによる開発や、あるいはSalesforceやService Nowに見られるような、開発ツールの提供というよりも、開発が既に行われていて、むしろ容易にカスタマイズできる点が、今現在の顧客の求めるものであるという段階にきていると言うことです。もちろん、スクラッチからの開発というのも今でもありますが、世間で言われるようにメンテナンス開発の方が案件が多いといった事情もあります。

もちろん、それは今に限ったわけではなく、私が昔から関わっているFileMakerは容易に開発作業ができる点を売りにしています。しかしながら、パッケージ化されたソリューションは他のサービスに比べてかなり弱い状態になっています。サンプルプログラムとパッケージ化されたソリューションの間には大きな溝があり、FileMakerと言う製品はまだそこのジャンプができていないと考えます。

先日、Service Nowのイベントがありました。導入事例を見る限りは、Serivce Nowだからと言うよりも、用意されている人事管理ソリューションなどが概ねそのままビジネス現場に持ち込めるから導入している企業が多いという気がしました。導入企業は開発する気がない、と言うか、開発しているつもりはないと言う感じです。要するに、開発環境というよりも自社向けに色々改良できるクラウドのSaaSみたいな見方をしていると強く感じました。

今時のIT導入では、『もはや開発をしている場合ではない』という状況ではないかと考えられます。スクラッチから開発すると、費用も時間もかかり、さらに思った結果が得られないリスクと戦いながら、顧客側にとっては強いコミットが必要になります。しかしながら、パッケージ化されたソリューションを導入しようとしている企業は、自社業務の独自性へのこだわりを少しだけ捨てて、パッケージの仕組みに適合することで、コストも時間も節約できることに気づいているのでしょう。

そうなると、開発環境の競争においては、パッケージの品揃えで勝負するか、一方、開発作業にフォーカスするとしたら、とにかく短時間で開発ができると言うことが最低限必要です。つまり、超高速開発ツール改め「ローコード」と業界団体の名前が最近変わりましたが、まさに、ローコードであるのが1つの重要なスペックになるでしょう。開発ツールそのものは需要はなくならないですが、既に業界の人は気づいているように一般的な業務はほとんどの企業でSaaSやクラウドを使うようになり、案件が発生するのはそうしたソリューションがない特殊な業務、あるいはその企業に特有の業務が中心になっています。もちろん、スクラッチから書くのがエンジニアリングなんだと言うことで従来型の仕事の方法をメインにする、つまり従来型のSIer業務で押し通すと言うこともあるかもしれませんが、そうした市場が年々縮小しているのは皆が知るところです。IT業界への期待はパッケージ化されたソリューションにあるわけです。

既存のソリューションがある上でのメンテナンス開発は、既に作られている部分があると言う意味では、パッケージ化されたソリューションとそのカスタマイズをするのに似ていると言えるでしょう。ただ、パッケージに比べて秘伝のタレがかかっているとか、謎のファイルなども出てきますが、ある形態の切り口ではよく似ていると言えます。

また、マイクロサービスについても、「既存のマイクロサービスを利用する前提」と言う開発であれば、やはり同様に、パッケージ化された部分があり、そこに適合すると言う側面があります。正し、マイクロサービスの携帯によってはバックエンド的に使われることもあり、そうなると、マイクロサービスそのものの影響は少なくなるかもしれません。一方、マイクロサービスの機能をメインに使うと、まさにERPの開発に近くなるかもしれません。

結果的に、フレームワークを利用した開発、クラウドサービスをベースにした開発、FileMakerやAccessなどのデータベース系開発ツール、ある種のマイクロサービスの利用形態、これらは全部、なるべく多くのソフトウェアの再利用をすることが根底にあり、さらにカスタマイズがやりやすいという共通の特徴を持っています。一方で、既存のソフトウェアはほとんどの場合改変はできません。カスタマイズができるとは言え、その既存ソフトウェアの動作を理解し、要求に合うように手を加えるというのが開発の作業となります。手続き型言語でスクラッチから作るソフトウェアと違い、既存のソフトウェアが存在することで、便利になる反面、そのこと自体が制約であると考えられます。こうした意味で「制約のある環境での開発」として抽象化して扱えるのではないかというのが前の記事に書いたことの詳細な説明です。

ここから、INTER-Mediatorの話になります。INTER-Mediatorには、パッケージ化されたソリューションはありません。雑なサンプル程度しかないということで、まさにトレンドに乗れていないフレームワークです。もちろん、ソリューションを作りたい気持ちはありますが、フレームワーク自体の開発にも時間が足りない状態なのに、今はソリューションに注力する余裕は全くありません。ただ、将来的に時期が来ればとは考えています。INTER-Mediatorは、スローガンとおり、少ない作業でデータベース連動Webアプリケーションが開発できるという点を追求するのが、取り残されないようにする最善策と考えます。

[続開発プロセス#2] 開発プロセスの目標

今月から書き始めたシリーズは「続・開発プロセス」というカテゴリにします。以前のシリーズでは、INTER-MediatorあるいはWebアプリケーションということで検討しました。要素を検討することで粒度を下げることをがんばってみましたが、粒度が小さすぎると、設計として成り立つ抽象度が下がってしまい、実装しているのと同じことになります。そこは反省点として、改めて考えてみるのがこのシリーズです。

検討しているうちに、INTER-Mediatorだけの問題ではないことに気付きました。Webアプリケーションでは様々なフレームワークを使います。それぞれのフレームワークを使う上での問題という見方もできます。また、FileMakerに代表される開発ツール系、あるいはSalesforceやServer Nowなどのクラウド系サービス、いずれも共通する問題を持っていると考えます。その問題とは、「制約された状況で実装可能な設計を行うこと」に集約されます。制約というとネガティブな感じがあるかもしれませんが、制約されているということは、言い換えれば既に出来上がっている仕組みがあり、より広い範囲でソフトウェアの再利用ができているとも言えるわけです。もちろん、適切な設計がなされている必要がありますが、多数のインストールベースがあるアプリケーションやサービスではそうした利用実績があることから、「一定以上の完成度を確保できる」という点が満たされると考えるのが自然でしょう。すなわち、ある特定の開発環境を利用することは事前に決まっていることも多いとも言えます。そうした特定の開発環境の世界を俯瞰する意味で「制約のある開発環境」と言えるでしょう。なお、マイクロサービスアーキテクチャーも状況によっては制約として適用されると思われますが、しばらくは、Webフレームワーク+FileMaker+クラウドサービスを中心に考えたいと思います。

そして、もう1つの方針は「ドキュメンテーションの方針」を示すことです。まず、ドキュメンテーションは軽く、最小限の時間で管理できるようにするということを目標に掲げます。いろいろな手法が提唱されていますが、時間がない、つまりは予算がないという理由でアクションのみのを採用してドキュメントが何も残っていないことはよくあります。メモでもいいのですが、埋もれがちです。もちろん、議事録はひたすら書くべきですが、それはナレッジにはなりづらいです。できればコアになる情報がなるべくコンパクトにまとめておける必要があります。その点も意識したいと考えます。

INTER-Mediator Ver.6をCentOS 8にインストールする

まだ正式に出していないINTER-Mediator Ver.6ですが、色々なOSにインストールしながら、インストール時のポイントを探っているところです。以前に、Ubuntu Server 18.04、CentOS 7へのインストールを紹介しましたが、今回は、CentOS 8です。

インストールに使ったインストーラは「CentOS-Stream-x86_64-dvd1.iso」というファイル名のISOファイルで、Virtual Box上で展開しました。同時期にはStreamでないものとして「CentOS-8-x86_64-1905-dvd1.iso」が配布されています。Virtual Box側では、ネットワーク1に「NAT」、ネットワーク2に「ホストオンリーネットワーク」を設定しています。ホストオンリー側の設定は、192.168.56.0/24の一般的な設定を適用しています。インストーラの最初の方で、Software SelectionではServer with GUIでなく、Serverを選択してインストールしました。

インストール後、/etc/system-releaseを確認すると、「CentOS Linux release 8.0.1905 (Core) 」でした。ネットワーク設定を行い、ISOファイルを指定して、後は原則そのままインストールを進めました。なお、rootのパスワードは設定せず、管理者権限のユーザーadminを登録して進めました。以下、adminが出てくれば、sudo可能なユーザーとみなしてください。

インストール直後のネットワークの設定

インストール直後はsshでの接続もできないので、VirtualBoxの場合はVMのウインドウでまずはログインをして、ネットワークの設定を行ます。「ip a」や「nmcli connection」で、どんなデバイスがあるかを確認します。通常、NAT側はenp0s3、ホストオンリーネットワーク側はenp0s8になっていると思います。それぞれ、以下のようにコマンドを入れて設定を行ます。ホストオンリー側は、192.168.56.91という固定IPにします。もちろん、設定したセグメント内であれば違ってもOKです。DNSに8.8.8.8を設定するのは嫌われるかもしれませんが、ホストオンリーネットワーク側なので、DNS利用することはほとんどないかもしれません。そして、2つのネットワークデバイスに大して、connection.autoconnectの値をyesにします。こうすればNAT側はDHCPから設定を行い、VMからインターネットにアクセスが可能です。また、ホストオンリーネットワーク側も同様なプロパティをyesにすることで、起動時にデバイスが動作するようになります。最後にホスト名の設定が行われていますが、外部に公開するサーバーならこの方法あるいは別の方法でホスト名は必ず設定すると思われます。この後のApacheの設定でホスト名が決まっていない場合は警告を出して設定ファイルの読み込みがなされず、動作しない場合もあります。なので、実験用にVMを起動する場合も適当なホスト名を必ず設定してください。以下のサンプルをそのまま使ってもらってもいいですが、このcentos.msyk.netはIPの正引き設定はしていません。なお、CentOS 7では「systemctl restart network」と入れて設定を反映させていたのですが、CentOS 8ではnetworkサービスに対するsystemdの設定ファイルが用意されていないので、このコマンドを入れても意味はありません。設定後、検証もかねてすぐにリブート(sudo reboot)するのが良いでしょう。

nmcli connection
ip a
nmcli connection modify enp0s8 ipv4.addresses 192.168.56.92
nmcli connection modify enp0s8 ipv4.gateway 192.168.56.1
nmcli connection modify enp0s8 ipv4.method manual
nmcli connection modify enp0s8 ipv4.dns 8.8.8.8
nmcli connection up enp0s8
nmcli connection modify enp0s3 connection.autoconnect yes
nmcli connection modify enp0s8 connection.autoconnect yes
nmcli general hostname centos.msyk.net

再起動をして、コマンド入力と同様なネットワーク設定になっていることを「ip a」コマンド等で確認します。ちなみにip aは「ip address show」の省略形です。再起動後は正しく設定されていれば、sshで接続できます。CentOS 8は、sshdが最初から起動していますが、ネットワーク設定ができていないので、実質的にはssh接続できないという状態です。上記の作業がsshを可能にする設定とは違います。

再起動後、sshで接続するなどして、dnf updateコマンドを打ち込みます。ネットワークに接続されているので、アップデート等の作業を進めます。

コマンドの収集

ネットワークの設定ができれば、ターミナル等からsshで接続して、以下のコマンドを入れます。まず、最初に、よく利用するコマンドを入れておきます。以下、gitは必須ですが、他に、nmapなど自分の用途に合わせて入れましょう。なお、zip、unzip、lsof、nanoは最初から入っています。

sudo yum install -y git nmap

SELinuxに対応する

ここで1つ重要な設定があるので、最初に行ましょう。CentOS 8は、既定値でSELinuxがアクティブになっていて、高いセキュリティを確保していることになっています。しかしながら、Apacheがデータベースサーバにネットワーク経由で接続することが許可されていないなど、かなり制限は強くなります。また、INTER-Mediator Ver.6より内部で複数のサーバーが動くようなアーキテクチャになっており、SELinuxの初期状態のままでは動作が正しく行われません。

そのため、SELinuxをオフにするか、一部のポリシーを緩めるかのどちらかの設定をしなければなりません。ポリシーを緩める方法は、この手順の後の方で説明しています。

テストや試用の上では、SELinuxをオフにすることで対応するのが手軽な方法です。SELinux自体をオフにしたい場合は、次のように作業します。SELinuxの状態をみるには「getenforce」コマンドを入れますが、「Enforcing」と次の行に出てくれば、設定されていることになります。そして、以下のコマンドを入れることで、SELinuxは基本的にオフになります。

sudo setenforce 0

上記コマンドを入れて、「getenforce」を実行すると「Permissive」と表示されるので、これにより制限が設定されていても実施できるようになったことを示しています。ただし、再起動すると、またオンの状態になります。再起動後にもオフの状態にしたいなら、/etc/selinux/configファイルの「SELINUX=enforcing」を、「SELINUX=disabled」にして再起動してください。このファイルは間違えた状態にすると起動しなくなるので、記述の変更は慎重に行ってください。

Apache2のインストールとFirewallの設定

Apache2のインストールは非常にシンプルです。以下のようにコマンドを入れれば、インストールされてプロセスが稼働します。再起動後にも起動できるように、enableサブコマンドも入れておきます。

sudo dnf -y install httpd
sudo systemctl enable httpd
sudo systemctl start httpd
sudo systemctl status httpd

これで、ブラウザからチェックと思っても、まだページは出ません。CentOS 7は、ファイアウォールの設定が最初からなされているので、要するにポートに穴を開けないといけません。ネットワークアダプタは、publicというゾーンを利用するので、そこで、httpとhttpsについてのサービスを透過することを以下のように設定します。一部、確認のためのコマンドも入っています。設定するとすぐに機能するはずなので、VirtualBoxでこれまで通りの設定を行っていれば、ホストマシン側でWebブラウザからhttp://192.168.56.92に接続すれば、Apacheのページが見えます。なお、DHCPのクライアント処理とsshは最初から通す設定になっています。

sudo firewall-cmd --state
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --list-services --zone=public
sudo firewall-cmd --add-service=http --zone=public --permanent
sudo firewall-cmd --add-service=https --zone=public --permanent
sudo firewall-cmd --reload 
sudo firewall-cmd --list-services --zone=public
# このように表示される dhcpv6-client http https ssh

PHPのインストールと設定

続いてPHPのインストールです。標準のPHPは7.2です。執筆時点で7.2というのは通常は受け入れられるバージョンだと思われますが、今後、PHPのバージョンが進むとCentOS 7のように別のレポジトリに頼る必要が出るかもしれません。ですが、まずは、標準のPHPを利用することにします。以下のようにコマンドを入れます。すぐに利用したいのなら、Apache2を「sudo systemctl restart httpd」で再起動しておきます。また、この状態でphpコマンドにパスが通ります。なお、INTER-Mediator Ver.6は以下のパッケージの追加で動作可能な模様ですが、チェック漏れがあれば、ここで更新します。チェック漏れがありそうなら教えてください。よろしくお願いします。

sudo dnf install -y php php-cli php-common php-bcmath php-gd php-intl php-json php-ldap php-mbstring php-pdo php-xml php-mysqlnd php-pgsql php-process

composerのインストール

PHPのライブラリ管理ツールにINTER-Mediatorは対応しています。しかしながら、composerを動かさないと、必要なライブラリを取ってきません。なお、npmも利用しますが、npmはcomposerがインストールするのでセットアップは原則的には不要です。セットアップは以下のコマンドを入れます。最初のcd以外は、composerのページに記載された通りですが、composerのページの内容は随時アップデートがあるので、以下のコードのコピペはしないで、composerのページのコードをコピーしてください。

cd
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

なお、composerもコマンドとしてそのまま打ち込んで利用できるようにしたいので、以下のように作業を行ます。前述の作業では、composer.pharというファイルがホームディレクトリのルートにできて、そのまま動かせるのですが、以下のようにコマンドを入れれば、composerコマンドとして普通にコマンド入力できるようになります。

sudo mv composer.phar /usr/local/bin
cd /usr/local/bin
sudo ln -s composer.phar composer

MySQLのインストール

データベースとしてインストールするのはここではMySQLのみ紹介しましょう。他のデータベースについては、別のサイトをなどをご覧ください。MySQLもPHPと同様に標準のレポジトリにあるパッケージを利用してインストールします。例えば、以下のようにして、インストールを行い、稼働します。

sudo dnf install -y mysql-server
sudo systemctl start mysqld
sudo systemctl enable mysqld

この方法でセットアップすると、MySQLのrootユーザーのパスワードが設定されなお応対になります。そこで、以下のコマンドを入れて、rootのパスワードを設定します。最初に、上記の仮に設定されたパスワードを入れ、その後に新しいパスワードを入れます。パスワードの検証をするかどうか、パスワードのポリシーの強度はどうするかを対話式に答えます。テストするだけの場合は検証しないか、するとしてもLOWを選択しておきます。その後に新しいrootのパスワードを入力します。もちろん、rootのパスワードはメモしておきましょう。

mysql_secure_installation

INTER-Mediatorのインストールとセットアップ

ここで、やっとINTER-Mediatorの登場です。まず、準備として、以下の作業を行ます。ここでは、Apache2はapacheユーザーで稼働しているものとします。

まず、apacheユーザーのホームディレクトリに、apacheユーザーが書き込みできるようにしておきます。インストール当初はrootユーザーにしか書き込み権限がありません。これは、node.jsのプロセス起動のためのユーティリティであるforeverの稼働のための条件です。

cat /etc/passwd|grep apache
# 出力例 apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
cd /usr/share
sudo chown -R apache httpd

次に、Apache2のドキュメント領域について、apacheユーザーとadminユーザーに書き込み権限を与えておきます。apacheユーザーについては読み出し権限で十分とも言えるのですが、オーナーをApache2のオーナーにして、グループ側にはログインするユーザーに応じたグループ、つまりコンテンツをいじる側のアカウントを指定するようにしました。通常はグループを新たに作るのが良いと思われますが、以下のコマンドは管理者のグループwheelを指定しています。ドキュメントルートは、/var/www/htmlですが、このwww以下を作業しやすいように、アクセス権を設定しています。なお、以下のコマンドは初期状態でファイルがないことを仮定しています。ファイルがある場合は、3つ目のコマンドについては、775ではなくg+rwでおそらく問題なく行くでしょうけど、既にファイルをコピーしてしまった場合は一概には言えない面もあるので、アクセス権について状況に応じて改めて見直してください。

cd /var
sudo chown -R apache:wheel www
sudo chmod -R 775 www

そして、以下のようにコマンドを入れて、INTER-Mediatorをインストールしてください。その後、composerコマンドを稼働して、しばらく待ちます。これでインストールは終了です。

cd www/html
git clone https://github.com/INTER-Mediator/INTER-Mediator
cd INTER-Mediator/
composer update

SELinuxのポリシーファイルは、dist-docs/selinuxディレクトリに用意しています。INTER-Mediatorをインストール後、次のようにコマンドを入れて、ポリシーをインストールします。INTER-Mediatorディレクトリがカレントであると仮定しています。これにより、即座にポリシーが適用され、再起動後も設定が継続します。なお、ここでのsemoduleコマンドを利用できるようにするために、policycoreutils-pythonパッケージのインストールも必要になります。

sudo yum install -y policycoreutils-python
cd dist-docs/selinux
sudo semodule -i inter-mediator.pp

INTER-Mediatorのファイルのアップロード機能を使うなど、Webアプリケーションからの書き込みがあるような場合もあります。その場合、前述のポリシーファイルだけでは許可は足りませんので、例えば、/var/www/filesにアップロードされたファイルを展開するような場合には、以下のようにコマンドを入力します。最初のコマンドが許可ポリシーを付与するもので、2つ目は設定確認、3つ目はファイルやフォルダを設定をsemanageコマンド通りにするとういうものです。

sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/files(/.)?"
sudo semanage fcontext -l | grep files
sudo restorecon -R /var/www/files

サンプルデータ用のスキーマは以下のようにして読み込みます。なお、MySQLのルートのパスワードを変更する時にお気づきだと思いますが、ポリシーをHIGHTなどにすると複雑なパスワードを設定しないといけなくなります。サンプルについては、ユーザーを作るコマンドも入っています。ROWを選択していれば、サンプルスキーマはそのまま使えます。

cd /var/www/html/INTER-Mediator/dist-docs/
mysql -uroot -p < sample_schema_mysql.txt

これを読み込んだ後に、http://192.168.56.92/INTER-Mediator/samples を参照すると、サンプルの一覧が出てきますので、郵便番号検索などのサンプルをご覧ください。Ver.6の新機能の1つであるサーバーサイドでのNode.jsによるサービスサーバーについても、自動的に稼働するはずです。

一通りの手順は以上です。色々、状況によって違う面もあるかもしれませんが、訂正やバリエーションがあれば、このページに追記します。レポート歓迎します。

INTER-Mediator Ver.6をCentOS 7にインストールする

まだ正式に出していないINTER-Mediator Ver.6ですが、色々なOSにインストールしながら、インストール時のポイントを探っているところです。以前に、Ubuntu Server 18.04へのインストールを紹介しましたが、今回は、CentOS 7です。

インストールに使ったインストーラは「CentOS-7-x86_64-Minimal-1908.iso」というファイル名のISOファイルで、Virtual Box上で展開しました。Virtual Box側では、ネットワーク1に「NAT」、ネットワーク2に「ホストオンリーネットワーク」を設定しています。ホストオンリー側の設定は、192.168.56.0/24の一般的な設定を適用しています。インストール後、/etc/system-releaseを確認すると、「CentOS Linux release 7.7.1908 (Core)」でした。ネットワーク設定を行、ISOファイルを指定して、後は原則そのままインストールを進めました。なお、rootのパスワードは設定せず、管理者権限のユーザーadminを登録して進めました。以下、adminが出てくれば、sudo可能なユーザーとみなしてください。

インストール直後のネットワークの設定

インストール直後はsshでの接続もできないので、VirtualBoxの場合はVMのウインドウでまずはログインをして、ネットワークの設定を行ます。「ip a」や「nmcli connection」で、どんなデバイスがあるかを確認します。通常、NAT側はenp0s3、ホストオンリーネットワーク側はenp0s8になっていると思います。それぞれ、以下のようにコマンドを入れて設定を行ます。ホストオンリー側は、192.168.56.91という固定IPにします。もちろん、設定したセグメント内であれば違ってもOKです。DNSに8.8.8.8を設定するのは嫌われるかもしれませんが、ホストオンリーネットワーク側なので、DNS利用することはほとんどないかもしれません。そして、2つのネットワークデバイスに大して、connection.autoconnectの値をyesにします。こうすればNAT側はDHCPから設定を行い、VMからインターネットにアクセスが可能です。また、ホストオンリーネットワーク側も同様なプロパティをyesにすることで、起動時にデバイスが動作するようになります。最後にホスト名の設定が行われていますが、外部に公開するサーバーならこの方法あるいは別の方法でホスト名は必ず設定すると思われます。この後のApacheの設定でホスト名が決まっていない場合は警告を出して設定ファイルの読み込みがなされず、動作しない場合もあります。なので、実験用にVMを起動する場合も適当なホスト名を必ず設定してください。以下のサンプルをそのまま使ってもらってもいいですが、このcentos.msyk.netはIPの正引き設定はしていません。

nmcli connection
ip a
nmcli connection modify enp0s8 ipv4.addresses 192.168.56.91
nmcli connection modify enp0s8 ipv4.gateway 192.168.56.1
nmcli connection modify enp0s8 ipv4.method manual
nmcli connection modify enp0s8 ipv4.dns 8.8.8.8
nmcli connection up enp0s8
nmcli connection modify enp0s3 connection.autoconnect yes
nmcli connection modify enp0s8 connection.autoconnect yes
nmcli general hostname centos.msyk.net
systemctl restart network

ここで再起動をして、コマンド入力と同様なネットワーク設定になっていることを「ip a」コマンド等で確認すると良いでしょう。ちなみにip aは「ip address show」の省略形です。再起動後は正しく設定されていれば、sshで接続できます。CentOS 7は、sshdが最初から起動していますが、ネットワーク設定ができていないので、実質的にはssh接続できないという状態です。上記の作業がsshを可能にする設定とは違います。

再起動後、sshで接続するなどして、yum updateコマンドを打ち込みます。ネットワークに接続されているので、アップデート等の作業を進めます。

コマンドの収集

ネットワークの設定ができれば、ターミナル等からsshで接続して、以下のコマンドを入れます。まず、最初に、よく利用するコマンドを入れておきます。以下、git、zip、unzipは必須ですが、他に、nanoなど自分の用途に合わせて入れましょう。例えば、プロセスやポートの情報を得るためのlsofや、開いているポートを確認するnmapあたりは、このままパッケージ名として記述すればOKです。

sudo yum install -y git zip unzip
sudo yum install -y nano lsof nmap   #  こちらは参考まで

SELinuxに対応する

ここで1つ重要な設定があるので、最初に行ましょう。CentOS 7は、既定値でSELinuxがアクティブになっていて、高いセキュリティを確保していることになっています。しかしながら、Apacheがデータベースサーバにネットワーク経由で接続することが許可されていないなど、かなり制限は強くなります。また、INTER-Mediator Ver.6より内部で複数のサーバーが動くようなアーキテクチャになっており、SELinuxの初期状態のままでは動作が正しく行われません。

そのため、SELinuxをオフにするか、一部のポリシーを緩めるかのどちらかの設定をしなければなりません。ポリシーを緩める方法は、この手順の後の方で説明しています。

テストや試用の上では、SELinuxをオフにすることで対応するのが手軽な方法です。SELinux自体をオフにしたい場合は、次のように作業します。SELinuxの状態をみるには「getenforce」コマンドを入れますが、「Enforcing」と次の行に出てくれば、設定されていることになります。そして、以下のコマンドを入れることで、SELinuxは基本的にオフになります。

sudo setenforce 0

上記コマンドを入れて、getenforceコマンドを実行すると「Permissive」と表示されるので、これにより制限が設定されていても実施できるようになったことを示しています。ただし、再起動すると、またオンの状態になります。再起動後にもオフの状態にしたいなら、/etc/selinux/configファイルの「SELINUX=enforcing」を、「SELINUX=disabled」にして再起動してください。このファイルは間違えた状態にすると起動しなくなるので、記述の変更は慎重に行ってください。

Apache2のインストールとFirewallの設定

Apache2のインストールは非常にシンプルです。以下のようにコマンドを入れれば、インストールされてプロセスが稼働します。再起動後にも起動できるように、enableサブコマンドも入れておきます。

sudo yum -y install httpd
sudo systemctl enable httpd
sudo systemctl start httpd
sudo systemctl status httpd

これで、ブラウザからチェックと思っても、まだページは出ません。CentOS 7は、ファイアウォールの設定が最初からなされているので、要するにポートに穴を開けないといけません。ネットワークアダプタは、publicというゾーンを利用するので、そこで、httpとhttpsについてのサービスを透過することを以下のように設定します。一部、確認のためのコマンドも入っています。設定するとすぐに機能するはずなので、VirtualBoxでこれまで通りの設定を行っていれば、ホストマシン側でWebブラウザからhttp://192.168.56.91に接続すれば、Apacheのページが見えます。なお、DHCPのクライアント処理とsshは最初から通す設定になっています。

sudo firewall-cmd --state
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --list-services --zone=public
sudo firewall-cmd --add-service=http --zone=public --permanent
sudo firewall-cmd --add-service=https --zone=public --permanent
sudo firewall-cmd --reload 
sudo firewall-cmd --list-services --zone=public
# このように表示される dhcpv6-client http https ssh

PHPのインストールと設定

続いてPHPのインストールです。当然ながら、PHP 7.1以上を得るためには標準のレポジトリではだめなので、remiのレポジトリを利用します。例えば、以下のようにコマンドを入れます。この例では、Ver.7.3系列のファイルがインストールされますが、remiのレポジトリは執筆時点では7.0〜7.4まで揃っていました。別のレポジトリを使う場合のレポジトリ指定方法は、–enablerepo=remi,remi-php73をパラメータに指定するなど、色々流儀があるとは思いますので、この方法に限らないとは思いますが、ともかく、PHPのバージョンを混在することは避けましょう。最後にApacheを再起動しておきます。そうしないと、PHPの動作が組み込まれていない状態のままになります。なお、INTER-Mediator Ver.6は以下のパッケージの追加で動作可能な模様ですが、チェック漏れがあれば、ここで更新します。チェック漏れがありそうなら教えてください。よろしくお願いします。

sudo yum -y install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
sudo yum --enablerepo=remi-php73 install -y php php-cli php-common php-bcmath php-gd php-intl php-json php-ldap php-mbstring php-pdo php-xml php-mysqlnd php-pgsql php-process
sudo systemctl restart httpd

phpコマンドを-vオプションをつけて実行して、念のために欲しいバージョンのPHPが稼働しているかどうかを確認しましょう。最後のphp -iで動作確認やモジュールが登録されているかを確認できますが、コマンドラインに大量に行が流れるのでちょっと見づらいかもしれません。

php -v
php -i

composerのインストール

PHPのライブラリ管理ツールにINTER-Mediatorは対応しています。しかしながら、composerを動かさないと、必要なライブラリを取ってきません。なお、npmも利用しますが、npmはcomposerがインストールするのでセットアップは原則的には不要です。セットアップは以下のコマンドを入れます。最初のcd以外は、composerのページに記載された通りですが、composerのページの内容は随時アップデートがあるので、以下のコードのコピペはしないで、composerのページのコードをコピーしてください。

cd
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

なお、composerもコマンドとしてそのまま打ち込んで利用できるようにしたいので、以下のように作業を行ます。前述の作業では、composer.pharというファイルがホームディレクトリのルートにできて、そのまま動かせるのですが、以下のようにコマンドを入れれば、composerコマンドとして普通にコマンド入力できるようになります。

sudo mv composer.phar /usr/local/bin
cd /usr/local/bin
sudo ln -s composer.phar composer

MySQLのインストール

データベースとしてインストールするのはここではMySQLのみ紹介しましょう。他のデータベースについては、別のサイトをなどをご覧ください。なお、PostgreSQLは標準のパッケージにあるpostgresql-serverを利用できます。また、SQLiteはsqliteというパッケージ名です。

MySQLもPHPと同様に標準のレポジトリにはパッケージがないので、開発元が提供しているレポジトリを利用してインストールします。例えば、以下のようにして、インストールを行い、稼働します。

sudo yum localinstall http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
sudo yum search mysql
sudo yum install mysql-community-server -y
sudo systemctl start mysqld
sudo systemctl enable mysqld

この方法でセットアップすると、MySQLのrootユーザーのパスワードが自動的に設定されます。まず、そのパスワードを以下のようにして取り出します。つまり、ログにrootのパスワードが残っているということです。以下の例だと、「!#si2Zx;!.CG」がパスワードです。

sudo cat /var/log/mysqld.log | grep root
# 例えば次のように表示 2019-11-12T05:38:49.015480Z 1 [Note] A temporary password is generated for root@localhost: !#si2Zx;!.CG

続いて、以下のコマンドを入れて、rootのパスワードを再設定します。最初に、上記の仮に設定されたパスワードを入れ、その後に新しいパスワードを入れます。パスワードのポリシー5.7の途中から厳しくなっていて、大文字、小文字、記号、数字を入れてある程度長い文字列でないといけません。もちろん、rootのパスワードはメモしておきましょう。

mysql_secure_installation

なお、MySQL 5.7で、INTER-Mediatorのサンプルデータベースをエラーなく読み込ませる手軽な方法は、/etc/my.cnfの最後の行に「validate-password=OFF」を追加して、MySQLを再起動させてください。サンプルのデータベースは、パスワードを単純な「password」という文字で運用させており、これだとパスワードのポリシーを満たさないためユーザー作成時にエラーになってしまいます。設定ファイルの記述でポリシーを満たさなくてもユーザー登録できるようになります。

INTER-Mediatorのインストールとセットアップ

ここで、やっとINTER-Mediatorの登場です。まず、準備として、以下の作業を行ます。ここでは、Apache2はapacheユーザーで稼働しているものとします。

まず、apacheユーザーのホームディレクトリに、apacheユーザーが書き込みできるようにしておきます。インストール当初はrootユーザーにしか書き込み権限がありません。これは、node.jsのプロセス起動のためのユーティリティであるforeverの稼働のための条件です。

cat /etc/passwd|grep apache
# 出力例 apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
cd /usr/share
sudo chown -R apache httpd

次に、Apache2のドキュメント領域について、apacheユーザーとadminユーザーに書き込み権限を与えておきます。apacheユーザーについては読み出し権限で十分とも言えるのですが、オーナーをApache2のオーナーにして、グループ側にはログインするユーザーに応じたグループ、つまりコンテンツをいじる側のアカウントを指定するようにしました。通常はグループを新たに作るのが良いと思われますが、以下のコマンドは管理者のグループwheelを指定しています。ドキュメントルートは、/var/www/htmlですが、このwww以下を作業しやすいように、アクセス権を設定しています。なお、以下のコマンドは初期状態でファイルがないことを仮定しています。ファイルがある場合は、3つ目のコマンドについては、775ではなくg+rwでおそらく問題なく行くでしょうけど、既にファイルをコピーしてしまった場合は一概には言えない面もあるので、アクセス権について状況に応じて改めて見直してください。

cd /var
sudo chown -R apache:wheel www
sudo chmod -R 775 www

そして、以下のようにコマンドを入れて、INTER-Mediatorをインストールしてください。その後、composerコマンドを稼働して、しばらく待ちます。これでインストールは終了です。

cd www/html
git clone https://github.com/INTER-Mediator/INTER-Mediator
cd INTER-Mediator/
composer update

SELinuxのポリシーファイルは、dist-docs/selinuxディレクトリに用意しています。INTER-Mediatorをインストール後、次のようにコマンドを入れて、ポリシーをインストールします。INTER-Mediatorディレクトリがカレントであると仮定しています。これにより、即座にポリシーが適用され、再起動後も設定が継続します。なお、ここでのsemoduleコマンドを利用できるようにするために、policycoreutils-pythonパッケージのインストールも必要になります。

sudo yum install -y policycoreutils-python
cd dist-docs/selinux
sudo semodule -i inter-mediator.pp

INTER-Mediatorのファイルのアップロード機能を使うなど、Webアプリケーションからの書き込みがあるような場合もあります。その場合、前述のポリシーファイルだけでは許可は足りませんので、例えば、/var/www/filesにアップロードされたファイルを展開するような場合には、以下のようにコマンドを入力します。最初のコマンドが許可ポリシーを付与するもので、2つ目は設定確認、3つ目はファイルやフォルダを設定をsemanageコマンド通りにするとういうものです。

sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/files(/.)?"
sudo semanage fcontext -l | grep files
sudo restorecon -R /var/www/files

サンプルデータ用のスキーマは以下のようにして読み込みます。なお、MySQLのルートのパスワードを変更する時にお気づきだと思いますが、複雑なパスワードを設定しないといけなくなります。サンプルについては、ユーザーを作るコマンドも入っています。dist-docs/sample_schema_mysql.txtの20行目にある’password’を、例えば’password#P3’など登録可能なパスワードに変更してください。また、INTER-Mediatorのルートにあるprams.phpの25行目の’password’も、同様に書き換えておいてください。

cd /var/www/html/INTER-Mediator/dist-docs/
mysql -uroot -p < sample_schema_mysql.txt

これを読み込んだ後に、http://192.168.56.91/INTER-Mediator/samples を参照すると、サンプルの一覧が出てきますので、郵便番号検索などのサンプルをご覧ください。Ver.6の新機能の1つであるサーバーサイドでのNode.jsによるサービスサーバーについても、自動的に稼働するはずです。

一通りの手順は以上です。色々、状況によって違う面もあるかもしれませんが、訂正やバリエーションがあれば、このページに追記します。レポート歓迎します。