新・日々録 by TRASH BOX@Eel このページをアンテナに追加 RSSフィード

2017-04-08

即席プログラマー養成読本 α版

やあ、ようこそ職業プログラマの世界へ!

この文書は、何の準備もなくコの業界に飛び込んでしまった文系プログラマ候補)や、将来的にコの業界に就職するかもしれないし就職する気もあるけど基礎が足りてないと自覚している学生に、比較的短期間で商品知識以外の職業プログラマの技術的基礎を叩き込むための技術書のリストだ。対象が対象だけに、そこそこやさしめかつ極力高くない本を選んでいるつもりだ。*1

比較的短期間ってどのくらいか、だって? 驚くなよ、3年だ

――えーと、3年なんて長すぎる? またまたご冗談を。10日間とか半年で何となかるだなんて信じてもないくせに。それぐらいで何とかなるのは、それなりに下地のある人か、非常に才能に溢れている人ぐらいなのよ。これを読んでいるあなたが、そんな一握りの人たちの仲間だというなら、それは非常に喜ばしいことだよね。でもそういう人はごくわずか。世の中は「自称『普通の人』」で溢れているものさ。

3年という区切りは、その間に常に新しいことを学び続けてきたと自信をもって言えるのなら、次の展開を考える良いタイミングだ。本格的に開発者の道に進むのか、開発者以外のキャリアに進むのか。コの業界から足を洗うのもありだ。いや本当に。コの業界だけが働き先ではないからね。

このリストの目的は「技術的基礎を叩き込む」だ。これはつまり、システム開発において抽象度の低い部分であるコンストラクション(詳細設計、実装、開発者テスト、デバッグ)の基礎体力をつける、ということだ。

システム分析・設計は抽象度の高いところから始まるけど、最終的にはソースコード(時にはオブジェクトコード)という抽象度の低い電算機寄りの世界に到達しなくてはならない。いくら設計がすばらしくても実装がグズグズならダメだから、コンストラクションの技術は必要だ。その逆に、いくらコンストラクションの技術が高くても、肝心の設計が「実装の都合」を全くもって無視していたらダメだ。その設計は使い物にならない机上の空論にすぎない。使い物になる設計にしたいなら、どこかの段階で「実装の都合」も考慮する必要がある。その「実装の都合」を知る方法の1つが「コンストラクションの世界を経験する」だ。

設計と実装の間に断絶なんてない。そこにあるのは、設計から実装にいたる1つのスペクトラム(連続体)だ。だから、設計と実装が分断された別物だという考えは改めるべきだ(そんな風に考えても、何も良いことはないよ)。どちらも学ぶべきなんだ。

このリストには欠けている部分がある。「技術的基礎を叩き込む」なので技術以外の要素が省かれている――だけではなく、特定のプログラミング言語や開発ツールといった商品知識の本も極力載せていない。

なぜなのか? 使用する言語やツールは、開発対象やチーム内文化によって変化するからだ。だから、まずは新人教育や学校の講義で教わるだろう言語・ツールに慣れてほしい。特に新人教育の場合、君の先輩は、例えばC#Java案件が圧倒的に多いのにCobolを教えようとはしないはずだ――外部要因がなければ、だけど。

それと、これを書いている私は、どちらかと言えば組み込み系のCプログラマで、少々移植性のあるミドルウェアライブラリを実装するのが本職の人なので、そういった方面のバイアスがかかっているだろうことを記しておこう。

とりあえず3年間、新人教育やOJTの合間をぬいつつ、このリストの本を読んで実践してみよう。あ、でも不幸にも炎上案件に巻き込まれてしまったなら、無理せず休もう。

ディジタル作法

まずは基礎知識から。技術面の下地がない人がコンピュータネットワークについて概要を学ぶのにちょうどよい本といえば『ディジタル作法』だ。

ディジタル作法 −カーニハン先生の「情報」教室−

ディジタル作法 −カーニハン先生の「情報」教室−

「未来の大統領のための情報教科書」という按配で、要は技術系ではない人がコンピューティングについて正しく理解するための基礎知識がまとめられている。技術系の人も元々は非技術系だった訳で、これから技術系を目指すにあたってのスタート地点にちょうどよい本だ。

作者が作者だけに*2、類似本と比較すると技術的な土台がしっかりしているし、類書で省略されていたりたとえ話で誤魔化していたりする部分も現実に即してかつ分かりやすく書いてある。

この文書技術者予備群を対象として書いている。なので、下手な省略やたとえ話で誤魔化すような本ではなく、真っ向から立ち向かって解説している本書のような本を推奨している。読者には、そういう本を読んで理解しようとする気概を求めたいんだ。この仕事、理解が曖昧なままに表面だけ見て突き進むと、結果として失敗することが9割だからね。ちなみに残りの1割は「大失敗する」だ。システム開発は、かくも険しいものなりて。

『痛快!コンピュータ学』

少し古いけど、『ディジタル作法』よりも情報科学寄りの入門書として、これも挙げておく。

痛快!コンピュータ学 (集英社文庫)

痛快!コンピュータ学 (集英社文庫)

この本も技術的土台はしっかりしている。コンピュータの原理については『ディジタル作法』よりも少し踏み込んだ内容になっている。

なによりも安い! さすが文庫本

17年前(つまり前世紀)の本なので、時事ネタこそ古びているのだけど……でも内容は結構良くてかつコンパクトにまとまっている良書なのよ、半導体プロセス量子力学の壁の話(今は10nmと7nmでの競争かな?)とか、さらっとだけど記述があるぐらいには。

『CODE コードから見たコンピュータのからくり』とアーキテクチャ本を一冊

コンピュータの原理について、もう少し突っ込んだ内容を学びたい人には、結構ボリュームがあるけど『CODE コードから見たコンピュータのからくり』を推奨する。

CODE コードから見たコンピュータのからくり

CODE コードから見たコンピュータのからくり

基本情報技術者の勉強をしていると、2進数や論理演算や論理ゲートの話が出てくる。この本を読めば、それらの要素が現実のコンピュータとどう結びついているのか分かるはずだ。

論理ゲートなどの話は、計算機科学的にはコンピュータアーキテクチャの話だと思う。大学の情報学部なんかでは、履修する講義によってはパタヘネ本こと『コンピュータの構成と設計』を買わされる気がする。

