ターニングポイントさん!?

リファクタリングと、その手法の話

◆初めに

妙なコードを書くな。
いや、妙な書き方以外知らないんだからしょうがないんだけども。
愉快な書き方以外知らないのだから、そのコードを観測した人はソレについて怒ったって駄目だ。だってその人は「良いコード」の書き方なんて教わってないんだもの。
お前が書き方を教えてあげればソイツの生産性は上がる。次はソイツが教育者になれる。お前の仕事は楽になる。

アホなコードでもクソなコードでも、個人の観点だと書かないよりは書いたほうが良いとも言える。コピペで引っ張ってくるよりマシ。
俺も妙なコード書いてたわ沢山。

でもアホなコード書いた人に対して「これはアホなので直していいですか」とか言っちゃうのは結構ブレイブいるし、今動いてしまっているものを書き直すことを嫌う現場は多い。
当然だな。壊れていないものを直すなという諺がまさにそれだ。
結果として、クソとは言わんまでもアホなコードが積み重なり、俺やお前が残業することになる。

だからブログで愚痴ろう。ついでにお前らを教育しよう。

◆するにあたり(ここポエム)

リファクタリングするべきだ。
そして、リファクタリングされるべきだ。

「コードに文句付けられるとムカつく」じゃなくて、まず自分よりもプログラミングをすこれ😭

本を読んだり、誰かとリファクタリングをしないと「こういう書き方できるな」ということを学ぶことができない。
ロジック(つまり動くコード)を書くのだけなら技量はいらない。誇張ではなく、小学生でも出来る。また、ロジックを速く書けてもしゃあない。テストやら保守やら改修する人がそのアホコードを読み解くのに時間がかかるからだ。

難しい、厳しい事を言っていると思われたかもしらんが、そんなことは無い。
プログラミングはパソコンをいぢくる才能を持っている人だとか、頭のいい人だけのものではない。問題解決に対する小さな興味さえあればジワジワと無限に成長できる。
俺みたいなガイジでも元気に白目剥きながらコーディングしてるだろ?

プログラミングの技能向上タイミングは、経験と、問題察知能力により発生する。
プログラミング歴3カ月の初心者だとしても「なんかこのコードうまくねぇな」「このプログラムって改修すんのすげぇ面倒くさいな」という肌感覚はあるだろう。そのコードは絶対にリファクタリングできる。お前がリファクタリングを積めば次に書くコードはもっとウマくなる。

リファクタリングを積むと引き出しが増える。初手から割と短いコードを書ける。
つまりコーディングも速くなる。読む人だってそりゃもうウキウキさ。つまり総合的なコストが下がる。時間のコスト、金のコスト、人間関係のコスト、いろいろ。

しかし、半端にコーディングできる人は、他人のコードを絶対に触らないほうが良い。動かなくなって死ぬから。俺はそれで死にました~♨
誰にも言わずに、自分のローカル環境に別名コピーを作ってそれを直して満足するのがいい。
「俺プログラミングできるじゃーん!」なお前は、極めて危険。その先には5枚くらいの壁があった。俺は「プログラミングできるじゃーん!」を5回やった。「あいつクソコード書きやがって」とワキワキしながら自分でアホなコードを書いていた。5枚目の壁を越えたけど今はもうひたすら自分のコーディング能力が疑わしい。
そんなんだから、例えば「コーディングできますけど?」って感じの上司が頭悪いコード書いてるのをみてると、昔の俺を見ているようでほっこりする。

ほっこりされたくないだろ。部下からほっこりされたくないなら勉強しろよな。停滞要因は自分の技術に対する買い被りだ。そのせいで俺は時間を無駄にした。自分のコードを疑え。周りの人間に聞け。ググれ。リファクタリングしろ。

なんでリファクタリングすんのかって、俺やお前らが「考えた事」をコードにすると、まず、モワッとした、有機的な、人格の出るコードが出来上がる。
そのモワモワを圧縮する方法を知っていると、そのコードはだんだんと小さくなり、硬くなり、綺麗になり、結果として宝石のようなものになる。

くっっっさ!ヴォエ!死ね!

もうポエムはいいや。疲れた。

この記事は、気が向いたら追記していく。気が向いたら見にこい。
そして、俺もまだ勉強中の身であるゆえ間違った内容もあろう。「ちげぇな」と思ったらコメントしてくれればいいし、「説明たりねぇ」と思ったらそれもコメントしてくれ。

