kei-p3’s blog

kei-pによる技術共有と思考整理

爆速タイピングを目指して! プログラマのためのタイピング練習 「Typing.lk」

f:id:kei-p3:20160723142717j:plain

一日に何文字も入力する我々プログラマにとって、タイピングは切っても切れない関係にあります。

そんなタイピングですが、自分はまだまだタイピング速度に自信がありません。

というのも、どうも自分はタイプミスが多いのです。 基本的には予測変換でなんとかなってるんですが、予測の効かないときのタイプミスがまぁ、多いこと。。。

そしてそのタイプミスの原因のほとんどは、通常のような文章入力ではなく、プログラム特有の記号を入力時に発生しています。

プログラミングでは、普通の文章と違い@:[{といったたくさんの記号を入力する必要があります。

def collection_actions
    [:index] + [@options[:collection]].flatten
end

記号は、ホームポジションから遠く、普通の文章を打つときはなかなか打つ機会がないため、 特別にタイピング練習していない自分はこの記号を打つときだけ、ブラインドタッチができなくなったり、ホームポジションが崩れるようになっています。 そして、これがタイプミスに繋がってしまっています。

大量に文字を入力するプログラマにとって、タイピング速度や精度は生産性の要です。 このタイプミスを減らすためになにかイイ練習方法はないかなと探したところ、プログラマに焦点を当てたタイピング練習サイトを発見したので、今回はそれを紹介します。

プログラマ向け タイピング練習サイト 「Typing.lk」

f:id:kei-p3:20160723142130p:plain

http://typing.lk/

なんとこのサイト、実際のプログラムを例にタイプング練習できます。 実際の画面はこんな感じです。

サポートしている言語は、現状C++, Java, PHP, Python, Rubyとメジャーどころは揃っています。

とくにユーザー登録も必要なく、気軽に試せるところもイイ!

結果画面では、入力にかかった時間と精度が表示されます。(大したスコアじゃないので、恥ずかしいw)

f:id:kei-p3:20160723142132p:plain

最後に

こういう基礎練習は、継続と練習意識が大切です。 自分の場合はタイプミスが目立っているので、それを減らしたいくのが目標です。 なので、速さを求めすぎて、フォームが崩れて、精度が落ちてはいけません。

とりあえずは、速度を気にせず効率の良いフォームやタイプミスを気にしながら、毎日続けていこうと思います。

データベース実践入門を読んでみた

購入のきっかけ

普段Webアプリケーションの開発をしているのだが、基本的に機能開発をすることが多く、細かなSQLのチューニングの仕方やインッデクスといったデータベースの知識に乏しく、不安がありました。

そんな中、データベースの設計についてググると「漢のコンピュター道」というブログを発見。
大変勉強になるなと感心してたら、なにやら本を出していたようなので購入。

勉強になったこと

本書では、

  • データベースは二次元テーブルではない。リレーションである。
  • データベースは数学(述語論理と集合)
  • 正規化
  • キャッシュやグラフのやり方

と幅広くデータベースの原理や、考え、実践方法を解説しています。

その中でもとくに、自分として悩んでいたインデックスによるチューニングについての解説が勉強になりました。

インデックスは貼ればいいだけじゃない!

インデックスで検索が早くなる理由は、B木 (wikipedia)にあった。

簡単に説明すると、B木では以下のように親の要素より大きいか、小さいかによって分かれて値が配置される。

f:id:kei-p3:20160705200617p:plain

するとインデックス内部では、事前にハッシュ化やソートされて格納されているため、 例えば、WHERE x < 10のレコードを探すときは、対象となる検索範囲が一部だけで済む。 インデックスの速さは、このB木によるアクセスによるものというわけだ。

f:id:kei-p3:20160705200620p:plain

そして、逆にこの仕組みがあるからこそ、不向きな面もある。

  • 貼ると遅くなることも。。。 (ハッシュ化されると範囲検索できなくなる)
  • enum や boolean のような種類の少ない値(カーディナリティが低い)にインデックスを貼っても効果が薄い
  • NULL はインデックス対象外
  • インデックスを貼ると、更新時のオーバヘッド、ディスクサイズの増大へ

今まで、インデックスを 貼る / 貼らない の区別をつけづらく、遅いクエリを見つけたら、インデックスが効くようにWHEREに含まれる絡むをマルチインデックスとしてやっていたが、フラグのような値を入っていたのでかなり無駄が多かったかもしれない。

いろいろ試す時間があればこの辺いろいろ検証できるんだけど、なかなかそれだけのための時間がとりずらいだけに、おろそかにし気味。。。
そんなときに本書のような解りやすい方針があるとかなり助かりますね!

まとめ

全般的に分かりやすく、リレーションや正規化の考え、インデックスのおおまかな仕組みが解説していたりと、原理から実践編へと話をつなげており分かりやすいかったです。まさにタイトル通り、「実践入門」でした。

しかし個人的には、1回流しで読んだ程度では、まだ正規化の章は完全に理解しきれてない(とくに第5、第6など)ので、再び復習しようかなと思います。

自分のようになんとなくSQLがかけるが自信がないような方々、是非読んでない方は読んでみるといいかなと思います。

rspecのdescribe, context, subject, letなどの書き分け

Everyday Railsを読んでみて、rspecの利便さに改めて気付かされました。 特にAPI周りの実装をすることの多かった自分としては、capybaraによるfeatureテストなんかはこんなことがこんなに簡単にできるのかと驚きました。

しかし、自分としては知りたかった、describecontextletの書き分けといった細かな部分についてはあまり深く触れていなかったので、
自分のいままでの経験上で「こんな感じでやってます」というのを、まとめついでに紹介したいと思います。

テスト名の宣言 - describe, context, it

describecontextについては、どちらも同じ挙動をするので、テストとしてはどっちで書いても機能するのですが、
言葉の意味合いから下記のように使い分けています。

itについては、エラーがでたときに内容を理解できればいいかなということで、複雑な内容でない限りは記述してないことのほうが多いです。

区分名 使い方
describe テストグループ ( クラス名, メソッド名, )
context テスト条件 ( 変数の違いや前提条件の違い )
it テスト結果
describe API::UserAuth do
    describe "POST /api/session" do
        context 'with valid password and email' do
            it do
                ....
            end
        end
         
        context 'with invalid password' do
            it do
                ...
            end
        end
        
        context 'when user has already signed in ' do
            it do
                ...
            end
        end
    end
end

変数宣言について - subject / let / インスタンス変数

どちらも変数を扱う記述ですが、subjectの使い道としては、そのテストする内容自身を記述します。
一方、letはそれ以外のテスト内で扱う変数の記述します。
インスタンス変数については、原則使わないほうが良いと思われる。というのも、テストのために、before文の中でインスタンス変数を宣言する形となってしまい、記述が見辛くなってしまう。 書き方を工夫すれば、letで代用できるので、こちらを扱うほうが適切だと思われる。

なお、subjectについては名前付きで宣言することもでき、sign_inのように返り値のない、副作用の生じるメソッドなどで、その対象を名前付きのsubjectをとして宣言して、テスト対象であることを明示するといいかも。

区分名 使い方
subject テスト対象 = expectの引数になるもの
let expectの引数になり得ないもの
@hoge 使わない
describe User do
    describe '#sign_in' do
        subject { user.sign_in(email, password) }
        subject(:user) { User.new(email: "hoge@example.com", password: "password") }
        
        context "with valid password and email" do
            let(:email) { "hoge@example.com" }
            let(:last_name) { "password" }
            
            it { expect { subject }.to change(UserSession, :count).by(1) }
            it { expect { subject }.to change(user, :session) }
        end
    end

beforeについて

beforeについては、テストを行う上での前提条件となるような内容を記述する。
主に、letでの変数宣言だけでは対処できないような処理はこのbeforeに書くようにしてます。

     context 'when user has already signed in' do
            before { user.sign_in(email: "hoge@example.com", password: "password") }
        
            it do
                ...
            end
        end

最後に

綺麗に書けたテストは見やすく、メンテもしやすいです。
テストだからと軽視せずに、テストも綺麗に書けるようになるといいですね!