ITも大抵筋肉でなんとかなる

気が向いたら技術的なことも書くかもしれないですが、技術的なこと=ITとは限りません。

筋トレについて書きたい。

しばらく更新をしていませんでしたが、またしてみようかなーーーと思ったので。ですが、あまりITエンジニア業とは関係ないことを書くことが多くなると思います。もちろんたまには書くでしょうけど、それよりも筋トレのことについて書きたいという感じなので。

ITエンジニアこそ筋トレすべき

人間は根本的には動物であり、その構造は数千年前より変化していません。元来動物とは「動かないと死ぬ」のが基本ですし、人間も例外なくそうです。「動く」ということを前提に作られているためです。「動く」というのは昔でいえば狩りをしたり農耕をしたりするということです。そうやって体を動かすことで血液の循環であったり細胞の入れ替えを正常に行なえるようにしていたのですが、昨今の人間は動かなさ過ぎて、そういったことがうまく機能していないことが多いです。
元来人間に備わっている機能を十二分に生かし切れないがために病気になっているケースは少なくありません。そして、特にITエンジニアは一日中座っている仕事なので信じられないほどの運動不足です。不足というよりももはや無いと言って過言ではありません。この状態がいいわけがない。

なぜ筋トレか

運動しないといけないなら、別になんでもよくね?なんで筋トレ?と思うかと思いますがその他のスポーツに比べ圧倒的に楽だからというのが本音です。楽なんですよ。筋トレは、ガッツリやらないのであれば週2回1時間程度で十分です。実に楽。そのうえ、一人で黙々とやることもできるし、家でもできるのでコスパもよい(ちゃんとやるならトレーニングジムにいかないとですが)。他にもこんな理由で筋トレを推しています。

  • トレーニングメソッドは科学なので100%結果が出る(大小はある)
  • スポーツのパフォーマンスが上がる
  • メリハリのある身体を作れるので服が似合うようになる
  • 自己管理・体調管理が上手くなる
  • 目的は人それぞれなので競う必要がない

メリットはたくさんある

以前ツイートしたものですが、大体こんなメリットがあります。メリットしかないですね(ゴリ押し)。

最後に

身体を鍛えないことに対するデメリットはそのうち言及するとして、筋トレはしましょうっていうそういうゴリ押しを。記事の中でも触れましたが筋トレはれっきとした科学です。身体を効率的に動かすためには解剖学の見地からアプローチを行なったり、効率的に体を変えるために栄養学の見地からアプローチを行なったり、裏側にはきちんと裏打ちされた理論があるわけです。そういったものを利用するわけですから、そりゃ効果もあるよっていう話でした。

コンピュータが人間を超えることはない

我々、計算機を扱う人間ならば皆これに気づいているはず。コンピュータ、すなわち計算機が人間を超えることはありえない。現在のハードウェア構造では 絶対に越えられない。

自然言語とは

今まさに自然言語を理解しているわけだ。つまり、日本語や英語、フランス語、ドイツ語等々である。これらは自然言語と呼ばれる。これらを計算機が解釈することはある意味人類の夢の一つである。 今もって自然言語を正しく解釈することは難しく、研究の発展途上ともいえる。形態素解析、意味解析、人工知能の利用…どれを以てしても正しく解釈できた事例はない。

プログラミング言語とは

それに対し、プログラミング言語、すなわち形式言語というものが存在する。これの本質は0と1しか解釈のできない計算機に対する命令を抽象化することである。つまり自然言語とは大きく性質が異なるものである。おそらくこれに近しいのは、数学の数式などであろう。

なぜコンピュータは人間を超えられないのか

至極単純な話である。プログラミング言語予約語は、いくつだろうか?おそらくは30ほどではないかと推測する。イコールで、「プログラミング言語を扱う上で知っておかねばならぬ単語数」とも言い換えられる。予約語とは、プログラミング言語内で使用する英単語だと思ってもらってよい。 対して、中学英語に必要な単語数は1,200ほどであると言われている。言い換えると、日本基準で英語を中学レベルで扱うためには1,200単語ほど必要であるということだ。予約語と比べると圧倒的に多い。

そもそも論として自然言語ってなんだ?

