@ledsun blog

無味の味は佳境に入らざればすなわち知れず

面白かったけど役に立てられる気がしないセッション #rubykaigi

Hijacking Ruby Syntax in Ruby

クレイジーでした。Binding#local_variable_set や TracePoint を使ってRubyの言語仕様を拡張しようという趣旨です。 CRuby本体を拡張せずに、新文法のProof of conceptが書ける意味はわかります。 とはいえ、いくらなんでもやりすぎなのではという思いで一杯です。

tagomoris.hatenablog.com

TTY - Ruby alchemist’s secret potion

github.com

の紹介でした。

クレイジーでした。CLIを作るのに便利なgem群まではわかります。 とはいえ、なぜそこまでCLIなのでしょうか? プログレスバーやテーブル表示までは理解できるのですが、Markdownの表示までいくと、もうブラウザをUIに使ったほうが簡単なのではという思いです。

印象に残ったセッション #rubykaigi

Ferrari Driven Development: superfast Ruby with Rubex

RubyのC拡張を作るためのプログラミング言語の話でした。 グルー言語好きにはたまらないジャンルです。

機械学習方面の計算を早くするために並列計算をしたいのですが、CRuby上ではGILがあるのでCPUヘビーな計算を並列化できません。C拡張を書けばGILを避けて並列化できます。C拡張を書くにはC言語の知識が必要で、それがハードルになっています。Rubyライクな言語を作ることでC拡張を書くコストが下がります。

何がすごいって、こんなにミニマルで実践的なプログラミング言語を作る余地があることに気づいたことです。Rubyライクな言語からC言語に変換するだけなので実装量はそれほど大きくありません。コンパイル言語やインタプリタ言語の実装と違い、pure Rubyで書くことが出来ます。言語デザインを除けば似た実装を書くのはそこまでは難しくないと思います。それでいて、現実の問題をクリアするための言語として機能しているところ、すごいです。

もう一つは、作っている人は東工大の院生だし、ソースコードをみれば普通にちゃんとした言語処理系だしで、恐るべきです。

Parallel and Thread-Safe Ruby at High-Speed with TruffleRuby (Keynote)

CRubyの5倍速いデモのインパクトがすごすぎです。

チューニングの詳しい仕組みは、「isreading Chat Episode 07 – One VM to Rule Them All」を聞くとわかりやすいです。 misreading.chat 聞いてから振り返ると、発表前半のチューニングの仕組み部分は、GraalVMの仕組みのようです。

JITコンパイラJVMバイトコードだけであれば、インライン展開(関数呼び出しを展開するチューニング手法)できます。展開したい関数がRubyの埋め込み関数やライブラリ呼び出しの場合は、インライン展開できません。そこで、GraalVMのPartial Evaluationという機能を使い、実行しながらプロファイルを取得して、関数の呼び出し結果が定数になる場合は、定数に置き換えます。これでインライン展開を適用できる箇所を増やして、鬼のようなスピードアップを図っているようでうす。

それにしても、GraalVM用のRubyインタプリタ実装書くのめちゃくちゃ大変なのでは・・・?という気持ちです。

参考

アルゴリズムとデータ構造をたどるWebサーフィン

#rustfestの発表

yoshが #rustfest の発表が、すごい面白かったとツイートしているのを見ました。

B木の論文

リンクを貼ってある先が RRB-Trees: Efficient Immutable Vectors いきなりこれを読むのは辛いので、一番古い引用文献*1

[2] R. Bayer and E. McCreight. Organization and maintenance of large ordered indexes. Acta informatica, 1(3):173–189, 1972.

をググります。2300引用されている神文献のようです。

Organization and Maintenance of Large Ordered Indexes

どうやらB木の論文のようです。

AVL木の論文

ついでに更に最古引用文献

  1. Adelson-Velskii, G.M., Landis, E. M. : An information organization algorithm. DANSSSR, 146, 263-266 (1962).

をあさります。

G. M. Adel'son-Vel'skii, E. M. Landis, “An algorithm for organization of information”, Dokl. Akad. Nauk SSSR, 1962, Volume 146, Number 2,Pages 263–266

タイトルは違うのですが、著者と発表年を見るとこれのようです。 中身はロシア語なので読めませんでした。 ていうかSSSRって、何かと思ったら旧ソ連のことでした。驚きました。

AVL tree - Wikipediaを見るとAVL木の論文のようです。 AVLって何かと思ったら、Adel'son-Vel'skiiとLandisの頭文字でした。RSA的なネーミングですね。

この辺のことが話題になるということは、Rustは、新しいシステムプログラミング言語なので、まだデータ構造のライブラリが少なく、自分で実装するチャンスがあるのかもしれません。

素振るには?

アルゴリズムの解説はAVL木 - Wikipediaにありますが、理解するには実装するのが手っ取り早いです。 C言語やRustのような低レイヤーの言語で実装しないと理解できないのでしょうか? 使い慣れたJavaScriptで実装しても理解できるものなのでしょうか? と、悩んでいたら

AVL Treeの実装も含まれていました。 これを参考にすると良さそうです。

*1:古典なので既知の情報である確率が高い上に、わざわざ引用しているので読む価値が高いと仮定

fluxのstoreはMVCのモデルではない

結論

fluxのstoreは、(意味があって)「プレゼンテーションとドメインの分離」(PDS)に則っていないので、MVCのモデルではありません。

要約

MVCが考えられた時代では、プレゼンテーションロジックとドメインロジックが同等、もしくはドメインロジックの方が多かったです。その場合、PDSが有効でした。

現代のWebフロントエンドでは、プレゼンテーションロジックの方が圧倒的に多いです。プレゼンテーションロジックが9割ということも珍しくありません。この場合は、PDSは役に立ちません。

プレゼンテーションロジックの中で状態を持つ部分と、画面を描画する部分を分離する方が合理的に分割できます。この分離された「プレゼンテーションロジック中の状態を管理する部分」が「fluxのstore」です。

