Visual Studio Community 2015 で Xamarin.Forms を使う

//Build/ 2016 で Xamarin が Visual Studio で無償で利用できるようになりました。ということで、一応、素の環境から Visual Studio Community を使って入れます。

Windows で Xamarin 開発をしたい方はインストールする前に読んでほしい – Xamarin 日本語情報
http://ytabuchi.hatenablog.com/entry/2016/04/05/142525

田淵さんがスタート向けを書いてくれたので、私のほうは既存の Visual Studio に追加というスタイルで話を進めます。

 

Visual Studio Community 2015 をダウンロード

https://www.visualstudio.com/ja-jp/products/visual-studio-community-vs.aspx から Visual Studio Community をダウンロードしてインストール

image

最初のオプションで「C#/.NET (Xamarin)」を入れてもいいのですが、今回は既定のままインストールした後に Xamarin を入れます。

image

Xamarin をインストールしていない状態でプロジェクトを作ろうとすると

新しいプロジェクトで「Visual C#」→「Android」あるいは「iOS」の下にひとつだけプロジェクトがあります。この状態は、まだ Xamarin がインストールしていない状態です。

 

image

試しにプロジェクトを作って開くと、Xamarin のサイトからダウンロードせよ、というプロジェクトが開かれます。

image

Download ボタンを押して xamarin.com からダウンロードしてもよいのですが、ここは再び Visual Studio のインストーラ(vs_community_JPN)を起動して、改めてスイッチを設定します。

image

Xamarin をインストールする

「C#/.NET (Xamarin)」をチェック。UWP も作りたい場合は「ユニバーサル Windows アプリ開発ツール」もチェックしておきます。

image

Android が入るので Java も入りますね。Hyper-V の Android エミュレータも込みです。
この時点で「共通ツールおよびソフトウェア開発キット」を開いて

  • 「Android SDK セットアップ(API レベル22)」
  • 「Android SDK セットアップ(API レベル23)」

もチェックしておくと、後ろのほうにある Xamarin.Forms をビルドするときの不可思議なエラーがなくなります。ここではあえてチェックせずに進んで、わざと「ハマり」ますw

image

Xamarin がインストールできるとこんな状態になる。

image

「Cross-Platform」を選ぶと Xamarin.Forms を使える。

image

PCL でプロジェクトを作った直後

image

最初の Xamarin.Forms を動かしてみる

このままの状態で Xamarin.Forms をビルドして動かそうとするとビルドエラーになります。最初のテンプレートをダウンロードしてビルドしようとしただけなのに「何で動かないのこれ!?」と思うぐらい変な感じです。

image

Xamarin.Forms のバージョンは「2.0.06482」というちょっと古いものが使われています。

これ、ちょっと事情があって、

  • Xamarin.Android は、下位の Android に対応するためにいくつかの Xamarin.Android.Support.* を用意している。
  • Android SDK のバージョンは Xamarin とは別に更新される。
  • Xamarin.Android 本体と Xamarin.Forms ライブラリは、別口で更新される。
    NuGet Gallery | Xamarin.Forms 2.1.0.6529

という微妙な関係があって、タイミング的に Xamarin.Forms のビルドがうまく通らないことが多いのです。NuGet から取得すると Xamarin.Forms の依存関係は以下のようになっています。

image

最新の Xamarin.Forms 2.1.xx は、Xamarin.Android.Support.* の v23.0.1.3 に依存しているのですが、現時点で Xamarin.Android.Support.* の最新バージョンは  v23.2.1 なのが厄介なところです。さらに、Android SDK のバージョンが絡んでくるので、それぞれの最新版を利用しようとするとうまくいかないことが多いのです。

このあたりは、Xamarin.Forms 自体が OSS 化されるということなので、最悪は自前で Xamarin.Forms のビルドをして最新の Android.SDK に合わせる(正確には Xamarin.Android の最新にあわせる)スタイルになるでしょう。まあ、今後も Xamarin.Android のバージョンアップとタイムラグが出るのは仕方ないところです。

エラーのほうは、values-v23 と出ているので、Android SDK 6.0 が由来っぽいです。「ツール」→「Android」→「Android SDK Manager」を見ると、Android SDK 6.0/5.1 が入っていないので、これを入れます。

image

Visual Studio のインストーラーのほうに Android 6.0/5.1 がないのが問題じゃないかな…というか、良く見直せば「Android SDK セットアップ(API レベル22)」と「Android SDK セットアップ(API レベル23)」があるので、これにチェックを入れれば Android 5.1/6.0 が入りそうです。

image

この状態で、ひとまずエラーがなくなります。

Visual Studio Emulator for Android を使う

Android のエミュレータは、Hyper-V を有効にして Windows Phone と同じ感じで動くものをツあくとよいです。

どうせなので Android SDK 6.0 のものを選択してダウンロード。

image

実行すると、結構なスピードで動きます。

image

Google Play が入っていないこと以外は、だいたい実機と同じように動きます。逆に言えば、Google Play からダウンロードして試してみる、ってことをやる場合には実機か別のエミュレータを使います。

image

XAML はどのように書くのか?

Xamarin.Forms の売りは2つあります。

  • Android/iOS/UWP等の複数のプラットフォームの UI を一気に書けます。
  • XAML + MVVM で書けます。

複数プラットフォームの UI を共通化するのであれば、適当なコンバータを作れば UI の同時生成ぐらいはできるのですが、もうひとつの要素があわさっていることが重要です。UI の記述(この場合は XAML のコード)が「共通化」されたのであれば、それを内部的に動作さえるロジックも「共通化」できるだろう、という発想です。具体的には Model だったり ViewModel だったりするわけですが、現実問題としてはプラットフォームに依存した UI は共通化できないし、それぞれのプラットフォームごとに記述するしかないですよね。そのあたりも含めて、大まかなところは XAML で共通化させてしまって(ついでにロジックも共通になる)、別々なところはできるだけ小さくなるように設計をします。

で、もともとの Xamarin.Forms の UI コードが、コードに記述になっているので、どうせだから PCL に XAML を含めて書いてみようってのが次のステップです(これ自体がテンプレートで含まれてもいいと思うんだけど、含まれてない)。

image

これを使った例を後日。

カテゴリー: Xamarin | Visual Studio Community 2015 で Xamarin.Forms を使う はコメントを受け付けていません

ギター練習とプログラムコードの手癖

うっかりして ギター練習を再開しました | Moonmile Solutions Blog にプログラムコードの手癖の話を入れるのを忘れていたので追記。

楽器の「コード」とプログラミングの「コード」に引っ掛ける訳ですが、意外と通じるものがあります。というか、通じるようにやってます。

ギターの手癖

Julian Lage の講義の映像を見ると「こんな風に上がり下がりして、ギターらしく弾くところに留まってしまいますよね」という科白があります。オレオレブルースを引いてブルーススケールに慣れてくると、上がり下がりだけで満足してしまうことが多いです。先のストアアプリのギターソロ練習も、ヘビメタのそれらしいスケール(それはそれでギターリストの個性なんだけど)の早弾き方法がたくさん載っています。が、実際やってみると(そんなに早弾きできるわけではないし、きちんとできたらそれでそれで面白いのだろうけど)それらしくはなるけど、それ以上になりません。

人間の指の反応がどれくらいのスピードに耐えられるのか分かりませんが(32拍で区切ると、1/32だから 30msec ぐらいで弾くことになります)、まあ16拍(50msec程度)でオルタネイトすることもあるでしょう。というか、そもそも16拍すべてを打つ必要はなくて、11拍目に打てば、16拍を感じることができるという技もありますよね(4:8:11:16で打つと、12拍からずれた1拍分を16分として感じられるというあれです)。

そのあたりも含めて、ブルースのリズムに乗って弾けば「ブルース風」になるし、jazz スケールで引けば「jazz っぽく」聞こえます。フラメンコもカントリーもそれらしいリズムとスケールがあって、だからこそ「フラメンコ」や「カントリー」に分類されているという逆の意味もあります。フリージャズとか音楽理論とか、理論方面は別として、感覚的に「そう聞こえる」ということです。

試してみると、グレンミラーのリズムで弾くと、ブルーススケールでも「グレンミラー」のように聴こえます。また、アタックNo.1の最初の「くるしくたって…」の部分をブルースに入れると「アタックNo.1ブルース」が出来上がります。なんだかよくわからないけど、自分でやってて面白いのです。

「ガンダム」と「魔女っ子メグちゃん」と「アタックNo.1」の音を拾っていくと、作曲した頃の渡辺岳夫を感じることができます。「ああ、ここはギターの運指上、ハンマリングの音がなるよね」ってな具合で、ギターで作曲するときの癖が随所にでてきます。たぶん、ピアノの場合とは違った癖があって、逆にピアノの作曲でもそれ相応の癖がでると思うんですよね。それは、指の動きの「制限」であったり、作曲家の癖であったり、同時にソロ演奏するときの手癖であったりします。

くそまじめにメジャースケール、マイナースケールと練習するのもよいのですが(私の場合は、きちんとスケール練習していないので、スケールのほうをちょっとやらないとダメなんですけど)、自分の「こうなって、こういう音が鳴って、そして運指がこうなって」という繰り返しをしていくと、なんとなく自分の好きな指の動きが作れます。まあ、それで何が弾けるというわけでもないけど、10分ぐらいはソロ演奏やっていても「自分を」楽しませる程度には弾けるようになります。

プログラムコードの手癖

