和風ペンタトニックとブルーノートは酷似している

プログラミングするときの手癖もあるのだから、ギターで作曲をするときの手癖があるだろうと感じで、あれこれやっていたらやっと原因が分かったという話です。

和風ペンタ(日本五音階)については下記を見てもらうことにして(’80年代は YMO のテクノブームがあったので、そのあたりから流れたところが真相っぽいですが)、

和風ペンタトニック・スケール(ヨナ抜き)~日本人の深層意識に響く民謡・演歌な音階:のびやかな暮らし
http://bossanovaday.hamazo.tv/e5967160.html

同じく ‘80年代の頃にギターを覚えたときに、何故かブルーノートのスケールを弾いているのに途中で演歌っぽくなるのが不思議でした。

 

image

でもって、改めて開放弦を活用して書き出してみたのがこれ。コードを押さえてじゃがじゃがやらないので、開放弦なんか使わないのだけど、ブルーノートで E コードで弾いたときと、和風ペンタの G コードがほぼ同じなんだな。なので、途中で三連符を打ったときに、ブルーノートから和風ペンタになって、何故かブルースから演歌に移行してダサい感じになってしまうのです。

ジャズとかブルースは普通、G か A で演奏するので(A のほうがフレットが狭くて少し抑えやすい)のと、E はカントリーでよく使われる(開放弦をじゃかじゃかやる)。日本人以外には、和風五音階はなじみがないので、そっちには勝手に動かないけど、日本人には民謡が染みついているから、そっちにスライドしてしまう。1音半ずらせばいいので、あれこれと曲を弾いている間(ベース音がわからない間)は、ブルーノートなのか和風ペンタなのかが区別がつかないわけです。そして、どちらかのベース音が響くと、その瞬間にブルーノートになったり和風ペンタになったりする。

この部分は、実際に音を聴かないとわからないので、またあとで。

服部良一から渡辺岳夫の流れで完成された?

仮説ですが、ジャズやブルースを持ち込んだ服部良一が作った民謡や東京ブギウギを踏まえて、渡辺岳夫が作った「アタック No.1」や「魔女っ子メグちゃん」、「キューティハニー」を通して、その後のアニメ曲が作らてしまったのではないか、と考えています。まあ、最近のアニメの主題歌は JPOP だったりロックだったりするので、そこから外れていますが、いわゆるアニメっぽくない主題歌(ロボット系とかヒーローものは別)の感じはそこから出てきているのかなと。

編曲した後は別なんですが、主旋律を追っていくとギター特有の手癖が出てきます。運指の都合と、弾きやすさの都合から、ああやっぱりこの装飾音が効いてくるってな感じです。このあたり、同時期のアニメ曲と戦前からのジャズ/ブルーノートの流れを追っていこうかなと、主旋律だけを流してみたり。

人工知能的に和風ペンタを眺める

ここで、人工知能的に和風ペンタを眺めてみます。この話は、Electroharmonix フォントが何故、日本人に読めないのかを Tesseract-OCR で紐解く と同じです。Electroharmonix フォントは、カタカナをもとにしたアルファベットフォントなのですが、カタカナを知っている日本人には「カタカナ」に見えてしまって却って読めない。逆に、カタカナを知らない日本人以外にはアルファベットとして読める(と同時に、異国の「カタカナ」という文字にも似ているように思える)という訳です。OCR 学習をさせると、当然ですがカタカナを覚えさせたときには、カタカナにマッチさえつつ Electroharmonix フォントを読もうとするし、カタカナを教えずにアルファベットだけならば、アルファベットとして読もうします。

同じことが、ブルーノートと和風ペンタにも言えて、日本の民謡で育った日本人(育ってないひともいるからw)には、ブルーノートを弾いても、和風ペンタとごっちゃになってしまう。逆にそもそも日本の民謡を知らなければ、単に不思議な音階でしかなくてブルーススケールはブルースケールのままです。

試しに、ブルースの G コードでたらたらとフリージャズっぽくやっている間に、和風ペンタのヨナ抜きを入れると一気に演歌に聞こえてきます(リズム的にそうするのもあるけど)。でも、G のベース音を強調するように音を入れ替えるとブルースになるという不思議…というか、本能的にそうなってしまうところがあります。

で、機械学習で絵画とか文章はあるけど、音楽はちょっと難しいですよね。それらしく聞こえるとか、曲がいいとか悪いとか、そういうのはどういう「評価関数」を作るのか、どうやって「聴く」のかが思い描けないところがあります。Jukedeck – Create unique, royalty-free soundtracks for your videos. というのがあって、ある程度の曲調(コード)と転回だけ合わせておけばイージーリスニングっぽいものが量産できます。おそらく、既存の曲あるいは譜面を入れて、ブルースっぽくするとか演歌っぽくするのも可能かな(スケールとリズムを合わせれば、それっぽく聴こえるので)と思われるのですが、では、そこで「ブルースのように聴こえる」あるいは「和風ペンタのように聴こえる」とはどういうことか?という点が気になりますよね。

和風ペンタとブルーススケールの混在は日本人にしかないのだから、「日本人的な耳」を作って評価関数を作れば「既存のブルースが和風ペンタのように聴こえてダサい」と評価だろうし、「欧米人の耳」を作れば「ブルースだけに聴こえる」という感じになるかもしれません。このあたり、評価関数の取り方≒学習アルゴリズムになるので、将棋ソフトと同じようにソフトとによって戦略が異なる(将棋の場合、勝ち負けが明確なので、トップ以外の評価が難しいのですが)≒人によって指し方が異なる≒好みがある、と言えるでしょう。

ってなところまで考えたのですが、続きはもう少しブルーススケールとカントリーを演奏ってみてから。あと戦後のアニメ曲も。

カテゴリー: 雑談 | 和風ペンタトニックとブルーノートは酷似している はコメントを受け付けていません

Xamarin.Forms を XAML を使って書くために

昨日の続きを少し書き足しておきます。

Visual Studio Community 2015 で Xamarin.Forms を使う | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/7873

Xamarin.Android/iOS を使ってそれぞれのプラットフォームに向けて C# で書けるのはそれはそれで充分です。UI にしても最新機種にあわせる場合は、Java/Swift で書くだろうし、iOS のほうはタイムラグ無しで Xamarin.iOS が出ていたし、Android のほうも数週間ほどで追随してきます。おそらく、Xamarin が Microsoft に買収された今後も同じ方針でしょう。同じ方針だけど、プラットフォーム三社の思惑があるし、そこはどう動くかわからない。ただし、あまり「最新機能」にとらわれず、Android/iOS かつ UWP の3つのプラットフォームに対して同時にリリースすることを考えると Xamarin.Forms が非常に有効に働きます。v1 の場合は、実質 Android/iOS の二機種だったけど、v2 からは UWP が入ったので Android/iOS/Windows の三機種なのでメリットが大きいのです。

サンプルは XAML がコードで書かれている

Cross-Platform で PCL や Shared をすると、UI のサンプルコードも一緒についてきます。単純に画面に “Welcome to Xamarin Forms!” と表示するだけのものです。PCL(移植可能)なプロジェクトの App.cs に入っています。

public App()
{
    // The root page of your application
    MainPage = new ContentPage
    {
        Content = new StackLayout
        {
            VerticalOptions = LayoutOptions.Center,
            Children = {
                new Label {
                    XAlign = TextAlignment.Center,
                    Text = "Welcome to Xamarin Forms!"
                }
            }
        }
    };
}

見慣れたような見慣れないような、スタイルで ContentPage を構築します。WPF などでデザイナを使って XAML を書いたり、Android で AXML を使ったり、Xcode で storyboard を使ったりしていると「え?」な気分になるのですが…まあ、え?ってなります。

最初に断っておきますが、モバイル機種のような小さい画面の場合には、結構 XAML のコードベースで作業をするほうが楽だったりします。PC などの液晶モニタに対して画面が小さい(解像度は同じだったりするけど)ので、操作するボタンとかアイコンを細かく配置するよりも、おおざっぱに位置を自動計算させたほうがうまくいきます。また、Android 機種は画面がまちまちなのでそれに揃えるためにもフローレイアウトみたいな感じで作るといいですよね、って感じです。Web のグリッドシステムと同じ感じで作るほうが手早いし、Xamarin.Forms との相性もよいです。