背景

以下の一連の議論を読んで、コンテキストに誤解がありそうなので、補完します。

blog.nkzn.info

nekogata.hatenablog.com

mizchi.hatenablog.com

本文

MVCが考えられた時代

Wikipediaの以下の記述を見ますと

1979年: パロアルト研究所にてTrygve Reenskaugが考案。[1][2]長い間、Smalltalk-80の実装のみが公開され、MVCに関する公開情報はなかった

MVCが考えられた時代は1979年頃のようです*1。 70〜80年代のアプリケーションの設計の話です。 Webアプリケーションはまだありません。 対象としているのはGUIアプリケーションです。 MVCは、Ruby on Rails等のWebサーバーアプリケーションでの設計にも活用されていますが、Webフロントエンドの話をする時に気にする必要はありません。

GUIアプリケーションといっても、現在のような複雑なプレゼンテーションは持っていません。 CUIに毛が生えたものと考えてください。 例えば、次の操作を想像してください。

  1. ユーザーは、GUIでパラメータを10個設定
  2. ユーザーは、実行ボタンを押す
  3. アプリケーションは、パラメータに基づいて計算をする(この間10分)
  4. アプリケーションは、結果を表示

複雑かつ重要なロジックは、3の部分にありこれをドメインロジックと呼んでいました。 それ以外の1, 2, 4は、記述は面倒さという意味の複雑さはありますが、重要度は低いです。 これをプレゼンテーションロジックと呼んでいました。

PDSMVC

このような構成のアプリケーションには、 プレゼンテーションとドメインの分離PDS)が大変有効機能します。 ドメインロジックをプレゼンテーションロジックから分離することで、入念にテストしたり、GUIの代わりにCUIをつけて他の環境で実行したりできます。

さらにMVCでは「ユーザーの入力」に関わる部分をController、「画面の表示」に関わる部分をViewと分割します。 上記の操作の

  • 1, 2がController
  • 3がModel
  • 4がView

と、綺麗に分割できました。

現代Webフロントエンドの複雑さ

現代のフロントエンドのもつプレゼンテーションロジックは遥かに複雑です。 ドメインロジックは変わらず単純です。 複雑なドメインロジックが必要な場合はサーバーで実行することが多いでしょう。

プレゼンテーションロジックは複雑です。 現代のアプリケーションでは、ユーザビリティを高めるためにユーザーの操作には即応することが可能であり、必要とされています。 例えば、ユーザーの操作に即座に反応してバリデーションの表示状態を変更します。 複数のパラメータから中間データのプレビューを作って表示するかもしれません。

次の操作をイメージしてください。

  1. ユーザーは、パラメータを変更する
  2. アプリケーションは、バリデーションを実行する
  3. アプリケーションは、バリデーション状態に変更があれば、バリデーション表示を更新する
  4. アプリケーションは、複数のパラメータから、プレビューデータを作る
  5. アプリケーションは、プレビューデータに変更があれば、プレビュー表示を更新する

これを何度も繰り返した上で、

  1. ユーザーは、保存ボタンを押す
  2. アプリケーションは、中間データをサーバに送る

このように、現代のWebフロントエンドのプレゼンテーションロジックは、MVC時代のプレゼンテーションロジックに比べて遥かに複雑です。 ユーザーの1操作ごとに、MVC時代のプレゼンテーションロジックと同等かそれ以上のロジックが実行されようなものです。

PDS適用の困難さ

前述の操作のうち、どこがドメインロジックで、どこがプレゼンテーションロジックでしょうか?

  • バリデーションはプレゼンテーションの状態を更新するので、プレゼンテーションロジックではないでしょうか?
  • 中間データの生成ロジックも、プレビューデータを更新するので、プレゼンテーションロジックではないでしょうか?

「バリデーションはサーバーと同じロジックを実行するので、ドメインロジックだ」と考えることもできます。一方で、「データをサーバに送るのは、永続化層であってドメインロジックではない」という考え方もできます。 PDSが簡単な判断基準ではなくなっています。

また、アプリケーションごとにPDSを拡張したルールを作成し、プレゼンテーションロジックとドメインロジックに分けたとしましょう。 さらにMVCに分割してみましょう。 一部は流用できるかもしれませんが、入力パラメータのバリデーションは、入力パラメータごとに実行する必要があります。 結局、ユーザーの操作1つに対して1つのMVCのセットを作ります。 これが設計の助けになるかというと、なりません。

私の経験では、ユーザー操作ごとプレゼンテーションロジックとドメインロジックの境界が揺らぎ、綺麗なレイヤードアーキテクチャにはなりません。 修正する時は、1つのMVCセットごとに、「これはここではプレゼンテーションロジックだっけ?ドメインロジックだっけ?」と悩みながら修正する羽目になります。

設計は、本来、アプリケーションの抽象度を階層化して、全体のアーキテクチャと個々のロジックを別々に悩めるために行うはずです。 PDSを適用してこれでは、教条主義であり、現場の助けになりません。

PDSの放棄とプレゼンテーションモデル

PDSを放棄します。 プレゼンテーションロジックとドメインロジックを分けることをやめ、両者を含んだものをプレゼテーションモデルとして扱います。

以上が、MVP / MVVMなどのアーキテクチャが提唱される背景です*2

結論

現代Webフロントエンドの複雑なプレゼンテーションにおいては、PDSに則ってアプリケーションを分割する意味が薄いです。 ですので、PDSに基づいているMVCのモデルは、現代Webフロントエンドの世界には居ません*3

宣伝

以上の話を、ソースコードを交えて「現代Webフロントエンドデザインパターン」の「第11章 プレゼンテーションモデルパターン」に書きました。

ledsun.booth.pm

また、「Android アプリ設計パターン入門」では、プラットフォームはAndroidですが、以上のようなUIパターンの議論がとても綺麗に整理されています。一読の価値があります。

