2012/09/28

線形代数学とオブジェクト指向は似てる!?


プログラミングを始めると「オブジェクト指向って何?」って壁にぶつかるのではないでしょうか?オブジェクト指向について調べると本当にいろんな情報が手に入って,結局よくわからなかったりします.とりあえずオブジェクト指向って難しいということだけ判るかもしれません.

結論から言うと,オブジェクト指向という言葉や概念に明確な定義はなく,
「プログラムなどをもの(オブジェクト)として考えること」
に近い意味を持っています.そして,定義が曖昧なために説明も抽象的になり難しく感じてしまうのでしょう.


しかし,現在ほとんどのプログラミング言語がオブジェクト指向をサポートしており,プログラミングを行う上でオブジェクト指向はなくてはならないと言っていいほど重要な概念であることも事実です.さらに最近ではオブジェクト指向を直接プログラミングとは関係のないシステム開発の上流工程に応用するといった動きすら存在します.ですが,オブジェクト指向についての理解が深まれば,オブジェクト指向言語の理解はもちろん,その概念は様々な場面で(時には無意識に)役立つことも多いかと思います.



では,どうやってオブジェクト指向を理解すればよいか?


そもそも,オブジェクト指向が1つの概念である(実際はそうなのですが)と思っていることを一度やめてはどうでしょうか?

1つの分野,プログラミングという科目のオブジェクト指向という分野.数学の線形代数学のような.

こう考えてみると,一言ではオブジェクト指向という分野について語れないとわかるでしょう.一朝一夕には学べないことがわかるでしょう.


ここで,結局時間をかけて学ぶしかないのかと残念に思わないでほしいのです.もはやオブジェクト指向という概念の把握にかける無駄な時間は必要ありません.いや,時間はかけなければならないのですが,オブジェクト指向という分野を構成している要素を1つずつ理解する有意義な時間の使い方を推奨します.学問の1分野を学ぶときも,1つ1つの概念を理解して,演習問題を解いて,応用問題に取り組んで…といった形で学んでいた人が多いのではないでしょうか.そして,その知識を使う段階(という経験があればですが)でより一層理解が深まっていったと思います.オブジェクト指向も同じで,構成する1つ1つの概念に対して,特に必要なものから順に理解し,応用し…を繰り返して学んでゆけばよいでしょう.結局は経験がなければただの知識しか残らないのですから.


とは述べたものの,オブジェクト指向プログラミング(OOP)について知りたい方と話したい筆者のために,少しOOPとは何かに対する抽象的な意見を述べておきます.OOPの本質はポリモーフィズムに代表される(同じ点を抽出して同じ像とみなす)抽象化にあると筆者は考えています.そもそも,コンピュータ上の(コードを含む)データをものとみなす行為が抽象化です.プログラミング言語の進化自体抽象化の歴史みたいな一面があり,オブジェクト指向を説明する人は抽象化が大好きで何でも抽象化して考える癖があるように思います.一般的な議論をすることも,異なるものに対して同じ要素を抽出してきて同じものとみなすことも,ある意味抽象化です.だから,オブジェクト指向の説明は抽象的なものが多く,実際の具体的なコードがなんとなく少なく,プログラム以外の他のものが例えとして用いられていることが多いのではないでしょうか.この文章のタイトルからしてすでに抽象化を用いたものになっています.
OOPでは,言語でサポートされているものとそうでないもの,基礎的なものから応用したもの(デザインパターンなど)まで様々なものとみなす抽象化のためのテクニックが数多く存在します.以下に基礎的な概念の一部を列挙してこの説明を終えようと思います.

概念 説明
ポリモーフィズム(多態性) 同じように振舞わせる操作の抽象化
継承,ダックタイピング 同じように振舞う動作の抽象化
型,クラス(構造体),インスタンス 同じ属性のデータや処理をまとめる概念の抽象化
カプセル化 詳細を隠蔽し単純にする抽象化


最後になぜ,似ている分野の例に線形代数学を挙げたのかを説明しておきましょう.
それは,筆者が始めにどんなものか知ったときは大して必要なさそうに感じたものの,学ぶうちに必要不可欠なものに変わった点が似ていたためです.また,どちらも抽象化し,簡単にし,人間の理解を助けるという点でも似ているのではないでしょうか.

2012/09/12

プログラミングを勉強しなくちゃと思ったら