◆どうなれば大満足なのか

読みやすければいい。
つまり、他の記事でも書いたんだが

綺麗でコンパクトで簡潔で疎結合で役割がハッキリしてて仕様が読み取れて仕変に強くて単体テスト可能なコード

を書けばいい。
最低「仕様が読み取れる」「動作が読み取れる」ができていればいいじゃんと思う。でも、それがリファクタリング線の終着駅なんです。

以下を読み進めるにあたっての注意は

  • 中途半端に適用すると逆に可読性が悪くなる場合がある
  • あらゆるパターンに適用することはできない

の2点だ。
1つのリファクタリング手法だけを適用すると、これまた妙な記述になる。
ネット上で「こんな書き方をするべき」「いやそれは違う」とか議論している人々は、「1つの記法」にのみ注目しているから話が食い違う。…時がある。あとは好みもある。しょうがない。絶対正義があるんならみんなその記法に準ずるだろう。
俺が望むことは「この記事で紹介された記法を頭の片隅に置いておいて欲しい」ということです。参考にするにとどめるべきで、個人の意見を鵜呑みにしてはいけない。
ロジックを書き終えた時に、その記憶を引き出してくれ。

書き終わったコードは読み直さないといけない。
読み直さないと当然リファクタリングできないし、よくわからんコードを書くと読み直すことが億劫になる。負のスパイラル。そのスパイラルから生まれるのは、超明確なバグが「ここに置いとくねー」って感じに放置されたコードだ。

一応注意しておくけど、この記事ではリファクタリングの話をしている。最適化とかデザインパターンは別のものだ。

◆if文

「if文ってなに?」って人は、この記事をブクマした後に刺身の上にタンポポを載せる作業に戻れ。

例となるコードは頑張ってC言語(99)で書いたからみんな読めるはず(希望)
動作確認はpaizaでしました。ポインタとか完全に忘却していてだらしねぇし…

▼ifの①

何となくインデントをスペース2つで書いたけど、僕はスペース4つ派です(激怒)

やっていることは
int型変数「foo」「bar」「baz」の中身を確認し、すべて0であった場合はcheckResultに「isAllVariableZero」を詰め、そうでなかった場合「isNotAllVariableZero」を詰めている。

これは、なんか無駄なことをしているのが分かるだろう。
「最初にisNotAllVariableZero詰めておけばよくね?」という話だ。
だが、「まだ判定してないのに結果詰めたら駄目だろ!」という人もいるだろう。
だが例えば、bool型を使う事を考えた時、宣言時にfalseが入ってしまうことは問題ないのだろうか?あるとも言えるし、ないっちゃないとも言える。

「判定してないのに!」っていうのは、単なる感覚の話だ。もっとシビアになれ。
コードは「なるべく人間が文脈を読みやすく」なるように記述するべき。アセンブラじゃないんだから。
「こういう値が来たらこういう結果になるね」ということを、いかに簡潔に読み手に伝えるかが問題だ。

「こういう処理をしたい」という思いをそのままコードに起こすのは誤りだ。そのほとばしる熱いパトスは仕様書なりコメントに記述するべきことで、コード自体はその仕様を満たす一番読み下し易い書き方をしなければならない。

上から処理を辿って、つっかえる部分は排除しろ。
今回で言うと、2回目の「else」でつっかえただろう。なぜなら、その「else」に紐づくifの記憶はもう失われているから。
この例に於いては、最初にisNotを詰めてしまって何の問題もない。
その理由は「コードを上から読んでいったときに何をしているのか分かりやすい」かつ「ロジックが正しい」からだ。変数を基本となる値で初期化できるのならば、余計なif文は減る。

つまり「if-elseを書く前に初期値を詰めたほうが良い」というケースがある。
それを覚えておいてくれ。

「ifにはセットでelseを付ける事」ということを教わった人もいるだろう。
その現場、その上司の下ではそうしろ。ちゃんとassert使ってるならそれでいい。
でも、常に「なんで?」と思ったほうが良い。