自然言語については専門家に聞くのが一番早いだろうが、個人的見解では「人間の複雑な思考・感情をできるだけ正確に表すための抽象化手法」であると定義する。なんのこっちゃいって話なので少し嚙み砕くと、自分の考えや感情をどうやって正確に相手に伝えるか?ということに重きを置いたツールだと思ってもらえばよい。つまり、人間の複雑な思考を表現するためには当然ながら30単語では足りないのである。ちなみにネイティブだと30,000単語以上を操るというから、1,000倍以上である。つまり計算機と人間とでは複雑さが単純な数値で表すと1,000倍以上違うのである。ちなみにこれは単語数だけであるから、文法なども組み合わせるともっとだ。

シンギュラリティの可能性

話が飛ぶようだが実はアナログ的であるのがこの話だ。計算機が人間を超える可能性は、先の通りなので100%否である。そもそも自分の持っている思考を抽象化したときの複雑さが全くもって異なるからである。厳しいことを言ってしまうようだが、もし今の仕事がAIにとってかわられるような仕事であるならば、それはその程度の価値・複雑さしか有していないということになる。すなわち、「人間でなくともできてしまう、仕事ではない『作業』である」ということになってしまうわけだ。
人間のような複雑な思考を持っていなければできないような仕事はこの世に複数ある。一部の人が信じてやまない、プログラムを書かない時代も、残念ながら来ないと言っていいだろう。正確には、設計書からプログラムを自動生成する時代は来るだろうが、そのころには設計書がプログラムと呼ばれているだろうということである。この辺りはコンパイラの歴史を調べていただければ納得できるだろう。結局のところ「知的活動」のようなものは残る。もう少し具体的に言おう。「英知」のようなものは残り続けると言っていいということだ。
だが残念なお知らせもある。今のは、ハードウェアの形態が全く変わらない場合の事象を指している。つまり、ハードウェアの形態が人間に近しくなった場合、そしてそれが自分自身で成長できるようになった場合は、正直分からないということである。そうなったとき、どう生きなければならないかは分からない。しかし、今生きる分には何が大切かは自明なはず。それを大切にしたいと思う今日この頃である。

型宣言なし言語への偏見をなんとかしたい

なんというか、型宣言のない言語への偏見がすごいので何とかしたい。

そもそもデータ型の存在意義とは

データ型の存在意義というのは、「その変数に対する抽象化」であるといえます。例を交えましょう。

a = 255

これはaという変数に255を代入しています。ということは、aという変数のデータ型はintであることが推測できます。

ではこれは?

a = b

分かりませんね。困りました。

という状態を防ぐのが型宣言です。データ型というのはその変数が取りうる値の性質をグループ化して表現することで、「具体的に何が入るかは分からない。ただ俺にはintしか入らねぇぜ!」という状態を作れます。そしてそれを事前に宣言するのが型宣言です。
こうすることで、intをbooleanと間違えて if (a)などとしなくて済みます。なぜならコンパイル時点ではじいてくれるためです。

型宣言がある場合の例

型宣言があることによるメリット

例えば

int a = 0;

としてあればaにはintしか入らないため、「この変数には文字列が入っているのか?それとも浮動小数点数か?」といったチェックを自動的にしてくれるようになります。これは潜在的なバグを引き起こしにくくなることを意味します。例えば、

a = 1;
b = 2;

とあったとして、a + bは当然3になるはずです。しかし何かのはずみでデータ型がstringになっていたとすると、a + bは12になってしまいます。仮にこの計算結果をどこかで使っていると、計算が合わなくなりバグを引き起こします。がしかし文法的に間違っているわけではないのでコンパイルエラーにはなりませんし、例外ログにも残りません。トレースの難易度が上がります。
そこで、

int a = 1;
int b = 2;

としておくことで、a + bが3になることを担保できます。型宣言にはこういった安全装置の役割もあるのです。

型宣言があることによるデメリット

一方、型宣言があることによってデメリットもあります。例えば、こんなもの。

double pi = 3.14;
int x = pi;

これでは、xに代入される値は3となってしまい、期待通りの結果となりません。また、型がオブジェクトの場合は少々やっかいなこともあります。例えば、これ。

List<int> list = [0, 2, 4, 6];

Javaにおいてこの記法は許されません。同等のことをしようと思うとこうしないといけません。

List<int> list = new ArrayList<int>(Arrays.asList(0, 2, 4));

いささか冗長ですね。そう、型宣言は自動でエラー検出をする代わりに冗長なのです。これは、プログラミングを熟練すればするほど鬱陶しく感じることでしょう。

型宣言がない場合の例

型宣言がないことによるメリット

さてはて、型宣言がない場合はどうでしょう。同じ例を取ります。

pi = 3.14;
x = pi;