Android アプリ設計パターン入門

Android アプリ設計パターン入門

  • 著者:日高 正博,小西裕介,藤原聖,吉岡 毅,今井 智章,
  • 製本版,電子版
  • PEAKSで購入する

*1:Wikipeidaに書いたのは私です。信用せずにWikipeida記載の参考文献を確認してください。

*2:MVP / MVVMについては詳しくありません。「Android アプリ設計パターン入門」などを読んでみてください。

*3:極々小さなアプリケーションでは、MVCが有効なこともあります。が、ほんの少しユーザー操作に反応する機能を増やすと破綻します。実例を「現代Webフロントエンドデザインパターン」に書きました。

RubyKaigi 2018 参加に関するお金の話

弊社では、今年からRubyKaigi 2018への参加支援を始めました。 今年は3人の参加者がいます。

主にお金周りの準備の仕方のメモを残します。

参加費

参加者個人で申し込んで支払いました。

以下の文書で経費精算

  • doorkeeperからの支払い確認メール
  • Paypalからの支払い確認メール

クレジットカードを持っていない社員もいたので、その人は会社のクレジットカードで支払いしました。

交通費

今回は仙台で移動時間が短いので、初日の朝と最終日の夜に移動します。

新幹線のチケットは、急な予定変更に対応できるように、 個人で取得し、後日精算します。

えきねっと(JR東日本)|新幹線・JR特急列車のきっぷ予約で予約できます。 いまどき、住所に半角文字を受け入れられない素敵なUIです。 指定席の前々日の取り消しでも310円*1なので、早めに申し込むのが良さそうです。

宿泊費

会場近くは栄えていないそうなので、仙台駅近くに、1人部屋を3部屋予約します。 会社で直接決済します。

#技術書典 #技術書典4 で「現代Webフロントエンドデザインパターン」を頒布しました

サマリ

完売。

赤字にならなかった点で成功、真の需要がわからなかった点で失敗でした。

電子版

在庫切れてしまったので、電子版を用意しました。

ledsun.booth.pm

bookwalker.jp こちらはEPUB形式です。

デザインパターンについて

GoFの23のデザインパターン

ほとんど同じでないです。被っているのはオブザーバーパターンの1つだけです。 クラス図は出てきません。サンプルコードでクラスは出てきますが、継承は出てきません。 JavaScriptでは継承、特にインタフェースの利用にほとんど旨味がありません。

GoFデザインパターンよりは広い対象に対して「デザインパターン」という言葉を使っています。 GoFデザインパターンではMVCも「デザインパターンではない」扱いでした。 現代のソフトウェア業界では、もう少し広い範囲を対象に「デザインパターン」を使っていると思っています。

デザインパターンの数

数は足りないと思っています。 パターンを考える会がやりたいです。

経費

  • サークル参加費 7,000円
  • 日光企画さん オンデマンド印刷 平とじ 68ページ 150部 58,300円
  • テーブルクロス 500円
  • コインケース 100円

よかったこと

  • 本文用紙を「淡クリームキンマリ」にしたら、「上質紙」よりかっこよくなった気がする
  • 「簡単後払い」のバーコードを印刷しておいた

次回やりたいこと

  • そろそろカラー表紙をつけたい
  • 300部に挑戦したい*1
  • オフセット印刷に挑戦したい

*1:客足と天候の因果の存在に恐怖しかない

#技術書典 #技術書典4 で「現代Webフロントエンドデザインパターン」を頒布します

techbookfest.org

モチベーション

Webフロントエンドの技術は、なかなか必要な状況や解決したい問題が明確にされないまま「流行っているからこの技術が良い」みたいな選択されることが大いように思っています。 もちろん、「新しくてかっこいい技術を使いたい」というモチベーションで新しい技術に取り組むのは良いのです。

それはそうとして、うまくマッチしない問題に適用してみて「イマイチな技術だ」っていう感想を抱いたり、 あれもこれも流行っているのに「どれにも自分は手を出せてないからイケてないエンジニアだ」って劣等感を抱いたり、 自分の環境ではレガシーな事ばかりやっていて、もう世間の流れについていけないと悲壮感を感じたりするのは、あまりハッピーではないと思います。

それもこれも、それぞれの技術がどういう状況のどういう問題を解決するのかが、上手く整理されていないからだと思います。最近、流行っていないみたいなのですが、そういうのを整理するのに最適なテクニックを僕は知っています。そうです、パターンランゲージです。

だから、デザインパターンの文法に則ってWebフロントエンドの技術や考え方を解体しました。

形態

  • A5
  • 68ページ (自己最長)
  • 700円(前作「受託開発インアクション 〜顧客の期待をコントロールする〜」と合わせてぴったり1000円)

内容

扱っているパターンは14種類。

  • タスクパターン
    • ポリフィルパターン
    • トランスパイラーパターン
    • スクランナーパターン
    • モジュールバンドラーパターン
    • パッケージマネージャーパターン
    • ユニバーサルモジュールパターン
  • 実装パターン
    • オブザーバーパターン
    • イベントデリゲーションパターン
    • テンプレートエンジンパターン
    • プレゼンテーションモデルパターン
    • 単方向データフローパターン
    • オニオンアーキテクチャパターン
    • 抽象インタフェースパターン
    • フレームワークパターン

ざっくりタスク系と実装系に分けました。 SPA/SSRみたいな、今ホットなところは扱っていません。 2010年頃からSPAに至るまでの、Webフロントエンド界隈で工夫されてきたテクニックを振り返る本です。

実装パターンに関してはソースコードを使った説明が多いです。 ライブラリに依存していない、現代的なWebブラウザ向けJavaScriptで書きました。 それぞれのパターンについて、理解するためのなるべく小さなサンプルのソースコードを用意しました。