三項演算子も、初期値詰めればあとはifでチェックしてその行で詰めるだけ。
三項演算子つかっちゃダメだよ。読みづらいよ。
何でかっていうと

  1. まず代入先の変数名が目に入る
  2. 「=」の右側に変数がある
  3. これが代入されるんだなと判断する
  4. 比較演算子が見える
  5. 一瞬思考が止まった後、「あぁbooleanか」と判断する
    ⇒補足:条件の結果を代入したいときは、その条件を丸括弧で囲もうね。
  6. 「?」が見える
  7. 一瞬思考が止まった後、「三項演算子か・・・これ書いたの誰だよ・・・」と思う
  8. のびのびし、座り直す
  9. コーヒーをすする
  10. 三項演算子の条件部分で使用されている変数を調べるために前のコードを読み直す
  11. 三項演算子の使用箇所に戻り、trueかfalseか判断する
  12. trueあるいはfalseに対応する、代入される変数を調べるために前のコードを読み直す

こうなるから。
12ステップを踏まないと三項演算子を理解することはできない。保守してくれる人を虐待するのはやめよう。でも・・・まぁ使わざるを得ないタイミングもある。絶対悪ではない。「なるべく避ける」で運用していけ。

▼ifの②

さっきのコードを読んで、こんなことを考えた人はいるだろうか。
「このifひとつにまとめられるやんけ!」

やめなされやめなされ・・・

なにが良くないかというと、条件が増えた時に困る。
同じifに詰める人もいれば、ifを入れ子にする人もいるだろう。
つまり、表記揺れが発生する。安易に&&や||を使用すると、修正した後にコードの前後比較をすることがあるが、その時も困る。一見してどこが変更されたのかが分かりづらい。

でも条件がクッソ複雑になってくると&&やら||でまとめたほうが良い場合も勿論ある。ぶっちゃけた話、この例の場合は&&でまとめてしまってもいいとは思うわ。
そこは臨機応変にな。

あと「foobarbaz全部足したら判定が楽やんけ!」と思ったお前。
お前は賢い。賢いが、賢いマネをすると可読性が落ちる場合があるから気をつけよう(占い)。
「俺の考えた最強のアルゴリズム」よりも「仕様が読み取れるロジック」のほうが長期的、大局的な観点ではより賢いと言える。

このへん見てみてね。

このコードを修正するとこうなる。

●何をしたか

  • 判定処理をメソッドに切った
  • ガード節を使用した

●結果どうなったか

  • メソッドが増えた
  • ifのネストが消えた

うん。

★メソッドの切り出し

何が嬉しいかというと、まず「明らかに正しいメソッド」が一つできた事だ。
このコードは単体テスト可能だ。よくわからないか?そうか。いつか分かる。

また、バグが発生したときに、とりあえず変数の中身を標準出力に書きだしまくることがあるだろう。その時「このメソッドは取り敢えず大丈夫」という判断ができる。

「長くて、どこかにバグが潜んでいる1つのメソッド」と「それぞれが短くて、どれか1つにバグが潜んでいる複数のメソッド」を想定する。
両方ともやっていることは同じだ。
上司に「どちらかの不具合を修正してくれ」と言われたら、俺は間違いなく後者を選択する。
なぜなら、バグの特定が楽だから。説明はしないでおく。読み進めれば微妙に分かってくるだろう。

「どこからメソッドを切るか」という判断は・・・慣れ・・・?
「使いまわすから」とか「長くなってきたから」というものでは無い・・・気がする。
いつか言語化するわ。

★ガード節

つまり「ある条件であった場合、処理を打ち切る」ということだ。

まず、if文に限らず深いネストは基本的に見たくないものだろう。
「うわっ」とか「あっ」と思うだろう。それは、いままでネストにいい思い出が無かったからだ。
それはそうだ。スッと読める書き方では無いのだから。
一行ずつ意味が通るコードのほうが、他の行を覚えておく必要が無くて楽。

じゃあcheckValueZeroメソッドを見てみよう。

これは見づらいだろうか?
あっ見づらいですよね。すみません。

だが、それは慣れの問題だ。
例えばfooに1が入ったときに、結果、どのような文字列が出力されるかを考えた時・・・
リファクタリング前のほうが見やすいかもな・・・

例が悪いよ例が!

※実際のところ、「数値の変数たち」が全てゼロかどうか判断したいのであれば、数値の配列を受け取ってその配列の中身をチェックするという関数を書けば良かろう。

「ガード節読めない」というのは、例えば「foreach知らないから読めない」とか「LINQ知らないから読めない」とかそのレベルの話だ。
楽をしたいのなら、本当はガード節を使用するべき。はじめは違和感あるかもしれないがな。