同じことはプログラムのコードにも言えます。コーディングする人の「性格」ではなくて、「手癖」のようなものですね。「性格」≒「手癖」は似た感じではあるのですが、「良い性格」「悪い性格」というのではなくて、その人を形作っている「手癖」(良いも悪いもない)というものです(まあ、性格に良いも悪いもない、という意味での「性格」ならば、それでも ok です)。

コードの手癖というのは、先のブルースケールやジャズスケールやカントリーのようなもので、その人の通奏低音みたいなものです。最初に C 言語を習った人は C 言語風にプログラムを書くし、Java だったら Java 風に書きます。C# だったら、 C# 風にって具合ですね。あと、Perl とか Ruby とか PHP とか色々あります。

ひとつのプログラム言語を一生使うことは稀なので、最初に習ったプログラム言語からそのほかの言語を覚えます。プログラム言語にも潮流があるのですが、プログラム言語を習う側にも潮流があるので、それが交差します。Java で C 言語風に書いたり、C# で Java 風に書いたりします。それぞれが、それぞれの潮流≒歴史を持っているのと、プログラム言語自体の歴史があるし、同時にこうありたいという個人の願望と、プログラム言語自体の願望があって、「いろいろな書き方」ができてきます。また、いろいろな制限を持ち込まれますよね。LINQ 禁止とかのアレです。

まあ、禁止事項は別として、一定の品質を保ったプログラムコードであっても、いろいろな書き方ができます。そういう時、新規の場合は「好みですよね」で済ますのですが、とあるコードに加筆するようになった場合(いわゆる改造とか改修案件とかいうものです)、もともとあるコード作成者の「手癖」をうまく延長しないと、そこだけ違った色合いになります。まあ、ガコっと欠けてしまったときには、速乾パテでも塗らないといけないわけで、時と場合によるんですが、できるだけ元コードの「手癖」をまねると、コードがなじみます。感覚的に言えば、元コードにうまくなじむので、なんとなく品質も高くなるし、再び同じ場所のコードを修正しようとしたときに、コードが修正しやすくなります。手癖が同じですからね。

コード規約とか、社内標準とか、補完機能を使って「強制的に揃える」のがよいのか、通奏低音としての「手癖」にあわせるのがよいのか、これも時と場合によるんでしょうが、どちらの使い分けがあってもいいですよね。

そういえば、ソフトウェア開発をオーケストレーションとして扱おうと思ったことがあるけど、それれぞれの演奏者は「プロ」の技を競うのだから、コーディングの協調性(ここでは「悪い意味での協調性」)を求められる時に困るし、いわゆるバックバンド的なスタイルでコーディングを求められることもあるのだから、ソフトウェア開発のオーケストレーションも一手段にすぎないのだな、と思い直したりしてます。

カテゴリー: 開発 | ギター練習とプログラムコードの手癖 はコメントを受け付けていません

ギター練習を再開しました

再開とは言っても、大学の頃と新人の頃にちょこっと練習していただけなので25年振りという感じですね。当時も今も、何を弾けるという訳ではないので何か疲労できるわけではないのですが(「東京ブギウギ」とか「アタックNo.1ブルース」とか変なブルースソロだけうまくなっています)、少し自由に楽器が弾けるようになると、プログラムとか電子工作の発想に良いかなと。年男なので48歳の手習いですね。

ちょっと自分のメモ用に書き残しておきます。

再開の発端は Julian Lage から

Julian Lage Workshop (Japanese Subtitles)
https://www.youtube.com/watch?v=pfOWWcQeP3Q

常々、死ぬまでにはカントリーとフラメンコぐらいは弾きたいと思っていたのですが、かといって何か対策をしている訳ではありません。ギターも引っ越した後に押し入れの中に突っ込まれたままでした。

ツイッターで勧めらていた Julian Lage のギター教室の映像なんですけど、彼は5歳からギターを弾いていて、映像現在で23歳です。映像自体が5年前なので、現在は28歳です。暫くジャズ・ギターの曲なんて聴かなかったのですが、これはすごい。演奏もすごいけど、彼の理論的な追及の仕方がすごいです。体系的に音楽理論を語っている訳ではないのですが、スポーツ選手が自分の走り方を科学するように、彼はギターの弾き方を科学しています。「科学する」ってのは、現象があって、それを再現できること、少し変えてみて試すことができることですね。漠然とギタースケールを弾いているのではなくて、次のステップにつなげるようにギターの練習方法を語ります。実に実践的です。

私が参考にしたフレーズ(彼の科白)を抜き出せば、

  • 6弦を低音/中音/高音の2本ずつに分けてフレーズを作る。これで、ギターを横に(フレット方向に)使える。
  • 横方向に長くスケール練習する。音が出る前は分からないので、音を聞きながら新しい組み合わせを読み取る。そして再現する(再現できないかもしれないけど、耳が覚えている)。
  • ギターの弾き方に制限があるけど、それは手で押さえることがぐらい。そして手癖がある。
  • ピックを持つ右手は、もっと敏感になれるから、ギター/弦から伝わるピックの圧力をうまく感じればオーケー。

ってな具合です。本当のフレーズは彼のビデオを見ると解ります。この探求の仕方に感動して、立て続けに3回ほど通してみて、2週間ほど練習しています。

服部良一に再会する。

山寺の和尚さん 歌詞と試聴
http://www.worldfolksong.com/songbook/japan/doyo/yamadera.htm

私の場合、基本的にオレオレブルースしか弾けないので、コードが弾けません。高校生の頃にフォークギターで指が痛くって投げたしたあたりからコードが押さえられません。まあ、今だと何となくコツがわかったので、オレオレブルースをやる分には大丈夫なぐらいなのですが、ふと「山寺の和尚さん」の突き当りました。

「カジノロワイヤル」をアマゾンプレミアムで見て、ああ、こういう音楽でもいいなと思いつつ、どうせならば「東京ブギウギ」ぐらいさかのぼってもよいだろうということで、さらに戦前までさかのぼります。大正、昭和ヒトケタまでさかのぼるのは、また別の意味があるのだけど「山寺の和尚さん」が服部良一のデビュー作であることを知りました。なるほど。こっちの路線でもよいわけです。

Julian Lage がエーデルワイスを弾くように、日本人が山寺の和尚さんを弾いてもよいわけで、昔なじみの民謡やおなじみの歌謡曲を jazz アレンジにしても良いですよね。矢野顕子も山下洋輔もやっています。

魔女っ子メグちゃんを弾いてみる

何故、覚えているのかわからないのですが、小学生の頃にリアルタイムで見た覚えがあります。なんか、オープニングの曲だけ印象的でずっと覚えていた曲なのですが、改めて調べてみると 渡辺岳夫 の曲でした。アタックNO.1 もキューティハニーもガンダムも彼の作曲です。

ギタースケールを練習していくと自分の手癖がわかります。弾きやすい運指と弾きにくい運指があります。オレオレソロをやると、どうしても弾きやすい運指に偏りがちですよね。おそらく、アニメの主題歌も作るときに手癖があるのじゃないか、と思ったりするのですが、どうやらあるみたいです。魔女っ娘メグもガンダムも同じ手癖で作られていることがなんとなく分かります。忙しい時期は、3日に1曲ペース(週に3日間スタジオにこもっていたらしい)っぽいので、もう頭の中のフレーズと手癖と好みだけでばりばり作っていく感じじゃないでしょうか。疲労のためか50歳半ばで亡くなっています。

そうやっていくつかの曲を真似てみると、世間的な音楽自体は5,6年という短いペースで流行が変わっていくけど、ひとりの作曲家/演奏家にとっては、当然のことながら3,40年という長いペースで音楽を作っていることがわかりますよね。ひとりの歌手/グループを追うのと同じでもあるし、彼や彼女が作る音楽の変遷というもの(それは学習だったり影響だったりするわけで)が現れてきます。

ウェス・モンゴメリーを改めて聴く

渡辺貞夫の最盛期をよく知らないのですが、サックス奏法がギターに取り入れらて、その逆もあるんでしょうけど、ウェス・モンゴメリー を改めて聴きます。 というか、ジャズ喫茶とかCD買ってたりして聴いていたのだけど、ああ、自分が生まれるより前の音楽なんですね。ってことは、オレオレブルース(B.B.キングの真似っこだったり)も、ずっと歴史をさかのぼっていってもいいのかー、っての分かって、昭和ヒトケタの日本から再開しているところです。

ギターで遊ぶために

ギターはまずコードを押さなければー、みたいな感じがしますが(まあ実際そうなんだけど)、コードをじゃかじゃかやっているだけでも音楽っぽく聴こえるのがよいところです。

GuitarStudio という iPhone のアプリがあってコードを指定してじゃかじゃかできます。本来はこんな音になるんじゃないかなぁ、と楽しむのがよいかと

iPhone Guitar Cover – Losing My Religion – YouTube
https://www.youtube.com/watch?v=yqgEl_Rt2lE&ebc=ANyPxKrVOPJsTWZkSi59VDdnBtRXGSDUjW8ohfoJHYnCy40I5ErwBWNxSLwYc-kc376ljVI2jsI7wN3L0Cw5LcWriz5sQr2ugA

Windows ストアアプリに教本っぽいものがあります。

ギターの練習で困るのは、運指をどうするかのですが、これだとスロー再生もあるので便利です。もちろん、youtube で運指をアップにしてもよいですよね。昔はビデオを買ってスロー再生だったので環境的にはよくなったかな。

「初心者講座」ってことになっていますが、どこまでの初心者wを対象にしているかわかりません。程よく弾ける人じゃないとついていけないんじゃないだろうか。けど、「~風」って発想が面白くて繰り返し見ています。

弾いてみよう!カントリー風(アコギ編)【ギター初心者講座】 – YouTube
https://www.youtube.com/watch?v=GKZEV102Ry8
弾いてみよう!フラメンコ風(アコギ編)【ギター初心者講座】 – YouTube
https://www.youtube.com/watch?v=8O1uIAuCcWY
アコースティック ソロギター道場|メロディ・パートとベース・パート by J-Guitar.com
http://www.j-guitar.com/ha/solo/index.html

リズムを合わせればそれっぽく聴こえるってことの実践ですよね。

そうそう、ぼちぼちタブ譜のほうでもやってみないと。

DLmarket / 【TAB譜】マクロス フロンティア (娘たま♀)15曲+おまけ4曲セット アコースティックギター伴奏譜 [ダウンロード版]
https://www.dlmarket.jp/products/detail.php?product_id=305177

カテゴリー: 雑談 | ギター練習を再開しました はコメントを受け付けていません

往年の Turbo C++ を触ってみよう

もうちょっと前に書こうと思っていたのですが、Turbo C++ のフリー版があるよ、ということで記事を残しておきます。

Turbo C++ or C for Windows 7, 8, 8.1 and 10 32/64-bit Full Screen Free Download – Home
https://turboc.codeplex.com/

Windows 10 でも動くので、そのままダウンロードしてインストール。起動すれば ok です…が、全画面になってしまうのが困りものなので、起動時に「full screen mode…」のチェックを外します。するとウィンドウモードで動きます。ただし、カーソルが取られてしまうので、Ctrl+Tab で他のウィンドウにフォーカスを移してください。なんか Tab キーが暴走してしまいますが。

かれこれ30年前の C++

私が大阪で大学生をやっていた頃なのでかれこれ30年前のことです。マンデルブローを描きたかった頃(確かCマガジンで特集をやっていたような気が)に N88 BASIC で組むと遅いから C 言語で組むんだということで、日本橋に行って買いました。店頭で「Turbo C++ を下さい」というと、冒頭のように「X1 Turbo」を出されたのは良い思い出ですが、きちんと Turbo C++ も出てきました。確か、2,3万円で買えたと思います。当時、MS-C が高値の華で8万円ぐらいした頃なので以上に「安かた」んですね。LSI-C 試食版があったような時期なんですが、実行サイズに制限があったので買うしかなかったという感じです。いや、正確に言えば、Unix が出てきて、Minix が動いたか動かなかったかで、Linux が出たか出なかったの頃なので gcc はあったような気がします。実際、2年後ぐらいには、研究室で DOS/V 機に Linux を入れてワークステーションにログインさせていました。

当時、貴重な1台しかもっていない PC98 RX に DR-DOS(MS-DOS の互換OSですね)を入れて、ぽちぽちとプログラミングしたり大戦略したりしていました。そうそう、大戦略していた頃の神戸大震災に遭ったのでした。たまたま、午前5頃までゲームともプログラミングともつかない生活をしていたので地震があった当時に起きていたのですが(机が50cmほどずれました)、寝ていたら本棚の下敷きになっていたと思います(まあ下敷きになる程度で死ななかったとは思いますが)。

そんな頃の C++ なのですが、この Turbo C++ はきちんと「統合開発環境」になっています。そうそう、当時「emacs は環境である」というセリフが流行ったのです。emacs の中でプログラミングもできるし、メールも打てるし、シェルも動かせるというやつですね。それと同じように、Turbo C++ には付属のエディタがついてて、この中でコードを書いたりコンパイル&実行をしたりすることができます。上の画面キャプチャを見るとわかるんですが、コードに色がついています。今の IDE のように候補がでることはありませんでしたが、キーワードには色がつきました。あと、テキストベースのウインドウを重ねることで、複数のソースコードを開くことができました。

当時の Macintosh にはマウスが必須でしたが、MS-DOS(DR-DOS)の時代には、まだマウスはついていませんでした。ついていませんでしたが買って、マウスドライバーを乗せることでテキストベースではありますがマウスカーソルを動かすことができました。

ノスタルジー以上のもの

昔はこうだった…の本が流行っているようですが、感傷(ノスタルジー)以上のものではないので、もう少し前向きな話をしましょう。

見て分かる通り、Turbo C++ の環境には上部にメニューがあります。メニューの位置がウィンドウに張り付いたり、Mac のように上に張り付いたりしますが「メニュー」があるという点では同じです。当時、Windows 3.1 が出た頃に MDI/SDI という概念があってダイナミックメニュー(メニュー自体が切り替わる)という方式が生まれましたね。その頃から DocView パターンがあったし、GoF の原著をみれば MVC パターン自体が相当古いところからある概念だということがわかります。それはともかくとして、

  • 上部にメニューがある。
  • メニューが階層化されている。
  • モーダルダイアログがでる。
  • ウィンドウがあって、前面と背面がある。

のような基本的なところは今の Windows でも変わっていません。当然、Visual Studio もその形を踏襲しています。この画面は Turbo C のものですが全体的にこの傾向は変わりません。Linux の X-Window ですら同じスタイルです。

じゃあ、このスタイルが完全であり将来的にもよいもの≒効率のよいものなのか、というとあまりそうとも言えません。ツールバーがついたり、MS-Office にリボンがついたり、スタートボタンがあったりなかったりする時代を考えれば、常に試行錯誤の段階であることは明白です。Windows が最初に出たころ(Macintosh が世間に浸透した頃かもしれません)に、科学的なユーザーインターフェースの指針としてマウスの動きとか、目の動きとかを使って「有利である根拠」を示したものもありました。当時、私もそういうものに気を使っていた時期もあるのですが、今考えれば「対案が出ていない」時点であまり科学的とも言えなかったのでは?と感じています。そう、比較対象がないんですよね。

Squeak のメニューの出し方は独特で、カーソルの周りにメニューアイコンが出ていた…ような気がするんですが、別の言語でしたかね?今だと、ふつうのコンテキストメニューが出てきます。まあ、そこは他のOSとの操作感の兼ね合いでもあり、淘汰でもあるのですが、現在のメニューシステムはキーボードとマウスを中心にして作られているので、スマートフォンやタブレットのように指先を使うとか別の入力デバイスを使うときには別の方法があるはずなんですよね。実際、スマートフォンのスクロールはマウスを使ったスクロール方法とは違うし、指を2本使ったピンチのような拡大縮小はマウスではできない方法です。そういう、新しい入力デバイス(タッチパネル≒指)が出てきたときに初めて、Turbo C++ の開発環境のようなメニューやウィンドウの表現との「決別」ができるのではないかな、と思っていますし期待しています。

じゃあ、VR のように仮想空間でこねこねしながらプログラミングするのがよいのかとか、仮想キーボードを使って仮想ターミナルを開くのがよいのかという模索もありますが(実際、あれは面白いし、なんかそっちの方向に行きそうな気もしています。空中に浮かんでいる複数画面の映像はあの VR 空間で実現できますよね)。

Scratch をはじめとするブロックプログラミング環境にしても、条件分岐の書き方とか非同期動作の書き方とか(実は Scratch はイベントを非同期で発生させられる可能性をもっています。今も非同期で動いている?)まだまだ書き方はたくさんあります。特に if 文が一次元(コードを書く方向≒文章を書く方向)であらわされていますが、多数に分岐させて2次元に遷移図として展開させることは可能ですよね。Unity のスクリプトがそんな感じです。

MDA(モデル ドリブン アーキテクチャ)を再開するならば(私は再開してもよいと思います)、ブロックの内部実装(低レベルの詳細実装≒戦術)と、ブロックを組みあわせる問題解決の層(高レベルの実装≒戦略)とは分けて考えてもいいのではないでしょうか。実際、Azure の機械学習はそれに近い感じになっています。そういうところを考え合わせると、マウス以外の入力デバイス(タッチパネル,VR 空間、その他のアナログな入力デバイス)も併せて、もう少し「過去とは断絶した」開発環境ができるのではないかな、と思ったりしますし、それを作りたいなと。

カテゴリー: 雑談 | 往年の Turbo C++ を触ってみよう はコメントを受け付けていません

ViewModel をテスト可能にするためにファイルストリームを活用するパターンを考察

一般的に(?)MVVM パターンを使うと xUnit が作りやすい。主に Model やロジックに対して xUnit を適用すると TDD 的にあとあと楽なのですが、もう一歩進んで ViewModel にも xUnit を適用してみましょう、という話の続きです。
まぁ、普通にオブジェクト指向のクラスを作っている中で、ある程度隠蔽化されていれば xUnit を使うのもそう難しくはないんですけどね。ただ、実務的にやってみると GoF の組み合わせパターンを使ったときに xUnit の適用どころが難しかったり、最初の簡単なロジックは xUnit を使っていたけど、だんだん拡張していくうちに xUnit が使えなくなってしまったという場合もよくあります。そうそう。プロジェクトが進む中で結合テストをしていて、あまりにも設定がややこしくなってしまった xUnit のコードはばっさり捨ててしまっても構いません。本来ならば、xUnit がきちんと動く中でクラスを拡張するのがベストなのですが、時間的な制約や他社的な制約などがあってなかなか理想通りにはいきません。ならば、ある程度、xUnit で品質が保たれているであろう基本的なクラスであると「信じて」、複雑怪奇になってメンテできなくなってしまった(主に設定関係で動かなくなってしまった)テストクラスを捨ててしまうのも作業的な効率化です。あえて言えば、そのときにいくつか正しく動くパターンを残しておくのがベターです。チェックしておきたい基本的なテストコードだけ残して、あとはばっさりとコメントアウトしてしまいます。

ファイルを扱うときの ViewModel は?

MVVM パターンを使うときには、View と Model との分離が目的であり、ロジックを View に置いたり ViewModel に置いたりしてコード量を調節します。でもって、Model は単なる POJO なデータクラスであったり、Entitiy Framework のようにデータベースに接続したりする訳ですが、永続的なストレージとしては「ファイル」もあたったりします。ファイルアクセスは設定を保存したり画像ファイルを読み込んだりします。時には XML をアクセスすることもありますが、これはデータベースと同じように扱ってもよいでしょう。どちらにせよ、何らかの形で「データ」が、Model と ViewModel の間でやり取りをすることになります。

このとき、ファイルオープンをする機能は ViewModel にあったほうがいいのか否か、ということを ViewModel に xUnit を適用するという観点から考察してみます。と言いますか、すでに考察した後なので、結論から言うと、ViewModel に xUnit を適用するためには「オープン済みのファイルストリーム」を使うのが良いようです。

OpenCCPM を作っていく中で、各タスクをファイルに保存して復元するという機能を実装してみました。データ自体は XML でシリアライズすればよいので、非常に簡単です。プロトタイプは WPF で作っているので一発で保存/復元ができるので便利ですよね。と思っていたのです。が、これを Xamarin.Forms に移植しようとしたときに考え込んでしまいました。そもそものファイルの保存先は、iOS/Android で異なるし、Surface で使えるようにするため UWP アプリにするときは Storage を使わないといけません。ってことは、ファイルアクセス自体は、実行環境依存になるのです。WPF の場合は System.IO でファイルオープンができるけど、UWP は Storage を通さないと駄目というアレですね。となると、環境依存部分を含んだまま ViewModel を作ると xUnit が結構面倒なことになります。そう環境ごとに異なった xUnit を用意しないといけないからです。

実は、データベースを扱う EF のときにも同じことが言えて、WPF 等を使って SQL Server を扱うときは EF として統一して使えるのですが、ASP.NET Core を使って .NET Core 上で作ろうとすると途端におかしなことになります。.NET Core でも SQL Server を使えば EF が作れますが、じゃあ MySQL の場合はどうなのか、SQLite の場合は?そもそも、独自の軽いDBを作ったときにはどうなのか、という問題が残ります。

となれば、ViewModel や Model から実行環境依存な部分を取り除いてしまうのがベターですよね。特にファイルオープンやクローズやファイル検索などの環境依存なところを ViewModel から取り除いてしまったほうが、統一的な xUnit が作れそうです。

System.IO.Stream を使って環境依存部分を外へ追いやる

一例を示します。ViewModel が Model を抱えるようにして View にアクセスするパターンです。Model 用のデータが二重化してしまっているのが面倒な感じなのですが、永続化するときに Model を一気にシリアライズ化できるのでこれはこれで便利なのです。

public class TaskCanvasViewModel : BindableBase
{
    CcpmModel _model;
    public TaskCanvasViewModel(CcpmModel model)
    {
        _model = model;
    }

    public ObservableCollection<CcpmTask> Items
    {
        get { return _model.Tasks; }
    }

    TaskViewModel _cur;

    public TaskViewModel Current
    {
        get { return _cur; }
        set { this.SetProperty(ref _cur, value); }
    }

~省略~

    public bool Save(System.IO.Stream st)
    {
        return _model.Save(st);
    }
    public bool Load(System.IO.Stream st)
    {
        _model.Load(st);
        return true;
    }
}

永続化のメソッド(Save/Load)は、ファイルそのものを扱うのではなくてストリームを扱います。.NET Framework の場合は、System.IO.Stream がストリームの基底クラスになっています。Java とか他の言語でも同じパターンが使えます。
ストリームはオープン済みなので、ファイルがないとか権限でアクセスできないとかのエラーはありません。また、ファイルストリームだけではなくメモリストリームや文字列のストリームも使えるので汎用性が高いのです。

Model クラスではシリアライズ機能を使ってストリームに対して読み書きをします。このあたりは、WPF だけではなくて、Xamarin.iOS/Android でも共有できるところです。

public class CcpmModel
{
    private CcpmTaskCollection _tasks = new CcpmTaskCollection();

    public CcpmTaskCollection Tasks
    {
        get { return _tasks; }
    }

    // *************************************************
    // 永続化機能
    // *************************************************
    /// <summary>
    /// XML形式で保存する
    /// </summary>
    /// <returns></returns>
    public bool Save(Stream st)
    {
        // 先頭に戻す
        st.SetLength(0);
        // カレントフォルダに保存
        var se = new System.Xml.Serialization.XmlSerializer(typeof(CcpmModel));
        var sw = new System.IO.StreamWriter(st);
        se.Serialize(sw, this);
        return true;
    }
    /// <summary>
    /// XML形式から復元する
    /// </summary>
    /// <returns>読み込んだ CcpmModel オブジェクトを返す</returns>
    public CcpmModel Load(Stream st)
    {
        var se = new System.Xml.Serialization.XmlSerializer(typeof(CcpmModel));
        var sr = new System.IO.StreamReader(st);
        var obj = se.Deserialize(sr) as CcpmModel;
        CopyFrom(obj);
        return this;
    }
    public static CcpmModel LoadXml(Stream st)
    {
        var se = new System.Xml.Serialization.XmlSerializer(typeof(CcpmModel));
        var sr = new System.IO.StreamReader(st);
        var obj = se.Deserialize(sr) as CcpmModel;
        return obj;
    }

    /// <summary>
    /// 自モデルにコピーする
    /// </summary>
    /// <param name=&quot;src&quot;></param>
    /// <returns></returns>
    public CcpmModel CopyFrom(CcpmModel src)
    {
        this.Tasks.Clear();
        src.Tasks.All(x => { this.Tasks.Add(x); return true; });
        return this;
    }

    // *************************************************
    // CURD 機能を実装する
    // *************************************************
~~省略~~
}

こうすると、ViewModel と Model が実行環境に依存しないので、PCL 化ができます。WPF/UWP/Xamarin.iOS/Android/.NET Core の5種類の環境で利用できるようになります。

これは永続化の機能部分をストリームとして抽象化していることで得られる利益です。

ファイルアクセスの環境依存部分は何処に作るのか?

さて、ひとつ大きな問題が残っています。具体的にファイルアクセスをする部分(ファイルオープンをしてストリームを作成する部分)は何処に持っていけばよいでしょうか?ViewModel と Model は PCL 化が目的でもあるので、ここにファイルアクセスのような環境依存部分を持ってくるとはできません。パターン的に、ViewModel, Model に置くことは可能です。その場合は、環境依存のための ViewModel, Model を別途作ることになります。

環境依存用の Model を作ってもよいのですが、ちょっと考えてみましょう。そもそも、View 自体は環境依存ではないでしょうか?WPFのXAMLや、Xamrin.Android の UI や、共通機能としての Xamarin.Forms の XAML などは、それぞれの実行環境に依存しています。ということは、View のほうに持って行っても良いですよね。

ということで、View のコードビハイドに持って行ってしまいます。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
~~略~~
    /// <summary>
    /// タスクカードを保存
    /// </summary>
    /// <param name=&quot;sender&quot;></param>
    /// <param name=&quot;e&quot;></param>
    private void clickSave(object sender, RoutedEventArgs e)
    {
        var st = System.IO.File.OpenWrite(OpenCcpm.Models.CcpmModel.SETTING_FILENAME);
        this.tc.Save(st);
        st.Close();

    }
    /// <summary>
    /// タスクカードを読込
    /// </summary>
    /// <param name=&quot;sender&quot;></param>
    /// <param name=&quot;e&quot;></param>
    private void clickLoad(object sender, RoutedEventArgs e)
    {
        var st = System.IO.File.OpenRead(OpenCcpm.Models.CcpmModel.SETTING_FILENAME);
        this.tc.Load(st);
        st.Close();

    }
}

これは、相当異論があると思うし MVVM パターンなのにコードビハイドを使わないと駄目なのはおかしい、と思うでしょうが、ViewModel を xUnit でテストができるようにするには、この方法がいいんですよね。

ちなみにテストコードはこんな感じになります。

/// <summary>
/// モデルを保存する
/// </summary>
[TestMethod]
public void TestSave()
{
    // 初期化
    var model = new CcpmModel();
    // 2つタスクを追加する
    model.Create(&quot;T001&quot;).Title = &quot;最初のタスク&quot;;
    model.Create(&quot;T002&quot;).Title = &quot;次のタスク&quot;;

    var st = System.IO.File.OpenWrite(CcpmModel.SETTING_FILENAME);
    var ret = model.Save(st);
    st.Close();
    Assert.AreEqual(true, ret);
    Assert.AreEqual(true, System.IO.File.Exists(CcpmModel.SETTING_FILENAME));
}

/// <summary>
/// モデルを読み込む
/// </summary>
[TestMethod]
public void TestLoad()
{
    // 初期化
    var model = new CcpmModel();
    // 2つタスクを追加する
    model.Create(&quot;T001&quot;).Title = &quot;最初のタスク&quot;;
    model.Create(&quot;T002&quot;).Title = &quot;次のタスク&quot;;
    var st = System.IO.File.OpenWrite(CcpmModel.SETTING_FILENAME);
    model.Save(st);
    st.Close();
    // XMLから復元
    st = System.IO.File.OpenRead(CcpmModel.SETTING_FILENAME);
    model.Load(st);
    st.Close();
    Assert.AreEqual(2, model.Tasks.Count);
    Assert.AreEqual(&quot;最初のタスク&quot;, model.Tasks[0].Title);
    Assert.AreEqual(&quot;次のタスク&quot;, model.Tasks[1].Title);
}

実際は、もうちょっと進めてから考えることになりますが(多人数で分担するとか、Viewの規模の問題とか)、いまのところ View に近いところが一番環境依存しているところなので、そこに Save/Load 機能を置いています。

まあ、環境依存のため(設定ファイル絡み)の Model をひとつ用意して、そこへ prototype パターン的にアクセスするのがよりベターかなと思いますが、ひとまず、これで。

カテゴリー: 開発, C#, TDD | ViewModel をテスト可能にするためにファイルストリームを活用するパターンを考察 はコメントを受け付けていません

UWPでファイルのドロップして画像表示させる

UWPでファイルのドロップをしたい – かずきのBlog@hatena
http://blog.okazuki.jp/entry/2016/02/21/162757

を見て、ああ「AllowDropプロパティをTrue」にするだけでよかったんだ、と思って画像の表示まで試してみました。

private void Grid_DragOver(object sender, DragEventArgs e)
{
    e.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.Link;
}

private async void Grid_Drop(object sender, DragEventArgs e)
{
    // ファイルの場合
    if (e.DataView.Contains(StandardDataFormats.StorageItems))
    {
        var items = await e.DataView.GetStorageItemsAsync();
        if ( items.Count > 0 )
        {
            // 画像ファイルを表示する
            var it = items[0];
            var sf = it as Windows.Storage.StorageFile;
            var fs = await sf.OpenReadAsync();
            var bi = new BitmapImage();
            bi.SetSource(fs);
            this.image1.Source = bi;
        }
    }
}

private async void button_Click(object sender, RoutedEventArgs e)
{
    //Storageファイルを取得
    var picker = new FileOpenPicker();
    picker.FileTypeFilter.Add(".png");
    var file = await picker.PickSingleFileAsync();
    var fs = await file.OpenReadAsync();
    var bi = new BitmapImage();
    bi.SetSource(fs);
    this.image1.Source = bi;
}

コツは、ドラッグしたファイルが IStorageItem なので StorageFile にキャストしてしまえば ok です。これでストアアプリの Storage として扱えるので定番処理で BitmapImage に突っ込みます。
と、さっくりと書いているように見えますが、最初は it.Path のようにパスを取ってきてメモリ上に変換してとあれこれやっていたんですよね。結構苦労しましたが、StorageFile にキャストができることが分かって、すっきりした状態になります。
ちなみに、ボタンのほうは試しに FileOpenPicker で開いたものです。

こんな風に UWP アプリにドロップできます。

ピクチャフォルダ以外もアクセスできる

8.1 のストアアプリの場合、パッケージマニフェストで「ピクチャライブラリ」を選択しないと、Windows.Storage.KnownFolders.PicturesLibrary がアクセスできなかったのですが、この方法だとどんなフォルダにもアクセスできます。UWP から PicturesLibrary を参照するときにアクセス制限がかかるんですが、これって意図した動きですよね? 8.1 のときがどうだったか覚えていないのですが、PicturesLibrary を使わない限り、ローカル PC のどのフォルダもアクセスできます。

おそらく、

– ピッカーやドラッグの場合は、ユーザーが「意図」して操作したので、どこでもアクセスできる。
– プログラムが自動で PicturesLibrary 配下を探ろうとするとアクセス制限がかかる。

という思想なのかもしれません。

カテゴリー: 開発 | UWPでファイルのドロップして画像表示させる はコメントを受け付けていません

パタンランゲージとアジャイルの関係を再考する

「パタン・ランゲージによる住宅の生産」の序文に「1. 建築と施工は分離されていてはならない。(アーキテクトビルダー)」とある。何処かで聞いたようなことがあると思う。アジャイルソフトウェア開発宣言 に「プロセスやツールよりも個人と対話を…」とあるのと非常に似ている。

引用として、生産プロセスの基本条件を抜き出すと、

  1. 建築家と施工は分離されてはならない。(アーキテクトビルダー)
  2. 生産システムは、地域の高度に分散化された職人群(拠点)を利用する。(ビルダーズヤード)
  3. 共有地はユーザーによって最も大切な場所であり、彼らの管理下にあるべきである。(共有地の共同設計)
  4. ユーザーは、自分自身の住まいの間取りについて、現代建築のような受け身の姿勢ではなく、核家族によってそれぞれ異なる間取りができるような積極的な姿勢で参加しなければならない。(個々の住宅のレイアウト)
  5. 施工のシステムや技術やディテールは、プロセスそのものが必要とする、連続的な巧妙かつ微妙な修正の利くものを選ばなくてはならない。(一歩一歩の建設)
  6. コストコントロールは、柔軟な設計思考のプロセスに適応しなければならない。(コストコントロール)
  7. 建物の細工は、手づくりの楽しいものではなくてはならない。(プロセスの人間的リズム)

とある。

GoF のパタンは、「パタンランゲージ」の真髄を取りこぼしてしまったのか?

その昔、アジャイル協議会があったころ(確か、2002年頃だったと思う)、MVC, GoF のパターンの説明会の中で、東野高校 の見学発表というのがあった。アレグザンダー建築に則った設計をしているので、アジャイル&パタンランゲージを学習する一環として発表していた方がいたのだが、果たして「パタンランゲージ」からヒントを得て「GoF パターン」を UML に加味して利用するというスタイルだったはずなのだが…真髄を取りこぼしてしまったのかどうかは定かではない。ちなみに、GoF の原著を読み直してみると、「6.3 The Pattern Community」あたりにアレグザンダーのあれとはあれこれが違うのだ、と書いてあるのでひょっとすると取りこぼしてしまっているのかもしれない。

ただし、建築のパタンランゲージから、プログラミングのパターンに移るときに重要だったのは、

  • パターンに名前を付けること。
  • 名前を共有することで、複雑な UML を共有できること。

がある。そこで「パタンランゲージ」の「ランゲージ(言語)」たる部分として、各種のパターンを組み合わせるベストプラクティスを作ることが可能、というのがある。GoF パターン以下、○○パターンというのを共有することができるようにはなったが、パターンの組み合わせで「相互の語る」ことができるようになったかというと疑問である。実は、Java カラー本や、ファウラーの「アナリシスパターン」のように、ある程度もまでは基礎パターンの組み合わせで構築物たるシステムを語ることができようになったとは思えるものの、まあ、浸透はしていない。まだ、データベースやネットワークやCPUやメモリなどの各部品は交差せずにそのままのような気がする。

ただし、建築業界がアレグザンダーの提唱する「パタンランゲージ」に則っているかというとそうでもなく、新国立競技場のごたごたしかり、別なところで変なことになってるし、脱構築ナントか的におかしなことになっている。少なくとも、建築と土建が別々になってしまい「アーキテクトビルダー」は不在である。

かつて「アーキテクト」ブームというものがあった

今思えば「フルスタックエンジニア(苦笑)」と同じぐらい「アーキテクト(苦笑)」という職種ブームがあった。SIer と下請けプログラミング会社のはざまだったか、全体設計をする人という意味で「建築家」に近い位置を想定したものだろうが、責任を負わないので建築家とも異なるし、国家試験があるわけでもない「自称アーキテクト」でしかない。様々なパターンを知っているという点では、一種の物知りではあったかもしれないが、そこには責任がない以上、職種とは呼べない。資格さえもない。最も本物の「建築家」のほうもずいぶん怪しい感じなので、それを真似した「アーキテクト」もかなり怪しい。今となっては、アーキテクチャという分野は存在するが、アーキテクトという人は存在しないような気がする。

というのも、先の「アーキテクトビルダー」に話を戻すと、「建築家と施工は分離されない」ので、いわば「設計」と「コーディング」は分離されない。「アーキテクト」を名乗る(あるいはアーキテクチャを構築する)のであれば、要件定義から全体への設計、そしてコーディングまで一貫するのが必須だろうし、そういう仕事の仕方をせざるを得ない。昨今のゼネコンのように、建築会社と施工会社(SIerと各種孫請け)を分けてしまっては、アーキテクトビルダーは成り立たない。成り立つことすらできない。

ゆえに、かつて「アーキテクト」ブームがあったと断言する。

それはさておき、アジャイルを再考する

一言で「アジャイル」と言っても、かつての「アジャイルソフトウェア開発宣言」から遠く離れてしまったアジャイル開発もあるので、元に戻って考えてみる。住宅を生産する、ということは一過性のプロセス(二度と同じ形では進まない)という点で、ソフトウェア開発と似ている。これは、製造業が主に「プロダクト」として同じ製品を効率よく作成することを目的としているのに対して、「プロジェクト」として同じ過程にはならないことを意味している。例えば、同じ IT 業界の中であっても、サーバーのセッティングやルーターの設定のようなものは限りなく「プロダクト」に近い。部品を使い同じレベルのものを大量に作るからだ。逆に何らかの業務アプリケーションを作る場合には「プロジェクト」になる。それぞれの会社では業務プロセスが異なるので、それぞれにカスタマイズされた「プロジェクト」が必要になる。当然、混在するパターンも多く、Wordpress でホームページを作るパターンは「プロダクト」に近いし、SAP などの製品を取り込むパターンも「プロダクト」に近い。また、研究開発は「プロジェクト」と言えるかもしれないが、終わり≒納期が判然としない場合が多い(とはいえ、永遠にやっている研究者はいないが)ので「プロジェクト」でも違ったスタイルになる。