個人的には、もはや「『コンピュータの構成と設計』ことパタヘネ本」と言った方が適切じゃないかと思うんだけど、どうだろう。

コンパクトにまとまった本として『コンピュータアーキテクチャエッセンス』もあるけど、一部微妙に翻訳が……。それさえなければ、懐にやさしい良い本なのだけど。

プログラミング作法

ソースコードを記述するようになったら、『プログラミング作法』を読もう。以下のどちらも内容は同じだ。

プログラミング作法

プログラミング作法

プログラミング作法

プログラミング作法

この本には、設計*3・実装・デバッグ・テストまで、コンストラクション一通りについて、プロのプログラマがとるべき所作がまとめられている。

所作や癖は、一度身についてしまうと、後で直すのが大変だ。だから、最初が肝心。鉄は熱いうちに打てということわざに従って、キャリアの初期にこそ正しく王道の所作を学ぶべきだ。そのためにも、この本を活用すべきだ。

ちなみに著者の片方は『ディジタル作法』の人。もう一人も界隈では有名というか、最近はGo言語で有名というか、そういう人だ。

『リーダブルコード』

システム開発は協調作業だ。ソースコードは他人や「数年後の自分自身」も読む。自分しか読まないと思って適当に書いたコードが、気づかぬうちに他人に引き継がれてしまい、読み難さゆえに陰で悪口の対象となることはままあることだ。例え引き継がれなくとも、数年後の自分が解読に苦労する羽目になることが大半だ。

だからプログラマは、いつでも「他人に読みやすい形式」でソースコードを記述しなくてはならない。

じゃあ「他人に読みやすい形式」って何だろう? その辺のエッセンスがこの本に凝縮されている。

この本が出るまでは、一冊にまとめられた知見を得るためには、他人のソースコード(それも筋の良いもの)を読んで勉強するか、『Code Complete』みたいな厚くて高い本に手を出すしかなかったと思う。良い時代になったね。

名前重要。別に『リーダブルコード』で扱っているのは「名前」だけではないけど、名前重要ソースコード名詞の集合体かと思えるほど名前が溢れているからだ。名付けの極意は「名は体を表す」だと思っているけど、なかなか難しい。

ソフトウェアの複合/構造化設計』

関数(プロシージャ/サブルーチン/etc)の作り方に迷ったら、古典だけどこんな本がある。もうちょっと新しい本がないものかなあ。

ソフトウェアの複合/構造化設計

ソフトウェアの複合/構造化設計

ざっくり言うと、この本の中で、基本情報技術者に出てくるモジュール強度/結合度・STS分割・TR分割・ジャクソン法について例題を元に解説している*4。なので、読んで実践することで、関数による機能分割を理詰めで行えるようになる。

もちろん、こういう技法は常に適用できるわけではないのだけど、でも関数を作る時に、関数の良し悪しを判断する基準の一つとして使える(あくまでも「基準の一つとして」だよ?)。札は多いに越したことはない。

最初はモジュール強度/結合度。次に状態遷移*5とジャクソン法(ジャクソン構造図って、文字列処理に適用したら、正規表現そのものだよね)。これだけでも、意識することで随分と見通しのよい関数群になる。

この本は古典なので、関数による機能分割について、書かれていないことは山ほどあることに注意してほしい。もう少し新しくかつフォーマルかつプログラマ向けな本がないかなあ。

アルゴリズムとデータ構造」についての基礎本を一冊

ハイ皆様、アルゴリズムとデータ構造にひれ伏しましょう :)

その昔『アルゴリズム+データ構造=プログラム』なんて本*6があったのだけど、実際のところ、現在でも大規模プログラミングにおける「モジュール」や「クラス」といった粒度の世界では一般的なアルゴリズム・データ構造は非常に重要な要素だ。

というのも、そもそも一般的なアルゴリズム・データ構造は小規模なプログラミングにおける重要要素なのだけれども、大規模プログラミングでは分割統治が当たり前な訳で、最終的に、分割された個々のパーツは小規模プログラミングの対象となる。ならば、個々のパーツたる「モジュール」や「クラス」の実装でも、一般的なアルゴリズム・データ構造は重要な要素となるのだ。*7

もう1つ言っておくと、システムが階層化された結果として、プログラムの上位階層の実装があたかも「便利なAPIを使った小規模プログラミング」風となった場合には、その上位階層の実装(≒小規模プログラミング)でも一般的なアルゴリズム・データ構造が重要な要素となりうる余地がある。

高度なアルゴリズム・データ構造は、当然ながら重要なのだけれど、そうではない一般的なアルゴリズム・データ構造も、地味だけど意外と重要なのだ。

現実のプログラミングでは、どちらかと言えばアルゴリズムよりはデータ構造の方が重視されることが多いと思う。ロブ・パイクの「Data dominates」は至言であり、同時に、これは私事なのだけど、私がかつて師匠に言われたことでもある。

アルゴリズムとデータ構造に関する本は色々あって、個人的には『アルゴリズムイントロダクション 第3版 第1巻: 基礎・ソート・データ構造・数学 (世界標準MIT教科書)』と『アルゴリズムイントロダクション 第3版 第2巻: 高度な設計と解析手法・高度なデータ構造・グラフアルゴリズム (世界標準MIT教科書)』とか、『入門 データ構造とアルゴリズム』とかを推奨したいのだけど、この文書の想定読者にはちょっとレベルが高いので……。

とりあえず「まずは、自分が使い慣れている言語で書かれた『アルゴリズムとデータ構造』の入門書を買って読んで手を動かしましょう」とだけ言っておく。

私の場合だと、最初に正式に触れた言語がJavaだったのと、職業プログラマになってからC言語でガリガリとコードを書いてきたこともあって、キャリアの初期には以下の2冊にお世話になった。

定本Javaプログラマのためのアルゴリズムとデータ構造

定本Javaプログラマのためのアルゴリズムとデータ構造

注意点として、この手の入門書に出てくる初歩的なアルゴリズムやデータ構造は、現実のプログラミングにおいては「よく使われるから言語機能ないしライブラリに用意されている」か「あえて使うメリットが薄いから用意なんてされていない」であることが多い*8。ある程度高度なアルゴリズム・データ構造でもなければ、プログラマが自作する機会は少ない。*9