なんとなく,プログラミングを勉強しなくちゃと思った時,まず,プログラミング言語を選んでいる(決めてしまっている)人が多いと思います.もちろん選択の余地がない人もいるかもしれませんが,もし,自分で選べるならこんなに幸運なことはないでしょう.もし,使ったことがある言語があったとしても,再考してみるのもよいかもしれません.

今回はすこし,プログラミング言語をどう選ぶかについて考えてみます.


ちなみに,誰でも,自分を無意識に正当化する傾向があるために,自分が使っている言語の短所が見えなくなりがちです.自分が使っている言語の長所を過大評価しがちです.プログラミング言語についての評価には必ずと言っていいほど,評価者が使っている言語が影響を与えていると理解した上で,情報収集することを推奨します.


まず最も重要なことは,プログラムを書いて実現したいこと(目的)をはっきりさせておくことです.

データ処理なのか? ライブラリ・アプリケーション・システム開発なのか? 等


特に各領域に特化した言語(DSLやそれに準ずるもの)であるほど,できないことが多いです.
(しかし,これは欠点ではなくむしろシンプルさを追求した長所でしょう.)


そんなこと,初心者にはわからないよーってときは有識者に聞くか,自分が達成したいことに近いことをしている言語を探すといいでしょう.ついでに,プログラミング以外の方法も検討するとよいかもしれません.既存のアプリケーションを使えばできることも多いと考えられます.小規模なデータ処理が目的ならExcelで十分な場合が多いです.Excel(VBAじゃなくて)はデータがフロントエンドのプログラムだという人もいます.


そして,次に拡張性と使いやすさ,簡単さを天秤にかけます.



どんな項目で判断していけばいいか列挙してみます.


フレームワーク

  • 簡単にプログラムを動かせるのか?
  • 環境は簡単にインストールできるか?
  • そもそもどうやって動かすか?
  • ツールのサポートは?

言語の入力しやすさは 文法の簡単さ単純さ・ツールによる補完 によって決まると考えられますが,両方を追求することは難しく,トレードオフの関係にあるといってもよいでしょう.文法の簡単さ有利なのが,動的と呼ばれる言語で,使う関数の数などがあまり大きくならない分野での,素早い開発に適しているといえます.一方,ツールによる補完には静的と呼ばれる言語が有利です.入力補完は開発者の記憶までも補完してくれると考えられます.


ライブラリ

  • 言語デフォルトのライブラリは充実しているか?
  • 目的を簡単に達成させられる既存のライブラリは存在するか?手に入るか?

とある言語を学ぶ上で,ライブラリの存在は大きく,そのライブラリを調べる作業が必要になってきます.そのためにはライブラリの調べ方と,調べたい内容についての知識が必要です.

コンピュータは人が考えたものなので,法律みたいに決まりごとが沢山あります.うまく使うにはコンピュータ自体の理解も必要になります.処理速度を上げたいならCPUの仕組み,ファイルを扱いたいならファイルシステムについてよく知っているほど,ライブラリを調べるのが容易になるでしょう.更にライブラリ自体にもプログラミングのノウハウが詰まっています.よってプログラミングパラダイムなどの知識も調べる役に立ちます.


リファレンス

  • どのくらい情報が出回っているか?どうやって情報を取得するか?
  • その言語が有名かどうか?
  • 使える人が周りにいるか?

勉強するなら情報は多いに越したことはありません.本屋での書籍数・Web検索結果でおおよそのその言語の普及具合がわかります.Web上の情報量を示したTOIBE Indexっていうのもあります.どうせ学ぶなら注目されているものを学びたいものです.


文法

  • 学びやすいか?
  • 記述しやすいか?

文法は上の3つに比べたら些細な問題です.最近はほとんどの言語が他の言語の長所を取り入れる形で文法とライブラリの拡張が行われています.



ほとんどの言語は拡張すれば(簡単かどうかは別にして)いろんなことができるようになっていきますが,面倒なことに変わりはないので,言語デフォルトのライブラリやフレームワークがその言語を特徴づけていると言えるでしょう.


最終的には上にあげたことを踏まえたうえで何を使うか自分で決めるしかありません.
おおまかな指針としては,
小規模な問題には動的な言語でライブラリが充実しているものを,
大規模な問題には静的な言語でリファレンスが充実しているものを利用するのがよいと考えられます.

2012/09/11

パラダイムシフトを受け入れよう

プログラミングは複雑な作業であるため,これまでに多くのノウハウが蓄積され,その多くがプログラミング言語の仕様として取り込まれています.そのためノウハウの取り入れ方の異なる数多くの言語が存在しています.