Forms Xaml Page を追加する

これをXAML形式で書けるようにします。

  1. PCL のプロジェクトに「Forms Xaml Page」を追加します。

PCL プロジェクトに Page1.xaml が追加されます。

  1. Label の Text プロパティを「Welcome to Xamarin Forms!」に書き換える。
<?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?>
<ContentPage xmlns=&quot;http://xamarin.com/schemas/2014/forms&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             x:Class=&quot;App4.Page1&quot;>
  <Label Text=&quot;{Binding MainText}&quot; VerticalOptions=&quot;Center&quot; HorizontalOptions=&quot;Center&quot; />
</ContentPage>

Binding を使って ViewModel を使うようになっていますが、ここでは Text プロパティを直接変更します。変更はちょっとずつやると解りやすいので。

<?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?>
<ContentPage xmlns=&quot;http://xamarin.com/schemas/2014/forms&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             x:Class=&quot;App4.Page1&quot;>
  <Label Text=&quot;Welcome to Xamarin Forms and XAML!&quot; VerticalOptions=&quot;Center&quot; HorizontalOptions=&quot;Center&quot; />
</ContentPage>
  1. App.cs のコンストラクタを書き換える。

追加した XAML が表示されるように App コンストラクタを書き換えます。

public App()
{
    // The root page of your application
    this.MainPage = new Page1();
}

MainPage プロパティに表示したいページクラスを設定すれば ok です。名前が「Page1」になっています。

これをビルドして実行するだけでエミュレータ上での動作が変わります。

試しにボタンのクリックイベントを付けてみる

XAML界隈では嫌われ者のコードビハイドですが、まあ手軽に作るにはこっちのほうが便利です。

XAML を書き換えて、x:Name プロパティにボタンとラベルに名前をつけます。これで、Page1 クラスのプロパティに追加されます。

<?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?>
<ContentPage xmlns=&quot;http://xamarin.com/schemas/2014/forms&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             x:Class=&quot;App4.Page1&quot;>
  <StackLayout>
    <Label x:Name=&quot;text1&quot; Text=&quot;Welcome to Xamarin Forms and XAML!&quot; />
    <Button x:Name=&quot;btn1&quot; Text=&quot;Click Me&quot; />
  </StackLayout>
</ContentPage>

コードビハイドを書く。

public partial class Page1 : ContentPage
{
    public Page1()
    {
        InitializeComponent();
        this.btn1.Clicked += Btn1_Clicked;
    }

    private void Btn1_Clicked(object sender, EventArgs e)
    {
        this.text1.Text = "クリックした";
    }
}

ボタンの Clicked イベントにラムダ式で書いても良いし、イベント用のメソッドを作ってよいでしょう。

実行すると、こんな感じでボタンが効くようになります。

現時点の Hyper-V のエミュレータのほうは、以下のようなエラーが出て2回目以降のコード変更が反映されません。エミュレータ再起動するか、Android 内で対象のアプリをアンインストールするかの対処が必要です。

04-06 11:01:12.659 D/OpenGLRenderer( 2235): Use EGL_SWAP_BEHAVIOR_PRESERVED: true
04-06 11:01:12.661 D/GLHostConnection( 2235): Waiting for host to establish connection for PID 2235 (App4.Droid)
04-06 11:01:12.662 D/GLHostConnection( 2235): HostConnection::get() New Host Connection established 0x9c319f40, tid 2235
04-06 11:01:12.687 D/GLHostConnection( 2235): Waiting for host to establish connection for PID 2235 (App4.Droid)
04-06 11:01:12.711 D/GLHostConnection( 2235): HostConnection::get() New Host Connection established 0x9c6e3050, tid 2260
04-06 11:01:12.713 I/OpenGLRenderer( 2235): Initialized EGL, version 1.4
04-06 11:01:12.719 W/EGL_emulation( 2235): eglSurfaceAttrib not implemented