ただ、自作するにもライブラリを使うにも、そのアルゴリズムなりデータ構造なりの特性を理解する必要があるし、正しく理解するための第一歩として計算量というかO(オーダー)記法に慣れる必要がある。安定である必要があるのに標準ライブラリクイックソートのルーチンを使ってしまったら台無しだし、O記法が分からないとvectorに代わる(解こうとしている問題に)より相応しいデータ構造をSTLから選び出せないかもしれない。

慣れるための第一歩としての「初歩的なアルゴリズムやデータ構造の入門書」を、私は否定しない。いずれ、必要に応じて次のステップに移るべきだとは思うけどね。

アルゴリズムとデータ構造の扱いにおいて注意すべきことがある。それは「ライブラリが用意されているか否か」だ。これによってアルゴリズムとデータ構造に対するアプローチが少し変わってくる。

まず、採用を考えているアルゴリズムやデータ構造がライブラリ等になく、自前で実装しなくてはならない場合には、ロブ・パイクの "Notes on Programming in C" のルール2〜4に従うべきだ。

Rule 2. Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest.

Rule 3. Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don't get fancy. (Even if n does get big, use Rule 2 first.) For example, binary trees are always faster than splay trees for workaday problems.

Rule 4. Fancy algorithms are buggier than simple ones, and they're much harder to implement. Use simple algorithms as well as simple data structures.

http://www.lysator.liu.se/c/pikestyle.html

凝ったアルゴリズムの実装は難しく、バグを入れ込みやすい。それに凝ったアルゴリズムはデータ量が大きい場合に効果がある反面、データ量が少ない場合にはかえって遅くなるもので、そして往々にしてデータ量は少ないものだ。だから、実際に計測した結果、(バグリスクを負ってでも)本当に必要であると分かるまでは、シンプルなアルゴリズム・データ構造を使うべきだ。

一方で、採用を考えているアルゴリズムやデータ構造がライブラリとして用意されている場合はどうだろうか?

こちらも計測は必要であるし、データ量を勘案しなくてはならない点も同じだ。しかし、採用の可否を検討する際に「バグリスク」は低く見積もってもよいだろう。ライブラリは(特に言語処理系に付属の標準ライブラリは)十二分にテストされているだろうし、多数の人が使ってきた実績があるだろうからだ。つまり、ルール4は低めに見積もってもよい可能性が高い。

リファクタリング』と『レガシーコード改善ガイド』

職業プログラマのお仕事は、全く新規にコードを書くだけではない。既存のコードベースに手を加えることも多い。なので、既存のコードとの付き合い方も考えなければならない。

……リファクタリングですな、余りにも汚いなら。

白状しておくと、先にも書いたように、私はどちらかと言えば組み込み系のCプログラマなので、『リファクタリング』と『レガシーコード改善ガイド』はところどころ読んだだけだ。オブジェクト指向プログラミングとは縁遠いのて――メソッドリファクタリングとか、参考になる部分もあるので、全く読んでいない訳ではないのだけど。

一方で、品質の要求が高いこと、コードベースの寿命が長いこと、ミドルウェアライブラリというドライバファームウェアより一つ上の階層にいることより、関数単位での開発者テストは毎度実施するし、3分の1ぐらいはテストを自動化している。意外とリファクタリングをしやすい環境にいるのだ。変則的だけど「リファクタリングした上で機能追加」というアプローチも多い。

――という程度には、オブジェクト指向プログラミングと縁遠くてもリファクタリングにまつわる知識は重要なので、好き嫌いせず読んだ方がよいっす。

『達人プログラマー

プログラミング作法』がコンストラクションでとるべき所作をまとめた作法本なら、『達人プログラマー』はコンストラクションの王道を説いた兵法書といったところ。

どちらもキャリアの初期から愛読すべき一冊ですな。

新装版 達人プログラマー 職人から名匠への道

新装版 達人プログラマー 職人から名匠への道

今なら新装版がオススメ。旧版も悪くはないけど、例えば新装版はツール類や言語が最近のものにアップデートされているらしいので、今からキャリアを築こうとする人や、最近この道を進み始めた人は新装版の方がまだとっつきやすいはず。

『達人プログラマー』は『プログラミング作法』よりも少しだけ抽象度の高い内容が書かれている。とはいえ、どちらもコンストラクションに根ざした内容ばかりだ。先輩プログラマからの「ああすればよい」「こうすれば効率的」といった実践的な助言集だと思えばよいかな。

この手の情報は、「職場という閉じた空間」では内容の良し悪しが構成メンバーの力量に左右されやすい。時に古い内容や、時に誤った内容が伝授されてしまう危険がある。

なので、密室に閉じこもるのではなく、せめて「書籍」という形でもよいので外の知識を参照した方がよい訳で。その上で、余裕があるなら布教を……。

『プロダクティブ・プログラマ

つくづく実感するのが、プログラマは怠惰が短気を背負って歩いている不遜な輩であるという事実だ。

実際のところ、例えばプログラマは毎月1回Excelシートに毎度同じような情報を入力する作業が面倒すぎて耐えられない。前月のシートから内容をコピペするのも、それ以前に前月のシートをコピーして当月のシートにすることからして、作業開始直後に発狂してしまうほどに耐性がない。

だから、VBAVBScriptJScriptPowerShellやその他COMを叩けるスクリプト言語を学んで、徹夜してでもツールを自作して作業自動化してしまうのである。

……うん、何の論理的破綻もみられない、完璧な理論武装だ。

基幹業務の何割かを情報システムで自動化してきた人が、自分たちの作業を全く自動化しないだなんて、狂気の沙汰以外の何物でもないよね。

ということで、プログラマとしてより生産的になるためにも『プロダクティブ・プログラマ』を読むこと。

本書前半の「技法編」に出てくる個々のツールには、今となっては時代遅れなもの(本書は8年前の本なので)や、業務内容的にそぐわないもの(iOSアプリEclipseで開発するのは、プログラマ的にも「酔狂」に分類される所業だ)もあるので、注意が必要だ。だけど、「なぜ、そのツールを使うのか?」や「そのツールから何を得られることを期待しているか?」といった背景部分は今でも変わらず通用するので、そこを理解した上で代替を探すようにすること。

