設計コンサルタントという職種と設計工程

とある就職サイトで「設計コンサルタント」という名称を知りました。
常々、ITの設計のことを「アーキテクト」=「設計者」という割には、詳細設計は大手若手SEに任せていたり、職種自体も雑誌の名を冠しているぐらいで怪しい感じがするし、と思っていて「アーキテクト」ってのはどんなもんなんですかね~、と思っていたわけですが。

なるほど、建築関係や三次元の意匠デザイン(かな?)の場合、「設計コンサルタント」という職名があるようです。

龍菜の3次元CAD活用相談室(1)私の設計、変ですか?
http://monoist.atmarkit.co.jp/fmecha/articles/dragon/01/dragon01a.html
http://www.page.sannet.ne.jp/gah01300/

本来、ITシステムを構築するときには、要件定義、設計、開発/実装、試験、運用、なる流れが必要なのですが(ウォータフォール形式的に言えばね)、受託開発を多くやってきたので、

・大手の要件定義
・大手の設計

が良く分かりません。つーか、見ていて不安なんですけど。
要件定義のほうは、提案/営業活動/製品説明/予算/納期などなど、顧客からの要望を引き出す技術(あるいは製品を押しつける技術)が必要になるので、いわゆるIT関係とは離れたノウハウがが必要です。あるいは他の業界とは同じような活動の仕方があります。
また、受託開発をする会社の場合は、設計が落ちてくるのを待つことが多いので(この体制が問題だと思うのですが)開発/実装/単体試験/結合試験/納品までのプロセスをいかに効率よくやるのか/コストを掛けないか、という「オフショア開発」的なノウハウに長けてきています。

なので、真ん中にある「設計」が抜けていることが度々あります。というか、設計とは名ばかりで、中身がいきなり細かい詳細設計をやっていたり、逆に要件定義で設計をやっていたりします。
設計の大まかな分類/種類を並べると、

・システム設計
・ソフトウェア設計
・概要設計
・外部設計
・内部設計
・詳細設計

というものがあります。他にもデータベース特有の

・概念設計
・論理設計
・物理設計

なるものもあり、オブジェクト指向で言えば

・ユースケース
・クラス図
・シーケンス図

などのUML関係があります。他にもデータフローチャートなんてのもあります。

本来、これらの設計工程は、建築業界の設計業務と同じように、三面図/見取り図などの図面と変わらない意味を持つはずですが、なかなかそうは行きません。
実際、CASEツールの筆頭としてUMLが持て囃されたころから10年経ちますが、未だにUMLで統一された設計書を出す会社を見たことがありません(部分的には使うことは多いのですが)。
UMLの場合は、所詮ツールですので、本来の目的は要件を如何に実装へ繋げるかという「設計」のサポートが本来の役割です。なので、UMLからJavaやC#のコードがはきだされるのは、補助的な機能に過ぎないんですよね~(というのを数年前に気付いた)。

と、改めて先のITの設計工程を見直してみると、実はこれらはプログラム言語に依存しません。当たり前といえば当たり前なのですが、予算/期間/製品/技術スキル/可搬性などを考慮するので、設計自体にjavaだのc#だのという制限は入ってきません。勿論、制約として現在のシステムがjavaで組んであるので流用を含めてjayaにしたいとか、フリーの環境で揃えたいので ruby や php を使うとか、組み込みシステムなので c 言語以外は使えないとか、があるので、これらは「制約事項」として設計工程に盛り込みます。

そういう訳で、しばらく

「プログラム言語に依存しない設計工程」

を考えていこうかな、と思っています。
言語に依存しないといえば真っ先に思いつくのは、UML でしょうが、これだけが設計ではありません。

DBA(データベース管理者)やオブジェクト指向/サービス指向/データ指向を交えて、考えていきたいと思います。

余談

と、前振り完了。
実はこの話2年前に考えていたことなのですが、ごたごたがあって立ち消えになっちゃんたんだよね~。
なので、再開しよかなっと。

カテゴリー: 設計 | 設計コンサルタントという職種と設計工程 はコメントを受け付けていません

ソフトウェア開発の超概算見積もり

(誰も待っていないと思うけど)お待ちかねの「3分間見積もりクッキング」の時間です。

結局のところ「概算見積もり」というのは、QCD(機能、コスト、納期)の枠を決めることで、その範囲内で、

・人員を確保する。
・機能を配分する。
・社員を育てる。
・できるだけ、利益を出す。

を行います。
なので、以上を踏まえたときに、大まかな見積もりは以下の点のみ決めます。

発注会社サイド

・全体の開発予算(コスト)
・開発期間(納期)

機能が抜けているのは、作らなければいけない機能よりも、予算や期間が優先されることが多いためです。
特に発注会社の場合は、

・開発予算から利用するアプリケーションの減価償却
・利用開始時期から、開発期間

が決まるために、ある意味で「機能」のほうが調節可能な場合が多いのです。

# 現に、予算が少ない場合は、機能削減で凌ぎますし、
# 予算が多い場合は「機能を盛り込み」ます。

# ただし、官庁系のように入札が行われる場合は、かなりの程度まで要求仕様=機能が
# 決まっているために、別な概算予算の立て方が必要です。

IT会社サイド

IT会社(受託請負)の場合は

・単価(コスト)
・確保できる人員(人)

が決まっています。
ソフトウェア開発の場合、必要経費のほとんどが人件費のため、概算予算を立てるときに「人の単価」と「人」が最大のボトルネックになります。

さて、この単価、と人はどこから決まるのかと言うと、

・給与(コスト)
・技術スキル(勤続年数など)

に依ります。
技術スキルを勤続年数に掛けるかどうかは疑問が多いところでしょうが、
若干でも「年功序列制の給与体系」をIT会社がしている場合は、勤続年数を考慮したほうがよいでしょう。また、年棒制など序列がない場合は、ITSSなどを利用したレベルを考慮するとよいでしょう(個人的にITSSは反対ですが、外部的な指標としてはアリです)。

IT会社サイド(その2)

さて、IT会社としては、先の人員(開発要員)だけで廻るわけではありません。
ここを、発注会社/IT会社ともに忘れてしまうことがあるので問題です。

・リスク(保険)
・管理費用
・営業費用

リスクは、いわゆる「保険」です。受注してはみたものの、要求仕様が膨らんだり、予期せぬ事情が発生したとこのバッファのためにお金を積み上げます。ここの「保険」の部分は、色々事情があるでしょうが、現実問題として無くすことはできません!。発注会社から「保険分をうちで持つから(仕様変更等は後で積んでもらえばいいから)」という理由で「保険」を外そうとする動きをしたとしても、必ず「保険」は積まれます。
ですので、外せないものであれば、あらかじめ積んでおくのがいいでしょう。

同様に、管理費用も積まれます。
一見、提出された見積もりに管理費用の項目が載っていない場合であっても、それは単価(人月)に積まれています。発注会社は「管理費用はそちらもちではないか?」と文句を付けたとしても、その項目が無くなっただけで新しい見積書には「薄く」管理費用は積まれています。
ですので、外せないものであれば、あらかじめ積んでおくのがいいでしょう。

