読者です 読者をやめる 読者になる 読者になる

蛍光ペンの交差点[別館]

"どの点に関心をもつべきか ―をわれわれが学びとるのは,もっぱら仮説からだけである"

プログラムと恐怖

プログラミングを始めて約3年が経ち、少し考えることがあった。

 

学ぶことが本質的に困難なプログラミングとは、どのようなものだろう?
あるいは、いつまでも怖いプログラミングは、どのようなものだろう?


プログラミングを習うというと、以下のようなことがパッと連想される。

  • RubyPythonといった初学者にもわかりやすい(?)言語
  • CやC++と言った比較的わかりにくい言語
  • RailsSwiftなどによるアプリ開発
  • プログラマやエンジニアになるつもりじゃないから、彼らに仕事頼めるぐらい理解できればよい」という発言と認識

 

今回は、自分が始めた頃には思いもよらなかった「怖い(難しい)プログラミング」について考えてみたい。

それは「設定ファイル」のプログラミングである。

 

プログラマは日々の作業のなかで、いろいろな道具を用いる。そして、それらの道具の細かな使い方を毎回いちいち指定するのは煩雑でミスが起こりやすいため、設定ファイルと呼ばれる特殊なファイルに予め指示を書いておくことが多い。

 

たとえば、オペレーティングシステムと私達ユーザーの仲介を行なうプログラムであるbashならば .bashrc (正式な読み方は知らないが、私は「ドット・バッシュ・アールシー」と呼んでいる)というファイル、遠隔のコンピュータにアクセスするためのコマンドの一つであるsshならば ssh_config (「エスエスエイチ・コンフィグ」)と呼ばれる設定ファイルを操作する。

 

これらの設定ファイル内での指示の書き方は、共通していない。たとえば .bashrc で変数を宣言するときは変数名と値の間に空白を入れないことが求められるが、ssh_configでは変数名と値の間に空白を入れることが求められる。プログラマは新しい道具をひとつ使おう(細かく使い込もう)とするたび、それらの文法を覚える必要に迫られる。

 

最近では .yml や .json という拡張子のファイルで、ある程度共通のフォーマットで書けるようになりつつある印象も受けるが、真に問題なのは書き方というより間違いの見つけ方である。

 

どういうことか。

 

RubyPython、あるいはCやC++と呼ばれるプログラミング言語では、文法上のミスがあるとそもそも実行される前にエラーを出して止まることが多い。変数が存在しませんだとかカッコが閉じていませんだとか言った類のものである。プログラマは多くの場合、これらのエラーを手掛りに、プログラムを修正して正しく動くようにする。

 

「エラーを手掛りに」というのがポイントで、設定ファイルにおいては、あるいはエラーの種類によっては、手掛りになるようなエラーの文言が表示されないことが多い

 

「初心者だけが間違えるようなミス」であれば、それほど問題はない。ググれば同じ問題に直面している人がいるから、その通りに修正すれば大抵直る。

 

問題は、「プログラミング自体は普通にできる人だったとしても、そのエラー自体に詳しくなければ防げないタイプの不具合」である。

 

たとえばsshであれば、アクセス先のコンピュータが(セキュリティ強化のため)デフォルトの22番ポートではなく他のポート(仮に20022番とする)での接続のみ受け付けるようにしていた場合、connection refused エラーが起きる。このエラーを見たプログラマは、だいたい次のような思考を巡らせる。

 

  1. ポート番号が間違っているのか?
  2. パスワード認証がオフになっているのか?
  3. 秘密鍵ファイルが ~/.ssh/ ディレクトリ以下に存在していないのか?
  4. それとも、存在はしていても、デフォルト名ではない鍵ファイルとして保存されているから、鍵名を指定する必要があるのか?
  5. プロキシか何かの関係で接続が阻害されているのか?
  6. それとも、アクセス先のファイヤーウォールで弾かれているのではないか?
  7. ほかに何か、自分の知らない技術的な理由でアクセスができないのか?そうだとしたら誰に聞けばよいのか?ネットの掲示板か?それとも社内システムなら、前任の担当者か?

 

このうち、アクセス成功にたどり着ける「正しい」試行錯誤は、1. のみである。そして仮に 6. から逆番号順に試行錯誤していった場合、相当な時間をかけなければ 1. の正解まで辿りつけない。

 

実際には、鍵が存在しないときのエラーは確か public key denied か何かであり、すなわち connection refused ではなかった気がするので、ポート番号から考えることができるかもしれない。では正解が 1. ではなく 5. だったら?あるいは 6. だったら?プロキシ環境下に ssh でアクセスする機会や、ファイヤーウォールによる弾かれ方(とそれによるエラーメッセージ)を「拝見できる」「貴重な」機会はそうそうあるものではない。少なくともRubyPythonでエラーを見る頻度と比べたら2ケタ以上の回数差で珍しいのではないか。

 

だから僕は、設定ファイルのプログラミングをすることがものすごく怖い。

 

極端なことを言えば、たとえばsshでアクセスするようなマシンを100台立てて、それらの環境をそれぞれ変えて、その時のエラーメッセージを調べてやればsshのあらゆるエラーに慣れることができるから、まったく怖くなくなるだろう。だがコスパに見合わない。怖いなかビクビクしながら何とか直すことのほうが、時間的には遥かに短く済む。

だからきっと、このプログラミングはずっと怖いままなのだ。

 

 

プログラマが使う道具は 、どんどん増えていく。数年前にはDockerなんて存在しなかった。今では企業でも実戦投入を始めている。DockerにはDockerfileという設定ファイルが存在する。その書き方はbashMakefileに似ているが、若干違うところもある。その「若干違うところ」を学ぶときは、全神経を研ぎ澄ませる。「怖い」からだ。まして新しい道具の場合は、エラーメッセージすら信用できない。公式のチュートリアルを全部無視して、githubに上げられている「実際に動く設定ファイル」を説明書として読むことだってある。

 

新しい道具を学ぶときには、つねにリスクが付きまとう。

Rubyが書けるようになったからとか、
どの入門書を読んでも知らないことがなくなったから、
それで学習が終わりなんてことはありえない。

 

ある程度書けるようになってくると、あとはプログラミングによる問題解決をいかに効率的にするかの最適化勝負になってくる。

 

 その最適化に含まれる小問題が、設定ファイルの「怖い」プログラミングだと思っている。設定ファイルのプログラミングでは常に、不確実な環境下での最善の判断が求められている。