デバッグの理論と実践』

書きたてホヤホヤのソースコードにはバグがあるもので、試しに少し動かしてみただけで変な振る舞いを見つけることもあれば、ソフトウェア・テストでいぶり出されることもある。

そういう怪しい部分を見つけたら、デバッグだ。問題が起きている部分を特定し、その箇所で問題が起こる原因を調査・特定し、外部要因その他を勘案して修正方針を決定し、修正し、テストして「バグが修正されていること」と「新たなバグを作り込んでいないこと」を検証する。

デバッグは非常に重要なものの、設計・実装・テストよりも属人性が強いためか、あまり書籍などで語られることのない領域だ。どちらかといえば、プロジェクトの現場にて先輩から後輩に伝授される系の技術であることが多い。

そんな中、『デバッグの理論と実践』はほぼ唯一の、科学的な手法にもとづくデバッグの戦略について書かれた本だ。

デバッグは「仮説と検証」の繰り返しだ。個々の仮説の内容や検証の方法はコンテキストへの依存性が強いものの、仮説を立てる時や検証の際の指針というメタ視点では、この本で語られている戦略は非常に有用だ。

ソフトウェア・テストの技法 第2版』

コンストラクションの締めに、ソフトウェア・テストの本。

テスト担当じゃなくても、コードを書いたら開発者テストは必要だ*10。書きっぱなしは悪い文化――いや冗談じゃなくて本当に。

見た目は正常に動作してそうでも、裏で問題が進行していたり、ちょっと周辺環境が変わると問題が表面化するような、「たまたま、偶然、それっぽい感じに動いていただけ」というケースは多いし、そのようなケースは「テスト担当によるシステムテスト」では発覚しにくいものだ。

だから、そのコードに一番詳しいだろう「書いた本人」が、出来立てほやほやのコードを、ハンマー片手に創造的に破壊しなくてはならない。それが開発者テストだ。そのためにも、テスト担当じゃなくともソフトウェア・テストについて学ぶ必要がある。

また同時に、ソフトウェア・テストに詳しくなるということは、テストにて注目すべき頻出事項――すなわち「よくバグを作り込んでしまう部分」に詳しくなることでもある。なので、ソースコードを漫然と記述するのではなく、ミスしがちな部分に最新の注意を払うようになることで、最初からバグを作り込んでしまう可能性を低くする効果も得られる(もちろん個人差はあるけど)。

個々の技法を除けば、ソフトウェア・テストの真髄は『ソフトウェア・テストの技法』にまとまっていると思う。

せめて「第1章 自己診断テスト」だけでも読んで、打ちのめされなさい。いや本当に、良いテストケースを考えるのは難しいのよね。

人月神話

コンストラクションについて一巡りしたところで、職業プログラマの基礎教養として、ソフトウェア工学とプロジェクト管理についての古典かつバイブル*11の『人月神話』を読もう。

あ、原書発行20周年記念増補版ないしそれの新装版がお勧め。

人月の神話【新装版】

人月の神話【新装版】

下っ端プログラマもプロジェクトの成員なので、大規模ソフトウェア開発がどういった点で難しいかについての知識仕入れておいた方が良い。じゃないと「後から追加で増員の増員」なんて話をもろ手を挙げて賛成しちゃいかねないよ。

なお、このページで推奨されているように、この本は最初から順に読むのではなく:

  1. 18章(著者自身による1〜15章の抄訳:1975年時点の見解)
  2. 16章(1986年時点の見解)
  3. 17章(1995年時点の見解)
  4. 19章(1995年時点の見解)
  5. 1〜15章のうち、気になったところ

――という順序で読むと結構楽だ。その情報、10年前に聞きたかった。

『アンダースタンディングコンピュテーション』

ここまで実務寄りの本ばかりだったので、ここで理論寄りの本を1冊。

理論計算機科学という計算機を理論的に研究する分野の中に、計算理論という「じゃあ『計算』って何なの?」とかそういうことを理論的に研究する学問がある。

その計算理論を齧る本として『アンダースタンディングコンピュテーション』を読んでおくといいことがあるかも。

忘れがちだけど、コンピュータって2進数の計算機なわけだ。たまたま、「情報」という形のない代物を2進数の数値で表現できることに気づいた天才がいたおかげで、「計算によって情報を生成・加工できる!」ということで情報処理に使われるようになったけど、結局は計算機だ。

だから、計算理論にて「理論上は可能」と判明したことは、現実のコンピュータでも可能である可能性が高いし*12、「理論上不可能」なら現実のコンピュータでも不可能だ。

それと、計算理論では計算モデル(コンピュータ数理モデル)を定義して考察するのだけど、計算モデルの中には有限オートマトンのように普通にプログラミングで用いられるものも多い。だから、例えば状態遷移図/状態遷移表を用いて設計する場合には、有限オートマトンの可能性と限界ぐらいの知識はかじっておいた方が良い。でないと、有限オートマトンでは無理がある問題を状態遷移図で設計しようとして破綻をきたすかもしれない。

可・不可の見極めのツールとして使える計算理論は、プログラマが齧っておいて損はないのだけど、数学コンピュータサイエンスの下地がないプログラマ独習するには難しい分野でもある。

そんな中、「数学的な厳密さ」よりも「概念の学びやすさ」を重視したこの本は、下地のない文系プログラマでもなんとか計算理論の初歩を学べるかもしれない最後の砦だ。

『詳説 正規表現 第3版』と『正規表現クックブック』、時々『sed & awk デスクトップリファレンス

商品知識になるけど、正規表現の本を挙げておこう。

正規表現は意外と使い勝手が良いツールだ。開発するソフトウェアにて正規表現を直接記述する人はもちろん、そうじゃない人も、例えばコーディング中に正規表現を使って検索・置換をするとか、開発者用の内製ツールを実装する時に正規表現を使うとか、正規表現を用いることで作業の効率化を推し進められる余地があるものだ。

だから、あえて正規表現の本も挙げようと思う。組み込みプログラマだって正規表現の1つや2つ使うものですよ。

正規表現については、ガッツリ学ぶための本と、実際に正規表現を書く際に便利なクックブック系の本を併用すると効果的だ。

