Posts From Category: docs

パッと切り替える

要約

やってることをパッと切り替えられるようになると時間を無駄にしない事が多い 一日中同じバグにハマるというようなことがなくなる

個人的によくあること

  • バグをみつける
  • 1つ目の仮説で解決できない
  • 2つ目の仮説で解決できない
  • このあたりでもう周りが見えなくなっている
  • ハマる
  • ハマる
  • 優先度高い作業ができない
  • 1日が終わる エンジニアとして、わからないことがあると解明したくなる気持ちが解決できないごとに強くなって、多分アドレナリンがめっちゃ出て、バグ修正中毒みたいになってしまうともうそれしかできなくなるということが結構誰にでもあるんじゃなかろうか。 そうなる前に、仕組みとしてパッと切り替えられるようにしておくと良い。
  • ポモドーロタイマーはそれにも良くて、強制的に25分立つと通知されるので、切り替えて他の作業するきっかけになる(実際に切り替える意志は必要)
  • それに加えて1日のスケジュールは切っておくことが必要。issueベースで開発をしていると一つができたら次という流れになるので、いくらでもハマれる温床になる

Read More

ポモドーロタイマー

要約

ポモドーロタイマーやってみた よかったこと

  • 1日何回(ガチで)集中できたかの指標がとれるので、改善につながる

よかったこと

これを実践することによって集中力が即あがるということはあまりないけど、 あとからログを見ることによって、「1つのことに集中している時間がとれたか」ということがわかるので、集中するための環境を整えるきっかけになる、というのが大きかった。 朝早く出社して誰にも話しかけられることがない状態でコーディングをしている期間は、例えば ポモドーロ1 bugfix ポモドーロ2 bugfix ポモドーロ3 セキュリティアップデート ポモドーロ4 セキュリティアップデート ポモドーロ5 lineログイン ポモドーロ6 lineログイン みたいに25分間なにをやったかが明確にわかるくらいに1つのことに集中できている(ので記録にも残せる)んだけど、 ランチを食べたあたりから、差し込みが多くて、自分でも何に集中してるかわからなくなって後半はログも取れなくなることが多い。 これってつまり1日何回25分間1つのことに集中できたかってことがわかるので、それを多く作れるように環境ややり方を整える指標になるということだと思った。

Read More

スタートアップでエンジニアに求められる能力

要約

スタートアップでエンジニアに求められる能力まとめ

  • コードを動かす(当たり前)
  • レビューする
  • 自動テスト書く&CI回す
  • コスパを求める
  • 技術的負債を(時には)許容する
  • 小さく作る
  • コーディング大好きでも、判断はクールに
  • 手を動かす

何様か、なぜ書くか

スタートアップでリードエンジニアでかれこれ5年以上やってきたので、そのなかで感じた、必要な能力をまとめたメモ。

コードを動かす

当たり前なんだけど、自分の書いたコードが動くことをちゃんと確認すること。そもそも人数がいないので、一人一人が自分が最終責任者だと思ってチェックする。

レビューする

チームが大きくなってくると、ソースコードの質を落とさないようにソースコードレビューを神経質なくらいにやる必要がある。メンテナンス/新規機能追加コストが落ちるので、そうなってくるとスタートアップとして致命的になる。

自動テスト書く&CI回す

メンテナンスにコストできるだけかけずに攻めるほうにコストかける必要があるので、自動化できるところはできるだけやる。

コスパを求める

問題解決するのに、一番時間がかからないやり方があればそれを使いたおす。聞ける人がいれば1回ググって手がかりなければすぐ聞く。時間あたりの生産性をあげることをさぼらない。

技術的負債を(時には)許容する

リファクタリングとかソースコードの質を上げ始めるとエンジニアとして楽しくなってやりすぎがちなので、適度なところでストップできるようにする。

小さく作る

検証したいと思っていることが検証可能なもので、最小限でつくる。大きく作るのは誰にでもできるが、小ささを保証するのはエンジニアしかできない。なぜならメンテナンスコストを自分ごとできるのがエンジニアだけだから。

コーディング大好きでも、判断はクールに

