30 Dec 2014, 08:14

Gof デザインパターンの勉強メモ記事とブックマークまとめ

はじめに

今年の目標は, デザインパターンの攻略!

ということで, この一年でまとめた情報や書いた記事のブックマークページです.

過去記事は, Ruby と Java が入り混じっていたり, 気まぐれでどんどん更新していったので, とてもまとまりがないとおもう.

強引に一つのページにまとめてみた感じ… (*‘д`*)

一年の振り返り

Rubyist になる

去年の 12 月から Rubyist になった.

そして, オブジェクト指向開発に触れることになった.

楽しかったので, 何も考えずにデザインパターンを使ってみたりした. しかし, これはのちに後悔することになった.

保守性よりもスピードを重視するべきだったのに, デザインパターンをつかって, 仕事が遅れてしまったという悲しい思い出.

POSA を学ぶ

coursera で POSA (Pattern Oriented Software Archtecture) をまなんだ.

ここで登場した Schmidt さん (POSA2 を書いた人) がとても情熱的に Pattern を語るのをきき, パターンが素晴らしいと洗脳された.

Javaer になる

年の暮れごろに Javaer になった.

すると, 一緒に仕事する人にすごく怖くてパターンに詳しいひとがいた.

OO でまともに設計した経験のない自分は, その人からしてみれば素人なので, レビューしているのだか教育をされているのだかわからない感じだった.

そんなことだから考え方がいつも手続的なんだ と, しょっちゅう罵倒された../ (._.)

毎日怯えつつ, あんなやついつかギャフンと言わせてやるという, なかば憎悪に似た感情を抱きつつ??, パターンの勉強をしたのだった.

これからどうするか?

Gof デザインパターンは 20 年前のもの.

最近, おもしろい podcast を発見した.

Gang of Four のメンバが 20 年たった今, なにを感じているのかをインタビューした podcast.

Gof デザインパターンは, 20 年も前のものなのだ.

そして, 今や時代はオブジェクト指向から関数型へと向かっている.

OO から FP へ

デザインパターンを学習していると, 関数型だともっと簡潔にかける気がしてきた.

たとえば, これ.

というわけで, 来年は関数型言語を頑張る. 関数型言語のパターンみたいなものはあるのかな??

Pattern

パターン

建築環境に繰り返し現れる課題を解決に導く具体的な方策を記述したもの.

アレクサンダーのパターン形式

  • パターン名
  • 写真
  • 上位パターンへのつながり
  • 本文
  • 下位パターンへのつながり

パターンランゲージ

建築において繰り返し現れる構造を再利用しやすい形式でまとめたもの. あるいは, パターンを集めて一つの体系としてまとぬあげたもの.

建築家クリストファーアレクサンダーが考えた建築手法.

時を超える建築の道

パターンランゲージを記した建築理論. 本の題名.

角谷信太郎さんのおもしろいはなしの youtube 動画も見つけた.

無名の質

生き生きとした建築や街が備えている特性. 古い街並みに潜む住みやすさや美しさ.

Design Pattern

Gof Degign Pattern

生成に関するパターン

Factory の原則

生成と実装を分離することで, プログラムはシンプルになる.

  • 生成パラメータの指定方法をシンプルに
  • 生成後の管理をシンプルに
  • 生成するオブジェクトの指定方法をシンプルに

特定のケースで特定のオブジェクトを生成するのは手続き思考的.

2 つをわけて考えることで設計に集中.

  • 動作方法
  • 生成,管理方法

Factory Method

オブジェクトの生成を行う時のインタフェースを規定して, インスタンス化するクラスを決定するのはサブクラスに任せる.

factoryMethod の中でオブジェクトの生成をすることで, 生成を生成オブジェクト (メソッド) 内にカプセル化.

switch 文は Abstract Factory によってリファクタリング可能.

  1. C 言語での応用

    C 言語で Abstruct Data Type な設計をつかうときの常套手段.

    int createInstance (void) {
      return calloc (4);
    }
    
    int destroyInstance (int ptr) {
      free (ptr);
      return NULL;
    }
    
    int main (void) {
      int *instance = createInstance ();
      instance = destoryInstance (instance);
      return 0;
    }
    
  2. 使いどころ

    グループ化されたオブジェクトについて,

    • 生成用オブジェクト (Creator)
    • 振る舞い用オブジェクト (Product)

    のペアを作成するとき.

Abstract Factory

関連するオブジェクト群を, その具象クラスを明確にせずに生成するための インタフェースを提供する.

関連するインスタンス群を生成するための API を集約することによって, 複数のモジュール群の再利用を効率化することを目的とする.

実装は意識せずに, インタフェース (API) のみで, 抽象的な部品をつくりあげる.

Factory Method 自体のカプセル化. マルチ Factory Method. Factory Methods.

Builder

オブジェクトの生成手順が複雑な場合に, その生成過程をカプセル化する.

ドメイン駆動設計でいうところのエンティティオブジェクトを生成する Factory.

Prototype

生成するオブジェクトの原型をコピーして新しいオブジェクトを生成する.

Abstract Factory と似ている.

  • new でオブジェクトを生成すれば Abstract Factory.
  • clone をつかう場合の Prototype.

複製を作成するためのメソッドを用意する. といういたって単純なもの.

プロトタイプ が複製を担当し, それ以外の生成における操作をクライアントが 担っている.

Map にテンプレートを登録しておいて, 利用するときに複製する. バイナリデータをマップにいれておいて, キーとなる名前をつけて管理する, など.

Java には, Clonable インタフェースがある.

クラスの数をかなり減らすことができる.

  1. 利用シーン

    • Abstract Factory パターンでなされるように,

    クライアント・アプリケーションにおいて オブジェクトの生成者をサブクラスにすることを回避する

    • 標準的な方法 (例えば’new’) で新しいオブジェクトを作ることによる

    固有のコストが所与のアプリケーションにとって高すぎる時にそれを回避する.

Singleton

システム内で生成可能なインスタンス数をひとつだけに制限する.

一般的なシングルトンパターンの実装方法は以下.

  • static method
  • private な 定数に オブジェクトを保存
  • オブジェクトは getInstance () メソッドで取得

各 Factory の違い

デザインはしばしば,

  • 比較的に複雑でなく,
  • カスタマイズしやすく,
  • サブクラスを急速に増やす

ファクトリメソッドを用いるところから出発

一層の柔軟性が必要となる箇所が発見されるに伴い,より柔軟だが複雑な Abstract Factory, Prototype, Builder へと発達してゆく.

  1. Factory Method

    ファクトリのクライアントとなるオブジェクトが, ファクトリオブジェクトにインスタンスの生成を委譲する.

    • 親クラスである Creator クラスが子クラスである

    ConcreteCreator クラスにオブジェクトの生成を委ねる

    • Creator クラスと ConcreteCreator クラスとの関連である.
    • 継承
    • [オブジェクト生成] の抽象化にポイントを置いたパターン
  2. Abstract Factory

    親クラスであるファクトリが, 実際のオブジェクトの生成をサブクラスに委譲する

    • Client のインスタンスが ConcreteFactory のインスタンスにオブジェクトの生成を委ねる
    • オブジェクト同士の関連
    • 委譲
    • [関連するオブジェクト群をまとめて生成するための手順] の抽象化
  3. 参考:

構造に関するパターン

Adapter

インタフェースを変換することにより, インタフェースに互換性がない クラス同士を接続する.

単なるラッパークラスとも言える.

ラッパー方法は 2 つ.

ここでは, ConcurrentLinkedQueue と ConcurrentArrayQueue を 生成時に交換するために, Adapter をつかっている.

Bridge

クライアントがアクセスするクラス (インタフェース) と実装クラスを分離して, それぞれを独立に変更できるようにする.

オブジェクト指向のこころの本にとても詳しく書いてある.

これぞ, オブジェクト指向の本質! みたいな.

  • インタフェースを用いて設計する.

機能追加と機能実装の組み合わせ爆発を抑止することができる.

Composite

部分-全体階層を表現するために, クラスの木構造に組み立てる. 同一の クラスから派生したサブクラスを木構造のノードとし, クライアントは木構造の任意の部分を同一のインタフェースで扱える.

別名, フォルダパターン. フォルダには, フォルダとファイルがある. こっちの名前のがわかりやすいし, 覚えやすい.

Decorator

サブクラス化ではなく委譲により, クラスに新しい機能を追加する.

ポイントは, オブジェクトの委譲方法が,

  • 集約ではなくてコンポジション
  • 継承ではなくてコンポジション

LinkedList 構造.

Facade

複数のクラス群からなるサブシステムにアクセスするための, インタフェースを提供する.

facade とは, 正面という意味.

Proxy

オブジェクトへのアクセスをフックするための代理オブジェクトを提供する.

Proxy は英語で代理人.

Windows のデスクトップショートカットもプロキシ.

本物のオブジェクトにアクセスするまえにクッションを置くことで, そこに機能追加できる.代理プラスアルファの機能をもつ.

Flyweight

一度生成したインスタンスはプーリングしておき, 必要なときに取り出して使う.

シングルトンパターンは フライウェイトパターンと合わせて利用されることがおおい.

特徴は,

  • private な 変数に オブジェクトを保存.
  • オブジェクトが存在すれば, getInstance で渡す. オブジェクトが存在しなければ, オブジェクトを作成して getInstance で渡す.
  1. wikipedia から説明引用

    その時点で対象のインスタンスが生成されていない場合

    • 対象のインスタンスを新たに生成する.
    • 生成したインスタンスをプールする (言い換えると, メンバのコンテナオブジェクトに格納する).
    • 生成されたインスタンスを返す.

    対象のインスタンスが既に生成されていた場合

    • 対象のインスタンスをプールから呼び出す.
    • 対象のインスタンスを返す.

振る舞いに関するパターン

Command

動作を表現するオブジェクト. 動作とそれに伴うパラメータをカプセル化したもの.

  1. 特徴

    • 手続きに必要なパラメータの一時格納場所として便利.
    • 関数呼び出しのためのパラメータを集めて,

    後で使用するためにコマンドを保存しておくことができる.

    • 保存されたデータ構造に対する追加, 削除が可能になる.
    • コマンドの生成と実行のタイミングの分離.

Chain of Responsibility

責務を持たせたオブジェクトの Chain に 要求を渡していく.

要求は,

  • そのオブジェクトで処理できればそこで処理する
  • そのオブジェクトで処理できなければ, 次のオブジェクトに渡す.
  1. 参考記事:

Interpreter

文字列からなる構文を構文解析 (Interprete) し, 構文を表現したオブジェクト構造ともとの文字列を関連付ける.

Iterator

オブジェクトの集合 (データ構造, コンテナ) があるとき, その集合の内部構造はカプセル化したままで, 要素に対して順にアクセスする方法を提供する.

コンテナオブジェクトの要素を列挙する手段を独立させることによって, コンテナの内部仕様に依存しない反復子を提供することを目的とする.

言語でサポートしていることがおおい. 拡張 for 文, for-each 文などと呼ばれる.

自前で実装するよりも, 言語に頼るほうがよい.

  1. Java

    Collection フレームワークでは, 反復子が利用できる.

    List<Integer> list = LinkedList<Integer>
    for (int i; list) {
    System.out.println (i);
    }
    

    Iterator インタフェースを実装することで, 自前のクラスにイテレータを適用できる.

  2. Ruby

    Enumerable モジュールを Mix-in する.

  3. 参考:

Mediator

複数のオブジェクトを相互作用させる場合に, お互いのオブジェクト同士が直接参照することをなくすため, 相互作用そのものをオブジェクトとして定義する.

Memento

オブジェクトの状態を保存しておき, 元に戻せるようにしておく. オブジェクトを以前の状態に (ロールバックにより) 戻す能力を提供する.

Observer

あるオブジェクトに依存した複数のオブジェクトがある場合に, 被依存オブジェクトの状態変化を, 依存オブジェクトに通知する.

Ruby ではライブラリがある.

イベントリスナ.

State

状態に応じてオブジェクトの振る舞いを変更したいときに, 振る舞いを別オブジェクトにカプセル化する.

Strategy

アルゴリズムをカプセル化して, アルゴリズムを交換可能にする. ひとつの入力データに対して, アルゴリズム毎に異なる結果を出力する.

アプリケーションで使用されるアルゴリズムを動的に切り替える必要がある際に有用.

  • Android
  • Windows
  • Linux
  1. 変更を考慮して設計するアプローチ

    オブジェクト思考のこころより引用.

    • 変更内容を予測するのではなくて, どこに変更が発生するのかを予測する
    • 実装を用いてプログラミングするのではなくて, インタフェースを用いてプログラミンクする.
    • クラス継承よりも, オブジェクトの集約を多用する.
    • 流動的要素をカプセル化する.

    switch 文を多用したり, グチャグチャになってきたら赤信号. switch 文は流動的要素なので, その部分をクラスに分離してカプセル化する.

    クラスに分離する際は, 継承をさけて集約を多用する.

  2. Effective Java から

    p101 戦略を表現するために関数オブジェクトを使用する

    • 戦略を現すインタフェースを用意
    • 個々の具象戦略に関してそのインタフェースを実装しているクラスを定義.
      • 具象戦略が一度しか利用されないならば, 無名クラスで作成
      • 繰り返し利用されるならば, public static final の フィールド or static factory method を通じて提供.
  3. 名前のつけかた

    xxxStrategy

Template Method

単なる継承.

アルゴリズムを複数のステップに分解し, それぞれのステップを抽象メソッドにする. 各ステップでのメソッドの実装はサブクラスで定義する.

システムのフレームワークを構築するための手段としてよく活用される.

Factory Method パターンは, 内部に Template Method パターンを包含することが多い

class A
  def execute ()
    raise "to be implemented"
  end
end

class B < A
  def execute ()
  end
end

class C < A
  def execute ()
  end
end

Visitor

複数のオブジェクトからなるオブジェクト構造があるときに, それぞれのオブジェクト要素に処理を追加または オブジェクト要素の処理を変更するため, Visitor クラスを用意する.

OOP の 2 大原則

オブジェクト指向のこころとは, ズバリ以下だ.

  • 流動的要素を探し出してカプセル化する
  • クラス継承よりもオブジェクトの集約を多用する

デザインパターンとともに学ぶオブジェクト指向のこころより

カプセル化の視点で整理

カプセル化がデータ隠蔽というのは狭義の定義.

カプセル化とはあらゆるものを隠蔽すること.

  • データ
  • メソッド
  • 実装
  • 派生クラス
  • 設計の詳細
  • 実体化の規則

流動的要素を探し出してカプセル化する. 委譲は手段.

この観点から, デザインパターンをとらえ直すと,

流動的要素 Pattern


アルゴリズム Strategy 状態 State 振る舞い Decorator パターンマッチ, 型 Visitor 動作, 要求 Command 実装 Bridge 変化への反応 Observer 相互作用 Mediator 生成 Factory Method, Abstract Factory , Prototype 一意性 Singleton, Flyweight 構造の生成 Builder 集合の巡回構造 Iterator インタフェース Adapter システム Facade 設計の詳細 Template Method

Links

概要がかかれたページ

噛み砕かれた, わかりやすい説明.

図解で解説されている.

サンプルソースが豊富.

30 Dec 2014, 07:23

Java で Memento パターンを実装をしてみた

はじめに

Java で Memento パターンを実装をしてみました.

Memento パターンとは

オブジェクトの状態を保存しておき, 元に戻せるようにしておく. オブジェクトを以前の状態に (ロールバックにより) 戻す能力を提供する.

パターン適用前

以前, State Pattern を実装したコードを改造. ステートを保存できるようにします.

public class StatePatternMemento {

    public static void main (String[] args) {
        Context context = new Context (new Morning ());

        while (!context.isDone ()) {
            context.greeting ();
        }
    }
}

class Context {
    private State state;

    public Context (State state) {
        this.state = state;
    }

    public void greeting () {
        state = state.greeting ();
    }

    public boolean isDone () {
        return state == null;
    }
}

interface State {
    public State greeting ();
}

class Morning implements State {

    public Morning () {
        System.out.println (" === It's 09:00 ===");
    }

    public State greeting () {
        System.out.println ("Good morning!! ('▽`)");
        return new Afternoon ();
    }
}