ガッツリ学ぶための本としては、『詳説 正規表現 第3版』が鉄板だ。ガッツリすぎてゲップが出そうなほど正規表現やその実装について解説している。

詳説 正規表現 第3版

詳説 正規表現 第3版

クックブック系の本は色々あるけど、正規表現は意外と方言が多いので、主要7言語の正規表現を網羅している『正規表現クックブック』を推奨したい。実際、便利だし。

正規表現クックブック

正規表現クックブック

おまけとして、awkgrepsedviあたりのツールを多用するようになった暁には、これらで使われる正規表現の方言が一覧化されている、この本もどうぞ。

伝統的なUnixツール正規表現は『正規表現クックブック』から漏れているので、代わりにこちらの本を使うこと。

『マスタリングTCP/IP 入門編 第5版』

もう一つ商品知識として、今やインフラ化しているTCP/IPの基礎本も挙げておこう。

マスタリングTCP/IP 入門編 第5版

マスタリングTCP/IP 入門編 第5版

データベースも「SQLiteを組み込んだスマホアプリ」のように使用領域が広がりつつあるものの、ネットワーク機能が組み込まれたシステムはもっと多い。組み込み機器でも、IoTというバズワードがあるぐらいで、例えデータベースは搭載してなくともプロトコルスタックは搭載していたりするものだ。

コンシューマ向けの多機能機器では「USB・BLE・WiFi」の御三家が欠かせない。有線LANのポートを持つ情報家電も多い。クラウドサービス花盛り。企業の社内システムもWebベース化し始めて久しい。あと、デスクトップアプリケーションが自動更新機能を持つようになってから何年経ったのだろう。

こうなってくると、インフラ・ネットワーク系以外の開発者もTCP/IPと無縁ではいられない。どうしても、何かしらの通信を行うソフトウェアを書くことになる。

もちろん、通信ソフトウェアといっても多種多様だ。組み込み機器とWebアプリでは、それぞれ学ぶべき内容は異なる。でも根っ子の部分である「TCP/IPの基礎」はどちらも同じなので、とりあえず『マスタリングTCP/IP 入門編』ぐらいは読んでおくべきだ。そして階層を意識せよ。

通信ソフトウェアのテスト・デバッグと、社内ネットワーク管理者トラブルシューティングは、紙一重の部分がある。どちらもプロトコル階層を意識して問題を切り分けることが肝要だ。

『Webを支える技術』か『オンラインゲームを支える技術』、もしくは両方

引き続き、商品知識TCP/IP派の本。この項は、もう少しTCP/IPに深入りするかもしれない人向けの内容なので、不要なら無視しても構わない。

これは私の独断と偏見なのだけど、TCP/IPを土台として何らかのサービスを構築する人は、大雑把に2つに分けることができる。

1つは、従来の「Webサービス・Webアプリケーション」のコンテキストないしその延長線上にいる人。HTTPHTMLJavaScriptを土台として、RESTアーキテクチャなどでシステムを構成するものだ。

そういう方面に縁がある人は、基礎教養として『Webを支える技術』を読むべきだ。

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

組み込み開発者でも、機器のWeb管理コンソールを作るような場合には、本書の知見が参考となる(というか周囲にWebアプリの開発者とかがいなくて、本書で独学するしかなかったりするものだけど)。

もう1つは、リアルタイム性の高いシステムをWeb上に構築しようとする人。MORPG/MMORPGのようなゲームや、サウンドや映像をリアルタイム配信するシステムなどだ。

リアルタイム性を追及すると、どうしてもTCPではなくUDPベースでの通信となり、パケットロスをどうするか考えざるをえなくなる。性能向上のためNAT traversalでP2Pを実現するべく四苦八苦することもある。サーバサイドではデータをオンメモリで保持して、データベースの読み書きを減らす工夫が必要になるかもしれない。何より、性能を求めるあまり「サーバサイドをCやC++で実装する」という魔境かもしれない。

――と、まあ一般的なWebシステムとは毛色が違う世界もあるわけで、そっち方面に進みそうなら、『オンラインゲームを支える技術』は結構参考となる。というかこの本以外に思いつかないんだな、これが。

オンラインゲームを支える技術  ??壮大なプレイ空間の舞台裏 (WEB+DB PRESS plus)

オンラインゲームを支える技術  ??壮大なプレイ空間の舞台裏 (WEB+DB PRESS plus)

ちなみに、リアルタイム性の高いシステムを構築したい人的には、無線通信と「モバイル端末の賢いバッテリー制御」は鬼門だ。無線はパケットロスやジッターとの戦いが激化するし、「賢いバッテリー制御」のおかげで通信モジュールのOFF/ONに巻き込まれてジッターが発生する(例えばWiFiモジュールがONになるまでアクセスポイントにてパケットが待たされるとか)などの問題が起きることがあるからだ。

だから有線LAN非搭載のPCとか止めてほしいなあ……将来、USB 4.xとか5.xとかの世代で直接Ethernetに接続できるようになるとか、そういう方向で生き残ってくれないだろうか。無理かなあ。

インタフェースデザインの心理学』と『続・インタフェースデザインの心理学

最後の締めとして、今までに挙げてきた本からすると変り種かもしれないけど、『インタフェースデザインの心理学』とその続編を挙げよう。

書名からUIやUX関連の本のように感じるけど、実際はヒトの認知の仕方や感じ方、注意の向け方などについて紹介している心理学の本だ。

なぜ、この本を挙げるのか? プログラミングという行為が本質的に難しいからだ。

本質的に難しい物事に取り組むとき、その物事に付随する偶有的(非本質的)な諸々まで難しかったら、正直やってられない。なので、まずは偶有的な諸々の部分の難しさを緩和する必要がある。コンピューティングの世界では、偶有的な部分の難しさを緩和するためにあらゆる手段*13がとられている。ヒトの認知の特性を学ぶのもその1つだ――プログラミングをするのは人間だからだ。

例えば、職業プログラマの書いたソースコードは、他人や数年後の自分に読まれるものだ。可読性の良し悪しについて考えるとき、ヒトの認知の特性も考慮するべきなのだ。