コード書いてて楽しいとか、ハマってて解決できるまでやりたいとかあるけど、常にそれが優先度高いかを判断してやめるときはやめる

手を動かす

新しいアイデアは考えてても進まないので、手を動かす、作る

Read More

プログラマーの英語

要約

プログラマーの英語

カヤックリビングではRailsを使ってSMOUTというサービスを作っています。 実際やってみるとわかるんですが、オープンソースを使っているプログラマーが働いている時間の8割くらいは動かないものを動かそうとしている時間だと思います。 つまりそれって仕様を調べている時間と言い換えることもできると思います。 そして、これもしばらく経験を積めばわかりますが、オフィシャルのドキュメント(とソースコード)こそが割と唯一の信頼できるソースになる場合が多いです。qiitaの記事とかは結構古かったり間違ってたりするので、それをやってみるコスパは悪いです。 オフィシャルのドキュメントはほぼ間違いなく英語で書かれているので、英語が読めないと作業効率が何割か確実に落ちます。 何十年かプログラマーをやっていくつもりなら、その効率が何割か上げるのをできるだけ初期にやっておくべき!

コーディング力とどっちが大事か

コーディングはプロのプログラマーやってれば自ずと上がってきますが、英語力は日本で働いている限り、よっぽど意識しないとあがらないはず。 逆に意識して勉強する人は少ないと思うので、他のプログラマーと差をつけるチャンス。

google翻訳でいいのでは

精度が上がってきているとはいえ、google翻訳が言ってることを解釈するのにそれなりに脳みそ使います。それよりは英語を解釈する能力を上げるほうが効率がよさそう。(単語単位で調べるのは全然あり。) あとマニアックなライブラリのreadmeとかは、結構スラングで書かれてるのとかもあるので謎の訳がでてきがち。

Read More

シーケンス図を書くとよい理由

要約

  • rubyは型チェックがないスクリプト言語
  • 引数になにをとるか、なにを返すかはメソッド名で表現するしかない

シーケンス図とは

こういう図です。 書き方はシーケンス図でググればたくさん出てきますが、なぜ書くといいかの個人的な意見を書きたいと思います。 図とかドキュメントの話になると、すべての実装項目やリポジトリ全体のものを作るという話と思う人もいるかも知れませんが、それはおすすめできません。(メンテできなくて実装とかけ離れたものになるので意味がない) ひとつの機能を実装するとき、小さい範囲で書いて、githubのプルリクとかissueに貼っておくといいです。その理由は

なぜ書くとよいか

  1. 自分の理解が進む
  2. 設計がブラッシュアップされる
  3. ドキュメントとして自分以外が見ても理解しやすい

自分の理解が進む

主に実装中に全体を俯瞰して見たいときに役立ちます。オブジェクト指向の特徴は抽象化なので、突き詰めればどんどんクラスが増えて抽象的になっていきます。全体としてどういうクラスがあったか、その間のメッセージ(メソッド)のやりとりはどうだったか、というのが自分が作ったものでもわからなくなってきます。 そういうときにシーケンス図があると、全体の地図として機能して、自分の頭のメモリーを全体像のリロードにとられることなく、目の前のコーディングに集中できます。

設計がブラッシュアップされる

一度作り始めると実装中は細かいことに目が行きがちで、最終的に出来上がってみると、「あれ、このクラスあったほうがきれいに書けたんじゃないか」ってことがよくあります。 全体の登場人物が足りてるか、その間のメッセージのやりとりであるメソッド名はそれで適切か(single responsibilityになっているか)、というのは作り始めちゃうと途中で軌道修正するのが結構大変になります。 そんなときにあらかじめシーケンス図でやりとりを書いてみると、実装の一番ライトなプロトタイプとして機能して、コードを書く前から(コードを書いてないので超ローコストで)リファクタリングができます。

ドキュメントとして自分以外が見ても理解しやすい

