Edited at

[WIP] プログラマ・エンジニアとして覚えておきたいと思ったこと


受け入れるのは寛容に、送り出すのは厳格に

UNIXの思想や、インターネットの原則の一つ。


3.9 Be strict when sending and tolerant when receiving.


なんでも寛容に受け入れればよいというわけではないけれど。


パレートの法則

いわゆる80対20の法則。

80%の利益が、20%の人からもたらされている、とかいうアレ。

数字の80とか20にはあまり意味がないので、実際には1%のものが90%を占めている、といったこともある。

元は経営方面の話からきているのだと思うけど、いろいろな分野に応用される。

一番実感できるのは、性能向上などで実測してみたら、ごくごく一部の機能が処理時間の大半を占めていたりする場合。

ただし「主要な少数に注力しろ」という解釈だけではないと思われる。


  • ロングテール商法

  • 神は細部に宿る


マズローのハンマー


ハンマーを持つ人には、すべてが釘に見える


便利な道具を手に入れたり、新しい方法を知ると、どんな問題に対してでもそれを使ってみたくなる、という意味。

自戒を込めて。適材適所。


プログラマの三大美徳


  • 怠惰

  • 短気

  • 傲慢


見える化、あるいはカンバン


  • 最新の正しい情報を

  • 大きくわかりやすく書いて

  • 一か所にまとめて

  • みんなで見ることができる


UNIX哲学


伽藍とバザール


誤字脱字

誤字脱字はなかなか無くならない(気づかない)。


こんちには みさなん おんげき ですか?

わしたは げんき です。 この ぶんょしう は いりぎす の ケブンッリジ だがいく の けゅきんう の けっか にんんげ は もじ を にしんき する とき その さしいょ と さいご の もさじえ あいてっれば じばんゅん は めくちちゃゃ でも ちんゃと よめる という けゅきんう に もづいとて わざと もじの じんばゅん を いかれえて あまりす。

どでうす? ちんゃと よゃちめう でしょ?

ちんゃと よためら はのんう よしろく



  • 上記はネットのどこかで拾ったもの

  • 1次情報源は不明

  • ケンブリッジ大学うんぬんについての真偽は怪しい


車輪の再発明

基本的には避けるべきだけど、学習のため(理解を深めるため)にあえてやることも重要かな。


枝刈り

探索アルゴリズムで、無駄な探索を早めに打ち切ること。

アルゴリズム的にも有効だけど、日ごろの思考・理解などでも重要かと。

例えば、副作用のない純粋関数、イミュータブル、変更不能変数(定数)などは、考えなくてよいことが明確なため、理解しやすくなっている。


分割統治法

大きな問題を小さな問題に分割して解決する方法、アルゴリズム。

例えば、32bitの整数型のビット列を左右反転させるとした場合、以下のような方法がある(ベストなコードではないけど)。

public static int reverse(int data) {

// 16bitづつ入れ替える
data = ((data >>> 16) & 0x0000ffff) | ((data << 16) & 0xffff0000);
// 8bitづつ入れ替える
data = ((data >>> 8) & 0x00ff00ff) | ((data << 8) & 0xff00ff00);
// 4bitづつ入れ替える
data = ((data >>> 4) & 0x0f0f0f0f) | ((data << 4) & 0xf0f0f0f0);
// 2bitづつ入れ替える
data = ((data >>> 2) & 0x33333333) | ((data << 2) & 0xcccccccc);
// 1bitづつ入れ替える
data = ((data >>> 1) & 0x55555555) | ((data << 1) & 0xaaaaaaaa);
return data;
}

(同様の考え方で、64bit整数型を8x8のビットイメージとして、90度回転させる、といったことも可能)

クイックソートや二分探索も、分割統治法を使っているといえる。

アルゴリズム以外にも、活用できることは多いかも。


処理量のオーダー

例えば1000件のデータを処理するのに100ミリ秒かかるとして、100万件のデータを処理するのにどれぐらいかかるか?

処理量のオーダーが $O(n)$ なら1000倍ぐらいで100秒ぐらいかなと思うけど(実際に1000倍かどうかはとりあえず置いておく)、オーダーが $O(n^2)$ だと 0.1秒×1000×1000倍で、10万秒ぐらい(1日以上。場合によっては数日)かかる計算になります。

可能なら $O(n \log n)$ ぐらいのオーダーにしたいですよね。

(一般的なアルゴリズムで、速いソートが $O(n \log n)$ で、遅いソートが $O(n ^ 2)$ になる)

O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(n^3) \ll O(2^n) < O(3^n) \ll O(n!)


性能向上・性能対策

プログラムの性能(処理速度)が悪い場合、がむしゃらになんでも最適化(高速化)をしてもなかなか結果に結びつかないことが多い。

プロファイラーなどでボトルネックのなっている個所を洗い出して、そこを重点的に対策する必要がある。

それ以上に効率的な対策は、アルゴリズムや処理方法を見直すことだと思う。


  • 前述 UNIX哲学 の中の「Cプログラミングに関する覚え書き」


    • 推測するな、測定せよ



  • 「早すぎる最適化は諸悪の根源」ドナルド・クヌース

  • パレートの法則


その他


  • RESTFul

  • The Twelve-Factor App

  • Git Flow, Github Flow

  • ボーイスカウトの原則:来た時よりも美しく

  • 1年後の自分は他人

  • KISS, DRY, COC, YAGNI, PIE, ...

  • Lie-to-children

  • などなど