業務でのプログラミングでは、もっと複雑に条件が入り混じる。
そういったときにガード節は有効だ。

  • コードを上から読んだときに仕様を読み取りやすい
  • elseを見た時にifの内容を確認しに行く必要が無い
  • ネストが浅い
  • ガード条件に一致した場合、それ以下のコードは読まなくても良いと判断することが可能になる
  • テストコードが書きやすい
  • ガード節を適用しようと考えた時、ifの(仕様の)整理をせざるを得なくなる。整理しないとガード節は使えない。
    ⇒ if文じゃないと書けなくね?っていうのも割とガード節で書ける。そして大抵の場合読みやすくなる。副次的に仕様漏れが見つかったりもする。
  • 条件の追加、削除、変更がしやすい
  • (たまに、メソッドを切るべきという判断のきっかけになる)

「自分が慣れた記法」と「読みやすいコード」「保守しやすいコード」の間に乖離は無いか?
ちんちんに手をあてて考えてみよう。

ちょっと例があれだったけど、もう面倒くさいから

ガード節? ⇒ すごーい! ⇒ たーのしー!

って覚えておいてくれたら良いよ。

このガード節について、かの有名なリーダブルコードでは「異常系で使用する」「ifとelseの条件の重みが釣り合わない時に使用する」的なこと書いてるけど、んなこたないよ。俺の経験上は。だから、使っていい時はガンガン使え。
「returnは最後の1回だけにしないと処理が追えない」とか言ってくる、自分でも何を言っているのか理解できてないような上司に突っ込まれたら即座に折れてif-elseに戻せ。だけど「長すぎるメソッド書いてるからやんけカス」と心の中で思っておいて損は無い。

メソッドに限らず、for文の中のif文なんてのも格好の的だね。
continueを駆使しろ。
ブロックの中のif文は基本的にガード節の使用を考慮しておきたい。

◆状態、ステートメント

さっきのコードに改修が入った。

  • int型変数「hoge」をmain内に定義する
  • hogeが「100より大きい」場合、hogeをbarに代入する
  • その後、判定処理を走らせて結果を標準出力に飛ばす

プログラマー系ガイジのぼく君はhogeの値を判定してbarに詰める関数を作ろうと思った。
結果、こうなった。ルル、かしこい!

ヌッ(憤死)

これは・・・まずい。
foo、bar、bazがフィールド変数になり、それぞれの関数で値を触ったり参照したりしている。問題は解決できているが、どう考えてもまずい。
じゃあ「ツ」のつくアレを込む

お前は、どこで宣言されたかわからん変数が出てきた時に、心がしおれるような気持ちになったことがあるはずだ。
俺も夏休みが終わったような気持ちになる。何故かわからんが。
でもそれは霊長類が長い進化の過程で獲得した正常な反応だ。

フィールド変数を安易に使うと、コードを追う労力が跳ね上がる。
バグが発生した時に概ねすべてのコードを確認する必要が発生する。だってどこからでも値を詰めることができるのだから。
また、そのフィールド変数が一体何を意味するのかを確認しに行かなければならなくなる。

「メソッドに沢山の引数を渡したくない」とか「値の持ちまわし方がわからない」とか「なるべく頭を使わずに仕様をそのままコードに落とし込みたい」とかいう時にこうなる。
結果、バケモノがうまれる。そして俺たちはまた、恋にドロップする

フィールド変数を使わないロジックを考えなければならない。
フィールド定義する変数は、基本的にstatic属性(つまり定数)だ。
今回の例でフィールド変数を使用する意味は全くない。

checkValueZeroメソッドが関数内でprintfせずに新しい文字列(のポインタ)を返していることも同じ理由だ。
関数というものは「値を貰い、何にも影響せずに値を返す」時が一番取り回しが良くなる。状態によって出力が変わったり、自分が状態を書き換えるようなことはしてはいけない。staticはお好きかな
引数として貰った参照に直接値を詰めるのも駄目だよ。なぜなら、どの引数の中身が書き換わるかわからないからだ。

でもゲームとか「画面」とかを扱う時はしょうがないわな。
しかしなるべくオロナイン控えろ!という気持ちでコーディングするといいよ。

さっきのコードをリファクタリングするとこうなる。

「getBarValue」というメソッド名はちょっとアレだけど、まぁ言いたいことは伝わったでしょう。

美しい関数は、値を貰い、何にも影響を与えずに新しい値を返す。

ということだ。