class Afternoon implements State {

    public Afternoon () {
        System.out.println (" === It's 15:00 ===");
    }

    public State greeting () {
        System.out.println ("Good afternoon!! ('▽`)");
        return new Evening ();
    }
}

class Evening implements State {

    public Evening () {
        System.out.println (" === It's 20:00 ===");
    }

    public State greeting () {
        System.out.println ("Good evening!! ('▽`)");
        return null;
    }
}

パターン適用後

状態保存する機能を順番に追加していく.

メメントパターンは, 保存/ 復元される側とする側の役割を独立させるのが普通.

  • originator (代表者) 内部属性を保存されるもの.
  • caretaker (世話役) originator 内部属性 (状態) を保存するコンテナ.
  • Memento (記念品) originator 内部属性 (状態) を記憶するデータ構造.

その 1 初期状態を復元

まずは, 初期状態を追加. originator である Context を拡張する.

class Context {
    private State initialState; 

    public Context (State state) {
        this.state = state;
        this.initialState = state;
    }

    public void restoreState () {
        System.out.println ();  
        System.out.println (" === Restore State ===");
        System.out.println ();      
        state = initialState;
    }
}

初期状態を保存する属性と 外部から restore するためのインタフェースを用意.

public class StatePatternMemento1 {

    public static void main (String[] args) {
        Context context = new Context (new Morning ());

        while (!context.isDone ()) {
            context.greeting ();
        }

        context.restoreState ();

        while (!context.isDone ()) {
            context.greeting ();
        }
}
}