xには正確に3.14が代入されます。これは期待通りでしょう。さらに、型がオブジェクトでも厄介なことにはなりません。

list = [0, 2, 4, 6];

Pythonであれば、これはlistオブジェクトとして解釈されます。制約はありません。 つまり、見たまま・やったままを実行してくれます。これは楽です。こちらが明示的に入れ物を変化させることなく入れ物を適切に変更してくれるためです。入れ物を変更するのは大変です。時にはデータ構造をも変更しなければならないほどです。これは純粋なロジックを記述するとき邪魔になります。なぜならば、ロジックを考えることに集中できなくなるからです。本質は入れ物の中に何が入るかなのに、どの入れ物を用意するかで多くの時間を消費することになるからです。

型宣言がないことによるデメリット

a = 1;
b = 2;

とあったとして、a + bは当然3になるはずです。しかしプログラマのミスでうっかり

a = "1";
b = 2;

などとしてしまっていると、a + bの結果が予測できなくなります。もし暗黙的にデータ型を変更されでもしてしまったら、a + bが3になるか12になるか、動かすまで検討がつきません(もしくはよほど言語仕様に詳しくない限り)。ただしPythonは異なるデータ型同士の足し算はエラーとしてくれます。ですので、どちらの結果になるか分からないではなく、実行時エラーとして知らせてくれるためこちらが考えるコストは幾分か少なくなります。

結論

型宣言がない場合のデメリット、なんだか微妙ですね。そもそも動かす前のエラーは、IDEが検知してくれない限り我々は知る由もありません(コンパイル時に知らせてくれるじゃないか!というかもしれませんが、インタプリタ型にとってはコンパイル=実行であるため、強く型付けされていれば大差ないのです)。そう考えると、残念ながら型宣言がないことについて、コーディング時はあまりデメリットはないということです。むしろ型変換を行なうロジックを組まなくて済むため、本質に集中できることでしょう。ただし残念ながら実行速度はデータ型があった方が上です。また、PHPJavaScriptなどの弱い型付けの場合はこの限りにはありません 。多少データ型がおかしくても実行されてしまうため、やっかいなバグを生みやすくなるでしょう。つまり、型宣言があるかないかではなく強い型付けなのか弱い型付けなのかで議論した方がよい ということになります。特にC#などは型宣言をしなくとも(正確にはvarなどで記述する)、型推論をしてくるため幾分か楽であると言えるでしょう。強い型付けの場合は、型宣言など行なわなくともほとんどの場合不整合が起きないです。
ということで、これからは
強い型付けor弱い型付け
で議論をしたいなぁという結論でした。ちなみに私は型宣言は足かせでしかないと思っています。コンパイル時にエラーがみたいな話は聞きあきました。動かせばわかることですし、仮に動かすのが難しいのであるとするとそれはそれで大問題です。もしどうしても性質上動かすのが難しいということであれば、テストコードを書けばよいのです。テストコード、書きましょう。

変数・関数・クラス名、などなど名前に関するアレ

多少長くなっても意味の分かる名称をつけよ

たまに変数名を短くしようと略しているのを見かけますが、あれは非常によくない。 なぜか。

意味の分からない・通じない名称は「hoge」「fuga」「aaa」などと何も変わらない

これに気づいていないのですよ。やたら短くしようとする人は。名称は、いわば「その値、その処理、そのものを説明するコメント」であるので、名称自体に説明が必要なものは既にアウト。よく使われる「i」みたいなものを除いて、そのプログラム内で固有の略し方ははっきり言って悪。

パッと見で分からない名称は名称として機能しない

こういうこと。その名称が何を指し示しているのかを記憶しておかねばならないという状態に。何のための名称なんだってなってしまう。

人間が一度に記憶できるモノの数は3

人間に備わっている主記憶装置は変数を3つしかスタックできないと思ってください。3つ以上入ってくると最初の1つをデキューしてしまうので、ソースを追う際、よくわからない名称が3つ以上あると詰みます。なぜならば、よくわからない名称を本当の意味に対応させる表を頭の中に作る必要があるからです。つまり、よくわからない名称が出てくるごとに対応表をエンキューすることになるので、当然3を超えた段階でデキューが走り、最初の名称の本当の意味が分からなくなるという。

まとめ

