2020-10-30

お願いだからセンスの無い人はプログラマにならないで下さい

プログラミングセンスです。センスの無い人がプログラマになると、他のすべての人に迷惑がかかります。だからセンスの無い人は絶対プログラマにならないで下さい。

プログラミングセンスが無い人や、プログラミングをやったことの無い人は、知識を得たり経験を積んだりすれば、誰でも「良いプログラマ」になれると思っているようですが、無理です。

というのも、センスの無いプログラマ問題は、知識経験の不足ではないからです。センスの無いプログラマの救いようの無い問題は「頭がおかしいこと」なのです。

題材は何でもいいのですが、具体的なコードを見た方がイメージがつきやすいと思いますので、とりあえず以下の問題を考えます

問題

住民リストが与えられるので、背の低い順に男女ペアにしたリストを作って下さい。ただし、男女の数は同数であるします。

コード

ふつうの人は、難しく考えずに以下のようなコードを書きます

const makePair = (persons) => {
  const males = persons.filter(person => person.sex === MALE)
  const females = persons.filter(person => person.sex === FEMALE)
  const compareHeight = (a, b) => a.height - b.height
  males.sort(compareHeight)
  females.sort(compareHeight)
  return males.map((male, idx) => [male, females[idx]]) // 男女の数は同数
}

この例はJavaScriptなので高階関数を使っていますが、仮にそういう機能が無かったとしても、

というコード構成は大きく変わらないでしょう。

一方、センスの無いゴミプログラマは、以下のような名状しがたきコードを書いてきます

function pair(psns) {
  var i = -1;
  var cnt = 0;
  var flg = psns[0] && psns[0].sex;
  var j = -1;
  var tmp = null;
  for(i = 0; i < psns.length; i++) {
    //console.log('■■■■■■■■■■■■■■■■■■■■ BEGIN ■■■■■■■■■■■■■■■■■■■■')
    //console.log(psns, 'i=' + i, 'cnt=' + cnt, 'flg=' + flg);
    if(psns[i].sex == flg) {
      //console.log('cnt: ' + cnt + '->' + (cnt+1));
      cnt++;
    } else {
      j = i - cnt + 1;
      //console.log('swap ' + i + '<-->' + j);
      tmp = psns[j];
      psns[j] = psns[i];
      psns[i] = tmp;
      i = j - 1; // <- 理由は分からないが、i = jだと上手くいかない(by XXXX)。
      cnt = 0;
      flg = flg == MALE ? FEMALE : MALE;
      while(j > 1) {
        if(psns[j].height < psns[j-2].height) {
          //console.log('swap ' + j + '<-->' + (j-2));
          tmp = psns[j-2];
          psns[j-2] = psns[j];
          psns[j] = tmp;
        }
        j -= 2;
      }
    }
    //console.log(psns, 'i=' + i, 'cnt=' + cnt, 'flg=' + flg);
    //console.log('■■■■■■■■■■■■■■■■■■■■ END ■■■■■■■■■■■■■■■■■■■■')
    //console.log('')
  }
  for(i = 0; i < psns.length; i++) {
    //console.log('■■■■■■■■■■■■■■■■■■■■ BEGIN ■■■■■■■■■■■■■■■■■■■■')
    j = Math.floor(i / 2);
    //console.log(psns, 'i=' + i, 'j=' + j);
    tmp = psns[i];
    if(!(i % 2)) {
      psns[j] = [null, null];
    }
    if(tmp.sex == MALE) {
      psns[j][0] = tmp;
      psns[j][1] = psns[i+1];
    } else {
      psns[j][0] = psns[i+1];
      psns[j][1] = tmp;
    }
    i++;
    //console.log(psns, 'i=' + i, 'j=' + j);
    //console.log('■■■■■■■■■■■■■■■■■■■■ END ■■■■■■■■■■■■■■■■■■■■')
  }
  psns.splice(psns.length / 2, psns.length);
}

こんなコードメンテナンスは御免被りたいです。一見して配列の要素を入れ替えていることが分かるだけで、実装を全て読まなければ(いや読んでも)処理の意図が全く分かりません。また、たとえば「i = j - 1」が間違って「i = j」などと書かれていてバグを起こしたとしても、原因を突き止めるのは困難を極めます

さて、このコードは具体的に何がいけないのでしょうか。長すぎることがいけないのしょうか。変数名が分かりにくいのがいけないのでしょうか。引数破壊的に変更しているのがいけないのでしょうか。不要コメントが残っているのがいけないのでしょうか。よく見ると、ソート処理で車輪の再発明をしていたり、「j」や「tmp」などが場所によって意味が違うカメレオン変数になっていたりしますが、それがいけないのでしょうか。どれも正しいですが、それらを逐一直したところで、本質的解決にはならないでしょう。

後者コードはもはや「ここを直したら良くなる」とかいレベルを超えています。たしかに、問題を具体的に挙げることはできます。このコードの致命的な問題が、凝集度の低さと、単一責任原則(SRP)違反にあるのは間違いありません。しかし、後者コードを書いてくる人に、

住民リストを男女に分ける処理や、リストソートをする処理、2つのリストをまとめる処理は、この問題とは独立して意味のある操作から、別の関数として抽出しましょう。その方がコードの見通しがよくなるし、一部の処理を修正したときの影響も小さくなるし、単体テストも書きやすくなります

なんて言ったって聞く耳を持たないでしょう。

そもそも、こういうコードを書く人は、この処理自体を「pair」なんて関数抽出すらしません。まだこの問題では入出力のフォーマットが明確に定義されているので、他人が1から書き直せますが、実際のプロダクトでは、無数の副作用を起こす数千行のコード迷路を彼の脳内フォーマットデータが通るわけです。もちろん、テストコードなんてありません。