プロジェクトというものは PMBOK で定義されているように、

  • とある予算(人員)のなかでやりくりをする。
  • 同じ生産プロセスにはならない。
  • 期限や納期が存在する。

ことがプロジェクトであり、これを統率するのが「プロジェクトマネージメント」になる。予算や人員は無限ではないし、納期が必ず存在する。そして経済的な側面から効率化を求められる。そういう点で「住宅を建てる」ことに似ている。特に、納期があることとコストマネージメントが必須になる(新国立にコストマネージメントが存在するかどうかは怪しい)。

ここで、セル生産のように分業式ではあるものの作り手の創造性が効率化に寄与する。かつ、住宅においては住む人自身が利用者であり、利用する期間が非常に長いゆえに下手を打つと快適さは長期に損なわれる。ソフトウェア開発の場合には、利用する期間が短期と長期にわかれる。ゲームや一過性のインターネットサービスのようなものは、リリースまでの短期性が重視されることがおおく(最近では、短期すぎるゆえに失敗するパターンも多いのだが)おもに利用期間は「短期」になる。ゆえに、それゆえにとある失敗を長く引きずらずに済むという利点もある(ただし、その失敗は短期的な収入に大きな影響を与えるかもしれない)。もう一つ、業務システムのように会社が続く限り長く使われる長期的なシステムもある。銀行のシステムや工場のFAもそうなのだが、十数年単位で成果物が使われる。

ソフトウェアは、バージョンアップすることによって後からの機能が追加することができるが、住宅においても有機的に住居を追加することも可能である。それは住宅地の進化なのかもしれない。最初に区画整理された計画に沿うだけではなく、ある程度の計画から想定しえない方向に進んでいくこともしばしばである。それは経済的な側面が多いだろうし、今からだと少子化とか過疎地化とかがある。それらを踏まえたうえで、完全な計画をせずに、順応させる。

住宅において、住んでいる家族の構成は年月とともに変わる。子が育ち家を出るかもしれないし、子が増えるかもしれない。それらは、硬直化された建築システムに縛られるのではなく、緩やかに変化できる「可能性」を残しておく必要がある。同じように、長期に利用する業務システムの場合にも、ある程度の変化を許容する「可能性」を残さねばならない。これらは、ソフトウェア開発から最初の納品(リリース)までではなく、その先にもある。昨今「継続的な」というスタイルで言及されることが多いが、これらの「リリース前」と「リリース後」は同列に扱う必要がある。逆に言えば、リリース後だけを重視してもダメだし、リリース前だけを重視してもダメだ。

そこには、建築家&施工と住宅(とそれに住んでいる人)と関係が続くことが分かっている。渋谷の拙い地下道のように造りっぱなしなのではなく、乗客は日々渋谷の地下と地上を行き来する。その往来の増減によっても、ある程度の「変化の許容」が必要になる。それは決して未来を見通すことはできないからだ。未来を見通すことはできないからこそ、ある程度の変化が許容できる状態を維持し、維持するために利用者と開発者との長期的な連携を維持する。ひょっとすると、本格的に維持するためには人の寿命は短いかもしれないが、創業100年と続く菓子屋のように、とある意思を次いでいくことは可能かもしれない。

そんな意思を継いでいくところで、「パタンランゲージ」があり「GoF パターン」があり「アジャイル開発技法」があるのではないかな、と思ったりするのだ、どうだろう。ちょっと、その道筋で肯定的に GoF のパターンをいくつか考え直してみたい。

[amazonjs asin=”4306052613″ locale=”JP” title=”パタン・ランゲージによる住宅の生産 (SD選書)”]

カテゴリー: プロジェクト管理 | パタンランゲージとアジャイルの関係を再考する はコメントを受け付けていません

後置型プログラム言語と記号論と生成文法の思考実験

ふと、ノーム・チョムスキーの生成文法とウンベルト・エーコの記号論を思い出したので、後置型プログラム言語を再考してみる。

たいていのプログラム言語は前置定義型だ

「全ての」と書きたいところなのだが、C# の拡張メソッドや Ruby の後付けメソッド、Javascript のオブジェクトへのメソッドの追加を考えると、後置型とも言えなくもないので「たいていの」にしておく。要は、あらかじめ定義したものを使う、というスタイルでプログラムコードを書いていくのが「前置定義型」だ。

class class A {
public:
  void method() { ... }
};
void main() {
 A a ;
 a.method();
}

な感じでクラスやメソッドを定義する。

記述場所は、main 関数の後からもしれないし、別ファイルかもしれない。ただし「A」として使う時点で、A クラスは定義してあるという前提になる。これは一見、当たり前のように見えるけど、あらかじめ定義されているクラス A がアプリオリであることが前提になる。コードとして記述する、あるいはプログラムが実行される時点で、A から生成される a は、何も A に既定されなければいけない、という法はない。法を作った上で、A を使って a を生成しているというルール的な意味になる。

ただし、コンパイラや補完機能の絡みからすれば、これは便利だ。A から a を生成した時点で、a の型は既定されているので、method というメソッドを持っていることが分かる。あるいは、別のクラス B を使って b を生成したときに、a != b が明確になる。事前に決まっているからこそ曖昧さがなくなり、型推論が可能だし厳密さを保ったところでコードを書けるというメリットを享受できる。

となれば、仮定として「プログラムコードとしての安全性を取り払ったどうなるのか?」という疑問を呈してみよう。厳密に動かすためのプログラムなのに、厳密さを取り除くという考え自体が矛盾しているような感じがするか、思考実験としては妥当だろう。

自然言語的に定義を補完する

例えば、A x としたときに、x の型は決まらないし、A というクラスの内容は定義しない。ただ、A というクラスができて、x というモノ(オブジェクト)ができるという意味だけを取り出してみる。

x is a A;

ってことだ。いわゆるオブジェクト指向の is a だから、A というクラスあるいはカテゴリというものがあることが分かる。かつ。A であるものと A でないものを分離するという役割を担う。しかし、ただそれだけの意味しか持たない。

これをいきなり、A というクラスは func というメソッドを持つということを考えてみよう。その方法は2つ考えられる。

  1. class A { func() { … } };
  2. x.func( … );

ひとつは、1 のようにクラス定義をして func メソッドがあることを知らせる。x は A クラスなので、x が A クラスであるという三段論法から x は func というメソッドを持つことが分かる。これは普通のプログラミングのスタイルだ。

もうひとつ、2 のようにいきなり、func というメソッドを使う方法がある。通常は A クラスは定義されていないのだから、func というメソッドを持つかどうかわからないのだが、いやいや、それ狭いコードの範囲しかみていなくて、コード制作者(コード自身の外の世界)の意図としては、すでに A には func というメソッドがあることを知っているので、コードだけの世界にいきなり func を持ってきても不思議ではない、というスタイルだ。つまりは、コードの外部にあるコード制作者が常に正しとしてコードを書くというスタイルをとる。

しかし、実行時には、func というメソッドがコードという世界で定義されていたら動きようがないので、それは「何事もなく動く」のでもよいし「実行時例外を発生する」方法でもよい。コードの厳密性を探るのであれば「実行時例外」が正しいように見えるが、コード制作者が常に正しいという視点に立ては「何事もなく動」いてもいいような気がする。ただし、コードを実行する世界では、func メソッドの動作は定義されていないので、「何事もなく動く」ということはイコール「何も動かない」ということに等しい。この何も動かないということは例外さえも動かないということだ。

A a ;
a.func();

そう、後置定義型を許せば、上の2行はそのまま動く≒何も動かない、ということになる。

コード外のアプリオリを追加する

もう少し具体的に考えみよう。なんとく変数 a に名前をつけておいて、プリントアウトすることを考える。

A a("masuda");
a.print();

これだけで十分だ。プリントアウトするという意味っぽい print というメソッドを使うだけ、名前を付けるという意味で “masuda” を引数として定義するだけで完成する。本当のとこは、名前付けがコンストラクタの指定なのか、(あるかもしれない)Name プロパティへの指定なのかはどうでもいいことだ。コードを書いた人は、コードの世界よりもすべてを知っているので、コードが動作する枠を超えていても構わない。プリントアウトするという print メソッドは習慣的にプリントアウトするという動作を定義するだけで、それが画面なのか紙なのか3Dディスプレイなのか、それとも他のプロセスへの通知をプリントアウトするのかはわからない。脳内にプリントアウトしたってかまわないはずだ。それらの動きを既定するのはコードの世界なので、それはコード内の世界の「アプリオリな」ライブラリに寄るという答えになる。

ここで、コードを書く人とコードを動かす人(実行環境)とのずれが発生する。一般的なコミュニケーションの伝達の問題であって、プログラムコードではそれらを「厳密さ」で補おうとするけど、人とのコミュニケーションであればそれらの厳密さあまりあてにならない。文化の違いもあれば育ちもあれば宗教的な違いや政治的な違いがある。勿論、学問としてひとつのルール(閉鎖的なルール)で議論することも可能なのだが、日常生活においてはあまり厳密に伝えることは少ない。例えば、居酒屋にて「とりあえずビール」と言ったときに、ビンなのか生なのかピッチャーなのかは問わない場合もあれば問う場合もあれば、盆に注がれたりどんぶりだったり氷入りだったりコーラを一緒に持って来たりといパターンも考えられるけど、まあ大体において「とりあえずビール」で通じることが多い。常連であればなおさらだ。