それぞれのパターンについて、こんなに簡潔に説明している文章はなかなか読んだことがありません。自分で書いててなかなか良い本が書けたと思います。

Webフロントエンドの開発に従事している方、これから従事する方、外から見ていてどういうことなんだろかと疑問を抱いている方、ぜひ読んでみてください!

また又・エンジニアの採用面接対策 コメントへの回答

愛の告白

就職活動は愛の告白のような活動です。

「愛の告白」というメタファーに乗っ取れば、現職のある方の転職活動というのは、 既婚者が離婚して別の方と再婚するようなものです。

エンジニアの採用面接対策 - @ledsun blog

転職とは「現職の総合点が自身の能力と比較して下」だからするわけであり、面接(官)は「弊社総合点はあなたの能力と比較して上ですか?(転職先に値しますか?)」ということを確認する場でないといけない

2018/02/03 11:19
b.hatena.ne.jp

なれば、募集企業としては略奪婚を仕掛けているのですから、応募者に対しては丁寧に丁寧を重ねても、重ねすぎることはありません。

企業からすると、たくさんの結婚相手のなかの一人にです。 実際の結婚相手ほど大切にはできません。 採用が決まったあとは、他の婚姻者と同等に扱った方が、長期的な幸福度は高いでしょう。

応募者の立場も様々で、一刻も早く現職と別れるために、早く決まればどこでもいい人もいます。 様々な所に応募して一番条件が良いところを探している人もいます。

結婚にも「好きな人と結婚するより、愛してくれる人と結婚した方が良い」という意見や、 「婚前に熱烈な愛情を示した人が、結婚したら同じぐらいの情熱でDVに走る」という事件があります。

結婚も就職も、人と人の相性は事前にはわかりません。 迷っても何も新しい情報は得られないので、何かしら良いと感じるなら飛び込んだ方がいいでしょう。 悩むのであれば、何か小さな行動を起こしましょう。 少しでも良いと思う相手には、人事は尽くしましょう。 焦って結論を求めずに、思いつく限りの準備を丁寧にしましょう。

続々・エンジニアの採用面接対策 コメントへの回答

学習力無力感

エンジニアの採用面接対策 - @ledsun blog

組織内での過去の経験から、相談が無駄だと思われてしまったケースもありそう "一人で不満を溜め込んで、やめることを決めてしまう人"

2018/02/02 18:36
b.hatena.ne.jp

おそらく、大抵の場合は、学習性無力感なのだと思います。 ただ、面接の場では、自社に所属すれば回復するのか、長期的な治療を要するものなのかは判断がつきません。 個人的なイメージでは、優しい人が周りにいるだけで改善するものではないように思えます。 一人でも否定的な物言いをする人がいれば、防御姿勢をとってしまうのではないでしょうか?

このタイプの人は、周囲に愚痴を言いながら、自分傷つけない相手かどうか試そうとする傾向があるように思います。 これは本人にとっては防御のための行動なのだと思いますが、愚痴を言われる周りの人間にはストレスです。

新しく採用する人のために、同僚にストレスを強いるのはなかなか難しいです。 自分が上司に「今度入ってくる人は学習性無力感なので、気をつけて接してください」と言われたら「なんでそんな人をとるのか?」疑問に思います。

「取引先の社長の子供で、採用すると今後数年間数千万単位の売上が見込める」と言われれば納得します。 「弊社が、今抱えている課題にフィットした経験を持っている」と言われれば、特定の課題を解決するまでの期間の有期契約で良いのでは?と思います。

給与と待遇

エンジニアの採用面接対策 - @ledsun blog

「一人で不満を溜め込んで、やめることを決めてしまう人」それって単純に給与や待遇に不満があるケースのような

2018/02/02 12:28
b.hatena.ne.jp

戦略的な給与体系をとるのであれば、給与は実績に応じて上げるのではなく、今後の成果への期待に応じて昇給すべきです。 社員の離脱を防ぐのに大きな効果があります。

この戦略を取れるのは成長フェーズにある企業です。 原資が必要です。 仮に、特定の社員の給与を上げるために他の社員の給与を下げると、下げられた社員の心理的なダメージは大変なものです。 数年内に回復しないと離職する確率が高いです。 成長の踊り場にある企業にとっては、戦略的な給与体系をとることは難しいでしょう。

その結果、社員の成長が給与と待遇を追い抜く可能性があります。 企業としては、成長を生かして新しいビジネスに挑戦すべきですが、ここでも原資が問題になります。 エンジニアとしては、自分をより高く評価してくれる環境にチャレンジするのが良いように思います。

この時、社員が所属企業の売上・利益の状況を理解していて、給与と待遇の改善は見込めないと判断しているのであれば、 相談なしで辞めてしまうのは止むを得ないと思います。

志望動機

エンジニアの採用面接対策 - @ledsun blog

志望動機を聞いてくるようなところには自分なら行かないかな。

2018/02/02 11:24
b.hatena.ne.jp

「志望動機」の質問から知りたいのは、会社に期待することです。 会社に期待することを1つも満たせない場合は、お互い不幸になるので、お断りしたいからです。

新卒採用の時のように、実績のない、比べようのない人材を比べるために使うわけではありません。 あくまで、職歴やスキルを優先して評価しています。 その上で、価値観が会社と著しくズレている可能性を懸念しています。

質問としては、雑に「志望動機」と聞くよりは、丁寧に 「(入社後に社員として)弊社に期待すること」を聞いた方が良いと思います。

写経

エンジニアの採用面接対策 - @ledsun blog

写経のちょい先レベルで書き捨てた物があればなんぼか持ってきてもらう感じかな>学習能力

2018/02/02 09:37
b.hatena.ne.jp

この発想はありませんでした。

個人的な予想では、

  • ほとんどない人
  • 小さいツール類を山ほど書いている人

に、綺麗に分かれると思います。

シニアエンジニアの採用であれば、後者にフィルタリングするのはありかもしれません。

