kazasikiがプログラミングするブログ

プログラミングとかコンピュータとかWebとか

開発速度が事業を回す

「ソフトウェアプロジェクトの開発速度は速ければ速いほど良い」という主張に異議を唱える人はいないでしょう。 ただ、今回はもうちょっと踏み込んで、開発速度が「速いほど良い」程度のものではなく、「事業の競争力を決める」ものであると主張します。

※ 私はWebサービスとか作ってる会社のエンジニアです。それを踏まえて以降の文章は読んで下さい。

仮説の検証としての開発

事業を作るときは何かしら仮説をもって取り組むものです。実際はだれも事業計画自体の正しさを確かめることは出来ず、それを確かめるためには実際に作って世に出すほかありません。そして世の中もしくは市場のリアクションを分析して事業を修正していきます。PDCAを回すのです。重要なのは、 事業家の仮説を検証するためには実際に作って世に出す他ないということです。

しかし市場は変わり続けている

ただし、市場は常に変わり続けています。特に娯楽・エンタメの分野ではそれが顕著です。仮説と検証を繰り返しても、そのスピードより速く市場が大きく変わっていってしまってはどれだけ時間を掛けても分析の結果が利益につながることはありません。学びが変化に追いつかないのです。

1つ1つのサービスや機能の開発に一々1ヶ月も2ヶ月も掛っていては実際問題として事業を成長させて利益を得ることは難しい、と言われたこともあります。開発者からすると手厳しい意見ですが、事業家としては至極まっとうな意見でしょう。

開発速度が事業の競争力を決める

開発速度は事業の基礎的な性能に該当します。事業として適切な戦略がとられたとしても、開発速度なしにサービスが成功することはありません。 開発速度はそれくらい重要で、投資する価値がある要素です。

そのためにエンジニアは開発フローを見直し、新たなツールを作っては活用し、新たな手法を編み出し続けています。 派手でなくても、仮説の検証に足る品質の開発を速く行えるということはそれだけで事業への貢献として大きな意味を持つのです。

2016年 ベストバイ!!!

年末なのでベストバイ記事が流行っていますね。自分も便乗してみました。
Amazonの購入履歴を漁って目ぼしいやつ拾ってくるだけの簡単な作業でした。

耳栓

耳栓です。今年買ったものの中で一番重宝してます。基本的に職場で使っていて、会話してる時以外は常に着けてます。 詰め合わせを買って、自分にあうものを見つけてから、それをまとめ買いするのがオススメです。私はSoftiesを愛用しています。

自炊セット(裁断機 & Scansnap

本の自炊セットです。裁断機とスキャナを一緒に買いました。家にあった主に技術書を全て裁断して電子データにしました。本棚スッキリ。あと、自炊できるようになってからマンガや小説のまとめ買いをするようになりました。本棚のスペースを気にせずに済むようになったので。まだまだ電子データで出ない本は多いのであると重宝すると思います。

近くに住んでる姉に貸してから、半年以上返ってきてないです。自分もかなり読書家なつもりですが、姉も自分以上に本を持ってるので苦戦している様子。あと、私の部屋は狭いので置かせてもらってるというのもあります。(裁断機は地味に場所を取ります)

あと、アメリカに留学してる友人が「(日本で出版された)本を買ってお前の家に届けるから電子データにして送ってくれ」と頼んでくるようになりました。クソ野郎だと思います。

DURODEX 自炊裁断機 ブラック 200DX

DURODEX 自炊裁断機 ブラック 200DX

筋トレセット(ダンベルなど)

自重でやる筋トレに限界を感じたので買いました。やっぱり腕〜肩周りの筋肉はダンベルが有ると鍛えやすさが段違いですね。
重さを簡単に変えられるのが嬉しいです。60KG買いましたが、まだ40Kgくらいしか使ってないですね。まぁ長く使うものなので良いでしょう。
あと、最初の素手でダンベルをもってたら手にマメができてしまったのでグローブも買いました。みなさんもダンベルでトレーニングする際は気をつけましょう。
ダンベルだと握力は鍛えられないのでグリップなども買いました。リストローラーボールは楽しいです。

La・VIE(ラ・ヴィ)ハンドグリップ ヒーローズ 40kg 3B-4155

La・VIE(ラ・ヴィ)ハンドグリップ ヒーローズ 40kg 3B-4155


リストローラーボールの回し方 初心者向け

バイルバッテリー

2-3年くらい使ってた3000mAhのモバイルバッテリーが流石にヘタったので買いました。10000mAhもあればオールで遊びに行っても安心です。

まとめ

筋肉はいいぞ!

Sendagaya.rb #176 の個人的まとめ

sendagayarb.doorkeeper.jp に行ってきました。

主な内容

オブジェクト指向設計実践ガイド を読む

75ページ〜

以下、印象にのこった会話とか

ゴミ箱と化すService層

  1. Fat Controller を避けて Model に処理を移す
  2. Model が Fat になりはじめる
  3. 複数のテーブル(モデル)に跨ぐ処理は、Service層に分ける
  4. 徐々にゴミ箱と化すService層

MVCなWebアプリケーションフレームワークが如何なる標準を提供したところで、私たちは適切なクラスを設計をする義務から逃れることはできない。

api/mypage.json ... うっ頭が...

Restfulに作ろうとしても、アプリ側のAPIアクセスを減らしたいという要求から逃げられず作ってしまうRestfulではないAPIの代表。仕方がないね ¯\_(ツ)_/¯
クライアントとサーバは簡単には分離できない。サーバ側はjsonレンダリングをView層として分離させることで上手く対応するのがベター。model層にjsonレンダリングのロジックを入れると死ぬ。

Rails5.1にwebpackが入るかも

github.com

Railsユーザのwebpack使用率も高そうだし、いい感じなのでは。
rails webpacker:compile をdeploy時に実行するコマンドに追加する必要があるかも。

MVVM(フロントの話)

フロントで持ってるモデル層がサーバー側のコードでかぶったりしないか?という話。 フロント側で持っている責務(UIの遷移や入力/出力)と、サーバ側で持ってる責務(DBのトランザクション管理など)が明確に違うから今のところあんまり設計に悩んだことない。

ドメイン貧血症

mamelog.hatenablog.jp

コードが語らないので、コメントで無理矢理語らせるのです。

以上、読書はあまり進みませんでしたが、有意義な会でした。

非エンジニアがエンジニアの作業品質を管理するためにするべきたった1つのこと

非エンジニアがエンジニアの作業品質を管理するためにするべきことを書きます。

前置き

今回の記事は珍しく非エンジニア向けの記事です。例えば、エンジニアに作業を依頼するもしくは発注する企画職の人を想定しています。
エンジニアの人も知っておいたほうが良いと思います。なぜなら作業品質を依頼者に示すことはお互いが安心して開発をすすめるのに必須の要素だからです。
以下の文章では、非エンジニア側の人間を依頼者と記述します。基本的にコードは全く読めない人間を想定します。

依頼者目線で作業を分解する

作業を細かく分けるのは誰でもやると思います。ただ、このとき注意することが1つ有ります。依頼者が作業の完了を確認できる単位に分解することです。 例えば、DBを構築することは作業の単位になりません。エンジニアではない依頼者は作業の結果を確認できないからです。簡易的だとしても入力フォームを作り、入力結果を表示するところまでセットで1単位としましょう。作業の分割を依頼者による確認方法とセットで必ず考えましょう。

メリット

このように作業を分解することのメリットはいくつか有ります。
まず、進捗が依頼者の目でも確認できます。絶対にエンジニアの自己申告を信用してはいけません。
次に、依頼者が早い段階で品質を確認できます。早い段階で動かせる物を用意してもらえれば依頼者でもバグに気づくことが出来ます。テストは開発の終盤にまとめて行うことが多いですが、進捗の途中であってもバグがない状態を維持するようにお願いしましょう。バグを多く作る作業者になにか対策を施すこともできます。この判断が早めに出来るのは大きなメリットです。

デメリット

もちろんデメリットもあります。それは依頼者が作業の完了を確認できる単位エンジニアが最も効率的に作業できる単位と一致しないことです。
ただ、これは信頼関係を構築できてないエンジニアと協業するためには必要なコストです。許容しましょう。
また、依頼者にも確認するコストがかかりますが、これはそもそも必要なものでしょう。途中経過を見れたにも関わらず確認を怠った人に、最終結果に文句をつける権利はありません。

まとめ

以上に述べた作業の分解手法は、ストーリーポイントと言われる手法の一部分だけ抜き出したもので、どちらかというとアジャイル開発でよくつかわれるアプローチです。
また、エンジニアと依頼者に信頼関係があればこのようなテクニックは不要だと思えるかもしれません。が、私はそんなに贅沢が言える環境ではないので こういったテクニックが必要なのです。 ¯\_(ツ)_/¯

ActiveRecordから理解するgroupの使い方

この記事では主にActiveRecordのgroupメソッドやそれに関連するメソッドをみつつ、仕組みを説明します。あと、ActiveRecordの集計関数ちょっと癖あるよね的な話です。

テーブル作成

まずはじめにこういうテーブルを作ります。

exam_scores

  • 教科(subject) : String
  • 人の名前(name) : String
  • 点数(score) : Integer
bundle exec rails g model exam_scores subject:string name:string score:integer

データ作成

中身のデータは以下のようにします

subject name score
国語 田中 50
社会 田中 70
社会 山田 30
scores = [
  { subject: '国語', name: '田中', score: '50' },
  { subject: '社会', name: '田中', score: '70' },
  { subject: '社会', name: '山田', score: '30' }
]
ExamScore.create! scores

メソッドたち

次に、集計操作に使うメソッドを列挙します。

  • groupを作る条件を指定する
    • group
  • 集計
    • sum
    • average
    • count
  • 集計結果のフィルタリング
    • having

group + sum

まず、groupとsumを指定してみましょう。

subject name score
国語 田中 50
社会 田中 70
社会 山田 30
ExamScore.group(:subject).sum(:score)
=> {"国語"=>50, "社会"=>100}

scoreの合計値をsubject毎に表示できました。しかし、結果が ExamScoreインスタンスではなくハッシュですね?

SQLの出力を見てみましょう。

SELECT SUM("exam_scores"."score") AS sum_score, subject AS subject FROM "exam_scores" GROUP BY "exam_scores"."subject"
-- 50|国語
-- 100|社会

SQLの結果にnameが含まれません。これはexam_scoresテーブルをsubjectでgroup化した時に、nameが特定できないからです。

AcriveRecordは

を原則として設計されています。

これは ActiveRecordパターン という有名なオブジェクト指向設計パターンに由来しています。group + sum を使ったSQLの結果は、そのテーブルの1レコードと等しくなりません。故に、 ExamScore.group(:subject).sum(:score) の結果も ExamScoreインスタンスではなく、只のハッシュとして戻ってきます。

group + average + having

次に、subjectをnameに、sumをaverageに変えてみましょう。

subject name score
国語 田中 50
社会 田中 70
社会 山田 30
ExamScore.group(:name).average(:score)
=> {"山田"=>30, "田中"=>60}
# 実際は数字の部分はBigDecimal型でもどってきますが今回は省略

havingを使ってみましょう。

ExamScore.group(:name).having('avg(score) > 50').average(:score)
=> {"田中"=>60}

山田くんが消えましたね(^-^)
SQLを見てみます。

SELECT AVG("exam_scores"."score") AS average_score, name AS name FROM "exam_scores" GROUP BY "exam_scores"."name" HAVING avg(score) > 50
-- 60.0|田中

結果がハッシュなのは先ほどと同様ですが、今回は2つ注意点が有ります。
1つ目は、havingメソッドが 引数をそのまま文字列としてSQLに入れること です。

例えば、 avg(score)average_score に変えます。

ExamScore.group(:name).having('average_score > 50').average(:score)
=> {"田中"=>60}

とすれば、SQLでも avg(score)average_score に変わります。

SELECT AVG("exam_scores"."score") AS average_score, name AS name FROM "exam_scores" GROUP BY "exam_scores"."name" HAVING average_score > 50
-- 60.0|田中

になります。

2つ目は、havingメソッドを入れる場所は、集計メソッド(sum, average, count)よりも前にする必要があります。 集計メソッドの戻り値はその時点でハッシュにされてしまうからです。

先ほどのrubyコードでhavingメソッドを最後に持ってきてみます。

ExamScore.group(:name).average(:score).having('average_score > 50')

実行結果は以下のようになります。

NoMethodError: undefined method `having' for #<Hash:0x007f5c837ec778>
    from (irb):11
    from /share/git_dir/simple_app/vendor/bundle/ruby/2.3.0/gems/railties-4.2.3/lib/rails/commands/console.rb:110:in `start'
    from /share/git_dir/simple_app/vendor/bundle/ruby/2.3.0/gems/railties-4.2.3/lib/rails/commands/console.rb:9:in `start'
    from /share/git_dir/simple_app/vendor/bundle/ruby/2.3.0/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:68:in `console'
    from /share/git_dir/simple_app/vendor/bundle/ruby/2.3.0/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    from /share/git_dir/simple_app/vendor/bundle/ruby/2.3.0/gems/railties-4.2.3/lib/rails/commands.rb:17:in `<top (required)>'
    from bin/rails:8:in `require'
    from bin/rails:8:in `<main>'

¯\_(ツ)_/¯

まとめ

集計関数は ActiveRecordの原則の外にあるので、ActiveRecordからDBに触り始めた人には馴染みにくく、関係するメソッドにも癖が強いです。 ただ、集計関数こそSQLの醍醐味なので、しっかり使えるようになりましょう。

Effective "if-else" ~分岐に関わる達人の思考~

経験豊かなプログラマの皆さんであればif文はご存知だと思います。
この記事では、様々な言語でのif文の機能や書き方の違いに触れつつ、より安全なif文の書き方を導きます。要点は、静的言語でコンパイルエラーになるような書き方は動的言語でもしないほうが良い、もしくは場所を選ぶということです。
言語によって文だったり、式だったり、関数だったりしますが、この記事では文という表現を主に使います。

機能の違い

if文は言語によって様々な文法が存在します。が、ここでは主にその機能の違いに触れます。

基本(分岐)

一番基本的な書き方は以下のようなものだと思います。rubyっぽい書き方です。

if 条件
  条件がtrueだったら何かする
end
if 条件
  trueの場合に実行する文
else
  falseの場合に実行する文
end

初期化

golangで実装されている機能です。http://golang.jp/effective_go#if

if err := file.Chmod(0664); err != nil {
    log.Print(err)
    return err
}

for文のように、if文の中だけで使う変数の初期化を行います。
これは非常に便利な手法なのですが、他の言語での良い代替手段はほぼありません。Cでよくある書き方は

if(  (fp = fopen( filne_name, "r" )) == NULL ){
  printf( "%sファイルが開けません¥n", filne_name );
  return -1;
}

ですが、あんまり綺麗ではありません。結局、変数(fp)のスコープも限定できません。
if文を全てメソッドに分離させれば同じことができますが、現実的ではありません。コンセプトは理解しておくといいでしょう。for文のiのスコープを限定でないとしたらゾッとしますね。(C言語からは目を背けながら)

戻り値

rubyではif文は正確には式であり、戻り値を返します。条件部分がtrueであれば、trueの場合に実行される部分の最後の文の戻り値が返されます。
それを利用して以下のような記述ができます。

# if式の結果を変数に入れる
result =
  if 条件
    trueの場合に実行する文
  else
    falseの場合に実行する文
  end

また、haskellでも同様に戻り値を返します。haskellは静的型言語であるため、戻り値の型が揃っていなければコンパイルエラーになります。

変数の代入検査

一部の言語においてif式が戻り値を返すことを説明しましたが、戻り値を返さない場合でも同じようなことはできます。例えば、Javaでは以下のようになります。

// if文の結果を変数に入れる
int result;
if (条件) {
  result = trueの場合に実行する文;
} else {
  result = falseの場合に実行する文;
}
System.out.print(result);

Javaで面白いのは、例えば以下の記述はコンパイルエラーになります。

int result;
if (条件) {
  result = trueの場合に実行する文;
} else {
  falseの場合に実行する文;
}
System.out.print(result);

これがコンパイルエラーになるのはelseの場合にresultに値が代入されないからです。このコンパイルエラーを回避する方法は大きく2つあります。
1つはresultの宣言時に初期値を入れることです。これはif文の条件がtrueになるのがあくまでも特殊なケースである場合に有効です。基本的には初期値のままで、特殊な場合にif文の中で値が設定されます。ただ、この方法は破壊的代入と言われ、あまり推奨されません。変数の状態が確認しにくくなるからです。
もう1つは元の通りelseの場合に値を入れる方法です。値は初期値と同じかもしれませんが、代入を複数回行わないため、変数の状態が確認しやすくなります。

条件の判定

if文において何がtrueで何がfalseか、です。私の知る範囲においてよくあるのは、0, null, falseがfalseで、それ以外は全てtrueというものです。golanghaskellではtrue/false以外を返す式を条件に入れるとコンパイルエラーになります。

シンタックスシュガー

if文には様々なシンタックスシュガー(書き換え)がありますが、有名どころはやはり三項演算子と後置if文でしょう。

三項演算子(?演算子

C言語Javaのようなif文が戻り値を返さない言語でも、1行で戻り値の代入までを明示することが出来ます。可読性が下がるという理由で嫌われがちですが、80~100文字程度で収まる場面なら使っていいと思ってます。ワンライナー御用達。

result = 条件 ? trueの場合に実行する文 : falseの場合に実行する文

後置if文

RubyCoffeeScriptにあるシンタックスシュガーです。以下のように書きます。

trueの場合に実行する文 if 条件

片方の条件の処理が長いときにif文を閉じるところまで読まずに済むというメリットが有ります。ネストも減ります。

# before
def do_something 
  if condition
    method0
  else
    method1
    method2
    method3
    method4
    method5
    method6
  end
end

# after
def do_something 
  return method0 if condition
  method1
  method2
  method3
  method4
  method5
  method6
end

テクニック

条件式を変数に入れて持ち回る

条件式を変数に入れて持ち回れば、例えばこんな書き換えが出来ます。
あと、条件式に尤もな名前を付けるのは常に良い習慣です。

# before
def do_something(a, b)
  if a > 0 && b > 0 && a > b
    c = a
    d = b
  else
    c = b
    d = a
  end
  puts "c:#{c}, d:#{d}"
end

# after
def do_something(a, b)
  condition = a > 0 && b > 0 && a > b
  c = condition ? a : b
  d = condition ? b : a
  puts "c:#{c}, d:#{d}"
end

等価演算子の変数を右側に書く

等価演算子の==と、代入の=を書き間違えたときにコンパイルエラーにしてくれるための技法です。C言語ではよく書いてました。
読みにくいので皆しなくなりました。条件式にboolean型しか許されない言語では無用な心配です。
ただ、現在においても==と=を間違えるのは比較的ポピュラーなバグであるというのは覚えておいたほうが良いです。

if (1==a) {
  do_something
}

まとめ

冒頭に書いたとおり、静的言語でコンパイルエラーになるような書き方は動的言語でもしないほうが良い、もしくは場所を選ぶの一言です。 それを学ぶためにも動的言語でプログラムを覚えた人は一度はモダンな静的言語のプログラムを覚えるのは良い刺激になると思います。
あと、if文のtrue/falseの時の実行内容を見比べやすくする意識を持つとよいです。

言い訳

検索などをせずに記憶をもとに書いたのでプログラムが間違ってるかもしれません。勿論動作確認もしてません。わかればいいのだ。

へぇボタンで理解するオブジェクト指向の利点

へぇボタンで理解するオブジェクト指向の利点