同じく、営業費用も薄く積まれます。
営業費用自体は、営業部のあり/なし、受注した時の形態などを加味する必要がありますが、
「その営業の人はどこから給与を捻りだしているのか?」
を考えると、ソフトウェア開発費用のどこかに積むしかありません。
ですので、これも考慮に入れておきます。

実例

さて、実例を示してこれを計算してみましょう。

20091026_011

Excel シートはここから。
http://moonmile.net/mymy/solution/011.zip
発注会社からは、予算2000万円、期間6か月で発注をしました。
このときに、IT会社が概算見積もりをするときの内容です。

・開発者(社員)の単価が100万円/月(給与から算出します)
・リスクを10%
・管理費用を50万円/月
マネージャは他プロジェクトとの掛け持ちです。
・営業費用を100万円
歩合の場合が多いので、100万円/プロジェクトで計算

これから、使える開発者の人数が計算できます。

C12の式は
=((C4-C11)*100/(100+C9)-C10)/C8
です。

・人員が、16.8人月
・期間が6か月なので、2.8人の張り付き

と計算できます。

さて、ここで問題ですが、ソフトウェア開発で 2.8 人の貼り付けをすることは難しいです。と言いつつ、そうやっている会社が多数なのですが、現実問題として、2.8人なんていう半端な割り振りはできません。プロジェクトが終わってみれば、3人の開発者が張り付いているのが普通です。

そうなると、プロジェクト終了予定時から逆算すれば、

・人員が、18人月
・人員が、3人貼り付け

がベターなわけです。

そうすると、差分1.2人月(金額にして120万円)が出ます。

ここで、発注側が予算額を 2,120万円に挙げれば、おそらくプロジェクトは安泰に終わります。
同様に、120万円分に機能を削り(5%程度の機能削除)をすれば、プロジェクトは安泰です。

ですが、これをIT会社に持たせようとする、2.8人という変な数字のために、無理矢理 1.2 人月分の効率化を社内でしようとします。採算確保のためですね。ですが、大抵はこの変な「効率化」のためにプロジェクトが破綻します。

また、この概算見積もりのように、リスク/管理費用/営業費用を見積もっている場合は、その分を引いていますのでスケジュールを縮めることは少ないのですが、これを忘れている(特にIT会社側が忘れていることが多い)と、これも変な「効率化」を始めてプロジェクトが破綻します。

経験上ですが、こういう変な端数に人は縛られてしまうようです。特にマネージャあるいは上司が採算を求められている場合は、このような 2.8 人という 0.2 人分を減らそうとして、プロジェクトから人を引き抜きます。そうすると、プロジェクトの最後で引き継ぎをすれば良かったのに、途中でプロジェクトを引き上げるために引き継ぎの作業が途中に入ってしまいます。これは全く無駄なことです。

そんな訳で、これぐらいの概算見積もりを出してから、見積もりを出しましょう。
という提案なんですが、どうなんでしょうねぇ?
いきなりボトムアップで作っているところが多いだけど。

追記 2019/01/11

10年ぶりに追記をしたので、こちらもあわせて もっと簡単に超概算見積もりver2 

 

カテゴリー: プロジェクト管理 | 2件のコメント

Windows 7 のタスクバーを小さくする/細くする

Windows 7 が昨日発売、ってことで、VMWare に入れてみました(MSDN版なので、手元にあるやつですが)。
日経新聞には Vista の3か月分の予約が入っていて売れ行き抜群だそうですが、XP->Win7の移行は進むんでしょうか?

さて、うちの家庭用PCもWindows 7にしました。Vaioの古いデスクトップを7年間使い続けてきたのですが、最近HDDの調子が悪くて。中身を空けてHDDの電源ケーブルを抜き差しすると、動くようになるので接触不良な気もするんですけど。いまいち、HDDのコネクタが悪いのか、電源のほうのケーブルが悪いのか判断がつかないので、かれこれ1年程。

で、新しいPCを買って Windows 7 を入れました。起動は早いですね~。が、あちこちのブログで書かれている通り、

・起動は早いが、そのあとのログインが遅い

ので、起動→ログインして使う、までの時間は Vista と変わりません。か、むしろ Vista より遅い気がします。
また、スタートメニューのデフォルトの「電源アイコン」(○のやつね)の動作が、

・Vista ではスリープ状態(休止状態だったかな?)
・Windows 7 ではシャットダウン

になっており、エコロジー対策?が為されています。まぁ、休止状態が楽なんですけど。

さらに言えば、スタートメニューの一番上に鎮座していた IE と Windows メール が無くなっています。
これは EU 向け対策(IE無しの Windows 7)と、メーラーが Windows Live メールに変わったためです。
IE/Outlookを使っている私には、不便ですねぇ~。
というわけで、「本当にUI/UXのプロが考えている」のであれば、プロではないね、と言いたくなる UI なんですが。
今、私が最も気に入らないのが、タスクバーが太くなってしまったことです。
Windows 7 の標準のタスクバー
<001>
snapshot20091023091250

これを見るとわかるんですが、XP/Vista のものより随分太くなっています。
とある記事には「スタートボタンの○がはみ出さなくなって、よくなった」なぞとフザケタことを書いてありましたが、このタスクバーは太すぎます。これがどれだけ使いにくいかと言うと。

・最近の液晶TVはワイド画面が多いので、横に細長い。
・Microsoft Office 2007 にはリボンが付いていて、編集画面が横に細長い。
・Windows 7 はタスクバーが太くなって、横に細長い。

ってな訳で、編集するところがどんどん横に細長くなってしまいます。

# タスクバーを隠すオプションもありますが、タスクへのアクセスを考えると、
# 常に出したままのほうが使いやすいのです。
# また、右に置くっていう方法もあるけど(マウスを右手で扱うので、タスクバーは右にほうが使いやすい)

というわけで、この太い Windows 7 のタスクバーをせめて Vista 並みに細くします。

タスクバーを右クリックして「プロパティ」を選択します。
<002>
snapshot20091023091329

「小さいアイコンを使う」にチェックを入れます。
<003>
snapshot20091023091345

そうすると、ほら、タスクバーが細くなりました。
このほうが、画面の圧迫感が少ないですよね。
<004>
snapshot20091023091407

カテゴリー: 雑談 | 14件のコメント

.NETからMySQL5のストアドプロシージャ呼び出しの落とし穴

別に落とし穴シリーズ化としている訳ではないのですが、諸にハマってしまったので。
# 英語圏の方も結構苦労している模様なので

.NET言語(C#やVBなど)からMySQL5のストアドプロシージャを扱うときには、
2種類のクラスライブラリを選択します。

・MySQL Connector/ODBC 5.1
 http://dev.mysql.com/downloads/connector/odbc/5.1.html
・MySQL Connector/NET 6.0以降
 http://dev.mysql.com/downloads/connector/net/6.0.html
 
で、今回は MySQL Connector/NET の方を使っていきます。
上記のクラスライブラリをダウンロードしてインストール。そして、参照設定までいけます。

さて、MySQL側のストアドプロシージャを

DELIMITER $$

DROP PROCEDURE IF EXISTS `StoredProc238` $$
CREATE <a href=&quot;mailto:DEFINER=`dbuser`@`%&quot;>DEFINER=`dbuser`@`%</a>` PROCEDURE `StoredProc238`( in i_age integer, out o_count integer)
BEGIN
  SELECT count(*) into o_count FROM t_person
   WHERE age < i_age;
END $$

DELIMITER ;

とします。

t_person テーブルを検索して、i_age を渡して、件数を o_count で返して貰うストアドプロシージャですね。

これを、Visual Basic 2008 から呼び出すようにします。

    'ストアドプロシージャを実行する
    Private Sub Button1_Click(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles Button1.Click

        Dim cn As New MySqlConnection( _
            "Data Source=xp-db;Database=sampledb;User ID=dbuser;password=dbpass")

        Dim age As Integer = Integer.Parse(TextBox1.Text)
        Dim count As Integer

        Dim cmd As New MySqlCommand("StoredProc238", cn)
        cmd.CommandType = CommandType.StoredProcedure
        cmd.Parameters.Add("i_age", MySqlDbType.Int32 ).Value = age
        cmd.Parameters.Add("o_count", MySqlDbType.Int32).Direction = _
         ParameterDirection.Output

        cn.Open()
        cmd.ExecuteNonQuery()
        cn.Close()

        count = cmd.Parameters("o_count").Value
        '結果を表示
        TextBox2.Text = String.Format("{0}件", count)
    End Sub

■mysql.proc の参照権限を付ける

先のストアドプロシージャを MySQL Query Browser で動かして「うんうん動くね」と確かめてから、
いざ、vb から実行すると、cmd.ExecuteNonQuery() で例外が発生します。

“SELECT command denied to user ‘dbuser’@’ホスト名’ for table ‘proc'”

なにやら良く分からない英語なのですが、どうも proc テーブルを SELECT できないそうです。
う~ん、なんでしょうね?これは?

というわけで、結構探しました。

24.2.4.3. Connector/NET のストアド プロシージャにアクセスする
http://dev.mysql.com/doc/refman/5.1/ja/connector-net-using-stored.html

によると、Connector/.NETからストアドプロシージャを呼び出すときには、mysql.procへのアクセス権限が必要なんですね。
先のサンプルの場合、制限をきつくして、dbuserが sampledb しか見れないようにしているので、mysql データベースが検索できないために、このエラーが出ています。

本当は mysql.proc だけ grant すればよいのですが、mysql の場合テーブル単位でできたか分からないので、SELECT 権限を付与。
# ただし、すべてのテーブルの SELECT 権限を与えると、他のユーザーの権限とかも見れちゃうので、mysql.proc のみにしたほうがよさそう。ちなみに、ストアドファンクションのほうは mysql.func です。

■outputのパラメータの書き方

ストアドプロシージャから値を受け取るときは、Direction を「ParameterDirection.Output」をにします。
正解は↓なのですが、

    cmd.Parameters.Add("o_count", MySqlDbType.Int32).Direction = _
     ParameterDirection.Output

ここに至るまで小一時間ぐらい掛かりました。

実は、connector/.net 5 のときは、

   cmd.Parameters.Add("o_count", 0).Direction = _
     ParameterDirection.Output

な書き方が許されていたんですね。
Parameters コレクションに名前を値を与える。
Direction のデフォルトは「Input」なので、入力値の場合はそのまま。出力の場合は  ParameterDirection.Output を設定する。
というお手軽な方法が。

ですが、6.0以降、何故かこの書き方が「旧来」になってしまいました。おそらく ADO.NET の書き方(こっちも旧来になってしまっている)に合わせたと思うのですが。ここで私は悩んでしまって、次な書き方をしました。

   cmd.Parameters.Add("o_count", MySqlDbType.Int32, _
     ParameterDirection.Output)

実は Oracle の場合、この書き方が許されるのですが、MySQL の場合は違った!
3つめの引数は、size を示すのでした。

それで「落とし穴」なんですが、この Enum ParameterDirection。Enum なんですが Visual Basic の場合、自動的に integer に変換されてコンパイルが通ってしまうんですよ~。試しに C# で書きなおすとコンパイルエラーになるという。。。
vb 限定の落とし穴です。

カテゴリー: 開発, MySQL | .NETからMySQL5のストアドプロシージャ呼び出しの落とし穴 はコメントを受け付けていません

Visual Studio 2010 Bate 2 をインストール

Visual Studio 2010 Bate 2 をインストール

ひとまず、MSDNからダウンロードしてインストールしました。

お馴染みのインストール画面です。
001

続いてセットアップ

002

VCの9.0と10.0のランタイムがインストールされます。

003
インストールするときに、「Full」と「Custom」を選べます。
中身を確認するために Custom を選択します。

004

Visual F# があるところがおちゃめです。
005

次へを押して、どんどんインストールします。
例によって SQL Server Express Edition もインストールされます。
.NET Framework は ver.4 ですね。

006

長々とやって、やっとインストールが終わり。
途中、.NET Framework 4 を入れた後に再起動します。なので、他のアプリケーションは落としておいてください。

007

Service Release はないので無視して「終了」します。

008

最初の起動時に開発環境の選択をします。
開発環境に「Visual F#」がありますね。

009

起動すると「ようこそ」画面が出ます。ベータ1とは全然違います。

010
新しいプロジェクトダイアログを開いたところです。
Silverlight アプリケーションが最初から導入されています。

011

VC++のほうは変わり映えしません。
ATLやMFCも健在です。健在じゃないと困るけど。

012

VBでWindowsフォームアプリケーションを作成したところです。
ツールボックスは詳しく調べてませんが、あまり変わり映えしません。

013

という訳で記念インストール終了っと。
「Visual Studio 2010」の第2ベータ公開、最終版は2010年3月に発売へ
http://www.asahi.com/digital/cnet/CNT200910200031.html
マイクロソフト2010年マーケティングカレンダー–主要製品計画を明らかに
http://japan.cnet.com/news/biz/story/0,2000056020,20397152,00.htm

な訳で、Visual Studio 2010 は来春にリリースになるそうです。
う~む、Microsoft Office 2010 も来春なんですよね~。悩む…

カテゴリー: 開発 | Visual Studio 2010 Bate 2 をインストール はコメントを受け付けていません

Google AppsとOffice Web Apps

遠隔地の人と文書ファイルを共有しようとする場合、メールでやり取りをしてもいいのですが、最近は Web 上の Office があります。

無料かつ手軽なところと言えば、Google Apps がいいでしょう。

Google Apps
http://www.google.co.jp/apps/intl/ja/business/index.html

最近は有償版があって、何が有償でどこまで無料なのか分かりにくいのですが、

無償のStandard版は「50人まで共有」できます。なので、数名の会社/グループであれば、Google Apps の無償版で十分でしょう。まぁ、そうかと言って、デスクトップにある MS-Office製品を全廃することはできそうもないのですが。

そう、Google appsの場合は「ドメインを持っていること」という制限があります。
具体的には、登録時に「googlehostedservice.html」というファイルを、公開ドメインのルートに置く必要があります。
なので、ドメイン&ホストを持っていないとダメなのですが、サブドメインも使えるのでロリポップなどの安いところを借りて、ひとまず運用ってのも手ですね。

対抗馬、ということで Microsoft のプレビュー版が発表されました。
Office Web Apps
http://internet.watch.impress.co.jp/docs/news/20090918_316581.html

まだ、限定だそうなので、使える機能が限られています。。。って Word が使えないんで、限られているどころではないんですが。

Windows Live SkyDrive
http://skydrive.live.com/?mkt=ja-jp

を使っていると、Excelシートを使えるので試してみてください。

で、どれだけ使える/早いものか、試してみました。

Google Apps
20091019_02

Office Web Apps
20091019_01

OpenOffice3.1
20091019_03

比較として、OpenOffice3.1でも同じものを作ってみました。
すると、使うときの体感スピードとしては、

Google Apps > OpenOffice > Open Web Apps

の順ですね。なぜか、ブラウザ上の Google Appls のほうが若干速いという。
まぁ、ざっくりと「見積書っぽいもの」(そのうち中身をブログで説明します)を作っただけなので、複雑な図形や請求書の類を作ったらどうなるのかは分かりません。使い勝手は、デスクトップアプリのほうが有利でしょう。

ただ、ちょっとした計算や文書、そして共有/配布、の手間を考えると Web アプリケーションのほうが手軽で、回覧などが楽だと思います。文書をメールに添付して回覧するよりも、Web 上にアップしておいて誰でも見られる状態のほうが、閲覧性は上ではないかと。
これらは、Outlook/ExchangeやNotesが担っていた分野なので、もう少し押してくるとサイボウズなどのグループウェアが食われる可能性もあるのかなぁ。それともサイボウズ+Google Apps なんてのを既に考えている?

衰弱堂雑記
なぜ誰もサイボウズのシェアを取りにいかないのだろうか
http://suijackdo.seesaa.net/article/40969901.html

最近はサイボウズ自体も苦戦していて、シェアの伸ばせないそうで(既に中小企業のシェアを食っているから頭打ちのような気もするし)、オープンソースのグループウェアってのはそれなりに需要はあると思う。

が、いま思いつきを並べると、

・国ごとのスタイルが違って、海外に進出しにくい。
・作り手がグループウェア自体に飽きた。
・そもそも、企業とはグループウェアを必要としない体制/体質である?
・作るとき種類が多すぎて手間ばかりかかる。
・ITバブル以降、何かとIT投資を控えてしまい、グループウェアもそのあおりを食った。
・SAPなどと違い、経営層に対してに売りにならず、投資されにくい分野である。
・グループウェアという思想を社内に入れるのが嫌だ。

なので Officeのように部品を社内に導入するのは良いけれど、SAPのように経営層が好きそうなもの(従業員を働かせるという意味でね!)以外への投資は控えられ、

「グループウェアを導入すると、どれくらいコストが削減できるの?」
「グループウェアを導入すると、どれくらい営業業績がよくなるの?」

という基本的な質問に答えられないのが問題ではないかなぁと思う。

Officeの場合は、「1本いくらだから、社員100人でいくらのコストダウンができる」と言えるけれど、グループウェアの場合はそういうことが言えない。これは、言えないのが問題なのではなくて、言えない状態の場合に導入できないという経営判断が問題なんだけどね。

カテゴリー: 雑談 | Google AppsとOffice Web Apps はコメントを受け付けていません

手始めに Silverlight+WCFの組み合わせで実験

手始めに Silverlight+WCFの組み合わせで実験

Silverlight+PHP(NuSOAP)の組み合わせを試す前に、Silverlight+WCFを試さないといけない。

ので、試してみた結果をメモ書き。

■最初はWindowsフォーム+WCFで

この手のお試しは確実なところからやっていくのが良いので、手堅くWindowsフォームからWCFを使えるかどうかの実験からスタートします。

1.WCFサービスライブラリのプロジェクト作成

2.初期状態で「Service1」と「IService1」が作成されるので名前を変える。
 ここでは「SampleService」、「ISampleService」と変更。
 名前の置換は、Visual Studio 2008のリファクタリングの機能を使うと楽。

3.インターフェース(ISampleService.cs)はこんな感じ

 
    [ServiceContract]
    public interface ISampleService
    {
        [OperationContract]
        string GetData(int value);
        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);

        // タスク: ここにサービス操作を追加します。
        [OperationContract]
        Product GetProduct(int id);
        [OperationContract]
        IList<Product> GetAllProducts();
    }

・サービスを追加するときは「OperationContract」属性を付ければOK。
・取得する場合は、戻り値にする(refが使えるかどうかは不明)
・リストで取りたいときはコレクションを戻り値にする。

ここで Product というクラス構造を受け渡しているので、定義する。

 
    [DataContract]
    public class Product
    {
        private int _id;
        private string _name;
        private decimal _price;

        [DataMember]
        public int ID
        {
            get { return _id; }
            set { _id = value; }
        }
        [DataMember]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        [DataMember]
        public decimal Price
        {
            get { return _price; }
            set { _price = value; }
        }
    }

・クラスは DataContract 属性を付ける。
・プロパティは DataMember 属性を付ける。

# 実は、Silverlight の DataGrid で扱いやすいように ObservableCollection を使う予定なのだが、
# 今回は試しなのでこのまま。

これでインターフェースはできたので、サービスメソッドの実装に入る。

4.サービスの実装(SampleService.svc.cs)を行う。
 先のインターフェースに従ってメソッドの内容を書く。

 
        IList<Product> m_products;

        public SampleService()
        {
            m_products = new List<Product>();
            m_products.Add( new Product() { ID=1, Name=&quot;Visual Studio 20X0&quot;, Price=40000 });
            m_products.Add( new Product() { ID=2, Name=&quot;SQL Server 20X0&quot;, Price=50000 });
            m_products.Add( new Product() { ID=3, Name=&quot;Expression Blend X&quot;, Price=60000 });
        }
        public Product GetProduct(int id)
        {
            var q = from p in m_products where p.ID == id select p;
            if ( q.Count<Product>() == 0 )
            {
                return null;
            }
            else
            {
                return q.First<Product>();
            }
        }

        public IList<Product> GetAllProducts()
        {
            return m_products;
        }

・本来はデータベースから拾ってくるのだが、今回は内部にデータを持ったままテスト。
・GetProduct メソッドは id を渡すと Product オブジェクトを返す。
・GetAllProducts メソッドはコレクションを返す。

大抵のパターンはこれだけで OK。
さて、普通はこれで十分なのだろうが、環境が悪いのか、そのままだと Windows フォームで参照するときに「ASP.NET互換ではない」というエラーが出る。よくわからないが、↓のように AspNetCompatibilityRequirements を付けると通るようになる。

 
namespace SampleSL2WCF
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class SampleService : ISampleService
    {
        ...
    }
}

■Windowsフォームの場合

WindowsフォームからWCFを呼び出すときは、

1.サービス参照で、先のWCFサービスを参照する。
 名前空間を「SampleServiceReference」と指定した。

2.この状態でバインドができているので、サービスの呼び出しは簡単。

 
 // サービスのクライアントを作成
    SampleServiceClient client = new SampleServiceClient();
    // オープン
    client.Open();
    // メソッド呼び出し
    Product pro = client.GetProduct(id);
    // クローズ
    client.Close();

3.先ほど、使ったインターフェース(ISampleService)のメソッドを使う。

 
using ClientWindowForm.SampleServiceReference;

namespace ClientWindowForm
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // IDを指定して検索
        private void button1_Click(object sender, EventArgs e)
        {
            int id = int.Parse(textBox1.Text);
            // サービス呼び出し
            SampleServiceClient client = new SampleServiceClient();
            client.Open();
            Product pro = client.GetProduct(id);
            client.Close();
            // データグリッドに表示1
            List<Product> products = new List<Product>();
            products.Add(pro);
            this.dataGridView1.DataSource = products;
        }
        // すべてのデータを取得
        private void button2_Click(object sender, EventArgs e)
        {
            // サービス呼び出し
            SampleServiceClient client = new SampleServiceClient();
            client.Open();
            IList<Product> products = client.GetAllProducts();
            client.Close();
            // データグリッドに表示1
            this.dataGridView1.DataSource = products;
        }
    }
}

これをビルドして実行すると、Windowsフォーム+WCFのできあがり。

■次はWPF+WCFの組み合わせ

SilverlightはWPFのサブセットなので、WPFの文法を覚えておくとSilverlightでも応用が利く。
が、サブセットゆえに、違い/落とし穴があるのが難点。
違い/落とし穴を示すために WPF+WCF でも動作させてみる。

1.Windowsフォームと同様にサービス参照でインタフェースを作る。
2.WPFにデータグリッドを付けたウィンドウを作る。

<Window x:Class=&quot;ClientWPF.Window1&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    Title=&quot;Window1&quot; Height=&quot;310&quot; Width=&quot;517&quot;>
    <Grid>
        <Button Height=&quot;23&quot; HorizontalAlignment=&quot;Left&quot; Margin=&quot;12,12,0,0&quot; Name=&quot;button1&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;75&quot; Click=&quot;button1_Click&quot;>ID指定</Button>
        <Button HorizontalAlignment=&quot;Left&quot; Margin=&quot;12,0,0,178&quot; Name=&quot;button2&quot; Width=&quot;75&quot; Height=&quot;23&quot; VerticalAlignment=&quot;Bottom&quot; Click=&quot;button2_Click&quot;>すべて</Button>
        <TextBox Margin=&quot;12,41,0,0&quot; Name=&quot;textBox1&quot; Height=&quot;24&quot; HorizontalAlignment=&quot;Left&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;75&quot;>2</TextBox>
        <my:DataGrid AutoGenerateColumns=&quot;True&quot; Margin=&quot;93,12,12,12&quot; Name=&quot;dataGrid1&quot; xmlns:my=&quot;clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit&quot; />
    </Grid>
</Window>

※DataGridのAutoGenerateColumns属性が True になっているのは、初期値の False だとグリッドが正常に表示されないため。
 おそらくデータのコレクションが間違っている(IListじゃだめ?)からだと思うのだが。

 

3.ボタンイベントを記述する。

記述の仕方は、Windows フォームとほぼ同じ。
データグリッドにバインドするときは「ItemsSourceプロパティ」を使う。

 
using ClientWPF.SampleServiceReference;

namespace ClientWPF
{
    /// <summary>
    /// Window1.xaml の相互作用ロジック
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

  // IDを指定して検索
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            int id = int.Parse(textBox1.Text);

            SampleServiceClient client = new SampleServiceClient();
            client.Open();
            Product pro = client.GetProduct(id);
            client.Close();

            List<Product> products = new List<Product>();
            products.Add(pro);
            this.dataGrid1.ItemsSource = products;
        }

  // すべてのデータを取得
        private void button2_Click(object sender, RoutedEventArgs e)
        {
            SampleServiceClient client = new SampleServiceClient();
            client.Open();
            IList<Product> products = client.GetAllProducts();
            client.Close();
            this.dataGrid1.ItemsSource = products;

        }
    }
}

これをビルドして動かすと問題なく動作する。OK。

 

■いよいよ、Silverlight+WCFの組み合わせを試す

1.Windowsフォームと同様にサービス参照でインタフェースを作る。

 ※このときに、WCFのデフォルトのバインディング(binding)が「wsHttpBinding」のままだと通らない。
 ※ので、basicHttpBinding に変更する。
 ※Silverlight 2 の場合は「basicHttpBinding」のみ有効、という記述があるのだが、Silverlight 3 の記述はない。
 ※どれが正しいのか不明。

WCFのweb.configを以下のように書きかえる。

  <system.serviceModel>
    <services>
      <service behaviorConfiguration=&quot;SampleSL2WCF.Service1Behavior&quot; name=&quot;SampleSL2WCF.SampleService&quot;>
<!--        <endpoint address=&quot;&quot; binding=&quot;wsHttpBinding&quot; contract=&quot;SampleSL2WCF.ISampleService&quot;> -->
          <endpoint address=&quot;&quot; binding=&quot;basicHttpBinding&quot; contract=&quot;SampleSL2WCF.ISampleService&quot;>
            <identity>
            <dns value=&quot;localhost&quot; />
          </identity>
        </endpoint>
        <endpoint address=&quot;mex&quot; binding=&quot;mexHttpBinding&quot; contract=&quot;IMetadataExchange&quot; />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name=&quot;SampleSL2WCF.Service1Behavior&quot;>
          <!-- メタデータ情報の開示を避けるには、展開する前に、下の値を false に設定し、上のメタデータのエンドポイントを削除します -->
          <serviceMetadata httpGetEnabled=&quot;true&quot; />
          <!-- デバッグ目的で障害発生時の例外の詳細を受け取るには、下の値を true に設定します。例外情報の開示を避けるには、展開する前に false に設定します -->
          <serviceDebug includeExceptionDetailInFaults=&quot;false&quot; />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  <serviceHostingEnvironment aspNetCompatibilityEnabled=&quot;true&quot; /></system.serviceModel>
</configuration>

# まぁ、考えてみれば、インターネット越しで Windows 認証を操ることはほぼ無いので、
# ベーシック認証にしておく(認証なし)にするのが良かろう。

2.Silverlightにデータグリッドを付けたウィンドウを作る。

このあたりは、WPF とほぼ同じ。

<UserControl
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:data=&quot;clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data&quot; x:Class=&quot;ClientSilverlight.Page&quot;
    Width=&quot;400&quot; Height=&quot;300&quot;>
    <Grid x:Name=&quot;LayoutRoot&quot; Background=&quot;White&quot;>
     <Button x:Name=&quot;button1&quot; HorizontalAlignment=&quot;Left&quot; Margin=&quot;8,8,0,0&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;75&quot; Content=&quot;ID指定&quot; Click=&quot;button1_Click&quot;/>
     <TextBox x:Name=&quot;textBox1&quot; HorizontalAlignment=&quot;Left&quot; Margin=&quot;9,34,0,0&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;74&quot; Text=&quot;2&quot; TextWrapping=&quot;Wrap&quot; />
     <Button x:Name=&quot;button2&quot; HorizontalAlignment=&quot;Left&quot; Margin=&quot;9,62,0,0&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;75&quot; Content=&quot;すべて&quot; Click=&quot;button2_Click&quot;/>
     <data:DataGrid Margin=&quot;88,8,8,8&quot; Name=&quot;dataGrid1&quot;/>
    </Grid>
</UserControl>

3.ボタンのイベントを記述する。

ここが、WindowsフォームやWPFと大きく異なる。

using ClientSilverlight.SampleServiceReference;

namespace ClientSilverlight
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
        }
        // IDで検索
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            int id = int.Parse(textBox1.Text);
            // サービスの作成
            SampleServiceClient client = new SampleServiceClient();
            client.GetProductCompleted += new EventHandler<GetProductCompletedEventArgs>(client_GetProductCompleted);
            client.GetProductAsync(id);

        }
        // 実行後のコールバック
        void client_GetProductCompleted(object sender, GetProductCompletedEventArgs e)
        {
            Product pro = e.Result;
            List<Product> products = new List<Product>();
            products.Add(pro);
            this.dataGrid1.ItemsSource = products;
        }
        // すべてを取得
        private void button2_Click(object sender, RoutedEventArgs e)
        {
            SampleServiceClient client = new SampleServiceClient();
            client.GetAllProductsCompleted += new EventHandler<GetAllProductsCompletedEventArgs>(client_GetAllProductsCompleted);
            client.GetAllProductsAsync();
        }
        // 実行後のコールバック
        void client_GetAllProductsCompleted(object sender, GetAllProductsCompletedEventArgs e)
        {
            IList<Product> products = e.Result;
            this.dataGrid1.ItemsSource = products;
        }
    }
}

コードを見ると分かる通り、
・サービスの呼び出し
・サービスの完了通知
の2つのメソッドが必要になる。
WCFを非同期で呼び出すために完了を待つ仕組みなのだが、、、これが結構うざったい。

ひとつのメソッドにまとめるならば、ラムダ式を使えばよいのだが、、、

        private void button3_Click(object sender, RoutedEventArgs e)
        {
            int id = int.Parse(textBox1.Text);

            SampleServiceClient client = new SampleServiceClient();
            client.GetProductCompleted += new EventHandler<GetProductCompletedEventArgs>(
                (s,ee) => {
                    Product pro = ee.Result;
                    List<Product> products = new List<Product>();
                    products.Add(pro);
                    this.dataGrid1.ItemsSource = products;
                });
            client.GetProductAsync(id);
        }

これは根本的な解決にはなっていない。

なぜならば、SilverlightでWCFを扱うときは非同期呼び出ししかないので「完了待ちをしている間、ユーザが何かアクションを起こさないようにブロックする必要がある」ということだ。これは面倒。
「SilverlightはWebアプリだから非同期であって~」の説明をちらほら見掛けるが、騙されてはいけない。WindowsフォームやWPFの場合は同じWCFを使っているのに、同期メソッドとして扱っている。これは、SiverlightがWebアプリかどうかという話ではなくて、Silverlightが扱うWCFのサブセットに「同期メソッドが抜けている」と言ったほうが良い。何故、抜けているのかは不明。

さて、これをビルドして動かそうとすると

「ドメイン間のポリシーが見つかりません」

と言われて動かない。

Silverlight 2 と WCF を使用したサービス駆動型アプリケーション
http://msdn.microsoft.com/ja-jp/magazine/cc794260.aspx

いわゆるクロスドメインの問題なので、WCFを公開するときに ClientAccessPolicy.xml というファイルを用意する。
# クロスドメインのブロックは、サーバーで行われるのではなくて Silverlight 側で自主的に行っている。
# つまり、、、今後「自主的に行わなくなる」という方向も考えられる。これは問題あり。

このファイルなのだが、ドメインのルートに置かないといけない。

たとえば、http://moonmile.net/ClientAccessPolicy.xml のように置く。

つまり、

http://moonmile.net/~masuda/
http://moonmile.net/masuda/

のようなレンタルホストの場合は Silverlight で使う WCF は公開できないということになる(レンタルサーバー会社で ClientAccessPolicy.xml を置けば別だが)。
また、他のサイトにあるサービスも簡単には使えない。先のエントリでも書いたが、別途プロキシを作る必要がある。
一番制限の緩い(いけない)設定はこんな感じになる。

ClientAccessPolicy.xml

<?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?>
<access-policy>
   <cross-domain-access>
       <policy>
           <allow-from http-request-headers=&quot;SOAPAction&quot;>
               <domain uri=&quot;*&quot;/>
           </allow-from>
           <grant-to>
               <resource path=&quot;/&quot; include-subpaths=&quot;true&quot; />
           </grant-to>
       </policy>
   </cross-domain-access>
</access-policy>

SOAPActionのヘッダに対して、どこのドメインからでもアクセスが可能。
サービスを提供するフォルダも自由(かな?)。
というわけで、Visual Studio上でWCFを公開するとポートは変わるし、先のポリシーファイルを置かないと駄目だし、ということで面倒なので、IIS 7.0 の仮想フォルダを使って設定する。

すると、OK。うまく SilverlightからWCFに接続ができる。

■パケットを見る

Siverlight+PHPの組み合わせを作るためにパケットを覗いてみよう。

Microsoft Network Monitor 3.3
http://www.microsoft.com/downloads/details.aspx?FamilyID=983b941d-06cb-4658-b7f6-3088333d062f&displaylang=en

を使うとパケットが見れる。

microsoftのサイトでダウンロードできるのは英語版のみだが、日本語化もできるそうだ。

Microsoft Network Monitor 3.3 の日本語化
http://d.hatena.ne.jp/wwwcfe/20090824/microsoftnetworkmonitor
Microsoft Network Monitor 3.3 日本語化パッチ
http://applications.web.fc2.com/j10n/networkmonitor.html
フィルタに

tcp.Port == 80

を設定してパケットをキャプチャする。

POST /SampleSL2WCF/SampleService.svc HTTP/1.1
Accept: */*
Content-Length: 157
Content-Type: text/xml; charset=utf-8
SOAPAction: http://tempuri.org/ISampleService/GetProduct
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618)
Host: iomante-pc
Connection: Keep-Alive
Cache-Control: no-cache

<s:Envelope xmlns:s=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot; >
 <s:Body>
  <GetProduct xmlns=&quot;http://tempuri.org/&quot;>
   <id>2</id>
  </GetProduct>
 </s:Body>
</s:Envelope>

 

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/xml; charset=utf-8
Server: Microsoft-IIS/7.0
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Fri, 16 Oct 2009 06:55:12 GMT
Content-Length: 385

<s:Envelope xmlns:s=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;>
 <s:Body>
  <GetProductResponse xmlns=&quot;http://tempuri.org/&quot;>
   <GetProductResult xmlns:a=&quot;http://schemas.datacontract.org/2004/07/SampleSL2WCF&quot; xmlns:i=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;>
    <a:ID>2</a:ID>
    <a:Name>SQL Server 20X0</a:Name>
    <a:Price>50000</a:Price>
   </GetProductResult>
  </GetProductResponse>
 </s:Body>
</s:Envelope>

中身が読みやすい SOAP になっているのが分かる(実際は xml の部分は1行で書かれている)。

なので、Siverlight+PHPを作る場合は、

・サービス参照をするための WSDL を作成
・SOAP で応答を返す

だけで良いので、NuSOAP が結構使えるのではないか、と期待できる。

続きは後日。

カテゴリー: 開発 | 手始めに Silverlight+WCFの組み合わせで実験 はコメントを受け付けていません

CentOSでLAMP、そしてNuSOAP+Silverlightは可能か?

クライアントが Silverlight な場合、バックエンド(サーバー側)はIIS 7.0を使うので、自然サーバーとの通信は WCF を使うことになります。。。っていうか、Microsoft の一番押しらしいんですが、MCF を使う場合には IIS 7.0 が必須なんですかね?

予算がある場合は、SQL Server 2008を買って、SQL Server 2005/2008を買って、IIS 7.0をインストールし、その上で、Silverlight を Visual Studio 2008 で開発して、デザインは Blend 3 を使って、ということが可能なのですが。
あまり予算が無い時はそうはいきません。つーか、そんなに予算をつぎ込めません!

なので、自然とLAMPの組み合わせを使うのが普通なのですが、ブラウザベースでリッチクライアント(俗にいうRIA)を作る場合は、Flash が第一の選択肢になります。あいにく Flex は触ったことがないので、どこまで作りやすいのか/無料なのかが不明なのですが、言語として Java を使う必要があるのが難点。

まぁ、そういうわけで、

・クライアントに Silverlight
・サーバーに PHP + MySQL

というのはどうでしょう?

あいにく Flash で本格的なアプリを作ったことがないので(使ったことはありますが)、想像でしかないのですが、開発時の再利用は結構大変なのではないかと。そういう場合は、Flex を使う訳ですが。

さて、Flex を使うとサーバーに Java が必要ですが、Silverlight を使っても ASP.NET を必要としません。DLL だけを置いてダウンロードできるようにすればOKです。そういう点では、Flash と同等の配置の手軽さが取れます。
Silverlight では開発言語は .NET を使えるので、クラスライブラリ等を使い再利用が可能です。NUnitやSilverlightのUnitTestも使えるので、かなり頑健なものができそうです。

で、問題は、サーバーからデータを持ってくるときは何を使うのか?ですね。

まぁ、サーバーがPHPなので、XMLサービスでも良いし、独自のWEBサービスを使ってもよい。が、基本はWSDLを公開しておけば、それを参照してクライアントのクラスを自動作成できる。

連載 Webサービスのキホン(4)
WSDL:Webサービスのインターフェイス情報
http://www.atmarkit.co.jp/fxml/tanpatsu/21websvc/websvc04.html
Windows Communication Foundation概説
WCFの基本的な概念
http://www.atmarkit.co.jp/fdotnet/wcf/wcf02/wcf02_02.html

なので、基本的なプロトコル?をサポートしてとけば、相手がPHPでも良い訳です。
PHP の場合、SOAP を扱うための NuSOAP が老舗なのでこれを使います。
詳しい実験は後日やるとして、方針をざっと書き出すと。

1.クライアントアプリを Silverlight で作る。
2.サーバーを CentOS の LAMP 環境で作る。
3.PHP の NuSOAP を使ってサービスを WSDL で公開する。
4.永続化等は MySQL を使う。
5.公開済みの WSDL を Silverlight 側でサービス参照する。
6.通信は WCF に準じる?
ただし、いくつか問題があります。

・Silvelight はクロスサイトドメインアクセスの問題があって、他のドメインにサービスを繋げないようになっている。
・NuSOAPを使って WCF 準拠ができるのか不明
・PHPのパフォーマンスの問題

基本は巷のレンタルサーバーのPHPを使って公開、クライアントはSilvelightで。
という一見不思議な(?)環境を整えたいので、ここらはクリアにしておきたいところです。
クロスサイトの問題は特定のhtmlを公開時に置けばよいので、まあ個人運用にはなんとかなりそうですが、既存のサービスを silverlight 側で使えないのはちょっと痛いです。
fs
Silverlightでのクロスドメインアクセス
http://d.hatena.ne.jp/coma2n/20080430/1209516432

まぁ、最初はプロキシを作る。そして、Microsoft が Siverlight + WCF を広めるのを待つ(各サービスが WCF に対応しようとする)のがベターかなと。

カテゴリー: 開発 | CentOSでLAMP、そしてNuSOAP+Silverlightは可能か? はコメントを受け付けていません

PHPとMVCモデル

<愚痴>
今回の仕事で痛感したのは、単体テスト(UnitTest)を活用してないプロジェクトは全然駄目ということですね。品質に理解があるようでいて理解/実践がないし、設計、レビューを繰り返したとしても正常に動作するあるいは作成可能であるかの保障がありません。
そうなると「SIer>下請け」ヒエラルキーの元で、割を食ってしまうのは下請けのプログラマです。単体試験の工費を貰えず、単体試験を省けば、不具合/障害の責任はプログラマにある。また、単体試験を行えばスケジュールに合わない。余計なことをやっているとみられる。時間を削られれば学習の時間(次への投資)ができなくなる。じり貧になってしまうのは、下請けの底辺プログラマばかり。
というわけで、今後そういう仕事は請けないことにします。
</愚痴>

な訳で、インストールマニアックスでPHPを少し触ったことだし、ASP.NETの開発者よりもPHPの開発者が多いわけだし、あるいはJava開発者が多いし、ということで、PHPとMVCあるいはMVVMの組み合わせはどうかな?とざっと調べてみました。

目的は、

・PHPの開発者が理解できる標準的なMVCモデル
・PHPの軽さ/手軽さを活かした開発スタイル
・基本はLAMP(Linux+Apache+MySQL+PHP)
・単体テスト/PHPUnitは必須
・自社開発の効率化/品質Up
・できれば、巷のオープンソースに組み込みやすい/流用しやすい

なところです。

PHPと他各種言語の比較記事
http://phpspot.org/blog/archives/2007/01/php_69.html
PHPUnit3で始めるユニットテスト
http://gihyo.jp/dev/feature/01/php-test/0001?page=1

PHPフレームワーク ちいたん
http://php.cheetan.net/
軽量なMVCフレームワークの自作(改訂版)
http://codezine.jp/article/detail/104

CakePHP
http://cakephp.jp/
CakePHP プログラマーズ リファレンスガイド
http://cakephp.jp/doc/

ざっと調べてみると、フレームワークとしてはCakePHPの評判が良さそうです。ただし、Ruby on Railsの影響を強く受けているみたいなので、Railsを知らない人/好きでない人にとっては、メリットが薄れます。ちなみに私は「Railsを知らない人」です。

現在、PHPを使ってWEBアプリを作るメリットとして、

・PHPの開発者は比較的多い(文法が簡単だから?)。
・LAMPのひとつとして確立されている(メジャー度)。
・レンタルサーバーではPHP、Perlが入っているところがほとんど。

なわけで、安いサーバーを使って、広く技術者を求めることが可能、かつ顧客にも説明しやすいというメリットがあります。

デメリットとしては、

・負荷の話になると、Java/.NETが有利
・データベース接続がMySQLが基本?(既存のOracleに接続するとか)
・クラスが一般に認知されていない?(PHPのクラス解説ブログ/ページは少ない?)
 よって、開発者が減る。
・Visaul StudioやEclipsのような開発環境が無い?(インテリセンスとかコンパイル時エラーとか)

なところでしょうか。
あと、うがった話で言えば「PHP開発者が大勢いるといることは、Javaや.NET、C++ほど優秀な人が少ない?」という偏見も出てきます。これはよくわかりません。モデルの会話とか、フレームワークの会話を実際にしたことがないので。なんかいい勉強会とかありませんかね?

# ちなみに Java の人と会話すると、直ぐにインターフェースとリスナーを駆使したクラス至上主義なモデルになってしまい困りものです。.net だとデリゲートがあるし、Rubyはメソッドを追加することができるし、と言語特有の特徴/有意性があるので、JavaライクなC#コードを書かれても、困るんですが。

さて、ASP.NETにもMVCフレームワークというのがリリースされていますが、何もその実装フレームワークを使わないとMVCモデルが実現できあい訳ではありません。先のエントリにも書きましたが「モデル」≠「実装」という実現の仕方でもよいのです。
特にMVCモデル(Model-Viewパターン)はViewを分離させようという発想、自動化できるUnitTestを使おうという発想が先にあるので、ここをきちんと押さえないと、ただ何かのフレームワークを使っている(お仕着せのライブラリとか)になってしまいます。

MVCフレームワークが気持ち悪くなってきた
http://d.hatena.ne.jp/ghostbass/20081126/1227673389

そういう点で私は上のエントリに同意します。

おそらくJavaのStrutsの影響を受けると、本来のMVCモデルが失われてしまうのかな?と。

少しPHP-MVCモデルと離れますが、思いつきを書いておきます。

PHPの大きな特徴は大抵のレンタルサーバーで使えることです。ですから、WEBサイトの数々の管理ツールをPHPで書いておくことは大きなメリットです。たとえ、サイト自体がJavaやASP.NETで運用されていたとしても、マスター管理の画面など管理者が使う画面をPHPで書いておけば、作成や改修にそれほど時間/工数をかけずに済みます。PHPのインストールは必要でしょうが、特定のPEARに依存せずインストールが楽になれば、別の言語であっても構わないのです。顧客向けのページをJavaやASP.NETで作成し(お金をかけ)、少数の管理レベルであればコマンドライン制御も含めて、PHPで手軽に書く(お金をかけず)、という適材適所の思想が必要です。そう、建築と同じで、どこでも檜を使えばいいってもんじゃないでしょう?

このとき、マスター管理などの画面を作るのに導入コストがかかるフレームワークは避けたほうがいいでしょう。勿論、同じ言語で同じ技術者で作りたい気持ちも分からないのではないですが、それだけ無駄なコストが掛かります。オーバースペックなわけです。

となれば、手早く作る部分には下記の要件が必要です。

・軽量なPHPのフレームワークであること。
・頑健であること。
・導入/学習コストが低いこと。
・不足を補う方法が用意されていること。

先の2つは軽量/頑健さを求め、複雑を排除します。単純であれば学習コストも減るでしょう。拡張性をトレードオフしますが、一定の複雑さを求めるのであれば、別のフレームワークを使うか、javaなりasp.netなりを使えばよいのです。

不足を補う部分を具体的に話せば、巷のオープンソースはPHPのコードをPHPから出力する自己記述を行いうまい具合に閉じていますが(これはこれでいいのですが)、何もかもこれでやるのは無理があります。
なので、設定自体をExcelで書くとか、コードの自動生成をExcelから行う(あるいはJavaのコマンドを使う)などの組み合わせがあってもいいはずです。
# 逆に何もかもExcelというのも無理があります。

こういう観点からPHPにMVCモデルを組み合わせると、いくつかの案がでてきます。
おそらく「ちいたん」がそれに近いと思います。

・VB6.0でCOMを扱うような手軽さ。
・VB6.0でCOMを扱うような頑健さ。
・中身が容易に想像できること。
・設定が一か所にまとまっていること。
・テストツールが用意されていること。

VB6.0とCOMの繋がりは非常に疎ではありますが、疎結合ゆえにメソッド/プロパティが用意に想像できる単純さを持っています(中身は複雑ですが)。
この外見の容易さは、車のハンドルを左に回すと、車が左に曲がるというアクションと動きの一致の重要さに通じます。見えない構造はどれだけ複雑でも構いませんが(実際CPUの回線は複雑だし)、活用する場面においてその複雑さを表に出してはいけません。
なので、MVCモデルを導入する際も、「中身が容易に想像でき」、インターフェースを眺めることができるように「設定を一か所にまとめる」工夫が必要です。あちこちのファイルを修正しないといけない実装は、ケアレスミスを誘発しますし、学習コストを押し上げてしまいます。

そして、忘れていけないのが、設定がきちんとできているか、その実装は思った通り動いているのかをテストするツールが必要なのです。最近、SQL Serverでは設定のチェックを行うようになりましたが、ほとんどのフレームワークは自己テストを行いません。
私がいささかスクリプト言語を敬遠するのは、コンパイル言語であればコンパイルすれば取れるエラーが、スクリプト言語の場合実行時にしか取れないことが多いためです。
# perlには文法チェック -wc というオプションがあります。ruby の場合は -c かな。

これだけ頑健にしておき、実装時のエラーが取れていれば、あとは開発者が作った独自のコードのエラーを取るだけです。UnitTest のフレームワークを活用しておけば(これが必須なのですが)、その延長線上でテストを作ることもできるでしょうし、本来 Model の UnitTest が実践できるという、MVCモデルの発端の思想に沿うものができます。

というわけで、無事 PHPとMVCモデルに戻ってきたわけですが、このあたり、実装できているMVCフレームワークは欲しいですか?

カテゴリー: 開発 | 6件のコメント

MVVMパターンの日本語訳

備忘録として。

M-V-VMパターンについてのエントリを訳してみた 原題:”WPF patterns : MVC, MVP or MVVM or…?”
http://blog.sharplab.net/computer/cprograming/wpf/1812/
M-V-VMパターンについてのエントリを訳してみた2 原題:「David Hill’s WebLog : The ViewModel Pattern」
http://blog.sharplab.net/computer/cprograming/wpf/1840/
M-V-VMパターンについてのエントリを訳してみた3 原題”CollectionViewModel”
http://blog.sharplab.net/computer/cprograming/wpf/1842/
関東地方は台風一過の秋晴れです。
その中で、台風情報を見ていたのですが、Yahoo!の雨雲ズームレーダーが Silverlight でした。

雨雲ズームレーダー
http://weather.yahoo.co.jp/weather/zoomradar/
Yahoo!天気のほうは、Adobe Flashなんですが、この手の複雑なアニメーションはデータ抽出から表示アプリの効率を考えたら Silverlight のほうが良いんではないかなぁ、と思ったり。Flex + java か Silverlight + .net の組み合わせかの選択ですね。

カテゴリー: 開発 | MVVMパターンの日本語訳 はコメントを受け付けていません