※Cでは、メソッドにintを渡すとき値渡しになる。つまり、参照が切れる。だから貰った引数をそのままreturnしても問題にはならない。でも例えばC#で(クラスの)インスタンスを貰ってそれを返すのはだめだよ。参照渡しだから。新しい値を作って返す設計にして差し上げろ。

getBarValueについては実際はメソッド切る必要なんかない。
実際はこう書かれるだろう。

if (hoge > 100) bar = hoge;

「フィールド変数使うなよ」の戒めとして残しておく。

※Cでは「int変数からint変数への代入」において値だけが渡るよ。ポインタ使えば参照を代入することもできるよ。

◆変数と代入

長くなってきたから一気に行く。

読みづらく、あやうい、ありがちなコードをご用意しました。
他の店で「初心者が書きそうなコードちょうだい」と言っても、なかなかこの品質のコードは出てきませんぜ。
ネット上にはゴロゴロ転がってるけどな(こわいはなし)

一通り読んで処理を把握してみてね。
リファクタリングジャンキー(造語)にとってはタマランチ会長だぞ。

はい。
じゃあ見ていこうね。

▼マジックナンバー

配列「arr」のサイズでforを回すために、「ARR_SIZE」定数を指定している。
これはオカシイ。
arrの大きさが変わったときに、この定数も直さなければいけない。
配列の大きさは、配列から随時取得するべき。

▼変数宣言

  • 宣言を一行にまとめんな
    まとめたところでどうにもならんから。
    改修するときに困るだけ。
    でも超大量の変数を宣言したいときとか、超大量のフィールドをnullやら0やら空文字やらで初期化したい時はやったほうがいいかもね。
  • 全部メソッドの上部で宣言しようとすんな
    変数は使用する直前で宣言して初期値を詰めるべき。
    さすれば、その変数のスコープは狭くなる。変数が何をしているのかを把握しやすくなる。変数の型を確認するために読み返す必要が無くなる。余計な変数を覚えておく必要が無くなる。処理をメソッドに切り分けやすくなる。
    昔は全部上で宣言しなければいけない時代もあったがな。
    ちなみにJavaScriptは変数の巻き上げがある。マジに工数を増やすために作られた言語としか思えない。
    あと、このソースでは「counter」なる変数が宣言されているが、この変数は使っていない。そういった判断すらもおぼつかなくなる。
  • でも処理の前提となる値はなるべく上部で宣言してね
    「arr」は処理される対象であるため、上部で宣言するべき。
    そして、なるべく早くその内容を確認して、早期リターンあるいは異常終了を狙うべき。
  • 変数名を省略すんな
    「arr」はつまり「array」の略なんだけど、省略する意味は無い。
    たとえ長い変数名でも、省略する必要なんざ全くない。
    省略の仕方は何パターンも考えられるのだから、その変数名を覚えていられなくなる。逆に変数名が正確だと、目が疲れた時は目を瞑りながらでもコーディングが可能になる。
    ただ、変数名が長くなりそうなときは処理を見直したほうが良いかもしれないな。
    「タイピング文字数を減らしたい」ていう欲求は意味不明だ。自分のするべき仕事をしないことによって人に迷惑をかけるな。タッチタイピングの練習しろ。意地になってやれば身につくから。
  • 何の情報もない変数名をつけんな
    いやそもそも「array」ってなんだよ。配列って。
    今回の例はちょっとアレだが、変数を宣言した限り、絶対にその変数には意味があるはずだ。だからその意味を明示してやる必要がある。
    逆説的に、意味のない変数名を付けざるを得ない時は何か設計を間違えている可能性が高い。モダンな言語では特にな。
  • 何回も使う要素は変数につめろ
    arr[i]を何度も参照しているが、これは最初に変数に詰めておくべき。
    読み手に対して何回もarr配列の事を思い出させてはいけない。
    arr[i]の中身を書き換える処理であっても、一旦中身を他の変数に入れて、その変数をいじり倒した後にarr[i]に入れなおすのが良い。メソッドを切るときも楽。
  • 見た目を揃えんな
    このソースでは例が無いけど、複数行で変数に値を詰める時に、スペースで全部の行の「=」の位置を揃えようとするやつ。
    そしてコメントで項目の日本語名を書こうとして、これまたコメントの開始位置を揃えようとするやつ。
    そんなの誰も気にしない。そんなことしてる暇あったらトイレ掃除してこい。
    逆に他人のコードみて「ちゃんと揃えろよ!」と思った事あるか?そう思っている人(神経症の人を除く)が多くいるならとっくにIDEがサポートしているだろう。半角スペースで見た目をそろえることは即ち、時空を超えたエゴに保守メンバーを巻き込む行為に他ならない。
    揃えないとどうにも見づらい時もある。また、揃えると劇的に視認しやすくなる時もある。でもあんまりない。