まり、指摘をしても絶対に直らないのです。いくら言語の優れた機能ベストプラクティスを紹介しても、馬の耳に念仏。それらの利点を理解できるだけの脳みそが足りていないのです。

どうして、同じ処理を実装するのに、ここまでの違いが生じるのでしょうか。

これは、プログラミング技術問題ではありません。既に述べた通り、ふつうの人なら、特定機能の有無とか知識の程度にかかわらず、ふつうコードを書くのです。なぜなら、ふつうの人にはそちらの方が楽だからです。つまり、前者のコード別に何か卓越した技術を身につけた結果書けるようになるものではなく、まともな感覚さえ持っていれば、プログラミング初心者にとっても前者のコードの方が書きやすいのです。

まり後者のようなコードを書いてくる奴というのは、現実世界の捉え方が常人とは著しくずれているのです。要するに、「頭がおかしい」のです。この病気はもう直りません。だからセンスの無い人は絶対プログラマにはならないで下さい。

  • すげえ 2つ目のコード意味わからなかった

    • 脳の短期記憶が強力な人は、 巨大な for 文で中にいくつ分岐があっても、難なく読めてしまうんだよ。 上手い書き方が分からないというより、 脳の思考をそのまま表現できていて読み...

  • 関数の引数に渡すと、一次元配列が二次元配列に変わるというのが凄まじい

  • 巨大なfor文の中ですべてを行おうとする人は、本当にコード書かないで欲しい

  • なんで処理の意味を関数名・変数名にするという簡単なことすらできないのだろう

  • こういうコードが蔓延してて、しかも社員が「7つの習慣」とかに被れてる意識高い系無能なところで働いてる 「マンパワーではなくマネジメントの力で改善しよう」とか言ってるが、...

    • そういうのBullshit JobsのDuct Tapersっていうんでしょ しってる

    • 当方中小SIer勤務ですが、経営陣がそういう自己啓発本にかぶれており、不定期に中身のない「プロジェクト」を立ち上げて、「プレゼンコンペ」「ほうれんそうグループワーク」みたい...

  • 後者の方恣意的に極端な例にしてるんだろうけど、実際割とあるよなこういうの。 パフォーマンスイシューが出てきて前任者が消えたインデックス変数使って逐次処理の中にif分岐を散...

    • 「リファクタリング」とかに載ってるような、典型的な改善点が目に付くクソコードなんかは、むしろ稀で 現実のクソコードはこういうのなんだよね

      • そもそも、改善点がある程度明確な時点で、そんなに悪いコードではない。少なくとも読めるから

      • if (条件1) { if (条件2) { 正常系の処理 } else { 条件2のエラー処理 }} else { 条件1のエラー処理} ……というコードを書くやつは死んでいい。

  • 数学の証明みたいな、確実な情報を組み合わせて何かを構成するという思考法ができないまま大人になってしまったのだろう

  • // 2020-11-02 ins-start masuda 元増田に対する返信を追加 言っとくが現場の糞コードには後者に加えてさらに、 数重にコメントアウトされた修正履歴が入ってるからな。 // 2020-11-02 ins-end masuda ...

    • たしかに

    • こうですか?わかりません >< function pair(psns) { var i = -1; var cnt = 0; var flg = psns[0] && psns[0].sex; var j = -1; var tmp = null; // modified on 2020-12-31 by XXXX // var k = -1; for(i = 0; i < psns.l...

  • 黙ってテストを書けばいいだろう。他のプログラマはみんなそうしている。お前達はなぜそうしない? 理由は1つ。レガシーコーダーは異常者の集まりだからだ。異常者の相手はもう疲...

  • 最近ブチ切れたコードの一部 public virtual class DataInfo { public Integer p; public Integer c; public Integer r; public Integer v; public String name; public DateTime time; // ...}public class CellInfo extends DataI...

  • 最近ブチ切れたコードの一部 public virtual class DataInfo { public Integer p; public Integer c; public Integer r; public Integer v; public String name; public DateTime time; // ...}public class CellInfo extends DataI...

    • これは何をやろうとしててどのあたりにブチ切れポイントがあるんや?

  • コードの動作理解せずに当てずっぽうで、変数のインクリメント増減させたり、行コメントアウトしたりして、 「エラー出ずに動いたからオッケー」 みたいなのも普通にいるから怖い

  • 正直こんなの(誇張を差し引いても)書いてるやつ見たことないけど,そんなのと働かなくちゃいけなくなったらこういう文句を言いたくなる気持ちもちょっとわかるな.

  • 日中も普通に働いてて夜の(午前の)3時くらいに書いたコードがそんなんだったりする

  • データ設計のセンス無い奴は、プログラマになったらいけない

  • 巨大なfor文ですべてを解決しようとする やたらといろいろなものを可変にしたがる (当人は「センスの良い抽象化」だと思っている) クラスを「コード置き場」としか思ってない 実...

  • できない奴は何度言っても、データのバリデーションや集計処理とDBへの登録処理を同じメソッドに書いてくるし、Viewにビジネスロジックを埋め込もうとする

  • 高階関数どころかループといえばFORしかなく 変数のスコープなんてものさえなかった時代は こう書くしかなかったんやろな……という悲しみはある

  • そんなゴミコード書く同僚がいる職場にいる増田の能力について

  • なんかこれ前も見たな。ぐだぐだ何度もお疲れさま。 性格的にしろ能力的にしろ合わない人がいるなら違う部署かあるいは違う会社にいくしかないよ。

記事への反応(ブックマークコメント)

ログイン ユーザー登録
ようこそ ゲスト さん