まぁこれは愚痴に近いですけど、ブランチを切ったら「長い」とか言われてですね。長いっつっても15文字ぐらいだったんですけどね。あれで長いって言われてしまうと、コーディング能力を疑いざるを得ないんですよ。ちなみに、名称の付け方≒コーディング力だと思ってほぼ差し支えないと私は思ってます。
名称の付け方とかコードの整理の仕方はリーダブルコードという書籍を読むのが手っ取り早いです。おすすめ。

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

開発環境の自動化によって得られるものとは

時間でも冪等性でもない。精神の安寧だ。

アホのようだけどマジです。冗談抜きで。恐らくこれが最も大きい。

それって意味あるんかいな

大ありです。効率に大きく差が出ます。

どうして!?

考えてみてください。「この環境はぶっ壊してもいくらでも作り直せる。だから豪胆に作ってやろう。」っていうのと、「一度壊すと大変だ…慎重に、慎重にやらないと…」っていうの、どっちが効率上がると思います?つまりそういうこと。

「ぶっ壊しても戻せる」ことによる精神の安寧は最強

最悪物理的に壊れても大丈夫という精神の安寧は最強です。人間は思いのほかパフォーマンスと精神状態が密になっているので、本当にこれは大きいことです。開発環境の自動化、しましょう。

気が向いたら

気が向いたら、個人でやってるプロジェクトの環境構築自動化の一部を公開するかもです。と言っても、御大層なことはしてないですが。役に立つとしたら、pyenvの自動インストールとか、atomの自動設定とか。そのあたりになるかもです。

AtomをPythonエディタとして使いたいけどうまく設定できない話

なぜなんだ…なぜなんだジョニー…

auto indent=前の行のインデントを引き継いでインデントしてくれる
って解釈なのに、なんかいらんインデントをしてくれてしまう。
例えば下みたいな感じ。(↓は行末だと思ってください。)

想定される動作

if hoge:↓

この状態でエンターを押すと

if hoge:↓
↓

となってほしい。だが実際の動作は違う。

実際の動作

if hoge:↓

この状態でエンターを押すと

if hoge:↓
    ↓

となる。

なぜ後者ではだめなのか

通常のテキストエディタでのauto indentの場合、前の行のインデントを引き継ぐというものなので、当然のことながら前者の動きになる。前者の場合はインデントを自分で作る必要があるので、こういう動きになる。

通常のテキストエディタでの遷移

if hoge:↓

Enter押す

if hoge:↓
↓

Tab押す

if hoge:↓
    ↓

ところが、後者の場合これをやってしまうとこうなるのである。

atomでの遷移

if hoge:↓

Enter押す

if hoge:↓
    ↓

Tab押す

if hoge:↓
        ↓

…。