class Context {
    private State state;
    private State initialState; 

    public Context (State state) {
        this.state = state;
        this.initialState = state;
    }

    public void greeting () {
        state = state.greeting ();
    }

    public boolean isDone () {
        return state == null;
    }

    public void restoreState () {
        System.out.println ();  
        System.out.println (" === Restore State ===");
        System.out.println ();      
        state = initialState;
    }
}

interface State {
    public State greeting ();
}

class Morning implements State {

    public Morning () {
        System.out.println (" === It's 09:00 ===");
    }

    public State greeting () {
        System.out.println ("Good morning!! ('▽`)");
        return new Afternoon ();
    }
}

class Afternoon implements State {

    public Afternoon () {
        System.out.println (" === It's 15:00 ===");
    }

    public State greeting () {
        System.out.println ("Good afternoon!! ('▽`)");
        return new Evening ();
    }
}

class Evening implements State {

    public Evening () {
        System.out.println (" === It's 20:00 ===");
    }

    public State greeting () {
        System.out.println ("Good evening!! ('▽`)");
        return null;
    }
}

実行結果

 === It's 09:00 ===
Good morning!! ('▽`)
 === It's 15:00 ===
Good afternoon!! ('▽`)
 === It's 20:00 ===
Good evening!! ('▽`)

 === Restore State ===

Good morning!! ('▽`)
 === It's 15:00 ===
Good afternoon!! ('▽`)
 === It's 20:00 ===
Good evening!! ('▽`)

その 2 状態 + アルファを復元

状態 + アルファを保存するためのデータ構造を用意する. これこそが memento!!

ここでは, アルファは count とする.

private int count;

count と state を保持するデータ構造 memento クラスを作成. memento のコンストラクタで状態を保存する. memento の getter で属性を取得してリストアする.

private static class Memento {
    private State state;
    private int count;

    public Memento (State stateToSave, int countToSave) {
        state = stateToSave;
        count = countToSave;            
    }
    public State getSavedState () { return state; }
    public int getSavedCount () { return count; }       
}

全コード

public class StatePatternMemento2 {

    public static void main (String[] args) {
        Context context = new Context (new Morning ());

        while (!context.isDone ()) {
            context.greeting ();
        }

        context.restoreState ();

        while (!context.isDone ()) {
            context.greeting ();
        }
    }
}

class Context {
    private State state;
    private int count;
    private Memento m;

    public Context (State state) {
        this.state = state;
    }

    public void greeting () {
        state = state.greeting ();
        count++;

        if (count == 1) {
            m = new Memento (state, count);
        }
    }

    public boolean isDone () {
        return state == null;
    }

    public void restoreState () {
        System.out.println ();  
        System.out.println (" === Restore State ===");
        System.out.println ();

        state = m.getSavedState ();
        count = m.getSavedCount ();     
    }

    private static class Memento {
        private State state;
        private int count;

        public Memento (State stateToSave, int countToSave) {
            state = stateToSave;
            count = countToSave;            
        }
        public State getSavedState () { return state; }
        public int getSavedCount () { return count; }       
    }
}

interface State {
    public State greeting ();
}

class Morning implements State {

    public Morning () {
        System.out.println (" === It's 09:00 ===");
    }

    public State greeting () {
        System.out.println ("Good morning!! ('▽`)");
        return new Afternoon ();
    }
}

class Afternoon implements State {

    public Afternoon () {
        System.out.println (" === It's 15:00 ===");
    }

    public State greeting () {
        System.out.println ("Good afternoon!! ('▽`)");
        return new Evening ();
    }
}

class Evening implements State {

    public Evening () {
        System.out.println (" === It's 20:00 ===");
    }

    public State greeting () {
        System.out.println ("Good evening!! ('▽`)");
        return null;
    }
}

実行結果

 === It's 09:00 ===
Good morning!! ('▽`)
 === It's 15:00 ===
Good afternoon!! ('▽`)
 === It's 20:00 ===
Good evening!! ('▽`)

 === Restore State ===

Good afternoon!! ('▽`)
 === It's 20:00 ===
Good evening!! ('▽`)

その 3 スナップショットを復元

最後にスナップショット機能を追加. 保存するためには, 第三者を登場させて外部に状態を保持する.

class SnapShot {
    private List<Object> states = new ArrayList<Object>();

    public void addMemento (Object m) { states.add (m); }
    public Object getMemento (int index) { return states.get (index); }
}

ここでのポイントは, Context の情報のみをもつ Memento データを 保存しておくこと. 保存する情報はメモリ上で小さくすることが目的.

全コード

import java.util.List;
import java.util.ArrayList;

public class StatePatternMemento3 {

    public static void main (String[] args) {
        Context context = new Context (new Morning ());
        SnapShot snaps = new SnapShot ();
        snaps.addMemento (context.saveToMemento ());

        while (!context.isDone ()) {
            context.greeting ();
        }

        context.restoreFromMemento (snaps.getMemento (0));

        while (!context.isDone ()) {
            context.greeting ();
        }
    }
}

class Context {
    private State state;
    private int count;

    public Context (State state) {
        this.state = state;
    }

    public void greeting () {
        state = state.greeting ();
        count++;
    }

    public boolean isDone () {
        return state == null;
    }

    public Object saveToMemento () { 
        System.out.println (" == Save to Memento == ");
        return new Memento (state, count); 
    }

    public void restoreFromMemento (Object m) {
        if (m instanceof Memento) {
            Memento memento = (Memento) m;
            state = memento.getSavedState ();
            count = memento.getSavedCount ();

            System.out.println ();  
            System.out.println (" === Restore State ===");
            System.out.println ();
        }
    }   

    private static class Memento {
        private State state;
        private int count;

        public Memento (State stateToSave, int countToSave) {
            state = stateToSave;
            count = countToSave;            
        }
        public State getSavedState () { return state; }
        public int getSavedCount () { return count; }       
    }
}

class SnapShot {
    private List<Object> states = new ArrayList<Object>();

    public void addMemento (Object m) { states.add (m); }
    public Object getMemento (int index) { return states.get (index); }
}

interface State {
    public State greeting ();
}

class Morning implements State {

    public Morning () {
        System.out.println (" === It's 09:00 ===");
    }

    public State greeting () {
        System.out.println ("Good morning!! ('▽`)");
        return new Afternoon ();
    }
}

class Afternoon implements State {

    public Afternoon () {
        System.out.println (" === It's 15:00 ===");
    }

    public State greeting () {
        System.out.println ("Good afternoon!! ('▽`)");
        return new Evening ();
    }
}

class Evening implements State {

    public Evening () {
        System.out.println (" === It's 20:00 ===");
    }

    public State greeting () {
        System.out.println ("Good evening!! ('▽`)");
        return null;
    }
}


実行結果

 === It's 09:00 ===
Good morning!! ('▽`)
 === It's 15:00 ===
Good afternoon!! ('▽`)
 === It's 20:00 ===
Good evening!! ('▽`)

 === Restore State ===

Good morning!! ('▽`)
 === It's 15:00 ===
Good afternoon!! ('▽`)
 === It's 20:00 ===
Good evening!! ('▽`)

30 Dec 2014, 05:31

パターンは暗記するものではなく導くもの! オブジェクト指向のこころを読んだ読書メモ

はじめに

オブジェクト指向の本質を学ぶために, オブジェクト指向のこころを読みました.

読んだ理由

主な動機は,

  • パターンの本質を身につけるため.
  • パターンを適用するベースとなるオブジェクト指向を深く理解するため.

以下の記事の NextAction で選んだ本だった.

オブジェクト指向の本質を学べる本として, ネットで評判が高かったので購入.

また, 今年の目標としてデザインパターンを理解することをあげていたので, デザインパターンという言葉自体に惹かれた.

内容

OOP の 2 大原則とは?!

オブジェクト指向のこころとは, ズバリ以下だ.

  • 流動的要素を探し出してカプセル化する
  • クラス継承よりもオブジェクトの集約を多用する

この 2 つの概念は書くページの至る所に現れる. この 2 つの概念を説明するために, 他のページが書かれているといってもいい.

そして, これを実現するための手段がデザインパターンだ. 本質から導いた結果を,

“ほら, これが Gof では xxx パターンと名づけられているんだよ”

といわれる. これが デザインパターンとともに学ぶ という副題の意味.

Bridge Pattern に OO の本質あり

そして, この原則を解説するために, Bridge Pattern が詳解されている.

Bridge Pattern については, こちらも参照.

登場するパターン

すべてのパターンが出てくるわけではない. オブジェクト指向のこころを解説するための例として, パターンを引用しているに過ぎない.

  • Facade
  • Adapter
  • Bridge
  • Strategy
  • Abstract Factory
  • Decorator
  • Observer
  • Template Method
  • Singleton
  • Factory Method

パターンで考える

この本の独特な手法は, パターンで考える方法が載っていること.(第 13 章)

  • Facade
  • Adapter
  • Bridge
  • Abstract Factory

以下がその手順.

  • パターンの洗い出し … コンテキストに存在するパターンをまずは列挙.
  • パターンの分析・適用 ここで大事なのは, このコンテキストに置いて

    • “なにか問題なのか?”
    • “なにを解決したいのか?”

    をかんがえること. 1-4 を繰り返す. 1. パターンの並べ替え 2. パターンの選択と設計の拡張 3. 追加のパターンの洗い出し 4. 繰り返し

  • 設計の詳細

詳細は書籍を.

Java と UML の知識が必要

パターンを表現するために クラス図と Java のサンプルコードもふんだんに載っている.

そのため, 本の前半には, UML を解説するページも少し割かれている.

感想

なんども読み返した

読み始めたのは半年以上前. 興味がある部分からつまみ読みをはじめた.

一回読んでも大抵は忘れてしまう. この本には, オブジェクト指向設計とはなにかについて, 凝縮した言葉でかかれているため,同じページを何度も読み返した.

Web での評判は本物.これからも折に触れて読み返すことになるだろう.

パターンは暗記するものではなく, 導出するもの

この本を読む前, デザインパターンは暗記してすぐに思い出せるように しておく必要があると思っていた.

実はそうではなくて, 本質だけ押されておいて, 自然とデザインパターンは導き出すことが大事だと思った.

大学受験の数学も, ひたすら公式を暗記しても応用問題が解けない. 逆に理論的なところを抑えれば, 公式を暗記しなく立って導出できるし, 応用も効くようになる.

それと同じことかもしれない.

学習メモ

オブジェクト指向設計

名詞/ 動詞 抽出法

  • 問題領域に存在する名詞を洗い出し, それらを表現するオブジェクトを生成する.
  • 名詞に関連した動詞を洗い出し, それらを表現するメソッドを追加する

共通性/ 可変性 分析法

  • 共通性分析:時間が経っても変化しにくい構造を見つけるもの 共通性分析によってまとめられた概念を抽象クラスによって表現
  • 可変性分析:変化しやすい構造を洗い出すもの 可変性分析で得た流動的要素は抽象クラスの派生クラスによって実装される

設計手順:

  • (抽象クラス) このクラスが持つ責務をすべて全うするにはどうようなインターフェイスが必要か?
  • (派生クラス) この特定実装の中でどうのようにして与えられた仕様を実装できるのか?

Jim Coplien が提唱. p235 第 15 章から抜粋.

  1. Links

カプセル化の視点で整理

カプセル化がデータ隠蔽というのは狭義の定義.

カプセル化とはあらゆるものを隠蔽すること.

  • データ
  • メソッド
  • 実装
  • 派生クラス
  • 設計の詳細
  • 実体化の規則

流動的要素を探し出してカプセル化する. 委譲は手段.

この観点から, デザインパターンをとらえ直すと,

流動的要素 Pattern


アルゴリズム Strategy 状態 State 振る舞い Decorator パターンマッチ, 型 Visitor 動作, 要求 Command 実装 Bridge 変化への反応 Observer 相互作用 Mediator 生成 Factory Method, Abstract Factory , Prototype 一意性 Singleton, Flyweight 構造の生成 Builder 集合の巡回構造 Iterator インタフェース Adapter システム Facade 設計の詳細 Template Method

これからどうするか

暗記はやめよう

デザインパターンをただ暗記する態度は改めなければ.

本質から導けば, 覚える量も減るし, 応用も効くはず.

暗記ではなくて, 本質を繰り返し唱えること.

問題を考えよう

何か問題でパターンによってなにが改善されるかを考える癖をつけよう.

デザインパターンは, 概して複雑. 実際に仕事で利用するには, 工数 との兼ね合いを考えるようにする.

保守なんてされないだろうコードを, たくさん工数をかけてデザインパターンを駆使して書いても, 価値はない.

問題が保守性だとして, 保守する必要がなければパターンは適用する必要はない.

OO から距離をおいてみてみる

今年の目標は OO を理解することだったので, かなりの時間を OO に割いてきた.

来年の目標は関数型パラダイムを理解することなので, 一旦 OO の世界からは距離を置こうと思う.

OO と関数型を比較しつつ, 距離を追いてみることで, また見える世界が変わるかもしれない.

29 Dec 2014, 15:57

Haskell で 関数型言語入門! edX の Introduction to Functinal Programming を受けた.

はじめに

edX で Introduction to Functinal Programming を受けた感想です. Introduction to Functional Programming | edX

今年の 2 月ごろに Ruby のブロックというものを知った. これは, いわゆる無名関数なのだが, その概念がとても新鮮だった.

それは, 関数型言語でよく利用されるということを知ったので, もっと関数型言語に触れようというのが今年の目標だった.

今年も終わりに近づく 11 月, edX で純関数型言語の Haskell の講座が開講された.

関数型言語を身につける絶好の機会だと思った.

内容

講座の内容は, 以下の本をはじめから終わりまで解説していくもの.

毎週の課題も 各章の練習問題そのものだった.

講座のスライドは github で公開されている.

感想

難しかった..でも, 学ぶことが多かった

難しかった. 1 日ずっと Haskell 漬けになったりした.

内容はさらっと解説されるのだが, 関数型言語という世界が, 今までいた世界とは異なる考え方を もっているので, 概念を理解するのに時間がかかる.

しかし, 知らない概念は刺激にもなって, おもしろい

  • モナド
  • 代数データ型
  • 遅延評価…

関数プログラミング実践入門

副読本として, 最近出版された以下の本を購入した.

この本はとても分かりやすいのておすすめ.

ボイントは, Haskell の文法に限定していないところ.

題名どおり, 関数型言語とはなにかということについてかかれている. その手段として, Haskell が解説されている.

C や Java と Haskell の比較がかかれているところがよい.

手続き型言語の世界にいるプログラマを関数型言語の世界へ 引っ張ってきたいという, 著者の意図を感じる.

数学とプログラミングの結びつきが見えた気がした

関数型言語における関数や型の概念から, プログラミングのベースには, 数学があることを強く感じた.

以下のような記事を書いている.

数学との関係性.

関数型言語のベースには数学がある.

  • 群論
  • 圏論

代数はプログラミング/ モデリングの数学的な基礎理論. 型とは代数学がベースになっている.

これからどうするか?

講座の終わりで, なんと次回予告の動画が流れた?!

Haskell の次は, 圏論 (Category Theory) の講座を予定しているらしい.

大学のとき群環体で心折れた自分としては, 代数学にやや引け目を感じるもの, 数学とプログラミングのつながりをもっ と知るためにこれも受けてみたい.

そのためには, Haskell の学習をここで終わらせることなく, 継続させたい.

AtCoder に挑戦

なにか, 計画をたてとかないと, 自分は勉強しないだろう.

継続的に学習する仕組みとして, 競技プログラミングの問題をといてみる. atcoder と, codeforces が Haskell に対応しているようだ.

Codeforces は, 海外なので深夜に開催されるが, Atcoder は日本時間に合わせて開催されているので, AtCoder をやろうと思う.AtCoder の問題を月 1 回, Haskell でとくぞ.

29 Dec 2014, 14:17

Java で 高階関数の map と filter を実装してみた

はじめに

Java 6 で 関数型言語のような map, filter を実装してみた.

結論としては, 結構めんどうだったのてやるべきではないということだった.

Environment

  • Java 6 (8 ではない)

実装方針

関数型言語の原則にそうように実装する.

  • クロージャは 無名クラスで実装
  • 高階関数は, クロージャとリストを引数にとって, 新しいリストを生成して返すように実装 (immutable).

実装

map

import java.util.List;
import java.util.ArrayList;

public class FunctionalMap {
    public static void main (String args[]) {
        List<Integer> xs = java.util.Arrays.asList (1,2,3,4,5);
        MyFunc<Integer> f = new MyFunc<Integer>() {
                public Integer evaluate (Integer x) { return x + 1; }
            };
        Functor<Integer> functor = new Functor<Integer>();

        List<Integer> ys = functor.map (f, xs);

        for (Integer y : ys){ System.out.print (y.toString () + " "); }
    }
}

class Functor<T> {
    public List<T> map (MyFunc<T> f, List<T> xs) {
        ArrayList<T> list = new ArrayList<T>();
        for (T x : xs) { list.add (f.evaluate (x)); }
        return list;
    }
}

interface MyFunc <T> {
    public T evaluate (T x);
}

results

2 3 4 5 6 

filter

import java.util.List;
import java.util.ArrayList;

public class FunctionalMap {
    public static void main (String args[]) {
        List<Integer> xs = java.util.Arrays.asList (1,2,3,4,5);
        MyFilter<Integer> g = new MyFilter<Integer>() {
                public boolean evaluate (Integer x) { return x % 2 == 0; }
            };

        Functor<Integer> functor = new Functor<Integer>();

        List<Integer> zs = functor.filter (g, xs);      

        for (Integer z : zs){ System.out.print (z.toString () + " "); }     
    }
}

class Functor<T> {
    public List<T> filter (MyFilter<T> f, List<T> xs) {
        ArrayList<T> list = new ArrayList<T>();
        for (T x : xs) {
            if (f.evaluate (x))
                list.add (x);
        }
        return list;
    }
}

interface MyFilter <T> {
    public boolean evaluate (T x);
}

results

2 4 

29 Dec 2014, 12:03

Emacs で ログ解析をするための便利機能まとめ

はじめに

前回の記事のつづき.

Java 開発で, log4j のログをみる機会がこれから増えそうだ.

ログといっても所詮はテキストなので, Emacs を使いたい. そこで, ログ解析に便利そうな, 使えそうな機能をまとめてみた.

とくに, Java の log4j 専用というわけではなく, どんなテキストログの解析にも応用できればいいな.

閲覧

Read Only Mode

ログなので, Read Only でファイルを開きたい.

  • M-x toggle-read-only (C-x C-q) で現在開いているテキストを 読み取り専用にすることができる

  • M-x find-file-read-only で読み取り専用で開くことができる. 解除は, toggle-read-only で.

参考:

(add-to-list 'auto-mode-alist '("\\.log$" . read-only-mode))

Tramp

ログはサーバからダウンロードする. Emacs からサーバに直接乗り込んで開くためには, Tramp を利用する.

tail -f 的な

リアルタイムログ解析のためには, M-x auto-revert-tail-mode を利用. これで, tail -f のようにファイルを更新することが可能になる.

検索

複数ファイル検索: grep/ ag / helm-ag

検索は grep が基本.

最近は, grep よりも高速な検索ができる ag というものもある.

さらには, 絞り込みを helm I/F から利用するための helm-ag もある.

単一ファイル検索: helm-swoop

helm-swoop を利用すると, 一文字打ち込む度に検索が走る. ログサイズが小さいときや, 単一ファイルならば, grep よりも使いやすい.

インクリメンタル検索

isearch (C-s) が基本.

インクリメンタル検索である isearch と helm-swoop をつなぐ, ace-isearch というものもある.

ブックマーク/ ハイライト

Bookmarks をハイライト

行をハイライトできる.気になる行に色をつける.

本当は移動用なのだけれども, 色付けとして利用.

helm-all-mark-rings

C-SPC でマークをした場所を覚えておいて, helm で選択してジャンプできる.

(global-set-key (kbd "M-SPC") 'helm-all-mark-rings)

シンボルをハイライト

highlight-symbol/auto-highlight-symbol

シンボルをハイライトできる.気になる単語に色をつける.

(require 'auto-highlight-symbol-config)
(require 'highlight-symbol)
(setq highlight-symbol-colors '("DarkOrange" "DodgerBlue1" "DeepPink1"))

(global-set-key (kbd "<f3>") 'highlight-symbol-at-point)
(global-set-key (kbd "M-<f3>") 'highlight-symbol-remove-all)

hl-anything

永続的に, ハイライトを保持することが可能になる.

以下の記事の解説が詳しい.

(require 'hl-anything)
(hl-highlight-mode 1)

(global-set-key (kbd "<f2>") 'hl-highlight-thingatpt-local)
(global-set-key (kbd "M-<f2>") 'hl-unhighlight-all-local)

Java

以下参照.

28 Dec 2014, 15:59

Emacs 高速化起動にむけたカイゼンのとりくみ

はじめに

Emacs の起動を早くしたい. Windows 環境 (Cygwin) 環境における Emacs の起動時間が異常.

というわけで, 改善に向けた取り組みを実施した.

計測

起動時間の把握

M-x emacs-init-time という関数を実行すると, 起動にかかる時間がわかる.

とりあえず, 現状は

Machine Time


Arch Linux 12.1 Windows 29.6

esup をつかう

esup を利用すると, 詳細な起動時間がわかる.

(require 'esup)

自分の環境だと, inits ディレクトリ配下がすべて結果が要約されてしまい, よくわからなかった.

initchart をつかう

Emacs のスタートアップを視覚化する.

(require 'initchart)
(initchart-record-execution-time-of load file)
(initchart-record-execution-time-of require feature)

init log の確認

elisp の管理には init-loader.el を利用してる. init log を確認すると, 各処理における読み込み時間がわかる.

Windows における時間.

loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/00_el-get.elc. 0.0
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/01_global.el. 2.2812822
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/03_display.el. 1.0277368
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/20_text.elc. 4.8438096999999996
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/30_programming.elc. 1.8992336
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/31_c_cpp.elc. 0.1406281
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/31_haskell.elc. 0.2656291
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/31_java.elc. 0.3750235
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/31_python.elc. 1.9972729
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/31_ruby.elc. 0.3281107
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/33_minorlang.elc. 2.2702037
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/40_helm.elc. 1.1719071
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/50_org-mode.elc. 1.2500322
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/60_utility.el. 7.3733458
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/61_wanderlust.elc. 0.13878569999999998
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/90_color.elc. 0.7656375
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/99_windows8.elc. 0.171875
loaded c:/cygwin64/home/tsu-nera/dotfiles/.emacs.d/inits/windows-init.elc. 0.1406362

分析

  • utility が一番のボトルネック
    • 利用していないものはコメントアウト.
  • プログラミング言語に関する lisp は普段利用しないのに読み込みに時間かかかっている.
    • 遅延ロードをすべてに適用する
  • text 編集関係に時間がかかっている.
    • 利用しないものはコメントアウト

課題

当たり前の結果だけれども, 以下の 2 点に絞られるようだ.

  • 遅延評価の積極的適用
  • 不要な行の削除

カイゼン

emacsclient をつかう

これはつかう, というよりもすでにつかっている. というより, これをつかわないと話にならない.

ちなみに, 早く立ち上げたいときは, emacs -q オプションを指定することで設定ファイルを読み込まずに立ち上げる.

X Windows 環境での起動カイゼン

よくワカってないけど, コンナおまじないがあるらしい.

(modify-frame-parameters nil '((wait-for-wm . nil)))

バイトコンパイルをする

パッケージ管理には el-get を利用してる. そして, elisp の管理には init-loader を使っている.

el-get で取得したものは自動的にバイトコンパイルされるのだが, 盲点があった. それが

  1. el-get 自体
  2. init-loader 自体
  3. inits 配下の設定ファイル

1,2 については, el-get でいままで管理していなかった. これらを el-get 配下で管理するようにしていた.

さらに, inits 配下の設定ファイルについては 編集するたびにバイトコンパイルするようにした.

を参考にして, 以下を init.el に記述.

;;; 設定ファイルのあるフォルダを指定
(setq inits_dir (expand-file-name "~/.emacs.d/inits/"))
(init-loader-load inits_dir)

;; inits フォルダのみ, 保存時に自動コンパイルして即反映させる
;; http://fukuyama.co/emacsd
(defun auto-save-byte-compile-file ()
  "Do `byte-compile-file' and reload setting immediately, When elisp file saved only in inits folder."
  (interactive)
  (when (or (equal default-directory inits_dir)
        (equal default-directory (abbreviate-file-name inits_dir)))
    (byte-compile-file buffer-file-name t)
    ))
(add-hook 'emacs-lisp-mode-hook
      (lambda ()
        (add-hook 'after-save-hook 'auto-save-byte-compile-file
;; nil t)))

init-loader で自動バイトコンパイル機能があるようだ.

(setq init-loader-byte-compile t)

有効にしたが, イマイチ使い方がよくわからない.

起動時にバイトコンパイル

野良 elisp もバイトコンパイルしておいた方が早い.

init.el に以下を追記する. 末尾に 0 をつけることで, 起動時にバイトコンパイル.

(byte-recompile-directory "~/.emacs.d/myelisp" 0)
(byte-recompile-directory "~/.emacs.d/elisp" 0)

設定ファイルに直書きしている関数も外部ファイルに出してバイトコンパイル

これは結構効果的だった.

ステップ数の多い defun は別のファイルに分けた.さらに

  • 末尾に (provide ‘hogehoge) を追加
  • gist に登録
  • el-get で取得する recipe 作成

することで, gist で外部ファイルを管理することにした.

遅延ロードを適用する

autoload をつかう

ライブラリを起動時にロードする必要がない場合は, autoload を利用する. xxx-command を利用するときになって初めて”xxx”がロードされる.

(autoload 'xxx-command "xxx")

起動時にロードしないことで, 高速化.

eval-after-load/hook つかう

あるモードでのみ利用するものは, eval-after-load or hook を利用する.

;; hook
(add-hook 'c-mode-common-hook
      '(lambda ()
         (gtags-mode 1)
         (gtags-make-complete-list)))

;;eval-after-load
(eval-after-load "isearch"
  '(progn
     (require 'isearch-dabbrev)
     (define-key isearch-mode-map (kbd "<tab>") 'isearch-dabbrev-expand)))

2 つの違いは以下が詳しい.

要約すると,

  • 一度だけ設定すればよいものは eval-after-load
  • バッファを開くたびに設定したいもの hook

Emacs24.4 からは with-eval-after-load という関数がある. これも以下の記事が詳しい.

use-package をつかう

autoload/eval-after-load の記述を簡潔に書くための elisp.

記述方法は以下の記事がとても詳しい. ここでは省略.

起動時のエラーログや load ログを除去

起動時のログで怪しいものは極力調べて排除した.

結果

起動速度が半分になった! v (\^\^) v

Machine Time diff


Arch Linux 6.0 -6.1 Windows 16.7 12.9

リフリァクタリングした 設定ファイル

26 Dec 2014, 07:55

AWS の Amazon EC2 で Windows サーバを立ち上げて リモートデスクトップ接続してみた

はじめに

Amazon Web Service (AWS) をずっと試してみたかったので, 冬休みに試してみた.

以前, OpenStack を動かしてみた.今回はライバルを試す.

環境

  • ArchLinux

手順

まずは, アカウントを作成.

やりたいこと

Linux サーバと Windows サーバをお手軽に借りたい

利用できそうか?

AWS にはいろいろなサブコンポーネントがある.

これによると,

  • Amazon EC2 というものを選択すれば, 仮想サーバが利用できそうだ.
  • Amazon Lambda というものを利用すると,イベント駆動でサーバを制御できるようになる.

今回は, Amazon EC2 を利用してサーバを立ち上げる. 使うときに手動で立ち上げて, やめるときに手動で落とす.

Amazon Lambda を利用すると, EC2 を常時立ち上げていなくてもいいよう なので, コスト削減と自動化が達成できそうだが, 時間がかかりそうなので, 後回しとする.

料金

以下で料金が見積もれる. はじめの一年間は無料らしい.

Windows と Linux を最小構成で週 2 時間借りた場合は, 0.6 ドル??

Windows のインスタンスを作成

まずは 最小構成の Windows のインスタンスを作成してみる.

  • EC2 サービスを選択
  • Launch Instance を選択
  • Microsoft Windows Server 2008 R2 Base 64bit 選択
  • t2.micro を選択
  • あとはデフォルト設定で.
  • Launch をおすと Key Pair の作成を聞かれるので生成して, 選択.

参考

リモートデスクトップで接続

Linux 環境から Remote Desktop のクライアント rdesktop で接続してみる.

まずは, 接続に必要なパスワードを取得する. さっきダウンロードした Key Pair ファイルをアップロードすると, パスワードが表示される.

以下のコマンドで接続.

rdesktop -k ja (IPAddress) -u (Username) -p (Psssword)

Linux から Windows に接続できた!

24 Dec 2014, 12:03

プロクラミングパラダイムの意義と 2014 年のプログラミング言語の勉強まとめ

はじめに

edX で プログラミングパラダイムの講義を受けたのでその記録.

実は, この講座は受講が今回で 2 回目だ.前回受けたときの記録は以下.

なぜ 2 回も受けた?

理由は以下だ, 前回の講座で,

  • 単位を落とした…
  • 内容があまりにも素晴らしかった
  • 内容の理解をもっと深めたかった.

内容

内容は, 前回とまったく同じだった. スライドも動画も, そして問題も.

前回は 12week 連続で講義があったのに対して, 今回は 6week x 2 というように 2 つの講座に分かれていた.

あらためてパラダイムの整理

以下のようなパラダイムとコンセプトを順に説明していく.

Paradigms Concepts Features


Functional Programming Functions and recursion Hihger-order programming Single-assigned variables Object-Oriented Programming + cell Data Abstraction Polimorphism Inheritance Deterministic Dataflow Programming + thread No race conditions Concurrent transparency Streams and agents Multiagent Dataflow Programming + port Deterministic dataflow Nondeterminism where needed Active Object Programming + local cell Object-oriented programming Multi-agent dataflow

パラダイムを身につけることでどんな言語にも対応できる

この一年での言語の勉強記録

この 1 年で, たくさんの言語に触れた.

  • VBA (1 月)
  • Oz (3-4 月)
  • Scala (5 -6 月)
  • x86-x64 Assembly (7-8 月)
  • Python (9-10 月)
  • Haskell (11,12 月)
  • R (12 月)

2 ヶ月に 1 回は, 新しい言語に挑戦していた気がする.

また, 仕事で Ruby と Java をつかうようになって, オブジェクト指向言語を 利用することに対して抵抗がなくなった.

2 年前は C 言語しかできなかった

思い返せば, 2 年前は C 言語ただ一つしか使いこなすことができなかった.

このブログを始めたのが 2 年半前くらい. なんとなく, このままではダメだと思っていた.

去年はオブジェクト指向言語に触れようと思い, C++ と Ruby を独学で学んだ.

今年は関数型言語に触れようと思い, Scala や Haskell に触れた.

今では, 2 年前に感じていたような, 単一言語しかしらない劣等感がなくなっていた.

プログラミングを極める最良の方法とは

一つ一つ, 新しい言語に触れる度に, 理解するまでの時間が短くなっていくことを感じた. 言語のもつコンセプトの差異や共通点が見えてくるのが楽しい.

そして, そういう言語の妙を味わうための審美眼は, 間違いなくこの講座を受けることによって得たものだった.

プログラミング言語のコンセプトやパラダイムを身につけることが, 数多くの言語を身につけたり, 言語の本質を理解するための 効率のよい方法だということを, たくさんの言語に触れることで実感した.

この 1 年の最大の出会いは, CTMCP 本 (ガウディ本) に出会ったことだった.

これからどうするか?

CTMCP 本はいったん寝かせる

さらにプログラミングのコンセプトの理解を深めていきたい.

CTMCP 本を 2 回繰りかえして読んだのだが, まだまだ理解したとはいえない. 後半の方は読んでもいない.

ただ, edX があったからこそ読み進めることができたけれども, 一人じゃなんだかこの先を読むにも心が折れて挫折しそうだ.

この本は, この先も何度も何度も読み返していくことになるだろう. なので, いったん読むのを止めて, 別の本を読んでみようと思う.

最近発売された軽めの本

最近, コーディングを支える技術という本の電子書籍版 が出たのでこれを読んでみる.

電子書籍版は技術評論社の HP から.

目次を読む限り, 内容的にも重量的にも軽そうだ.

ガウディ本のライバル魔術師本

この CTMCP 本の前に出版された, 似たようなコンセプトでかかれた本がある.

通称, SICP 本, 魔術資本.これを来年読んでみる.

この本を扱った edX の講座と MIT のオンライン講義を見つけた. この講座のどちらかをベースにしつつ, 読んでみるつもりだ.

UC Berkeley: CS 61AS Structure and Interpretation of Computer Programs :SICP:

MIT courseware: Structure and Interpretation of Computer Programs

22 Dec 2014, 13:23

Emacs で R 言語を利用するための設定メモ (ESS)

はじめに

最近, 統計学と R 言語をさわり始めた.

なぜなら, 本屋にいくとビッグデータやら, データマイニングやら, データサイエンティストやら, そんな単語がポンポン目に入るから.

ということで, まずは Emacs で R 言語を快適に利用するための設定をしてみた.

もちろん, RStudio なんて便利なものは知っているがね.

ESS

Emacs を統計用 IDE にするツール. デファクトスタンダードと言えよう.

起動は M-x R.

(setq load-path (cons "/usr/share/emacs/site-lisp/ess" load-path))
(when (locate-library "ess-site")
  (require 'ess-site)

(setq auto-mode-alist
      (cons (cons "\\.[rR]$" 'R-mode) auto-mode-alist))
(autoload 'R-mode "ess-site" "Emacs Speaks Statistics mode" t)


;; R 起動時にワーキングディレクトリを訊ねない
(setq ess-ask-for-ess-directory nil)

ESS Auto-complete

R 言語の入力自動補完をするために, auto-complete を利用する.

(when (locate-library "ess-site")
(setq ess-use-auto-complete t)
;; (setq ess-use-auto-complete 'script-only)
)

ESS R Data View

データの中身がみれる.

;; (define-key ess-mode-map (kbd "C-c v") 'ess-R-dv-ctable)
(define-key ess-mode-map (kbd "C-c v") 'ess-R-dv-pprint)

popwin と組み合わせると便利.

ess-R-object-popup

オブジェクトの中身をポップアップで表示.

(when (locate-library "ess-site")
(require 'ess-R-object-popup)
(define-key ess-mode-map "\C-c\C-g" 'ess-R-object-popup)
)

gist 版は古いようだ.

no ESS process is associated with this buffer というエラー がでたら C-c C-s を叩く.

helm-R

helm インタフェースで 関数のヘルプをひくことができる.

(when (locate-library "ess-site")
(require 'helm-R)
(define-key ess-mode-map "\C-ch" 'helm-for-R)
(define-key inferior-ess-mode-map "\C-ch" 'helm-for-R)
)

org-babel-R

org-mode で R を利用する.

(when (locate-library "ess-site")
(org-babel-do-load-languages
 'org-babel-load-languages
 '((R . t)))
)

R 言語と org-mode で Reproducible Research を.

以下のようにタグでソースを加工する. C-c C-c で評価する.

#+begin_src R :file age_at_intake.png :width 400 :height 400 :results graphics

#+end_src

おわりに

半分以上のパッケージが myuhe さんが作成したものだと気づく. すごい. Special Thanks!