それでも、自社の事業領域と、職務経歴の一致度を優先して評価すると思います。 中途採用の場合は、雇用から成果を出すまでの期間が短い方が嬉しいからです。

業務時間外の学習の強要

続・エンジニアの採用面接対策 コメントへの回答 - @ledsun blog

業務外に何をしようが自由ではあるが、実際にはそういった勉強時間を取らないとやってけないのでは。。。それが嫌なら勉強しなくて良い会社に行けば良い。

2018/02/02 12:58
b.hatena.ne.jp
続・エンジニアの採用面接対策 コメントへの回答 - @ledsun blog

エンジニア側から「あっブラックだ、やめとこ」と足切りされるやつだ > 「現職で、仕事に関する調べものを、仕事以外の時間でしたかどうか」

2018/02/02 11:16
b.hatena.ne.jp

コメントを見て気づきました。 これは合法的に「業務時間外の学習を要求」する方法です。

時間外の学習の強要 ブラック - Google 検索 を検索すると、経営者から「時間外の学習」を要求すると違法か、ブラック企業と言った趣です。

(上司でなく)一緒に働く予定のエンジニアとの面接の結果 「この人は自習しなさそうだから一緒に働きたくない」と拒絶されれば合法です。 まあ、恣意的に「自習しないエンジニアが嫌いな人」を面接官に起用して運用したら、グレーになると気もします。

大人力を要求されない場面であれば「教えてもらうだけで、自習する気がない人とは働きたくないのだけど、あなたは大丈夫ですか?」 と率直に聞くのが良いと思います。

続・エンジニアの採用面接対策 コメントへの回答

エンジニアの採用面接対策 - @ledsun blog

技術的なことについて自学自習できる人を見抜くコツが知りたい。簡単なテストをしてもあまり無意味な気もするし、めちゃくちゃ勉強はできるけど、仕事に全く活かせないorスピード感を掴めない人もいるし。

2018/02/02 07:56
b.hatena.ne.jp

技術的なことについて自学自習できる人を見抜くコツが知りたい。

面接中に確実に見抜く方法はないという前提で、 「現職で、仕事に関する調べものを、仕事以外の時間でしたかどうか」を聞くといいのではないかと思います。

本当に欲しいのは、現在の自社の業務の周辺知識ではなく、将来ぶつかる問題を(自力である程度)調べる能力かと思います。 (労働者に要求していいのかは法的に微妙ですが)「仕事に対して、要求された以上に興味をもって試したり調べたりして欲しい」のだと思います。

「現職では、業務内容に興味がないから調べたことがない」という人は怪しいです。 例えば「Deep Learningを勉強して試してみている」という人でも怪しいかもしれません。 現職と全く関係ないのであれば、自社に転職したあとも、自社の業務と関係ない流行っていることを自習するかもしれません。

これは、技術者としては、全く正しい姿勢です。 会社と一蓮托生するよりは、業務外は業務と関係ないことを勉強をした方が、技術者としての寿命は伸びそうです。 が、欲しがっている人材と一致しない可能性はあります。

簡単なテストをしてもあまり無意味な気もする

おっしゃる通り、自習能力をテストで判定するのは難しいと思います。 面接では、技術について好き嫌いと、その理由を質問するのが良いと思います。 例えば、

Rubyは好きですか?嫌いですか?それは、どういうところですか?」

Rubyの部分は別の言語でも、OSでも、アルゴリズムでも、フレームワークでもなんでも良いです。 応募者の職務経歴に載っていて、ある程度使っていそうな技術が良いです。 技術に対して、「意見」を持っているかどうかを確認します。

自分なりに「これはどう使うものか?」「自分の使いたいやり方にあっているか?」を考えながら、技術に接している証拠になります。 質問のコツは「良い・悪い」(客観的な評価)ではなく「好き・嫌い」(主観的な評価)を聞くことです。

主観評価を聞いていても、教科書的な回答をしてくる人には、ちょっと警戒します。 他人と違う意見をいうのが苦手な人がいます。 そういう人は、技術選択をする際に、自分たちの問題にフィットしているかより、世間の評判を優先する傾向があります。 技術理解度を確かめる質問だと、誤解されている場合もあります。即断はできません。

経験年数が2〜3年ぐらいで、比較可能な複数の技術を扱ったことがない人には、使えない質問かもしれません。

めちゃくちゃ勉強はできるけど、仕事に全く活かせないorスピード感を掴めない人もいるし。

「完璧主義でアウトプットを出すまで時間がかかる人を、採りたくない」状況を想定します。

面接の時点で「我々の扱っている分野は正解がわからず、トライアンドエラーで失敗を繰り返すことが多い。失敗した結果でも、同僚に見せなくちゃいけないし、恥ずかしい場面もあると思うけど、対応できる(耐えられる)か?」と、質問する(伝える)と良いと思います。

もっとストレートに表現するのであれば「どんどん失敗して、失敗を共有して欲しい。失敗を肥やしにして、周りの人を成功させて欲しい」と、伝えられると良いと思います。

当然、応募者には「それで失敗した自分は評価されるのか?」と疑問を持たれると思います。 胸を張って「評価します」と言いたいところですが、正直難しいです。

エンジニアの採用面接対策

paiza.hatenablog.com

に、面接で落とした理由があります。

最近は技術者が面接をすることが多いです。 技術者は採用面接に不慣れなことが多く、質問が下手くそです。 面接官側の不手際で、コミュニケーションに齟齬があって落ちていることもあると思います。

自分の採用面接経験での「こういうことが聞きたかったんだよ」という辺りを書きます。

実践すれば面接に受かることを保証するものではありません。

1位:自己表現(プレゼンテーション)力

職務経歴を聞かれて、一から十まで細かく説明しようとする人

面接の最初にお互いの緊張をほぐすために、自己紹介をしてほしくて使います。 面接官がどっから本題に入っていいのかわからないので、とりあえず聞いてみます。