だから、例え言語仕様で許されていようとも、基本的には個々の識別子を空白(スペース)で区切るべきだし、関連性の高いステートメントは隣接させつつ、関連性の低いステートメントの間には空白行を入れるべきだ。同時に、関数メソッドといった「比較的関連性の高いステートメントの集合」の中に、無造作に2〜3行もの連続する空白行を入れるような暴挙は慎むべきだ。

――こういう細かい話も、掘り下げていくとヒトの認知の仕方が関連しているものだ。

まあそれだけではなく、アプリケーションの画面構成やWebアプリのデザインを考える時や、大勢の人の前で話すときに注目してもらう工夫など、いくつかのシチュエーションで参考となるネタも書かれている。UIやUXのデザインでも参考となる一冊だ。

――要するに、UIやUXをデザインする時の視点は、プログラマ間のコミュニケーションで用いられる「ソースコード」という特殊なインタフェースにも流用可能である、というだけなのだけどね。本書は認知心理学とかのネタが多いので、応用が効くのだ。

まとめ

7冊とか10冊にまとめられなかったのは、ひとえに私の不徳の致すところであります。

まあ、情報系の課程を進みつつ趣味でガリガリとコードを書いていた人とは、スタート時点でそれなりに差があるわけだ。だから、その差の分だけリストに挙げられた本が増えていると思ってほしい。

*1:定番書でも、難易度ないし価格的に省いたものもある。

*2:知らない人向けに書いておくと、この本の作者はUnixの開発に多大な貢献をした人で、ミニ言語であるAWKの共同開発者で、プログラマ向けの古典ともいえる名著を何冊か共著で出している人で、コンピュータサイエンスの教授である。少なくとも、古参のC言語使いや、Unix界隈の古くからの住人の間では有名な人だ。

*3:設計といっても、教科書でいう「詳細設計」の局面の話だ。

*4:ワーニエ法については記載なし。

*5:『ソフトウェアの複合/構造化設計』には載っていないけど、重宝する技法だ。

*6:このタイトル、日本語訳の際に付けられたのではなく、原書が "Algorithms + Data Structures = Programs" なのである。なお新訳版は『アルゴリズムとデータ構造』というタイトルだが、こちらの原書は "Algorithms + Data Structures" である。

*7:付け加えると、「モジュール」や「クラス」は他のパーツと組み合わせて使われるものなので、インタフェースも重要となってくる。

*8:ただし組み込み系のCプログラマを除く。

*9:例外は二分探索かな? ログファイルのような「ソート済みのファイル」を検索する需要は意外とあると思うのだけど、標準ライブラリの二分探索ルーチンはオンメモリのデータが対象だから……。

*10:もっとも「開発者テストを実施するプロジェクトか否か」という点は、また別の問題である。まあ、組み込み開発のように高品質なソフトウェアが求められるプロジェクトでは必須だろうけど。

*11:なお、「名前は知ってるけど読んでない」とか「読んだけど実践していない」という点でもバイブル聖書)並みらしい……。

*12:ただし現実のコンピュータには「物理的制約」があるわけで、例えば理論上は可能だけど現在のコンピュータでは数万年かかるとか、全世界のコンピュータのメモリをかき集めても足りないとか、そういう理由で「現実的ではない」ということもある。

*13:高水準言語、特定用途向けのDSL、再利用可能なライブラリフレームワーク統合開発環境、高速な開発マシンと広いディスプレイ、その他。

2017-03-12

Python高速学習 経験者編

最近少しだけPythonに触れているのだが、他言語でそれなりにプログラミング経験がある人がPythonを学ぶ場合、差し当たり次の3つのドキュメントがあれば割と短期間でなんとなくPythonっぽいコードを書けるようになるみたいだ。

まあ、本当にPythonに通じている人からすると、こけおどしにすぎないかもしれないけど。

Python.jpのチュートリアル

Python.jpのチュートリアルは、本家のPythonチュートリアルの日本語訳だ。本家本元が執筆したドキュメントなこともあり、必要な機能についてコンパクトにまとまっている。

プログラミング未経験者が独学で勉強するときには、このドキュメントは少々レベルが高いので*1、他のドキュメントを探すほうがよいだろう。

しかし経験者の場合、このドキュメントぐらいのレベルで書かれているほうが読みやすかったりする。プログラミング未経験者を前提に書かれているドキュメントは、経験者からすると冗長に過ぎるものだ。Pythonチュートリアルは丁寧に書かれているが、プログラミング初心者向けのドキュメントほど冗長ではない。

PEP8

Pythonチュートリアルで言語機能について学びつつ、PEP8に目を通して書き方を学ぶ。

PEP8はPython界隈で割と知られているコーディングスタイルだ(なにしろPythonの公式サイトで公開されているぐらいだから)。PEP8を参考にコードを記述するだけでも、随分とPythonっぽくなる。

ついでにPEP8のスタイルに準拠しているかチェックするツールを導入しておくとよい。

『Effective Python Pythonプログラムを改良する59項目』

PythonチュートリアルとPEP8では足りない部分を補完するため、これも参照しておく。

『Effective C++』の読者なら想像がつくと思うが、この本はPythonの言語機能に着目して「あの方法よりもこの方法を使うべき」とか「この機能は避けた方がよい」とか、59項目ほど理由付きで解説している。

なので、『Effective Python』を参考にすることで、言語機能面についてもPythonらしいアプローチを採れるようになる。

*1:といっても主人公Lv.1にたいして、このドキュメントはLv.7ぐらい。まだまだ序盤のキャラクターだ。

2017-02-25

diruseの出力結果をCSV形式に加工する

HDDをあさったら、古いプロトタイプ・コードが見つかった。ちょっと晒してみる。

今は不明だが、かつてWindowsサーバの管理用にdiruseというコマンドがあった。Unixのduのように指定したフォルダのディスク使用量を表示するツールで、その昔はWindows Serverのリソースキットに付属していた。私がdiruseに遭遇した頃には、Microsoftのサイトからダウンロードして使用するようになっていた。

このツールが吐き出す出力をCSV形式に変換する必要が生じた。Windows Server 2003 R2上で変換したかったのだが、本番環境で使用可能なスクリプト環境がWSHしかなかった。そこでJScriptプロトタイプを実装してみた。

それがこのコードだ。