抽象化が進むと、人が書いたコードをひと目見ただけではわかりにくくなってきます。これはオブジェクト指向のウィークポイントなのかもしれませんが、それは置いておいて、そこを補うドキュメントとして見た上でソースコードを読むと理解度がぜんぜん違うと思います。 githubのプルリクを見返したときに、作者がシーケンス図とか貼ってあるともう感動的だと思うので、やるといいと思います。

参考

オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方 この本の中でもシーケンス図のよさが語られてて参考になります。

Read More

rubyでメソッド名が大切な理由

要約

  • rubyは型チェックがないスクリプト言語
  • 引数になにをとるか、なにを返すかはメソッド名で表現するしかない

Rubyは型チェックがないスクリプト言語

Rubyでメソッド名は大切です。 rubyは型がないので、メソッドの引数でなんでも取れるし、戻り値もなんでも返せます。 何が返るかはメソッド名で判別できないと、都度そのメソッドの中身をみなければいけなくなり、せっかくのオブジェクト指向で抽象化した意味がなくなってしまいます。 なのでしっかり意識して返すようにしましょう。

class User
  has_many :towns
  def name
    "nishizaki" #string返す
  end

  def hometown
    my_home_towns.last.name # やりがち
  end

  private
  def my_home_towns
    ...
  end
end

class Town
  has_many :users
end
user = User.last
user.hometown
=> "横浜市"

だとTownクラスが返ってきそうですが、よくあるのはその名前のstringを返しちゃうパターン。 名前を返したい場合は、メソッド名がhometown_nameであってほしいです。

Read More

RSpecのテスト高速化

要約

  • これから書くテストにはこれらの高速化手法取り入れるべき
  • 既存のテストは結構時間かかるので、リソースがあれば。

    テストが遅い

    ソースコードの量はまだまだ多くないですが、テストは約1200件ほど。すべて走らせると6〜7分ほどかかってしまい、多少の変更では回さなくなってしまいます。エンジニアの手は常に足りない状態なので、できるだけコストをかけずに速くできるなら速くしたいです。

    調査

    既存の知識

    rspec本体にもprofile機能があって、どのテストが遅いかとか、遅いtop10とか出せます。

    Top 10 slowest examples (21.36 seconds, 43.4% of total time):
    User has_many :plans should eq ...
      9.32 seconds ./spec/models/user_spec.rb:9
    User scope ...
      2.1 seconds ./spec/models/user_spec.rb:391
    ...(以下省略)
    

    ただ、圧倒的に遅いテストが5個ほど見つかればいいのですが、大抵のアプリではなかなかそうは行かず全体的にちょっとずつ遅いので、なかなかアクションに繋がりません。

test-profの導入

test-profというgemを使うと、テストのいろいろなprofile(実行時間の診断)がとれます。

日本語翻訳記事(若干リンク切れあり)

英語ドキュメント

例えば、テストのtypeごとの合計時間とか平均速度とかがとれます

https://test-prof.evilmartians.io/#/tag_prof

TAG_PROF=type bundle exec rspec

           type          time   total  %total   %time           avg

          model     06:23.089     813   62.16   47.61     00:00.471
        request     04:28.072      63    4.82   33.32     00:04.255
     controller     01:59.925     298   22.78   14.91     00:00.402
         mailer     00:33.489     112    8.56    4.16     00:00.299
        routing     00:00.012       8    0.61    0.00     00:00.001
           view     00:00.000       8    0.61    0.00     00:00.000
         helper     00:00.000       6    0.46    0.00     00:00.000

これだけだと僕の場合はなかなかアクションにつながりませんでした。 まあcontrollerの平均が遅いかなという感じ。

次にdatabaseアクセスのトータル時間を見ることもできるのでやってみます。

EVENT_PROF=sql.active_record bundle exec rspec

**[TEST PROF INFO] EventProf results for sql.active_record

Total time: 01:06.671 of 14:02.567 (7.91%)
Total events: 218946

Top 5 slowest suites (by time):