MVVM化する

このままコードビハイドで書いていっても良いのですが、どうせなので Binding を使って MVVM 化します。Clicked の ICommand はそのままにして、Label のほうだけ。

  1. ViewModel クラスを追加する。

PCL プロジェクトに ViewModel のクラスを追加します。いろいろ引き継いできた BindableBase を継承します。
ラベルに表示する文字列を Text プロパティで連携させます。

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace App4
{
    class MyViewModel : BindableBase
    {
        private string _text;
        public string Text
        {
            get { return _text; }
            set { this.SetProperty(ref this._text, value); }
        }
    }
    public abstract class BindableBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
        {
            if (object.Equals(storage, value)) return false;

            storage = value;
            this.OnPropertyChanged(propertyName);
            return true;
        }
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var eventHandler = this.PropertyChanged;
            if (eventHandler != null)
            {
                eventHandler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
  1. XAML で Binding を使う

Label の Text プロパティを Binding に変えます。

<?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?>
<ContentPage xmlns=&quot;http://xamarin.com/schemas/2014/forms&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             x:Class=&quot;App4.Page1&quot;>
  <StackLayout>
    <Label Text=&quot;{Binding Text}&quot; />
    <Button x:Name=&quot;btn1&quot; Text=&quot;Click Me&quot; />
  </StackLayout>
</ContentPage>

  1. ViewModel を BindingContext に割り当てる

いろいろ XAML+MVVM でどのプロパティが使われているのかが混乱していますが、Xamarin.Forms の場合は BindingContext という名前になっています。

public partial class Page1 : ContentPage
{
    public Page1()
    {
        InitializeComponent();
        this.btn1.Clicked += Btn1_Clicked;
        _vm = new MyViewModel();
        this.BindingContext = _vm;
    }
    MyViewModel _vm;
    private void Btn1_Clicked(object sender, EventArgs e)
    {
        _vm.Text = "MVVM でクリックした";
    }
}

これで無事 MVVM 化ができます。

本家のサンプル

本家のサンプルが github にあるので、ごっそりダウンロードして試してみるとよいです。

GitHub – xamarin/xamarin-forms-samples: Sample apps built using the Xamarin.Forms framework
https://github.com/xamarin/xamarin-forms-samples

これを何処に使うのか?

まあ、一般的な話で言えば Android/iOS のアプリを同時に作れるという話が順当です。が、もうちょっと話を飛躍させると、こんな感じになります。

「FlashAir+Arduino鉄道模型制御-1」 by 綾瀬ヒロ│MakersHub
https://makershub.jp/make/1030

綾瀬ヒロさんも Xamarin を使っていますが、この手のタブレット操作画面を作るのに Xamarin.Forms が有効なのです。スマートフォンじゃなくて、iPad や Surface、大き目の Android タブレット(候補としては Amazon タブレットぐらいしかないのですが)で操作系のアプリを作ろうと思うと、スマートフォンのような小さな画面とは異なった作りが必要になります。かつ、タッチパネル使える/必須なので、操作としてはスマートフォンっぽい感じで使えるのが良い訳です。
UWP が使えるので、Windows IoT Core on Raspberry Pi でも使えますよね(実際使える)。なので、このあたり UWP だけで閉じていれば、Surface, IoT Core 画面でデバッグができる&操作が同じにできるという話なのですが、もうちょっと Android/iPad に範囲を広げると Xamarin.Forms で画面を構成するのは結構有効です。IoT 絡みになれば、スマートフォンの通信や加速度センサーだけでなく、具体的に自作したセンサーの類を使えるわけですから、UI まわりをさっくりと作る(ある意味で、スマートフォンの最新機能には依存しない)ことができます。高めではありますが、Android 組み込みボードのほうでも Xamarin が使えるようになるとよいかなと思ったりしてます。

そのあたりを含めて、入門的に手を付けるのがお薦めです。

カテゴリー: 開発, Xamarin | 1件のコメント

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」とは確実に異なる。異なるので「同じ動作をする」という保証はない。保証はないが「だいたい同じ動作をする」という現実的な解を持つという訳だ。

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

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

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