最も根本的なノウハウはプログラミングパラダイムと呼ばれ, プログラミングパラダイムの取り入れ方の違いでプログラミング言語の基本仕様が異なります.

プログラミング
パラダイム
説明
命令型 CPUへの命令を順番に記述していく.
命令の構造化 CPUへの命令をループ・条件分岐・式などのブロックに分けて記述していく.
データの構造化 複数のデータをまとめて1つのデータとして扱う.
オブジェクト指向 複数のデータと処理を関連付けて,それらを1つの「もの」として扱う.
関数型 複数の関数を組み合わせて関数を作っていく.関数と値を区別しない.
アスペクト指向 呼び出す関数の処理の詳細を,呼び出している側で把握,改変できるようにする.
論理型 論理を記述して,結果を得る.


各プログラミングパラダイムの詳細な説明はかなり長くなるのでここでは割愛します. 各プログラミング言語は複数のプログラミングパラダイムを持つことが多く,パラダイムの影響度も言語によって異なります. 更に1つの言語をとってみても何回かのバージョンアップで異なるプログラミングパラダイムを取り入れていることも珍しくありません.

1つのプログラミングパラダイム(言語)に慣れ親しむとそのやり方(=ノウハウ)だけでほとんどのプログラムは作成できてしまいます. それで十分なときもありますが,もっと簡単な方法がある場合が多いので複数のプログラミングパラダイムを体験することは (同じ言語を使うときでも!)今後の作業を大幅に短縮してくれることでしょう. もともとプログラミングパラダイムは言語仕様以前のノウハウなのです.

最近ではほとんどの言語でOO(Object Oriented=オブジェクト指向) が取り入れられているので知らないうちにオブジェクトを使っていることが多いです.

しかし,使い道がわからない道具は無いのも同然で, オブジェクト指向が何かがあいまいなままでは,どんな道具も同じ釘を打つ物体にしかなりません.

オブジェクト指向プログラミングにおいて,最も重要なのはオブジェクトの存在と, そのオブジェクトがどのようなものかです.

オブジェクトがどのようなものかをコンピュータ上で表す方法に型システムというものがあります. これは元来,コンピュータ上のデータを意味のあるものとして扱えるように導入されたノウハウですが, さらに拡張されてオブジェクトがどのようなものかを表すために用いられています.

プログラミング言語は型の扱い方とそれに伴う言語仕様で大きく以下の3つに分類されます. この分類は言語の実行環境との関係も深いです.

型システム 説明
1 型システム無し  初期・低レベルのプログラミング言語に多い.
 CPUの機能を最大限活用できるが,データの意味を間違いやすい(わかりにくい).
 C言語などプログラマ自身でメモリ管理を行える(しなければならない)言語は高速なコードが生成可能.
アセンブラ
C言語
COBOL
BASIC
強引に型を変換する

弱い静的型付け
2 型をコンパイル時に確認し,型変換エラーを検出する

強い静的型付け
 型の間違いをコンパイル時に見つけることができるが,記述が面倒.
 コードから型が判別でき,エディタでのサポートが充実しているものが多いが,コンパイルなどの実行のための作業が面倒.
C#
C++
F#
Java
Fortran
Haskell
Objective-C
ObjectiveCaml
ObjectPascal(Delphi)
Scala
VB.NET
3 型を実行時にインタプリタが確認し,強引に型変換する

弱い動的型付け
 型の宣言が不要で簡素な記述ができるが,実行するまで間違いに気付けない.
 エディタのサポートがない反面,多くの言語に記述と実行が同義のインタラクティブな環境があり,すぐコードがテストできる.
 コードから型が判別でき,エディタでのサポートが充実しているものが多いが,コンパイルなどの実行のための作業が面倒.
 弱い型付けは型の概念が希薄で初心者にとってわかりやすいが,強い型付けよりもエラーに気づきにくい.
Erlang
JavaScript
Parl
PHP
MATLAB
型を実行時にインタプリタが確認し,型変換エラーを検出する

強い動的型付け
Lisp
Mathematica
Prolog
Python
R
Ruby
Scheme
Smalltalk


OOとは何か,簡単にいえばただのノウハウですが,OO言語を使えば否応なしに型の存在と向き合うことになります. その時,型が「コンピュータ上のデータ+αを表すもの」ということを, OO言語(OOとしての機能)を使い始めた方は意識するとよいでしょう.

型システムはもはや無くてはならないプログラミングのノウハウなのです.