XXX (./spec/models/xxx.rb:3) – 00:25.661 (109029 / 1) of 01:17.926 (32.93%)
XXX (./spec/models/xxx.rb:3) – 00:07.682 (19580 / 17) of 00:20.489 (37.49%)
SomeController (./spec/controllers/some_controller_spec.rb:3) – 00:05.341 (14820 / 152) of 01:09.949 (7.64%)
SomeModel (./spec/models/some_model_spec.rb:4) – 00:04.138 (9190 / 164) of 01:44.833 (3.95%)
User (./spec/models/user_spec.rb:3) – 00:03.198 (10320 / 154) of 00:52.016 (6.15%)

DBアクセスが多すぎる場合の対処法として、以下の3つがあげられています。

  1. 不要なデータの生成
  2. beforeで作っているデータが重い
  3. factorybotの埋め込みが多重になっていて遅い

1は、テスト的にデータを永続化する必要ないところで律儀にcreateまでしちゃってる、ということです。 test-profにはこれをやっちゃってるところを指摘してくれる機能があります。 FDOC=1とすると、具体的に無駄にデータを作っている箇所を指摘してくれます。 Factory Doctorというらしい。

FDOC=1 bundle exec rspec

Total (potentially) bad examples: 59
Total wasted time: 00:16.543

User (./spec/models/user_spec.rb:3) (80 records created, 00:00.599)
  should eq true (./spec/models/user_spec.rb:511) – 20 records created, 00:00.158
  should eq true (./spec/models/user_spec.rb:512) – 20 records created, 00:00.138
  should eq true (./spec/models/user_spec.rb:513) – 20 records created, 00:00.158
  should eq true (./spec/models/user_spec.rb:514) – 20 records created, 00:00.142

...省略

指摘された箇所を直してみます。 直し方として、FactoryBotのcreateの代わりにbuild_stubbedを使うと良いと書いてあります。 指摘された箇所で単純にこの変換を行えば良いのであれば、このtotal wasted timeである16.543は短縮できたも同然!と思ったのですが、事はそうかんたんではなく、associationの関係で通ってたテストが通らなくなったりしました。あとwhere使ってるメソッドとかはDBに入れたデータが前提となるので、結構build_stubbedの使い所は限定されるかもしれません。 1ファイルあたりの短縮効果は、例えば上のUserモデルでは00:00.599とかなので一箇所ごとに考えながら変えていかないと行けないとなるとちょっと手が出そうにありませんでした。 (total wasted timeは20ファイルくらいのチリツモによるもの) これもプロジェクトの規模による感じだと思います。

次に2の対処法を試してみます。 before(:each)が重いというのはかなりピンときます。 rspecはbefore(:each)内で書くと、テスト1件ごとにデータの生成と破棄を行ってくれます。 テストとして、他のテストケースとの依存を避けるために1件毎にデータの生成も分けたほうがいいというのが基本としてあると思うので、いままでかなり律儀に分けてきましたが、たしかに無駄だと思う箇所はたくさんありました。 before(:each)でやっていたものをbefore(:all)にするというのをやってみます。 注意点としてbefore(:all)の場合はデータの破棄をrspecがやってくれないというのがあります。 test-profの機能で、これを自動でやってくれる記法があります。

before_all do
  @paul = create(:beatle, name: 'Paul')
  @ringo = create(:beatle, name: 'Ringo')
  @george = create(:beatle, name: 'George')
  @john = create(:beatle, name: 'John')
end

書き換えてみました。

# before
Finished in 16.63 seconds (files took 6.69 seconds to load)
# after
Finished in 10.62 seconds (files took 7.33 seconds to load)

20テストケースくらいの1ファイルを書き換えるのに1時間弱ほどかかりましたが、6秒ほど速くなりました。 ただ上記1の場合と同じで、プロジェクトの規模感考えるとそこまで効果的じゃないかなと言う結論になり、全部書き換えるには至りませんでした。

つぎに3の対処法を試したいのですが、これはまた長くなりそうなので別の機会にすることにします。

結論

  • これから書くテストは
    • build_stubbedつかえるところは使う
    • beforeをまとめるのは、使えるところは使う。read系のメソッドのテストは状態変えないので積極的に使えそう
  • 既存のテストは結構時間かかるので、プロジェクトが規模的に大きくて数秒の短縮が全体としてリソースの削減になりそうな場合はやる

Read More