あ゛あ゛あ゛あ゛あ゛あ゛あ゛あ゛あ゛あ゛あ゛あ゛あ゛あ゛!!!!どう゛じでぞう゛い゛う゛ごどずる゛ん゛だよ゛ぉ゛ぉ゛ぉ゛ぉ゛ぉ゛ぉ゛ぉ゛ぉ゛ぉ゛ぉ゛お゛お゛お゛お゛お゛お゛お゛!!!!(CV:藤原竜也

総括

普通のテキストエディタとかvim使えってことですかね。辛い。

RDBのマイグレーションを半自動化しようとあがいている話

新年あけました。おめでとうございました。

私は大みそか前日から正月休み丸々コーディングに費やした(プライベートで)ので全く年明け感がないです。ようやく年明け感がでてくるかなーという1月中旬に喉の激痛でぶっ倒れました。新年早々なにしてるんじゃ。

最近やっていることの話

まぁとりあえず生きてる

いろいろやってます。プライベートで。現状はvagrant+ansibleでローカルの開発環境を自動化しているところです。他にもWebアプリを作っていて、それのDBマイグレーションとかをゴリゴリ自動化してます。自動化きもちいい。この記事はそれの話です。

要するに自動化おじさん

まだ四捨五入したら20歳なのでおじさんではないのですが、まだおじさんではないのですが、とにかく自動化してます。私は単純作業が死ぬほど苦手で手順が5つ以上あったら絶対にミスります。なので自動化。

どんな自動化?

DDLを所定のディレクトリに配置すると、DDLに従ってDBを書き換えてくれる君です。誰だ今大したことないって言った奴。まぁこの段階では大したことないんだけどね…。

まず使ってるDBツールを紹介するよ

私はA5M2というSQL/E-R図開発ツールを使っています。なぜかっていうと、これ一つですべてできるから。E-R図が書ける(しかも論理名も表示できる!)、SQL実行できる、当然DB接続もできる、SSHトンネル経由の接続もできる、値の書き換えもできる、DB定義書の出力もできる、と至れり尽くせり。なんといってもE-R図からDDLを生成できるのはでかい。

でもここが不便

ただ当然のことながら不便なところがないわけじゃない。というよりはこれはもうどうしようもない話だと思うんだけど、E-R図で新たに変更があった部分だけをDDL出力することができない。つまり、初回は

  1. E-R図を作成
  2. DDLを生成
  3. DBに反映
  4. みんなハッピー

になるんだけど、2回目以降は

  1. E-R図を修正
  2. DDLを生成
  3. 前回出力したDDLと新しく生成したDDLを見比べてALTER TABLEを作成する
  4. ALTER TABLEでDBに反映

ってなるから、死ぬほどめんどくさい(もちろんソースも修正しなけらばならない。)。特に開発環境でローカルDB持つ形式だと、DROP DATABASEもできないのでなんとかALTER TABLEで頑張るか、マイグレーション用のSQLを書くしかない。そんな面倒なことやってられっか!!
この世からすべての手作業を消し去りたいマン(つまり死ぬほどめんどくさがりマン)なので、何とか自動化しようとしてあがいた話。

方針

まとめると、こう。

  1. 既存のマイグレーションツール「south」を使うよ(Djangoが内包)
  2. テンポラリDBと開発環境用DBを分けるよ

結論から言って、マイグレーションツールを作ろうなんて話になると果てしなき長い道のりになるので既存のマイグレーションツールを使いましょうということ。私の場合、WebフレームワークでDjangoを使っているため、Djangoに内包されているsouthというマイグレーションツールを利用することになります。つまりDjango使ってる人向け。

あとは、テンポラリDBという概念を導入。どうしても内部でデータを保持しておく必要があるので、仮にDROP DATABASEなんてやった日には、データをINSERTしなおさないといけない。
もしDROP DATABASEをしないとなると、ALTER TABLEしないとなのでこれもあり得ない(面倒)。じゃあもう最初からデータを保持しないDBを構築しておいて、これは変更反映用のDBとしてのみ使用、開発環境用DBはマイグレーションツールによる変更1択で任そうよっていうこと。
Djangoの場合、Entityのような形で記述する(DBと1対1のメンバ変数を持つクラスのやつですよ。)models.pyというものがあり、このファイルを変更後所定のコマンドをたたくことでDBのマイグレーションを行なってくれる仕組みになっている。ということは、テンポラリDBを変更後、テンポラリDBからmodels.pyを自動生成し所定のコマンドをたたけば開発環境用DBも書き換わるということ。イコールで、E-R図を変更してDDLを所定の場所に配置するだけでDBのマイグレーションが行なわれる、となるカラクリだ。

全体のフロー

  1. A5M2でE-R図を修正する(手動)
  2. DDLを生成する(手動)
  3. 所定のディレクトリへDDLを保存(手動)
  4. cronが走りテンポラリ用のDBを更新(自動)
  5. テンポラリDBから情報を抽出しmodels.pyを自動生成(自動)
  6. models.pyの情報を元にDjango内包のsouthによりDBマイグレーション(自動)

とまあこんな感じ。DBマイグレーション自体は失敗することもあるみたいなので、この辺は柔軟に対応する必要はあるにせよ、ほぼ手作業が介入しない状態に。

E-R図必要?

絶対必要です。正直DB定義書よりほしい。DB定義書なぞ最悪自分でクエリ書いて自動生成すれば済む話で、E-R図だけはそうもいかない。それに直感的にDB構造を把握するために必要。 なので今回のような大掛かりな自動化を施したわけです。Django使っている以上、本来であればmodels.pyの修正でいいっちゃいいんですけどね。どうしてもE-R図がほしかったので。

ちなみに

自動化って言ってるけど、これ実際は2つの自動化があって、1つ目は説明した通り「DBの変更を自動化」ってことです。そして2つ目は「設計書と実装を自動的に揃える」ってこと。もちろんE-R図を直すっていう工程を先にしないと成り立たないんだけども、それさえ守ればE-R図と実装は必ずイコールになる。どの現場でも設計書と実装がズレていくと思います。それは個人レベルでも起こりうるというか、個人レベルだからこそ時間がないがゆえに起こりやすいのではないかと。 そういったものも含め今回のカラクリを作成。これで面倒な手作業から解放されると思うと…。ただまだ5.6.をシェルスクリプトに乗っけられてないので、それはやらないといけないです。さくっとやろう。