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

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

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

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

* [RFC 1958 Architectural Principles of the Internet](https://www.ietf.org/rfc/rfc1958.txt)

>3.9 Be strict when sending and tolerant when receiving.

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

## パレートの法則

* wikipedia - [パレートの法則](https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%AC%E3%83%BC%E3%83%88%E3%81%AE%E6%B3%95%E5%89%87)

いわゆる80対20の法則。
80%の利益が、20%の人からもたらされている、とかいうアレ。
数字の80とか20にはあまり意味がないので、実際には1%のものが90%を占めている、といったこともある。

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

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

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

* ロングテール商法
* 神は細部に宿る

## マズローのハンマー

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

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

## プログラマの三大美徳

* 怠惰（Laziness） - 効率や再利用性の重視
* 短気（Impatience） - 処理速度の追求
* 傲慢（Hubris） - 品質にかける自尊心

【参考】wikipedia: [プログラマの三大美徳](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%AE%E4%B8%89%E5%A4%A7%E7%BE%8E%E5%BE%B3)

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

* 最新の正しい情報を
* 大きくわかりやすく書いて
* 一か所にまとめて
* みんなで見ることができる

## UNIX哲学

* wikipedia - [UNIX哲学](https://ja.wikipedia.org/wiki/UNIX%E5%93%B2%E5%AD%A6)

## 伽藍とバザール

* [伽藍とバザール](http://cruel.org/freeware/cathedral.html)

## 誤字脱字

誤字脱字はなかなか無くならない（気づかない）。

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


* 上記はネットのどこかで拾ったもの
* 1次情報源は不明
* ケンブリッジ大学うんぬんについての真偽は怪しい
* wikipedia: [タイポグリセミア](https://ja.wikipedia.org/wiki/%E3%82%BF%E3%82%A4%E3%83%9D%E3%82%B0%E3%83%AA%E3%82%BB%E3%83%9F%E3%82%A2)

## 車輪の再発明

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

## 枝刈り

探索アルゴリズムで、無駄な探索を早めに打ち切ること。
アルゴリズム的にも有効だけど、日ごろの思考・理解などでも重要かと。

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

## 分割統治法

* wikipedia - [分割統治法](https://ja.wikipedia.org/wiki/%E5%88%86%E5%89%B2%E7%B5%B1%E6%B2%BB%E6%B3%95)

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

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

```java
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)$ になる）

```math
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哲学](https://ja.wikipedia.org/wiki/UNIX%E5%93%B2%E5%AD%A6) の中の「Cプログラミングに関する覚え書き」
  * 推測するな、測定せよ
* 「早すぎる最適化は諸悪の根源」ドナルド・クヌース
* パレートの法則

## 不具合

時として、思いもよらない不具合が起きることもある。

* [バニラのアイスを買ったときだけ車のエンジンがかからなくなる不思議な現象、その原因は？](https://gigazine.net/news/20200511-vanilla-ice-allergic-car/)
* [500マイル以上離れた場所にメールが送れないのだが](https://cpplover.blogspot.com/2015/04/500.html) 日本語訳 ( [英語の元ネタ？](http://web.mit.edu/jemorris/humor/500-miles) )
* [中国人のAさんがお茶を入れると会社のネットが繋がらなくなる](https://togetter.com/li/1618067)
* [朝7時にインターネットが突然つながらなくなる](https://gigazine.net/news/20200924-old-tv-dsl-interfer/)
* [祖母が就寝するとDBインサートができなくなる](https://qiita.com/bohemian916/items/46f9f1e8bb32fc0a1f99)

あるいは、相関関係と因果関係の違いは分かりにくい、ともいえるのかも？

## 簡単そうに見えても奥が深いことが多い

* 性別：[システムで「性別」の情報を扱う前に知っておくべきこと](https://qiita.com/aoshirobo/items/32deb45cb8c8b87d65a4)
* 名前：[プログラマの抱いている名前についての誤謬](https://emptypage.jp/translations/kalzumeus/falsehoods-programmers-believe-about-names.html)
* 時刻：[タイムゾーン呪いの書](https://qiita.com/dmikurube/items/15899ec9de643e91497c)
* 国際化：[ぼくたちのかんがえたさいきょうのi18n国家](https://qiita.com/yugui/items/55f2529c5a731badeff7)
* 色：
  * [ガンマ補正のうんちく](https://qiita.com/yoya/items/122b93970c190068c752)
  * [グレースケール画像のうんちく](https://qiita.com/yoya/items/96c36b069e74398796f3)
  * [画像リサイズ処理のうんちく](https://qiita.com/yoya/items/95c37e02762431b1abf0)
  * [色覚の多様性と色覚バリアフリーなプレゼンテーション](https://www.nig.ac.jp/color/barrierfree/barrierfree.html)
  * [プログラマが知っているとよい色使い(JIS安全色)](https://qiita.com/kaizen_nagoya/items/cb7eb3199b0b98904a35)
* 乱数：[乱数について本気出して考えてみる](https://techracho.bpsinc.jp/yoshi/2019_12_20/85193)

## データ

* [国民の祝日](https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html) [csv](https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv)

## まとめ系

https://qiita.com/e99h2121/items/4b5e3ff9001ede108fa9

https://qiita.com/e99h2121/items/6d5cc72679f43aa37be2

https://qiita.com/goyae/items/196221169391dd44125d

https://qiita.com/yoshi389111/items/7a6280bd138c26fd2717

## その他

* RESTFul
* [The Twelve-Factor App](https://12factor.net/ja/)
* Git Flow, Github Flow
* ボーイスカウトの原則：来た時よりも美しく
* 1年後の自分は他人
* KISS, DRY, COC, YAGNI, PIE, ...
* Lie-to-children
* などなど