/*jslint continue: true, indent: 2, maxerr: 50, windows: true */
WScript.Quit((function () {
  'use strict';
  var print = function (s) { WScript.Echo(s); },
    stdin = WScript.StdIn,
    line,
    fields;

  print("Size,Files,Directory");
  while (!stdin.AtEndOfStream) {
    line = stdin.ReadLine();
    fields = line.split(/\s+/);

    if (fields.length < 4) {
      continue;
    }
    if (fields[2] === "SUB-TOTAL:") {
      print([
        '"' + fields[0] + '"',
        '"' + fields[1] + '"',
        line.slice(line.indexOf(fields[3]))
      ].join(","));
    }
  }

  return 0;
}()));

diruseからパイプ経由で出力を受け取る前提で、標準入力からの入力にのみ対応している。

フォルダ名を取得する所だけ少し変わったことをしている。というのもフォルダ名に空白文字が含まれているとその部分も「line.split(/\s+/)」で分割されてしまい、fields[3]には不完全なパス文字列しか格納されないのだ。

ところで、diruseはフォルダ名に日本語が含まれていると使い物にならなかったのだが*1サーバ上でで少しばかり特殊なアクセス権限を付加していたフォルダでも正常に使用量を取得できた唯一のツールだったため、捨てることができなくて困ったものだった。あれから、どうなったのだろうか?

*1Windows Server 2003 R2にて確認。

2017-02-11

プログラミング初心者向けに「環境構築の容易さ」をアピールしてはいけない

一言述べておかなければ。

「最初に学ぶべきプログラミング言語」 - mizchi's blog

プログラミング言語の「売り」として、プログラミング初心者向けに「環境構築の容易さ」をアピールするのは止めた方がよい。

だって、それをするなら、WindowsユーザにはPowerShellを、macOSユーザにはAWK/Perl 5/PHP 5.6/Python 2/Ruby 2.0.0/Tcl 8.5あたりを推奨すべき、という話になってしまう。どれも各システムにデフォルトで用意されている*1ので、環境構築など不要だ。究極の「環境構築の容易さ」ではないか。

百歩譲って、「macOSユーザ向けに挙げた言語って、どれも処理系だけで、IDEとかエディタとか無いじゃないか」という批判を甘んじて受けるとしよう。

では、予めREPL*2も簡易IDE*3も用意されているPowerShellはどうなるのだ――という話になる。

だが、だがしかし、しかしながら、PowerShellVBAと同じ枠で扱われていて、コマンドリファレンスや、やりたいことからの逆引きリファレンスは見つかるが、PowerShellを「立派なプログラミング言語」と見なしてプログラミング入門するような本に遭遇した記憶がないのである。少なくとも日本国内では*4

うん、だから「環境構築の容易さ」をアピールするのは止めようよ。PowerShellの境遇に涙が出らぁ。

追記:2017-02-13

AppleScriptを忘れてた! macOSには標準で「スクリプトエディタ.app(AppleScriptエディタ.app)」が付いてくる。「エディタ」という名前とは裏腹に、AppleScript用の簡易的な開発環境だ*5。だが、PowerShell以上に碌な和書が見つからない。

熱心に情報発信している人BOOTHで電書を出している人の情報が頼りだ。

*1PowerShellWindows 7以降の話。macOSユーザ向けに挙げた言語のバージョンは、macOS 10.12で確認したもの。

*2:スタートメニューから起動できる、PowerShellのコンソールのこと。

*3Windows PowerShell ISEのこと。

*4:海外の反応は知らない。

*5:OS X 10.10 Yosemite以降ではJavaScript 1.1も使えるが、あくまでも「JavaScript 1.1仕様の言語でシステム自動化のコードが書ける」というだけなので注意(Webクライアントサイド開発に使える訳ではない)。WSH(Windows Script Host)でJScriptを使えるがWebクライアントサイドのコードは実行できない、というのと同じである。

2017-02-04

正しいフローチャートの書き方

1月以上経っているから、もう書いてもよいかな。

若手プログラマー保存版!フローチャート徹底解説と作成カンニングペーパー

これは、日本ではあまり知られていないことなのだが、普段私たちがプログラミング教育で目にするフローチャートや、または「フローチャート」と聞いて思い浮かべるもの――JIS X 0121-1986の「情報処理用流れ図・プログラム網図・システム資源図記号」とかを使って手続き型のアルゴリズムを表現したようなアレは、少なくとも実務向けのツールとしては、40年ほど前にdeprecatedになっている。

フローチャート業界(!)では1975年パラダイムシフトが起きており、それ以降に推奨される「近代的なフローチャート」は、私たちが思い浮かべるソレとは似ても似つかないものとなっている。

具体的には、例えば次のような図だ。

f:id:eel3:20170204205811p:image

石を投げないで! その前にお茶でも飲んで落ち着いて、『人月の神話【新装版】』を買うか借りるか本棚から取り出すかして「第15章 もう1つの顔」の「フローチャートの呪い」を読んで、それでも投げたければ私だけでなくフレデリック・フィリップスブルックス・ジュニア*1にもお投げなさい

私たちがプログラミング教育で目にするようなフローチャート――仮にこれをフローチャート 1.0と表記し、上図のような「近代的なフローチャート」をフローチャート 2.0と表記するとしよう。

フローチャート 1.0の表現力は、手続き型の高水準言語とほぼ同等だ。

H・H・ゴールドスタインとJ・フォン・ノイマンによって発表されたときには(文献1)、小さな箱やその中の内容があたかも高水準言語として機能し、不可解な機械語ステートメントを意味のあるまとまりにしたものだった。

フローチャート 1.0の起源は、1947年の非公開レポート "Planning and coding of problems for an electronic computing instrument" になる*2。レポートの作者はハーマンハイネ・ゴールドスタイン*3ジョン・フォン・ノイマン*4だ。

1947年といえば、高水準言語どころかアセンブラさえ影も形もなかった時代だ。世界初の高水準プログラミング言語となるFORTRANは、ドラフト仕様の作成が1954年、マニュアルのリリースが1956年コンパイラのリリースが1957年だ。で、おそらく世界初のアセンブラはEDSACのもので、1949年5月に稼働し始めたようだ(Wikipedia調べ)。フローチャート 1.0が歴史の表舞台に現れたのは、アセンブラ誕生の2年前だ。