30秒〜1分くらいで、簡単に説明してもらえれば良いです。 内容よりは、喋り方を見ています。 評価をするためよりは、これから会話をして行くときに「質問と回答のスパンをどれぐらいのリズムでやるか」などを考えながら見ています。

ここで落とすのは「うんざりするような自分語りが続いて、会話を成り立たせるのが疲れすぎる」場合ぐらいです。 苦手であれば1分間のトークスクリプトを用意して、カラオケボックスにこもって練習しましょう。 大事なのは時間の上限と、1つ1つの話題の区切り方です。正確性ではありません。

面接の場で、職務経歴を喋るときは、多少不正確な説明をしても問題ありません。 普通の面接官は、事前に職務経歴書を読んで質問したいことを用意しています。 職務経歴書の内容と、しゃべっている内容に気になる齟齬があれば、確認の質問をします。 その時、内容を修正してください。

稀に、職務経歴書に書いてあることをそのまま質問してくるなど、職務経歴書を読んでいない風の面接官もいます。 その会社はやめましょう。 その会社には、会議の前に資料を作成・共有し、共有された資料を読んでから会議に臨む文化がありません。 非効率な会議が多い会社です。

2位:志望意欲・やる気

転職理由が年収や福利厚生などの「条件面をよくしたい」だけで止まっている人

この質問は、「会社に期待すること」を知りたくて聞いています。 「会社に期待すること」を全て満たせるわけではありませんが、全く満たせなかった場合はすぐ辞めてしまうでしょう。 それを防ぎたいと思って聞いています。

ここで落とすのは、「うちの会社は、君が思っているような会社じゃないぞ」と思う時です。 直接言えることもありますが、大人の事情で直接言えずに落とすこともあります。

ただ、この質問には罠があります。 「志望意欲」の1つの質問で、実は2つのことを聞いています。

  1. 業界・業種を選んだ理由
  2. 会社を選んだ理由

本来は、「この業界・業種を選んだ理由は?」「その中でうちの会社が良いと思った点は?」と二段階で聞くべきです。 が、あまりにもありふれた質問なので、雑に「志望理由はなんですか?」と聞いてしまうことが多いです。 この場合は、丁寧に両方答えましょう。

「まず、業界・業種を選んだ理由は・・・。次に御社を選んだのは・・・」

業界・業種

「業界・業種を選んだ理由」は、素直に業界・業種に期待することを話しましょう。 「サービスを使う側から作る側に回りたい」「受託開発より長いスパンでサービス開発に携わりたい」などです。 一般論なので、そんなに深く突っ込むことはありません。

突っ込むとしたら、「業界・業種」への期待が現実と違いすぎる場合です。 例えば「サービスを当てて億万長者になりたい」な理由の場合は、「受託開発業界に来ても遠回りすぎるからやめとけ」な思いを抱きます。

会社

「会社を選んだ理由」は、競合が何社かある中で、その会社を選んだ理由です。

BtoC

BtoCのサービスを提供している会社であれば、「サービスを使ったことがあって好きだから」みたいな理由ができていいですね。

面接の前に試しにサービスを使ってみるのは重要だと思います。 サービスのコンセプトやユーザが気にくわない会社はやめましょう。 自分が嫌いなサービスの開発に携わるのはストレスがたまります。 短期であればいいですが、長期的な関係を築くのは厳しいです。

BtoB

BtoBの会社であれば、待遇面の話でよいと思います。 「働き方に共感した」「教育制度が充実している点に期待している」などと言えば良いと思います。

企業のインタビュー広告などあれば、それを見て共感したとか言うとポイントは稼げるかもしれません。 ホームページにある「会社の理念」がどうこうな話は、新卒採用の場合はわかりませんが、中途採用の場合は興味がないです。

大望

もし大望があるのであれば、可能な限りでかい話をしておいてもらった方が良いように思っています。 「御社の〇〇で業界の悪習を変えたい」や「御社の〇〇で、XXの生活を変えたい」のようなレベルでも良いと思います。 面接官が「会社の求めているレベルより理想が高すぎる」「こんなに意識が高いやつがうちの会社に入ると苦労する」と思えば落としてくるはずです。

自分が「御社の〇〇で業界の悪習を変えたい」と思っている時に、会社の幹部が「そういうのはどうでもいいので売上を増やしたい」と思っている会社に入ると、あまり幸せにはなれないように思います。

3位:技術的な取り組み・技術探究心

やってないことに対して「やりたいです」「やる気はあります」と言うだけの人

この質問で聞きたいのは、技術的なことに対して、教えてもらうだけでなく、自分から調べる能力があるかどうかです。 要するに、「自習する力があるか」と「それを技術に向ける関心があるか」を確認しています。

これには2つの理由があります。

  1. 技術の変化が早すぎて「誰かが正しい技術を調べて展開する」で対応できない業界事情
  2. 自習力を教える方法がわからない

業種の転換をしたい面接者の場合は、

  1. Web業界に行きたいです
  2. そのために何をしていますか?
  3. 具体的にはなにも・・・

となることがあります。 この場合でも

  1. 現職で、社内教育で学んだこと以外に、自力で調べて問題を解決したこがある
  2. Web業界に興味があって、こんな媒体を見ている

と言う話をしてもらえれば大丈夫です。

1をやったたことがない人は、マジで技術者に向かないと思うのでやめておいた方がいいと思います。

2の媒体があまり技術方面でなく、ビジネス方面だった場合は、「業界・会社に期待していることが合わない」可能性を考えます。 「泥臭いことの方が多いけど大丈夫?」のような質問します。

プログラミング未経験者の場合は、プログラミングをやってみてから全く合わないことが判明することがあります。 この質問とは別の対策が必要だと思っています。

4位:忍耐力

転職回数が多い人

人を採用すると、

  • 転職斡旋業者への報酬
  • 教育費用
  • 事務手続き費用
  • 営業費用

などなどかかるので、できれば一度雇った人には長期的に働いて欲しいです。

ここ知りたいのは「やめると決める前に、不満点をあげるなど事前の相談をしてくれる人」かどうかです。

一人で不満を溜め込んで、やめることを決めてしまう人は、 採用コストはかかるわ、会社としてフィードバックは得られないわで、雇っても嬉しくありません。 辞めること自体が悪いわけではありません。

「あまりにもヘビーな環境だったが、相談したが職場転換などしてもらえなかったので辞めました」というのは十分な理由です。

5位:責任感・当事者意識

転職理由が「やりたいことができないから」「周りが悪いから」だけの人

ここでは「一緒に仕事をして気分が悪くなる人」でないことを見ています。

落とすのは、面接官が「周りが悪いから」の対象になったことを想像した時に 「自分の仕事には関心を持つ価値がない」「自分の仕事を馬鹿にされた」と感じた時です。 面接の場で、特定人物の悪口を言うのはやめましょう。 面接官は人間なので「人への悪口」は自分に飛んでくることを想像します。

現職では今後、金融系の受託開発事業のみに絞られていくことが決まっています。このままでは自分が将来のために身につけてきたスキルも無駄になってしまうと感じたため

のように、会社の方針とのミスマッチを理由にするのが良いです。

本当のところ、知りたいのは「問題を上司にでなく同僚にだけ言う人」かどうかです。 不満や問題を会社の事としてエスカレーションできない人は、職場の文化を破壊します。 とは言っても、実際に愚痴っぽい人は、面接官のように立場が強い人には何も言いません。 面接の場でこの性質を見抜くことは、とても難しいです。

2017年にやった技術的なチャレンジ

d.hatena.ne.jp

をみて、なるほどと思ったので、自分の成果も棚卸しをしておきます。

一年を通して

一年を通して見ると、Rubyを使ったHTTPサーバーで非同期に結果を返し、ブラウザで非同期に受け取った結果を画面に反映した一年でした。

2016年に比べて成長を実感するのは、一見難しいことを簡単に実装できるようになったことです。 「DOM更新アルゴリズムの実装」「同時処理リクエスト数制限の実装」は一見難しそうです。 やる前は、「正しく動くようにするのに1〜2週間はかかるかな」と思いました。実際にやってみたら数日で実装できました。

まだ、自分でも何が変わったのかはよくわかっていません。 必要な要件から、問題の核心をより小さいサイズに絞り込む能力が身についたのかもしれません。

伝統武術のでいう「心・技・体の体」ができたような気がします。 そのつもりで、今年は体を生かして、技を増やそうと思います。 今までやったことないことに、色々チャレンジしようと思います。

チャレンジ

UIのデザイン変更のためにDOM更新アルゴリズムの共通化

LODQA : Question-Answering over Linked Open Dataユーザーインターフェースの大幅な修正を行いました。表示項目は今までの開発経験により絞り込めていましたが、リンクドデータに馴染みのないユーザ向けに配置や表示順を工夫する必要がありました。特に検索結果を詳細に表示するのではなく、サマリーをまとめて表示する変更を行いました。

これまで検索結果の表示は、受け取った結果を随時、末尾に追加するのみでした。ブラウザのDOM APIを使って、DOM要素を追加して表示を更新していました。サマリー表示のためには、追記の他に既存DOM要素の中間への挿入が必要になりました。

そこでReactのVirtualDOMのような差分更新アルゴリズムが欲しくなりました。一方、すでにHTMLテンプレートとしてHandlebarsを使っていました。これをJSXに置き換えることは避けたいです。

そこで、DOM更新アルゴリズムを自前で実装し、DOM APIを使ったDOM要素更新処理を置き換えました。これにより、アプリケーション上のDOM更新のロジックは新規作成と更新が全く同じになりました。プレゼンテーションロジックの記述量が減ったため、修正工数も減りました。大幅なユーザーインタフェース変更に対応することができました。

この時作ったDOM更新アルゴリズムの説明は

ledsun.hatenablog.com

にあります。

サーバサイドのクエリ生成・実行処理の無限リスト化

LODQA : Question-Answering over Linked Open Data では

  1. 自然言語(英語)の質問からSPARQLへの変換
  2. 登録されている全てのSPARQLエンドポイントへの問い合わせ

を自動で行います。ここで問題になったのは特定の英文をSPARQLに変換する際に、サーバ上のメモリをGB単位で消費することでした。その英文からは、50万を超えるSPARQLを生成してしまいます。

そこでRubyEnumeratorクラスを作って

  1. SPARQL生成
  2. SPARQL実行
  3. クライエントへの結果送付

を逐次的に行う実装に修正しました。 これによりサーバのメモリ消費を、同時処理リクエスト数によらず、100MB程度に抑えることができました。

サーバ処理を並列化するときに懸念されるのは、レスポンスの悪化です。 クエリのボトルネックはSPARQLエンドポイントにあります。 SPARQLの生成に比べるとSPARQL実行の方が10倍以上遅いです。 サーバのレスポンス低下は、ユーザーから見ると誤差の範囲でした。

Wampリクエスト処理の並列化

IoT機器と通信を行うRailsアプリケーションを作成する際にWampRailsというGemを使いました。 性能上の要件を満たすために、Wampリクエスト処理の並列化をしました。 WamapRailsはEventMachineに依存しているため、EM.deferメソッドを使ってマルチスレッド化することで並列化を実現しています。 これによりRailsの1リクエスト=1スレッドというRail Wayを外れることになりました。

まず、高負荷時に応答を返せるように、同時処理数に上限を儲けました。 たとえば、Rails+Pumaではワーカスレッド数で同時処理リクエスト数を制御しています。 同様の制限を行います。 WamapRailsは非同期にレスポンスを返すためにDeferインスタンスを生成します。 この生成処理を利用し、Deferインスタンスの同時生成数を管理することで、同時リクエスト数制限を実装しました。

もしこれをスレッドプールとして実装した場合は、スレッドプールのテスト自体の工数がバカになりません。 さらに、Pumaのスレッド管理、EventMachineのスレッド管理が既に存在するので、運用上スレッドに何らかの問題が見つかった場合に、原因切り分けが困難になるでしょう。

次にDBコネクションの解放処理を追加しました。 RailsではRackミドルウェアで使用済みのDBコネクションを解放しています。 WamapRailsのための作成したスレッドは処理を終了しても、Rackミドルウェアを呼び出すことはありません。 これもDeferインスタンスを活用し、レスポンス返送時に、明示的にDBコネクションを解放することで対応しました。

RailsのDBコネクションプールの統計値を取得

あるRailsアプリケーションで複数のデータベースを扱いました。

この時、Google Cloud Platform上のデータベースとのコネクション状態がActiveRecordのコネクションプール場では検知できない現象に悩まされました。 実際のコネクションが切断されていてもコネクションプール上では切断が検知されず、実際にSQLが発行されるときになって例外が出る現象に出会いました。

残念ながら、原因を特定するに至りませんでした。 アプリケーションの特性上、GCP上のデータベースは参照機会が限られていました。 データベース利用終了時にコネクションを明示的に切断して対応しました。

この調査の際にActiveRecordのコネクションプールの状態を取得したかったのですが、Rails 5.0には適当なAPIがありませんでした。そこでRails5.1に追加された、ActiveRecord::ConnectionAdapters::ConnectionPool.stat をバックポートして使いました。

その他

Redmineプラグインの作成

ledsun.hatenablog.com

IoTゲートウェイモデリング

ledsun.hatenablog.com

技術同人誌執筆

ledsun.hatenablog.com

ledsun.hatenablog.com

「有名な統計力学ゲーム」をcanvasで表示してみる

今回のテーマ

前回の

ledsun.hatenablog.com

では、やり取りの結果をSVGのレーダーチャートで表示しました。 SVGではやり取りが1000回を超えると快適に表示できませんでした。 今回は、canvasのレーダーチャートに表示します。

チャート

See the Pen statistical_mechanism_on_canvas_chart by shigeru.nakajima (@ledsun) on CodePen.

さすがはcanvas、圧倒的な描画性能です。 やり取りを一万回ぐらいやるとバランスよく星型になるのがよくわかります。

ちょっとした工夫

canvasであっても1万回描画すると*1それなりの時間がかかります。 そこで複数回のやり取りをまとめて描画しています。 かつ、やり取り回数が多い時は、たくさんまとめて、少なく立ってきたらまとめる数を減らして描画しています。 これで

  • 1千回で1秒
  • 3千回で3秒
  • 1万回で7秒

ぐらいの比率で描画しています*2

やり取り回数が多い時は、たくさんまとめて、少なく立ってきたらまとめる数を減らすための計算式が

Math.ceil(Math.log(残り回数)) + 1

です。logを取って、残り回数の桁に比例*3して、まとめる数を増やしています。 最後に1を足すのは、log(1)が0だからです。まとめる数が0回だと無限ループします。

考察

「有名な統計力学ゲーム」の驚きは、「公平なルールに見えるのに、実際に運用すると不公平(偏り)が生まれる」です。 これは「公平になるには、たかだか数百回のやり取りで十分だろう」という思い込みを利用したトリックに思えます。

「宝くじは、超長期的には損するが、短期的に得することがある」という仮説が考えられます。 このルールを見たときにも同様に 「長期的には公平であるが、公平になるまでには偏りは生まれる」までは予想できます。

実際に手で試してみると、数十回〜100回程度やり取りしても、公平になりそうな雰囲気が出てきません。 「もしかして、このまま続けても不公平なままなのでは?」という疑問が出てきます。 ここに驚きを感じます。

1000回試すと、偏りが持ち回りになる様子がわかります。 これで、もっと続ければ公平になりそうに思えてきます。 実際は、3000回やり取りしても、公平にはなりません。 これは当初の「たかだか数百回」の予想とは大きく違っています。

*1:正確には1万回setTimeoutを呼ぶのに掛かる時間です。

*2:実際の時間は実行環境、ブラウザを開いているPCの性能、に依存します。

*3:厳密には比例ではありません

「有名な統計力学ゲーム」をレーダーチャートで表示してみる

今回のテーマ

前回の

ledsun.hatenablog.com

では、分配アルゴリズムの実装と結果を数値で表示しました。 今回は、アルゴリズムには変更を加えずに結果をレーダーチャートで表示します。

チャート

See the Pen statistical_mechanism_on_chart by shigeru.nakajima (@ledsun) on CodePen.

毎回のやり取りの結果をクリアせずに上書きしています。コインの偏りの時系列変化が見えるようになりました。

考察

頂点が尖る人(コインを多数獲得している)が時系列で変わっていることがわかります。 やり取り回数を増やせば、満遍なく全ての人が尖るのではないでしょうか?

現在の、やり取り回数は1000です。 1000回では、頂点が尖らない人がいます。 何回まで増やせば偏らないことが確認できるでしょうか?

今回はSVGを使って実装しています。 SVGでは、polygon数が2000個、頂点数が2500個ぐらいで、描画が明らかに遅くなります。 一度のやり取りの描画に1秒以上かかります。 試しに3000回やり取りしてみても、頂点が尖らない人がいます。 もっと回数を増やす必要があります。

  • canvasなら、もっと多くの頂点が描画でき、もっと多くのやり取りを表現できるでしょうか?
  • やり取りの毎回のコイン数を描画せずに、偏りの推移を表現できるでしょうか?*1

*1:「大沢流-手づくり統計力学-大沢-文夫」第2−2節では、トップ回数と0の回数で表現していました。