Kaketan::Note

人生をやり直すときのバックアップ

明日から使えるソフトウェア開発効率化 TIPS

今年、実務で Web アプリケーションのチーム開発をする中で「これは習慣化させたほうがよいな〜」と個人的に考えてメモしたものがいくつかあったので、それを共有します。どなたかの参考になれば嬉しいです。

設計

過去に似たようなことをやってないか探す

  • 大規模アプリの場合、似たようなことをやっているところが他にもあることが多いので参考にする(パクる)。

早めに具体レベルのコードを書いてツッコミをもらう

  • ミーティングなどで抽象的な議論で合意がとれたら、早い段階で具体のレベルのコードを書いてツッコミをもらう。(抽象的な会話だとそれっぽくよさそう感が出るけど...)
  • 目指すべきゴールが間違っている状態で道のりに時間をかけることは勿体無いので、自分が目指しているゴールと他のチームメンバーが思い描いているゴールが離れすぎてないかを早めに確認することが大事。
  • そのために、自分の頭の中はこういう状態ですというのを簡単にでよいので、プロトタイプとしてより具体的なコードのレベルのものを書いてみるとツッコミを貰いやすい。

実装

ドキュメントを読む

ログを読む

  • 自分が書いだコードによって実際に発行されるクエリや処理が意図したものであるかどうかをちゃんと見る
  • 意図したリクエストが行われているか、パラメータが適切かだけでなく、N + 1 が発生していないか、意図した render が行われているかなど、テストで漏れそうなところも含めて確認する。
  • ref: エンジニア初級者が意識すべき3つのこと - QKAKE::TECH

質問する

何を伝えるか

質問するときに伝えたほうがよさそうなことは 3 つあるなと思っていて、

  1. 自分がどういう仮説を立てて検証したか
  2. そこから何がわかって、何がわからなかったか
  3. いまどういう仮説を立てているか

これを一度言語化することで、フィードバックが貰いやすい気がしている。
このときどういう仮説を立てているのか(どう考えたのか)が重要だと思っていて、なぜなら、わからないこと(検証がうまくいかないこと)だけ伝えても、仮説の立て方が間違えている場合があり、その2つは連続しているので検証結果だけ伝えると「何を言っているかもわからない」状態になりがちだから。 だから上の 3 つくらいを押さえるとよさそうな気がしている。

いつ質問するか

ググってわかるようなことは自分でググって解決してしまったほうが早いので、じゃあいつ質問したらよいかというのが議題にあがることがしばしばあるが、個人的には、質問するタイミングは、1つの課題について仮説を検証する作業が 3 回以上になってしまったときかなと思っている。
基本的には、課題発見、(1)実装・ググる(仮説を立てる)、(2)動作確認(検証する)、(1)、(2)、解決、課題発見、(3)実装・ググる、(4)動作確認、解決...といった感じで開発すると思うけど、(1) -> (2) や (3) -> (4) の回数が増えてきたときは問題を正しく理解していないことが多いので、効率的に自分の気づいてないこと(あるいは知らないこと)を知るために他の人に質問してしまったほうがよさそうな気がしている。

また、質問したときにどういう回答が来るかを想像してみるだけで「質問している間に自己解決する」現象を再現できることもあるのでオススメ。

テスト

どういうバグが生じるか考える

  • どういうバグが想定できるかを考えて、それが生じないことを示してあげる

責務を意識する

  • テストしたいメソッド、クラスの責務はなにかを考える
  • (1) User がお気に入り登録されたときにメールを送る Job を呼び出すメソッド
  • (2) お気に入りされたことを知らせるメールを送る Job
  • があってそれぞれテストを書くときに (1) のテストの中では「(2) の Job によって正しくメールが送られるか」ついてのテストは書かない。

レビュー

ルフレビューを行う

  • 自らツッコミモードになって、椅子の高さを調整して姿勢も変えるなどして GitHub の Files changed などを客観的に見てみると単純なミスに気づくことがある。
  • 保守性があるか、DRY かなど様々な視点でチェックする。
  • コードレビューの文化がある場合、「レビューしてもらう」「取り込む」「再度レビューに出す」というこのプロセスをいかに少なくするかが時間を効率的につかうためのキーなので、自分で気づけることは自分で気づきたい。
  • それでも気づかないことはしょうがない!そのためにレビューがある!