このような歴史的経緯を考えると、高水準言語が無かった頃や、高水準言語がまだ普及していなかった時代には、高水準言語と同程度の表現力をもつフローチャート 1.0は有用ツールだったといえる。機械語アセンブラでは直接書き下すことができない、一段上の抽象度でシステムを表現した、いわば「システムの設計図」の役割を担っていたのだ。

――が、しかし、逆に言えば、高水準言語全盛期である現代に、同程度の表現力しかもたないフローチャート 1.0は不要だ。わざわざフローチャート 1.0を書いたうえで高水準言語で書き直すぐらいなら、最初から高水準言語で書いてしまえばよい。これは、フローチャート 1.0だけではなく構造化チャートの類でも同じだ。

この辺りの疑念は、早い人ではFORTRAN誕生前後にすでに抱いていた。『人月神話』の記述によれば、ケネス・ユージン・アイバーソン*5からの1957年私信にて、フローチャート 1.0と高水準言語の表現力についての指摘がなされていたようだ。

アイバーソンが早い時点で気づいたように(文献2)、系統立った高水準言語ではそうしたまとめがすでになされており、それぞれの箱にはステートメントが入る(図15・2)。そこでもう箱自体、下書き段階での退屈で場所ふさぎな用途以外の何ものでもなく、削除してしまった方がよい。

(中略)

だから、リストに矢印を書き込むことにして、フローチャートはすっかりやめてしまった方がよいだろう。

つまるところ、高水準言語が広まったことにより、フローチャート 1.0は(実務向けのツールとしては)役目を終えたといえる。*6

ただし、「フローチャート 1.0が役目を終えた」という事実は、「フローチャートそのものが役目を終えた」ということを意味しない。なぜならば、高水準言語で短く簡潔に書くことが難しい抽象度の事象を描いたフローチャート 2.0は依然として有用だからだ。

先に挙げた図のようなフローチャート 2.0について、『人月神話』にはこう書かれている。

現実のプログラムに関する1ページのフローチャートは、本質的にプログラム構造および局面または段階を示した図になる。その点に関しては非常に便利なものだ。図15・1は、そういうサブプログラム構造図を示している。

当然のことながら、このような構造図は苦労して作り上げられたANSIのフローチャート基準に従うことも、それを必要とすることもない。箱形、コネクタ、番号付けなどに関する規則はすべて、詳細なフローチャートを理解しやすくするためにだけ必要なのだ。

要するに、システム設計用の、抽象度の高い事象を記述するためのツールとしては、フローチャート 2.0の寿命はまだ尽きていない。また、フローチャート 2.0ではANSIやJISの記号を使う必要はない。

人月神話』で挙げられているプログラム構造図や、「UMLフローチャート」とも噂されるアクティビティ図は、いずれもシステムの一局面について、高水準言語では直接書き下すことのできない抽象度で表現するためのツールだ。自由度が高すぎるフローチャートに「明確な役割」と「役割に基づく制約」を設けたことで、より扱いやすいツールとなっている。それらを書く時に使用する記号はシンプルで、ANSIやJISのフローチャート用記号のような数が多くて複雑な代物ではない。

もちろん、システムのすべてをフローチャート 2.0のみで記述・設計することは難しい。しかし、それをいったらDFDや状態遷移図/状態遷移表などの他の記法だって同じだ。

構造化モデリングではイベントリスト・コンテキストダイアグラム・DFD・状態遷移図・構造図などの複数の記法を用いるし、オブジェクト指向分析・設計で用いるUMLは複数の表記法UML 2.0で13種類)をまとめたものだ。すなわち、たった一つでシステムの全ての側面を記述・表現できるような、便利な記法は存在しない。どの記法も一長一短があるので、用途に応じて記法を使い分けよう――というのが現実解だ。

だから、フローチャート 2.0で記述できない事象について、フローチャート 2.0を責めるのはお門違いというか、そこを責めるのなら「お前それアクティビティ図でも同じ事言えんの?」と茶化される覚悟はしておいたほうがよい。

アクティビティ図でアクターの操作を記述できなくても、誰もアクティビティ図を責めないどころか、むしろ「いやいや、そこはユースケース図でいきましょうよ」となるはずだ。これがフローチャート 2.0になると、途端に「フローチャートじゃ書けないものがあるし……」という態度をとる人がいる。

そう言ってしまう前に、冷静になって、フローチャートをアクティビティ図に入れ替えて考えてみるべきなのだ。「アクティビティ図じゃ書けないものがあるし……」って、どう考えても当たり前だ(アクティビティ図で全て表現できるというのなら、UMLの残りの記法は何なのか……)。フローチャート 2.0も同じだ。

だいたい、フローチャート 2.0とUML 2.0の戦力比は1対13なのだ、記法の数的に。だから、「フローチャート 2.0の表現力はUML 2.0の13分の1ぐらい」と考えておけばよろしい。で、フローチャート 2.0で苦手なものは、別の記法で書けばよい。

フローチャート 1.0は戦力外だが、フローチャート 2.0はまだ生きている。まあ、フローチャート 2.0は、フローチャートという名前よりも「プログラム構造図」とか「UMLのアクティビティ図」とか、それぞれの方向に特化した別名のほうがしっくりくるのだが。

ともかく、フローチャート 1.0とフローチャート 2.0の区別をつけた上で冷静に議論できる人が増えることを祈るばかりである。

さて、一通り書き終えたから、状態遷移図と状態遷移表とシーケンス図の教育用サンプルでも作るとするか。

*1:『人月神話』の作者。念のため。

*2:「プログラミング向けのフローチャート」という視点では、これが起源だといえる。フローチャート一般としては、それ以前に起源があるようだ。

*3:『復刊 計算機の歴史 ―パスカルからノイマンまで―』の作者。ENIACの開発プロジェクトのメンバーで、のちにIBMにてコンピュータ開発に関わった。

*4:「ノイマンコンピュータ」のあの人。

*5プログラミング言語APLの創案者。

*6プログラミングの初等教育用のツールとしては、まだ役目が残っている気がするが……コンピュテーショナル・シンキングの方面を含めて、教育方法やツールが現在進行形で進化しているので、もうそろそろオワコンになる気がしないでもない。