▼意味のあるコメントをつける

「//配列を作成する」というコメントは、まったく無意味だ。
無い方がマシ。「なんか意味があるのか?」と思って読んでしまうから。コメントを書きたいんなら読み直した時に助けになるような事を書け。見栄えを整えたいときは、俺の場合「//」だけを入れたりする(ここ賛否両論)

あと、意味なく1行1行にコメントをするな。
「ある処理をしたい複数行」についてまとめてコメントするように心がけろ。

▼コメントアウトを残さない

//foo = getBarBalue(foo, hoge);」というコメントが残っている。
要らないものをコードに残すべきではない。Gitとかソース管理ツールを使おう。使ってるんだとしたらその行を消せ。
「あとで使うかも」と思ったんだとしても、コメントアウトでやり過ごすのではなく、そのソースファイルごとバックアップするべき。
そして「いつか必要になるのかもしれない」コードは全て削除しろ。

▼意味の同じものは定数にする

「isAllVariantZero「isNotAllVariantZero」という文字列を別々のメソッドで判定値に使っているのだから、定数にしろ。改修があったときに修正が漏れる。

ただ、消費税定数「1.08」と、おちんちん定数「1.08」を1つの定数で賄おうとしてはいけない。消費税とおちんちんは別々のものなのだから、例えば消費税が将来的に10%になり、お前のおちんちんが1.5になったときに困る。

▼同じ処理を何度も書かない

for文の中で「~と一致」とかの文言をprintfしている。
条件分岐ごとに処理を書くのではなく、なるべく1箇所で済むような書き方をするべき。読む時、直す時、メソッドを切る時に楽だから。
ただ、1箇所というのは、必ずしも「1回」という意味ではない。

以上。
事前にリファクタリングしたものがこちらです(キューピー3分クッキング

メモリとか大丈夫か不安(C素人)

「リファクタリングした」とは言ったものの、所詮「俺ならこう書く」でしかない。
ツッコミ所さんがあったら優しく突っ込んでくれ///

この一連のコードでは「fooとbarに同時に一致した時」という仕様が漏れている。
その仕様漏れを嗅ぎ付け易いのはリファクタリング前と後のどちらだろうか。また、その仕様を盛り込もうとしたときに、より改修が楽なのはどちらだろうか。考えてみて欲しい。
elseという構文には謎の安心感がある。「条件を網羅できている感」が発生する。その魔法から逃れるという意味でも、if-elseよりもifで一行ずつ詰めていく処理のほうが見通しが良い。また「なんとなく動く処理」を書きづらくなる。

極論いうと、elseを書くな(ここ賛否両論)

補足させていただくと、例えば「fooとbarに同時に一致した時」の条件を記述したいのなら、&&で条件を拾う行を書くだろうな。俺は。お前どう?(迫真)

◆メソッド

いいとこで新しいメソッドに切れ。
そして、いつでもメソッドに切れるように書け。
変数のスコープを絞れば多分そうなる。

じゃないと、すべての処理を追うことになる。
また、一回のループでありとあらゆることをしようとしてイカれたコードになる。メソッドを切ると、そのメソッドの変数についてだけ考えればよくなるから楽。

あと、前の段でも言ったけど、なるべくフィールド変数やらプロパティには触れるな。アクセスできたとしても、やめておけ。親の処理から値を貰って、新しい値を返せ。
そして、privateなメソッドはprivateと明示し、staticなメソッドはstaticと明示しろ。余計なことを考えずに済むようになる。

メソッド切れって話したけど、C#erはLINQ使え。C#自体かなりすこれる言語だが、それ以上にLINQが使えるって事が本当に恵まれている。アレ気が狂う程気持ちええんだから使わないという選択肢が無い。便利の権化。
他の言語で5行6行と必要になる処理であっても、可読性を損なわずに1行で記述できたりする。むしろ可読性は上がる。さらにコード量が減る。すなわち保守性も高まる。
他の言語からリプレイスしたんならメソッドは絶対に減る。
ただメモリの消費には気を配るべきだな。無茶したらいかん。

【C#】LINQの使い方のはなし

◆興味の対象を絞る

問題をひとつずつ解決すること。

後回しにできることは後回しに、先に処理したほうが良いことは先回しに。
色々な問題をまとめて同時に解決しようとすると可読性が低くなる。コードを「その行」に書かなければいけない必然性について考えて欲しい。

暇なとき追記する。

◆追記用メモ:
for文から新しいList作るときに、先頭要素詰めたい。
でも詰めるべきものが無かった時は先頭要素詰めない。
for回しながら先頭要素詰めるのではなく、for回しきった後にListの個数を判定し、Concatする。

◆データアクセス

▼データアクセスというものはクッソ遅い

データベースへの問い合わせはもちろん、HDDからファイルの取得するのだって遅い。
だから何回もデータベースにアクセスするのではなくて、(意味が通る範囲で)なるだけまとめてアクセスするように。

▼地獄の刑罰みたいなSQLを書かない

とりあえず範囲を取っちまってメモリに展開してから処理してしまえばいい。
つまり、SQLで込み入った条件を書かずに、ある程度絞ったら、あとはコード上でフィルタしよう。
なぜなら神みてぇなSQLは読むのがしんどいから。
書くのもしんどいな。考えるのは楽しいけど。

でもそれで残業したくないっしょ?

ただ、ちゃんと絞らないとデータ件数が多すぎるって場合や、マシンのメモリやパワーが貧弱な場合は通用しないね。

◆正規表現使え

知らん人には呪文にしかならないから使い時が難しい。
正規表現についてみんなが了解しているなら凄い助かるんだが。

みんな正規表現の勉強してくれ(泣)
コードが短くなる場合も多いし、みんなの友達サクラエディタが超便利になるぞ。

ただサクラエディタは「上から検索」機能つけて💖。(検索文字列が勝手に置き換えられて困る人は共通設定を確認しろ。)
あと最下行で下アローキー押したときに終端まで飛ぶようにしてくれ。
パッチ投げようかと思ったけどコードちらっと読んで難しくて諦めた。
あとアレTortoiseSVNでチェックアウトできねぇ。
bashあったからそれで入れたが、バージョン管理ツール内でフォルダ切ってバージョン管理してんのはどういう理由なんだ?病気?

話を戻す。
正規表現が見にくいっていうのは凄い分かる。
でも文字列の込み入った内容判定をするときは、絶対に使いたい。
それなりのテストは必要になると思うが、正規表現のテストなんざ機械化できるでしょ。

そういうページつくるかなぁ。

ここは暇なときサンプルコード作って追記する。

◆ドキュメンテーションコメント

つまり、メソッドやらクラスやらにはちゃんと説明書けってこと。

https://ja.wikipedia.org/wiki/Javadoc

暇なとき追記する。

◆テキストエディタで書くな

単純に時間が無駄になる。Visual Studio Code使え。

配色テーマをHigh Contrastにしろ(賛否両論)

ゑ?現場の決まりでアプリケーションをインスコできない?
とりあえず上司に訴えてみれば?駄目なんだろうけど。

◆設計を見直せ

リファクタリングってレベルを超えた話になるが

正規化とかしろ。
抽象化可能なデータを考えろ。
他にも色々。

UNIX哲学

データはすべてを決定づける。もし、正しいデータ構造を選び、ものごとをうまく構成すれば、アルゴリズムはほとんどいつも自明のものになるだろう。プログラミングの中心は、アルゴリズムではなくデータ構造にある。

データ構造がイカレてると、まずそのもつれを解きほぐすコードを書かなければいけなくなる。以前、イカレたデータを取りまわすためのラッパークラスを作ったら「変なクラス増やさないで」って言われたことがあったな。「じゃあこういうユーティリティークラス作ります」って言ったら「それならいいよ」って返されたね。今となっては笑い話だけど。
データの構造とデータの名前には十分な注意を向けなければいけない。

◆結論

すきにしろ。ただ、ゴミが溶けて中からキレイでカチカチなものが出てくる感覚は是非に味わっていただきたい。

じゃあな。元気でやれよ。俺はC#を使わさしていただく。

【ゴミ記事】パターンを考えよう

BuzzFeed編集者の耳はどうなっているんだ

1件のコメント

  1. 匿名

    (笑)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


Powered by WordPress & Theme by Anders Norén

%d人のブロガーが「いいね」をつけました。