【MySQL】Using filesort について調べた

Using filesort とは

  • MySQL のクエリの実行計画をみたときに、Extra 列に Using filesort; と表示されること。
  • インデックスを利用しないクイックソートが用いられていることを示している。

なにが問題か

  • Using filesortはインデックスを利用しないクイックソートにより速度が低下する。
    • filesort が何ソートなのかは以下が詳しい。

blog.shibayu36.org

いつ発生するのか

  • ORDER BY 句があるときに適切なインデックスがないと Using filesort が出る。
  • ソートに必要なメモリが sort_buffer_size より大きくなったとき。
    • テンポラリファイルが作られ、メモリとファイルを併用してクイックソートが実行される。
    • ちゃんとインデックスが利用されるようにして、インデックス順で行をフェッチできるようにすれば filesort は不要である。

どう解決するか

mysql>EXPLAIN SELECT name, type, from users WHERE type = 3; 

上記でクエリの実行計画をみて、適切にインデックスが貼られているか確認する。複数のカラムにまたがるクエリの場合、複合インデックスを追加するなどする。

mysql>EXPLAIN SELECT name, type, from users WHERE type = 3 \G 

末尾に \G をつけると結果が縦に表示されてみやすくなるっぽい。

refs

【Ruby】連想配列(ハッシュ)の値を複数個設定したいとき

pry(main)> users = Hash.new
=> {}
pry(main)> users[:male]
=> nil
pry(main)> users[:male] = "Yuji"
=> "Yuji"
pry(main)> users[:male]
=> "Yuji"
pry(main)> users
=> {:male=>"Yuji"}

ユーザの名前を管理する連想配列(ハッシュ)をつくり、 male という key で "Yuji" という値を代入したらこうなる。 次に同じ key の male"Taro" を代入すると次のようになる。

pry(main)> users[:male] = "Taro"
=> "Taro"
pry(main)> users
=> {:male=>"Taro"}

あたらしく別のオブジェクトとして {:male=>"Taro"} という連想配列が出来上がっている。 このように連想配列はひとつの key に対してひとつの value を取るような機構になっている。

そこで、ひとつの key に対して複数の value を持ちたい場合は value を配列でとるといい。

pry(main)> users[:male] = ["Yuji", "Taro"]
=> ["Yuji", "Taro"]                  
pry(main)> users
=> {:male=>["Yuji", "Taro"]}
pry(main)> users[:male].each {|user| puts user}
Yuji                                 
Taro              
=> ["Yuji", "Taro"]

そうすることで users[:male]Array#each で回すことなどもできるようになる。

ブロックを用いてデフォルト値を設定する

pry(main)> users = Hash.new { |h, k| h[k] = [] }                                                                                                                          
=> {}             
pry(main)> users[:male]           
=> []

Hash.new のときにブロックを渡すと、対応する値がまだ無いキーが呼び出される度に式が評価される。 したがって、上のようにまだ存在しない :male というキーで値を取ろうとしたときに配列が返ってきている。

これを使えばキーが存在する・しないにかかわらず、 Array#<< を用いて次のように値を追加していける。

pry(main)> users[:male] << "Yuji"
=> ["Yuji"]                     
pry(main)> users[:male] << "Taro"                                                                                                                                 
=> ["Yuji", "Taro"]                   
pry(main)> users[:male] << "Ryo"                                                                                                                          
=> ["Yuji", "Taro", "Ryo"]      
pry(main)> users                
=> {:male=>["Yuji", "Taro", "Ryo"]}

同様に女性も追加するなら

pry(main)> users[:female]
=> []
pry(main)> users[:female] << "Saori"
=> ["Saori"]
pry(main)> users[:female] << "Aiko"                                                                                                
=> ["Saori", "Aiko"]

こんな感じ。 ハッシュの中身を見てみると...

pry(main)> users
=> {:male=>["Yuji", "Taro", "Ryo"], :female=>["Saori", "Aiko"]}

といったように male と female で分類しながら、値に複数の名前をとるような構造ができあがっている。

女性の名前を取り出したいときは key を指定しながら each 処理するなどして次のようにかける。

pry(main)> users[:female].each { |user| puts "#{user} さんは女性です" }                                                            
Saori さんは女性です
Aiko さんは女性です
=> ["Saori", "Aiko"]

refs: