kazasiki's blog

プログラミングとかVRゲームとか

長時間労働は"スポーツマンシップに反する"と思ってる

昨年は電通のいざこざもあったし、最近はこんな記事も上がってるので長時間労働について個人的に思ってることを書きます。

http://www.tokyo-np.co.jp/article/politics/list/201702/CK2017021502000124.htmlwww.tokyo-np.co.jp

まず、今の労基法は基本的に経営者から労働者を守る意味合いが強いルールです。なので、過労云々の話題も基本的に経営側に責任が追及されます。長時間労働云々の議論も基本的にこの観点で進められることが多いです。それはそれで妥当だと思います。

ただ、日本のような資本主義社会は個人レベルで見ても競争と金儲けの社会です。なので、出来るだけたくさん働いて競争に勝ちたい、多くの利益を得たい、社会的な評価を得たいという考えは個人レベルでも深く根付いています。単純に働くことを楽しいと感じる人もいるでしょう。別に経営者に命令されなくてもたくさん働きたい人というのはある程度は必ずいます。

じゃあ、そういう人たちが好き勝手に長時間働いていいかというとそういう訳にはいかないだろうと私は思っています。その人達が過労で死ぬ分にはその人達の勝手ですが、競争社会では、その人達の労働が長時間労働したくない人たちにも影響を及ぼします。利益を上げなければ食べていけない以上、競争相手にも同じだけかそれ以上の労働をする圧力が発生します。それは無視できないものです。

それはそれでいいじゃんということも出来るのですが、長時間労働健康被害が出やすいとされています。端的にいって人は過労で死にます。労働者に自由に働かせて競争させた結果として、過労で労働力が失われるのでは社会は成り立ちません。なので、競争には程よいルールが必要なのです。今のところ労基法にそういった意味合いはありませんが、そういう意味でも程よいルールだと思っています。(もっと厳しくてもいいくらい)

例えば、オリンピックやプロ野球の世界ではドーピングの問題がたびたび話題にされます。ドーピングとは薬物などを使用した身体機能の強化のことで、現在は禁止されています。理由は色々ありますが、最も大きいのは選手への健康被害です。たとえドーピングによってスポーツがよりエキサイティングになるとしても、健康被害があるのでは業界自体の持続性を損なう可能性が高いからです。選手に自由な競争を許しているとしても制限は必要です。たとえ個人の権利や選択肢を奪う形だったとしても。

自分が長時間労働に耐えれて、その分成果を出せて、それを楽しんでたとしても、やっぱりそれはスポーツマンシップに反するのでは?と私は思います。結局それは業界自体を壊す行為なのでは、と。

これまで書いたことは結局綺麗事で、なんだかんだ言って長時間労働することはあります。ただ、私はいちおう長時間労働で成果を上げている人たちに対して3つのポリシーを持ってます。1つめは尊敬しないこと。2つめは参考にしないこと。3つめは競わないことです。簡単に言えば、選手として認めないということです。簡単なルールですが、個人的にはこれだけ頭に入れておけばだいぶ気は楽になります。

極端な話、この社会には「業界とか知るか!あと10年間だけ死ぬ気で働けばその先遊んで暮らせる金が手に入るんだぜ!」とか言って死ぬ気で働いて本当に死んでいく人もいるのでしょう。みんな週40時間労働くらいでぼちぼちやっていきましょう。

「今時の若者はコンテンツを無料だと思ってる」わけではない

この間同僚とランチを食べた時に、小学生くらいの息子が見たいアニメを動画投稿サイトで検索して見てるって話をされて、最近の若者はコンテンツが無料で手に入るのが当たり前だと思っている的なお決まりな若者批判をされた。自分としてはその辺にちょっと変わった所感を持ってるのでそれをまとめておく。

結論から言うと、若者はコンテンツを無料で手に入れるのが当たり前だと思っているわけではない。だが、コピーは無料だと思っている。この差は結構、その、微妙なんだ。

CDがよく売れていた頃、自分の周りでよく見かけたのは以下のような光景だ。

  1. 誰かがCD(オリジナル)を買う
  2. それをリッピングしてMP3にコピーする
  3. 友人たちにコピーを配る

このケースならまだCDは買われていた。コピーの範囲もまだ友達程度。 今はWebが普及して1がどこかに飛んで行ってしまった。

逆に考えれば疑問はこうだ。なぜコピーにコストがほとんどかからない今、コピーにお金を払う必要があるのか?大人の人はご存じで、オリジナルを作るのにはお金がかかるからだ。でも、それはコピーネイティブな連中には納得できない。

いくつか納得いく例を挙げる。ニコニコ動画のプレミアム会員はコピーに必要なサーバー費を会員で負担している。プレミアム会員かどうかによって動画の画質が変わるのは合理的だ。クラウドファンディングはオリジナルの製作に必要なお金を製作の前に募っている。コピーの配布を有料にするかはプロジェクト次第だが。

物を先に作ってコピーを売って金儲けするというビジネスモデルはデジタルデータにはそぐわない。Webが民衆に行き渡った以上、売る側だけスケールメリットを得る方法は納得されない。

作ってほしくば金を払え。続けて欲しくば金を払え。

開発速度が事業を回す

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

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

仮説の検証としての開発

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

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

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

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

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

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

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

2016年 ベストバイ!!!

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

耳栓

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

自炊セット(裁断機 & Scansnap

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

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

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

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

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

  • メディア: オフィス用品

富士通 ScanSnap iX500 (A4/両面)

富士通 ScanSnap iX500 (A4/両面)

  • 発売日: 2015/02/06
  • メディア: Personal Computers

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

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

[asin:B0116CTLX2:detail]


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

モバイルバッテリー

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

[asin:B00EPZOGMY:detail]

まとめ

筋肉はいいぞ!

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の醍醐味なので、しっかり使えるようになりましょう。