ならば、コード制作者がコードに対して、いちいち厳密に説明することはすくなくて「とりあえずビール」感覚で「とりあえずプリントアウト」でもいいですよね、って感覚でコードを書くこともできるのではないだろうか。実際、Outlook でメールを印刷しようとすると「とりあえずメモ形式で印刷しますよ」みたいな感じになる。

じゃあ、プリントアウトする用紙を A4横にしたいときは、こんな感じで補完する。

A a("masuda");
a.print()
print() is A4横.

いきなり自然文法になってしまうが、 こんな感じで後付け書く。「プリントアウトしておいて、ええと、A4横でね」みたいな感覚だ。英語文法/文章法でいうところの、結論を先に書いて後から詳細を足す感覚で書けばいい。普段は「A4縦」で印刷するのだから、普通のデフォルトは print だけでいいのだが、ちょっと変わったことをしたいときは後から追加する。

A a("masuda");
a.paper = "A4横"
a.print()

普通のプログラム言語であれば、こんな風に print の前に書く。なぜかというと、print する時点でプリントアウト自体が実行されてしまうので、後から「ちょっと待った」ができないからだ。 インタープリタだったら、逐一実行するためにこう書かないと駄目なのだ。あらかじめ「これは A4横 で印刷するんだぞ」と初心者的にオーダーするわけだ。だが、コンパイラ言語であって、コードを解析するときとコードを実行するときでは時間的なずれがあるのだから、ほどよく プリントアウトに対する設定変更が終わったころにおもむろにプリントアウトを実行する熟練者がいても不思議ではないはずだ。

また、print 自体の動作も、印刷する先は実行時に決まってもよい。実際、コードを動かして Windows で動かすのか、Linux で動かすのか、何かの組み込みデバイスで動かすのか(小さな液晶に出すのか)という違いが出てくる。それでも、print というコード制作者の意図が達成されれば、それでよいし、逆に実行する環境で print という実行メソッドがなければ「何もしない」ことを実行すればよい。そのあたりの、コード外の実行環境は、コード外のアプリオリとして存在するのであって、コード制作者は未来のコード実行環境を想像しながら作るしかない。逆に、想像するしかないから大ざっぱにプリントアウトするという動作だけ決めてしまう。

記号論と生成文法を加味する

厳密に生成文法を使うかどうかは別として、記号論/現象論的な、シニフィエ/シニフィアンの問題を取り扱ってみる。実際の print の動作は、実行環境のアプリオリなライブラリ(ひらたく言えば既存のライブラリ)により実行されるが、先のコードに、コード制作者の意図を加えてもよいだろう。

A a("masuda");
a.print()

print() is "A4横"
print() {
	name <- name.upper()
}

こんな風に、プリントアウトするときに name プロパティを大文字にすることを考えてみよう。print メソッドの中身は print メソッドを使う時点ではなく、実行時に決まるので、コードの記述上 print メソッドの中身はいつでも変えられる。この場合は、”masuda” が指定されたら “MASUDA” のように大文字に変換すること示している(当然、upper 自体が「大文字にする」という動作がになっていれば、という限定がある)。

つまり、print というメソッドは、記号としての意味しかなくて、それはコード制作時と実行時の意味をつなげるという意味しか持たない。解釈する順序は、現実的な時間制約として、

  1. アプリオリな print メソッドが存在する
  2. コード制作者が print メソッドを使う
  3. 場合によっては、コード制作者が print メソッドを補足する
  4. 実行時に print メソッドが実行される。

の順序しかない。場合によっては、1 のアプリオリな print メソッドのライブラリがない場合もある。コード制作者の頭にしかない print メソッドを、なんとなくコード制作者が 3 で補足して、コードを実行する段階において(コード制作者とは異なる) print メソッドが実行される。コード制作者の「print」と、コード実行時の「print」とは確実に異なる。異なるので「同じ動作をする」という保証はない。保証はないが「だいたい同じ動作をする」という現実的な解を持つという訳だ。

このコードには「厳密さ」はないし、厳密に書くことは不可能だ。コード制作者は、あくまで過去においてコードを制作するので、未来において実行される実行コードを制御はできない。大体、想像して作るだけだし、そこにはとある「約束」や「ルール」があるだけだ。

そういう緩い結合で「後置型プログラム言語」を実装できないかな、と思考実験してみる。文法的に英語の自然言語っぽい形で書ければ(しかし、決して自然言語ではない)なんとなく動くというスタイル。

カテゴリー: 雑談 | 後置型プログラム言語と記号論と生成文法の思考実験 はコメントを受け付けていません

ASP.NET MVC 6 でデータベースに接続(データベースファースト編)

前回の続きで、今度はデータベースから構築するパターン。基本的なところは、ASP.NET5 MVC6 Entity Framework 7 を使って Database First する と同じで、あらかじめ SQL Server で作ったテーブルをもとに ASP.NET MVC の Model クラスを作る。

ASP.NET MVC 6 の Web Application テンプレートを使う

こちらも、Web Application のテンプレートを使う。無駄なページができるのは仕方がないのだが、project.json などの設定がそのまま使えるので活用する。

SSMS(SQL Server Mangement Studio)でテーブルを作成する

ここではローカルPCに SQL Server を入れて testdb に「Movie」というテーブルを作っている。前回のとテーブル名を合わせると比較しやすい、ってのとどうやらテーブルに主キーとIDENTITYが設定していないと Model クラスの作成に失敗するので、元の Movie クラスから引っこ抜いている。

テーブル作成時にスクリプトはこんな感じ。

USE [testdb]
GO

/****** Object:  Table [dbo].[Movie]    Script Date: 2016/02/04 0:31:47 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Movie](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[Genre] [nvarchar](max) NULL,
	[Price] [decimal](18, 2) NOT NULL,
	[ReleaseDate] [datetime2](7) NOT NULL,
	[Title] [nvarchar](max) NULL,
 CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

ちなみに、最近の SSMSは後から列名の変更をしたり、IDENTITYの設定をし直したりできない。昔はできたような気がするのだが、最近の SSMSを使うとエラーになる。SQL Server のスクリプトで直接「alter table …」を使うと変更ができるので SQL Server 側の制限ではないらしい。MySQL の Workbench では自由にできるのでかなり残念。

…と思い続けていたのだけど、SSMSのオプションで [デザイナー] 部の [テーブルの再作成を必要とする変更を保存できないようにする] とできるようになる。これはハッピー。

project.json に EntityFramework.MicrosoftSqlServer.Design を追加する

SQL Server から Model クラスを作るときは「EntityFramework.MicrosoftSqlServer.Design」が必要なので、NuGet から取得しておく。
取得しないまま、「dnx ef …」をすると、きちんとエラーを返してくれるので、それに従ってもよい。

Unable to find design-time provider assembly. Please install the EntityFramework.MicrosoftSqlServer.Design NuGet package and ensure that the package is referenced by the project.

dnx ef で Model クラスを作る

ちょっとややこしいけど、次のように書くと Models フォルダに対象データベース内にあるテーブルの EF を作ってくれる。

dnx ef dbcontext scaffold "Server=.;Database=testdb;Trusted_Connection=True" EntityFramework.MicrosoftSqlServer --outputDir Models

Azure とかにつなぐ場合は(たぶん)接続文字列を変えればよい。出力先は、–outputDir で指定して今回は Models フォルダ内にしてある。

これを動かすと、Visual Studio のほうに EF クラスと接続のための testdbContext クラスを作ってくれる。接続用のクラスは、「データベース名」+「Context」になるようだ。

スキャフォールディングで、Controller と View を作る

Model クラスができたので Controller と View を自動生成させる。
「追加」→「コントローラー」を選択して、「Entity Framework を使用したビューがある~」のほうを選ぶ。

モデルクラスで「Movie」を選んで、データコンテキストクラスでは「testdbContext」のほうを選ぶ。

ちなみに、testdbContext クラスは、元のテンプレートにある ApplicationDbContext と同等の機能を持つデータコンテキストクラス。接続先のデータベースがハードコーディングされているので、デフォルトでここに直結という感じになっている。きちんと手を加えれば、ApplicationDbContext と同じように applications.json から読み込めるようにできるだろう。

public partial class testdbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        options.UseSqlServer(@&quot;Server=.;Database=testdb;Trusted_Connection=True&quot;);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Movie>(entity =>
        {
            entity.Property(e => e.Price).HasColumnType(&quot;decimal&quot;);
        });

        modelBuilder.Entity<person>(entity =>
        {
            entity.Property(e => e.name)
                .IsRequired()
                .HasMaxLength(50)
                .HasColumnType(&quot;varbinary&quot;);
        });
    }

    public virtual DbSet<Movie> Movie { get; set; }
}

データベース接続のために Setup.cs を書き換える

データベースコンテキストを使って接続するので、Setup.cs に AddDbContext なところを書き加える。

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddEntityFramework()
        .AddSqlServer()
        .AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration[&quot;Data:DefaultConnection:ConnectionString&quot;]));

	// ここを追加する
    services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<testdbContext>();

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc();

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
}

実行してみる

動かしてみた結果がこれ。コードファーストのときと同じように CRUD を動かすことができる。

SSMS を使って select してデータ確認もできる。

カテゴリー: ASP.NET | 2件のコメント

ASP.NET MVC 6 でデータベースに接続(コードファースト編)

コードファースト自体は結構前に話題になったハズなのですが、ASP.NET MVC 6 でデータベースに接続する場合にはなんだかよくわからなかったので再調査。いやいや、データベースから POCO を作ることはあまり重要ではなくて、ASP.NET MVC 6 自体なんだけど…まあ、EF(Entity Framework)が扱えたほうがいいので、ちょっときちんと手順を追ってみる。

チュートリアル的にはいろいろあって、

を使って手早く済ますのもよいし、Getting started with ASP.NET MVC 6 ? ASP.NET MVC documentation にチュートリアルがあるので、それに沿って進めてみる。急がば廻れというスタイルです。github のほうは、ちまちま作っている途中らしいので抜けもあるけど、Building your first MVC 6 application からの一連の操作はひと通りできているようです。英語だけど、画面キャプチャが貼ってあるので分かりやすいはずです。

本来やりたいことは

本来やりたいことは、テンプレートを使わないシンプルな ASP.NET MVC を作りたいのだけど、実はなにやら設定がややこしい。一度、Empty のテンプレートから作ってみたもののうまく DB に接続できなかったので、これは後で調べてみる。ポイントとしては、

  • project.json に必要な dependencies を追加する。
  • ApplicationDbContext クラスを用意する。
  • POJO な Model クラスから dnx ef を使ってデータベースを作成する。

するらしい。後で手順を追いなおしてみる。

ASP.NET MVC 6 の Web Application テンプレートを使う

project.json の設定と ApplicationDbContext クラスがややこしいので、Getting started with ASP.NET MVC 6 に従って、テンプレートをそのまま使う。

image

あれこれ無駄なページができるのだけど仕方がない。最終的には Empty から作れるようにする。

image

POJO な Model クラスを作る

Adding a controllerAdding a view はチュートリアル的に流せば ok。ここで必要なのは、Adding a model になる。

手順通り Models/Movie クラスを作る。このあとスキャフォールディングを使って、Movie クラスに対応するコントローラとビューを自動作成する。

「追加」→「コントローラ」を選択して「Entity Frameworkを利用したビューがある…」を選択する。

image

対象となるモデルクラス(Movieクラス)を選択して、データコンテキストでは「ApplicationDbContext」を選ぶ

image

ApplicationDbContext はローカルPCにデータベースを作る方式で、もともと ASP.NET MVC 6 の Web Application に入っているものでユーザー認証とかに使っている。だから、自前で Empty プロジェクトから作るときは、ApplicationDbContext クラスと ApplicationDbContext クラスあたりを自前で作る必要がある(と思う)。

データベースの設定自体は、Startup.cs の ConfigureServices メソッド内に書かれていて、

// Add framework services.
services.AddEntityFramework()
    .AddSqlServer()
    .AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration[&quot;Data:DefaultConnection:ConnectionString&quot;]));

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

なところで DI 化されている。配布を考えると project.json にあったほうがいいのだが、試験的に使うのであれば直書きしてもいいと思う。

dnx コマンドで Entity Framework を作る

EF を使ったほうが LINQ が使えるようになる(そのためにわざわざコードファーストしている)ので、EF に対応させるのだがデザインでやるのではなくコマンドラインから実行する。ここの部分、最終的に DB から各テーブルを読み込んでという形になるのかコマンドラインのままなのかはわからないけども、Linux 上で ASP.NET MVC + EF + MySQL という組み合わせを考えたときにはコマンドラインでできたほうがよい。この手順は Use data migrations to create the database あたりから書いてある。マイグレーション(migrations)というスタイルで、EF クラスと DB のテーブルとを相互に反映させる仕組みになる。あれこれ書いてあるけど、コマンドラインで project.json のあるフォルダを開けばよい。

dnu restore
dnx ef migrations add Initial
dnx ef database update

dnu や dnx と打ったときにコマンドが見つからないと言われたときには、パスなどを設定するために

dnvm upgrade

するのだが、そもそも dnvm 自体がないといわれるときには、c:¥users¥ユーザ名¥.dnx¥bin にある。このあたりの手順は Installing ASP.NET 5 On Windows にある。Mac 版、Linux 版もあるのでインストール時に一度やっておけばいいだろう。

image

dnvm use 1.0.0-rc1-update1 -p を実行していないのは、dnvm upgrade したときのバージョンをそのまま使うからだ。

そんな訳で、うまく DB が作成されるとデバッグ実行ができるようになる。Create New でデータ登録をしてリストを表示させることも可能。

image

ローカルデータベースは何処にあるのか

できあがった ASP.NET MVC のサンプルを動かすとデータが保持されているようなので、どこかにデータベースがあるはずだ。MVC 5 の場合は、App_Data の中にローカルデータベースがあってそれを参照していたのだが、MVC 6 の場合にはそれがない。

何処にあるのだろうかと調べると Setup.cs の

services.AddEntityFramework()
    .AddSqlServer()
    .AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration[&quot;Data:DefaultConnection:ConnectionString&quot;]));

から、設定の Data:DefaultConnection:ConnectionString から接続文字列を読み取っているらしいことが分かる。

そこで applications.json という設定ファイルらしくものを覗くと

"Data": {
  "DefaultConnection": {
    "ConnectionString": "Server=(localdb)mssqllocaldb;Database=aspnet5-CodeFirst2-848a6bc9-9651-4b68-a5db-8b56f15a8be0;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
},

と書いてある。なんか接続文字列っぽくて、スキーマ名が 「mssqllocaldb」になっている。Working with SQL Server LocalDB にも書いてある。試しに SSMS(Sql Server Management Studio)を使って (localdb)mssqllocaldb を開いてみると、うまく接続できた上にそれらしいデータベースができていることが分かる。

image

データベースのプロパティを見れば、保存場所のわかる。

image

どうやら、c:usersmasuda の直下に置かれている。ああ、確かに豪快に Cドライブに置かれていることが分かります。まあ、これだとユーザー領域とか Cドライブを圧迫しちゃうよねという感じなので、これは別途データベース接続文字列を書き換えて元の SQL Server などに移せばよいでしょう。

image

これがコードファーストなので、コードからデータベースを生成する方法。だが、普通は既存のデータベースを使って EF なクラスを作るような CakePHP の Bake のような方法をとると思うので、これも後で試してみる。

ノーム・チョムスキーとコードファーストな余談

ふと Noam Chomsky: Bernie Sanders has the best policies な記事にあたって、チョムスキーが87歳で健在なことを知る。チョムスキーといえば言語学者で人工知能絡みで対話型の形態素解析とかで出てくるんだけど(最近では人工知能というと自動運転とか深層学習とかになっているので「言語」から離れているが)「哲学者」というよりもレッキとした科学者だ。言語の発生から扱い方はウンベルト・エーコの「ウンベルト・エーコの文体練習」を合わせて読むといい。いちだいブームになった「薔薇の名前」や「フーコーの振り子」も読んでもいいかもしれない。「薔薇の名前」がマスコミ的にもブームになったのは、そういう余裕があった時代ではなかったのかなと思ったり。

で、言語学的に言えばプログラミング言語も「言語」のうちだろう。非常に限られた文法しか持たない(最終的には厳密なアセンブリに変換するという束縛があるので)し、限定的な使われ方しかしないから、普通の自然言語とは違った見方がされる。狭いプログラム言語の中で、C# という言語があって、SQLという言語がある。コードファーストってのは、C# のコードの言語を、SQL という言語(正確にはデータベースの世界)に変換することだ。それを「テクスト」と言い直せば、C# が持つテクストと SQL が持つテクストを結び合わせて同じコンテクストで語ろうという話だ。翻訳の世界と同じになる。当然、日本語と英語のように、というよりも日本国内でも東北弁と鹿児島弁の違いのように単純な変換だけでは済まない。片方のテクスト上で語られるものは、片方のテクストの一語としては対応するものがない。しかし、とあるテクストが全体を網羅を持つという前提条件を付ければ、別のテクストはもうひとつのテクストに対して語数の違いはあるかもしれないが正確に変換できることになる。2つのテクストが存在する空間が、完全に重なりあっていないのであれば変換しえないものが出てくる。これがコードファーストとデータベースファーストとO/Rマッピングのインピーダンスミスマッチだったり、それぞれの違和感だったりする。ただし、「完全に一致する」ことを捨て去ってしまい、ある程度の共有領域を多くするという方針にすれば言語同士の変換は比較的楽になる。

このあたり、Scratch をはじめとする教育用言語も同じだよなーと。「教育用」という縛りを設けるのか、プログラミングをする思考に対する完全性を重視するのか(いわゆる道具立て)というところで、そこに「子どもだから」というプログラム言語的な欠損を最初に認めて作ってしまうと、そもそもが「教育」→「プログラミングができる」の達成すら危うくなってしまうのではないかなーと思ったりもする。だら、あくまで「プログラミング的な思考を養う」のほうがよいのかなと。

教育はさておき、現実的なところで言語で伝えることの限界と、その厳密性を突き詰めていくと、修辞法やら過去の習慣やら小学校での教育やらを含めて、相手とのずれとそれを許容する現実がある。それと同時に、許容できない現実もあることを認める…というか許容しなくても良いというのがある。なんというか、自分だけを中心にして世界が廻っているような人が権力を持つと(どういう経緯なのかよく知らんけど)あれこれ変なところに逝ってしまうんだなーと呆れたりする。まあ、現実的に呆れてもどうしようもないところに落ち着く前に、チョムスキーのように「いい加減にしろよ」ぐらいの釘は刺したほうがいいかもね。半藤一利によれば下り坂の30年間だったりするのだから。

カテゴリー: ASP.NET | 2件のコメント