• このエントリーをはてなブックマークに追加

  • 型から学ぶプログラミング その2

    2016-03-02 23:00
    モデルを作成する前に、必ず通っていかなければいけないのが、型になります。

    モデルは、物質の原子(atom)のように最小単位の集まりで構成されています。その最小単位が型になるのです。きちーっと型を選択し、プログラミングしていけなければ、すぐに使えないソフトウェアとなって捨てられるでしょう。

    型を適切に選べることと、優れたプログラマであることは、かなり関連性があると思います。では、熟練プログラマと、未熟なプログラマを比較してみることで、型の大切さを考えてみましょう。

    熟練プログラマ

    熟練プログラマは、モデルの構成が上手なので、そのプログラムやソフトウェアは、バージョンアップがあったとしても修正は最小限となります。

    モデルを構成する、適切な型を選択できるので、不正なデータが入る余地がありません。適切にデータを管理できるためにバグが少なく、ハッキングもされにくいでしょう。もし、修正があってもすぐに直すべき場所をみつけることができます。

    結果として、仕事上のミスも少なくて、仕事をすればするほど、未熟なプログラマとの差が、クライアントや同僚に感覚として伝わっていきます。感謝や賞賛を受ける機会も多いでしょう。

    未熟なプログラマ

    未熟なプログラマは、モデルの構成が下手なので、そのプログラムやソフトウェアは、バージョンアップがある度に、大量のソースコードが改変されます。

    Webアプリケーションであれば、アップロードのし忘れが生じたり、関係ないファイルを上書きしてしまったりしてクライアントによく怒られます。

    モデルを構成する、適切な型を選択できないので、不正なデータが入り乱れるようになります。適切にデータを管理できないので、バグを直す度に新たなバグを呼んでしまいます。ハッキングもされたい放題。適切に直す場所が見つけられないので、回りくどい直し方をしてしまいます。

    熟練したプログラマからすると、不快でもはや吐きそうです。熟練プログラマは、一人でやったほうが速いので、できることならプロジェクトから未熟なプログラマを外そうとするでしょう。

    未熟なプログラマは、結果的に、仕事上ミスが多く、仕事をすればするほど、熟練プログラマとの差が、クライアントや同僚に感覚的に伝わっていきます。チーム編成を要求されたり、雰囲気が悪くなったりと、あまり褒められたものではないでしょう。

    実務経験3年でいけるか

    プログラマは、英語や中国語の勉強のように、とにかく身体で覚えることが大事という風潮があります。それは、一理あります。

    履歴書に実務経験3年程度あるのとないのとでは、見栄えが違ってくるでしょう。業界的に、手を動かしている人が評価される雰囲気はやはりあります。

    どれだけ、一流大学の計算工学科を出ているからといっても、就職する際は、経験や実績が見られるところでしょう。僕が、大学時代、アルバイトに応募した際も、実務経験が問われるところが多かったです。

    しかし、アウトプットされるコードは、いつも背景となる知識に基づくものです。きちーっとした基準から生まれた設計やコードかは、ひと目で解るものです。

    手を動かしていれば、熟練プログラマになれるかと言われたら、そうでもないというのが、僕の意見です。業務内、業務外関係なく、どれだけ、設計に関する思考を深められたかが重要です。

    これを踏まえて、きちーっと勉強していきましょう。今回は、型に関して学んでいきましょう。

    リスト (List)

    リストは、次に述べる、配列やベクトルとは違って、長さが可変なものを格納しておくための型です。つまり、リストは可変長な構造を持っています。

    長さが可変なので、扱うのは非常に便利です。値を追加する際は、末尾に付け加えるだけです。削除も、各言語の仕様や、自分で作成したリストの構造によりますが、基本的には簡単です。

    便利さに引き換え、犠牲にしているものは、読込速度です。リストは、基本的に要素を前から順番に読んでいきます。最後の要素を読み取るには、要素数だけの回数検索を掛ける必要があるのです。

    まとめます。リストのメリットは、追加、削除が簡単な点。デメリットは、検索にコストが掛かるです。このメリットとデメリットを覚えて次回から使ってみてください。

    配列・ベクトル (Array / Vector)

    リストの次に勉強するのは、配列、ベクトルです。配列とベクトルは基本的に同じなので、配列と呼ぶことにします。

    配列は、基本的に、定義した時点で長さが決まります。すなわち、配列は、固定長ということになります。

    リストに比べて、値を新規に追加する際は、配列の長さを伸ばさないといけません。削除は、配列の長さを短くする。これは、結構大変。配列は、定義した長さを変えることが基本的にないようにしなければいけません。

    配列の値の操作は、基本的に上書きと読み込みのみになります。どちらも、リストと違って、コストは非常に小さいです。配列の長さによらず一定時間で取り出せるのが配列となります。

    まとめます。配列のメリットは、読み書きのコストが掛からない点。デメリットは、配列の長さが変え難いということでした。

    連想配列 (Dictionary / Associative Array)

    連想配列は、値をキー・バリュー(key / value)で格納するための型です。

    { name: "ysawa", age: 29 }

    は、JSON (ジェーソン) と言われる連想配列の一種です。name と age がキーです。 "ysawa" と 29 がバリューです。

    連想配列は、辞書と呼ぶこともあります。辞書は、索引に対する定義や内容を調べるためのツールです。索引がキー、定義や内容がバリューということですね。

    読み込みは非常に簡単、先ほどの連想配列に、name を投げると、

    "ysawa"

    が出力されます。

    書き込みも簡単ですね。age に 30 を入れると、

    { name: "ysawa", age: 30 }

    となります。

    前回から扱っている、集合の中ではちょっと特殊な感覚がしますが、よく使う型です。PHP などでは、連想配列は非常によく用いられる型ですね。

    連想配列は、キー・バリュー。これだけきちーっと覚えておいてください。

    まとめ

    まとめです。集合やペアから始まって集合的に値を扱うための型を見てきました。

    全て特徴があり、適材適所だということがお解りいただけたのでは無いでしょうか。型というツールをきちーっと使い分けることが熟練プログラマへの第一歩となります。

    熟練プログラマになれるように日々努力していただければ、これほど嬉しいことはありません。
  • 型から学ぶプログラミング その1

    2016-02-24 20:00
    前回まででモデルに関して勉強してきました。今回は、モデルを構成する最小単位とも言える型に関して勉強していきます。

    ソフトウェアは、多くのユーザに対して同等の体験を提供するという役目があります。n次元では、「ユーザ体験は繰り返し」と言ったりします。

    ソフトウェアのソースコードを見ていると、複数のユーザやデータを取ってきて、ループ(繰り返し)させるようなコードがよく出てきます。まさにユーザ体験は繰り返しなのです。

    なので、プログラミングでは、複数の要素を集合的に扱うことが必要になってきます。集合的な要素を扱うことは、プログラマのスキルの中でも必須項目なのです。

    この機会にきちーっと勉強していきましょう。

    集合ってなんだったっけ?

    集合というと高校時代、数学で出てきてアレルギーになっている人も多いかもしれません。

    集合は、あまり受験でも重視されていないようで、「集合が出てきたら捨て問題」のように言われたりしてました。本当は数学の最も根幹となるような概念なのに残念です。

    しかし、理解すべきことは実は非常に簡単です。集合というのは、扱う世界の広さを制限します。集合は世界の広さ・狭さだと考えてみてください。

    ただ、集合は、広ければ広いほど良いというものではありません。

    郡(ぐん・Group)、環(かん・Ring)、体(たい・Field)の様に集合を拡張することがありますが、この拡張は、より優れたものにするということを意味するわけではありません。集合の広さは、制限することで扱いやすくなったり、より面白く世界を開拓していけるものなのです。

    例えば、同じ足を使うスポーツでも、サッカーとフットサルがあります。フットサルは、サッカーよりも狭いコートで構成されるスポーツですが、フットサルの方が面白くないとはならないでしょう。

    狭いには狭いなりの面白さがあります。人数が少なく、コートが狭ければ一人ひとりの働きがより重要になったり、初心者でもボールに触れやすかったりするメリットもあります。

    郡、環、体とある中で一番狭い集合を扱う、郡は、群論(ぐんろん)という数学の分野になって研究されています。また、体の中でも有限集合のみを話題を制限して有限体(ゆうげんたい、ガロア体、Galois Field)とし、こちらも非常に研究されています。

    集合は、数学の定義の中の一部で、ルールなるものです。ルールを縛るからその中で楽しむことができる。集合という概念がなければ、数学はそもそもなかったでしょう。

    桃太郎で学ぶ「集合」

    僕と皆さんで桃太郎の演劇をやるとします。そのときに、まず考えるのが登場人物の整理ですね。桃太郎に出てくる登場人物は、次の6人(匹)です。面倒なので、今後、動物も単位を「人」とします。

    A = { 桃太郎, おじいさん, おばあさん, さる, キジ, 犬, オニ }

    ここから、オニ退治に出る人を取り出すと、

    B = { 桃太郎, さる, キジ, 犬 }

    となります。これを部分集合 (Subset) と呼びます。B ⊂ A と書きます。人や動物の全体集合を U とすると、 A ⊂ U, B ⊂ U となります。

    ここで、重要なのが、A において、オニは何人かということはどうでもよいということです。実際は、オニは10人いるかもしれませんが、とりあえず、A では登場人物の種類のみに注目したということです。

    ここで、数も一緒に考えた方が便利じゃないかと思う人もいるかもしれません。素晴らしい想像力ですね。もちろん、それは可能です。

    A' = { { 桃太郎, 1 }, { おじいさん, 1 }, { おばあさん, 1 }, { さる, 1 }, { キジ, 1 }, { 犬, 1 }, { オニ. 10 } }

    という形で管理すれば、なんとか人数とペアで、登場人物を管理できるようになりました。一見、こっちの方が便利な気がします。しかし、本当でしょうか。

    もし、僕らの作った演劇のクライマックスがあまりにもしょぼかったら、さらにオニを追加したくなるでしょう。では、 A' に { オニ, 5 } を追加してみましょう。

    A'' = A' ∪ { オニ, 5 }
    = { { 桃太郎, 1 }, { おじいさん, 1 }, { おばあさん, 1 }, { さる, 1 }, { キジ, 1 }, { 犬, 1 }, { オニ. 10 }, { オニ. 5 } }

    あれ、求める結果となんだか違うような気がします。これは、{ オニ. 10 } と { オニ. 5 } が異なる要素なので、別々の登場人物として認識されてしまったからです。

    ここで、理解したいのは、今回の登場人物と人数の管理の仕方が間違っていたということです。前半は、登場人物の種類が把握できればよかったので、集合はすごく上手く機能してくれました。素晴らしいです。

    しかし、登場人物と人数の管理に関しては、別の方法があったのではないでしょうか。経験の浅いプログラマは、概してこのような間違った設計を選びがちです。

    知っている道具が少ないので、より適切なものがあっても気付かず、つい使い慣れたもので作業してしまうのです。解決方法は簡単ですね。道具の数を増やせば良いのです。

    では、順番にその道具を見ていきましょう。

    集合 (Set)

    先ほどやりましたね。プログラミング言語として集合を扱う場合、同じものが入らないことを保証します。

    A = { 1, 2, 4 }

    としたときに、

    A に 5 を追加すると、

    A = { 1, 2, 4, 5 }

    となります。

    再度、 A に 5 を追加しようとしても、

    A = { 1, 2, 4, 5 }

    のままです。複数のユーザに対して、1回ずつ繰り返し体験を届けたいときに使いやすいです。ユーザIDを集合に入れていくことで、同じユーザIDは、集合に2つ以上入れることができないため、重複を防ぐことができます。

    集合は非常に便利ですが、プログラミング言語によっては、使える言語は限られています。

    ペア (Pair)

    次に、ペアです。ペアは簡単で、2つしか要素を入れることができません。

    (ysawa, ブロマガ担当)

    とか

    (Shun, 動画担当)

    のように、2つを組み合わせてなにか情報を整理したいときに使います。

    シンプル過ぎて、使う場面がないまたは使いにくそうな印象を受けますが、Lisp や Scheme などの関数型言語では、非常に重要な型になります。

    Lisp や、Scheme では、基本的にペアを組み合わせて、次の節で述べるリストを構成します。ペアは、集合的な要素を考える基礎となっているわけです。

    Lisp や Scheme では、ペアは、以下のように作ります。

    (cons 1 2)

    => (1 . 2)

    1 と 2をペアにしたわけです。それぞれの要素を取り出すときはこうです。

    (car (cons 1 2))

    => 1

    (cdr (cons 1 2))

    => 2

    となります。car (カー) という関数、cdr (クドゥアー) という関数を使って取り出すわけです。

    ペアと、次に述べるリストや配列を組み合わせると連想配列ができあがります。Haskell ではよくこの型を使います。

    (Haskell ではペアという用語はなく、 タプル (Tuple) というような有限個の要素を代わりに使います。)

    続く...

    長くなりましたので、また続きは次回!


  • 動物園で学ぶモデル化

    2016-02-16 19:30
    プログラミングにおける「モデル」の大切さ、モデル化の難しさを、前回話ました。今回は、モデル化を皆さんにできるようになっていただこうと思います。

    もう一度、モデル化とは何か

    まずは、おさらいです。

    ある事象から、性質、動作、傾向などの特徴を抜き出し、抽象化することを「モデル化する」といいます。そして、事象をモデル化すると「モデル」になります。「ビジネスロジック」と言ったり。単に「ロジック」と言うこともありました。

    モデルを考えるときには、物事を俯瞰(ふかん)することが必要となります。上から見下ろす感じです。地図を見たことがある人なら解るでしょうが、地域によって、碁盤目状になっていたり、まばらに民家が存在したりといった、特徴があることが解るでしょう。

    このように特徴を掴むことがモデル化するための第一歩となるのですが、好き勝手に特徴を抽出したのでは、役に立つ物は作ることができません。やはり、ある程度トレーニングが必要となります。

    モデル化のトレーニングをする上で、プログラミングのオブジェクト指向では、いきなり自動車やポットを持ってくることが多いのですが、最初にやるトレーニングとしては、高度すぎるかと思います。

    最初のトレーニングでやると良いのは、パズル感覚でできる分類から初めてみるとよいです。分類をするには、特徴を必ず掴まないとできませんし、モデル化のよいエッセンスが含まれています。

    動物園にいってみよう

    では、実際に動物園の例で見てみましょう。

    僕も先日、動物園にいってきましたが、実に沢山の種類の動物がいます。自然界に、なぜこのように多様性が生まれるのかは実に不思議ですね。

    さて、今回は、「動物園で学ぶモデル化」です。動物園で会えるであろう動物をあげてみました。以下の動物をあなたなりに数個に分類してみてください。小学校とかで習うよくある分類でも構いません。
    このくらいでよいでしょう。用意するものは、紙とペンです。次の文章を読む前に、是非、手を動かしてやってみてください。

    さっそく分類してみた

    おそらく皆さんは、以下の様な分類になったのではないでしょうか。
    • 哺乳類: サイ、ニホンザル、白くま、リス、イルカ
    • 鳥類: ペンギン、ふくろう
    • 爬虫類: ワニガメ
    • 魚類: シーラカンス、サメ
    このような分類ができた僕らは、学校で非常に優秀な学生だったことでしょう。なぜか、僕ら日本人は、この分類を軽々とできるようにトレーニングされています。しかし、その詳しい理由は不明です。ダーウィンの進化論が大好きな人が多いからでしょうが、この分類が役立つことはクイズ番組意外ではほとんどありません。

    その証拠に、大学に入って生物学を勉強すると、上の分類は教科書や講義にほとんど出てきません。よく考えてみてください。生物としての特徴を把握するのに、この分類は不便ではありませんか。

    よくあるミスとして、イルカを魚類に入れたくなりそうになります。その感覚のほうがモデル化を勉強する人にとっては正しいのです。彼らの住環境、食生活は、サメなどの魚類とあまり変わりません。

    考えれば考えるほど、この分類が機能しないことが解るでしょう。困ったものです。

    こういう分類もある

    そして、より良く生物の特徴を掴んでいる人の分類は、以下のようになるかもしれません。
    • 水中に住む: シーラカンス、サメ、イルカ
    • 陸上に住む: ニホンザル、白くま、リス
    • 空中に住む: ふくろう
    • 水中、陸上両方に住む: ペンギン、サイ、ワニガメ
    このように分類をすることで、より特徴を掴むことができるかもしれません。その他にも、食生活や求愛活動に関する分類もできるかもしれません。

    住環境に関して分類してみたわけですが、住環境は、それぞれの生物の持つ「機能」にも、もちろん影響してきます。水中に住むには、「泳ぐ」という機能が必要かもしれませんし、陸上に住むには「歩く」とか「走る」といった前進するための機能が必要になるかもしれません。

    このようにして、分類するトレーニングを普段からするようにおすすめしたいです。例えば、電車に乗る人は、時間軸や服装や格好でどのような分類ができるか。一見、全く関係なさそうな2人を同じ分類に入れるにはどのようにしたらよいかなどです。

    このように分類しているうちに、自然に特徴や共通点に関して注目するようになっていることでしょう。実は、これが、僕の狙いです。

    いきなり目の前のものをモデル化してといっても不可能なのです。全体から考えたら対象物はどのようなものなのかを考えるようにするのです。分類するためには、当然、対象同士の共通点に関して考慮しなくてはいけなくなります。

    そのようにしているうちにもう、僕らは、モデル化できるようになってしまっているでしょう。

    プログラマがすべきこと

    プログラマがやらなければいけないことを簡単にいうと、世の中を便利にすることです。世の中を便利にするということは、将来のことをいっているように思えるかもしれませんが、それでは、今現在の飯代が稼げません。

    もちろん、お腹が減っているからといって、ご飯を食べ続けてもいけません。今を生きつつ将来の世界を便利にするのがプログラマとしてのあり方です。

    当然問われるべきは、今作っているものは、1年後にも使えるものか、もっというと10年後20年後も使えるかは常に考えるべきなのです。

    そこで必要なのが、モデルです。今作っているのは、今必要な機能として、将来も必要とされるためには、最大限の広がりをもってモデルを作成すべきなのです。

    将来使うか分からないような変数や関数をダラダラと並べていくのではなく、将来も使いやすいように、きちーっと分類してモデル化しておくことです。

    例えば、動物園のチケットを扱うモデル Ticket を考えたとします。子供は200円。大人は500円と仕様が決まっています。僕らは、Ticket を設計する際に、子供なのに500円という値が入らないように保証すべきです。同時に仕様になくても将来的にシニアが入れられるように考えておく必要があります。

    将来、キャンペーン・イベントなどをやったときに Ticket はどうなるのかも考えなければいけません。仕様にない場合も、プログラマとして気に掛けなければいけない問題となります。

    モデル化はやっぱり難しい

    先ほど、分類に関して学んでいただいたのは、分類は1つではないということを学んでいただくためでもあります。複数の分類がありますし、モデル化も1つの方法だけではありません。

    哺乳類、鳥類、爬虫類、魚類という分類で、そのままモデル化して安心していると、すぐに、「哺乳類なのに、住環境は水中です」、「鳥類なのに飛べない」などの複雑な要件や仕様が追加・変更がなされていきます。

    なにか、きちーっとモデル化が上手く言っているような気がしても、すぐに方向転換が求められることがあります。僕らのモデル化が間違っていたり、根本的に問題解決に繋がりにくいことがよくあるのです。モデル化がやっぱり難しい理由となります。

    このような難しい問題には、分類やモデル化に関するトレーニングを積むしかありません。テクニックでは、なんともならない問題となります。

    プログラマのよく発する言葉に、「気持ち悪い」「臭い」などの共感覚じみたものがあります。これは、将来も通じるモデルという視点で考えたときに、どう考えてもおかしなコードや設計だということから出る言葉です。なんだと言われても説明不能ですね。

    まとめ

    さて、プログラマがなぜ稼げるかというところに戻ってきますね。プログラマの仕事は、充実感がありますが、大変難しいものなのです。

    モデル化を的確にできるプログラマは、いつの時代も重宝されるでしょう。日々、きちーっと努力していく。モデル化のトレーニングは、プログラマの日々の筋トレのようなものだと捉えてください。