soy-curd's blog

へぼプログラマーです [https://twitter.com/soycurd1]

バーチャル賽銭箱になって時代の最先端を目指す

f:id:soy-curd:20180613004233p:plain

youtube投げ銭機能がすごくて、実際に月ノ美兎とかおばあちゃんyoutuberとかの生配信とかを見てるとどんどんユーザーから金が投げ込まれていく。100円単位のものばかりかと思いきや1000円単位でぶちこんでいる人もいて、これは明らかに経済の流れの革命であり、絶対に儲かるやつで、この流れに乗るしかないといった思いが高まった。それで週末、家のPCにfacerigを入れて、

配信できる環境を整えるまでやったところで、絵が書けないとvtuberになることができないことに気づき、vtuberになることは断念した。(↑の犬はfacerigのサンプルキャラクター。)

他の手段はないものかと調べてみると、投げ銭サービス的なものは世の中にかなり出てきているようで、pixivの出しているfanboxもその一つだ。fanboxは絵師に投げ銭できるやつで、投げ銭するとそれまで非公開だった画像が見れるようになったりする。

しかしその対価である画像も、つきつめれば物理的実態のないデジタル情報であり、fanboxで投げ銭をしたとしても実態としてユーザー←→クリエイター間で移動するのは投げ銭された金銭の数字だけである(その数字も実態なのかという話もあるが)。つまり、投げ銭だけ可能な状態のfanboxがあったとして、それは他の画像が見れるfanboxのページと物理的には等価なのではないか?

そこで作ったのが先にリンクを貼ったバーチャル賽銭箱だ。このfanboxから、pixivのアカウントを持っている人ならだれでも、お賽銭を投げ入れることができる。自分は絵師でもなんでもないので、投げ銭したからといって絵が見れたりなにかできたりするわけでもなんでもない。これは経済の&>/dev/null/だ。金は天下の回りものというが、この賽銭箱に金を投げ入れてもそれが再び社会を還流する保証は一切なく、ただ純粋にお賽銭を投げ入れることができるのがこのバーチャル賽銭箱だ。

またこのバーチャル賽銭箱にはささいなギミックとしてバーチャルおみくじ機能も設けた。これは引く前からすでに運不運がわかっているという画期的なおみくじだ。凶がひきたければ凶の分賽銭を投げれば良いし、大吉をひきたければ大吉分賽銭を投げれば良い。非常に簡明であり、現代的だ。現実の寺社仏閣もぜひこのシステムを流用してほしい。

なお、このバーチャル賽銭箱にもメリットがないわけではなくて、お賽銭を入れる練習になる、大晦日で神社が混んでいても気軽にお賽銭を入れることができる、お金を捨てる場所に困っていてもここなら気兼ねなく捨てられる、などがある。日頃からお賽銭に困っている方はぜひご活用ください。

制御の反転と DI の関係を完全に理解した

自分は会社で利用している web フレームワークや Angular で DI を日頃から使っているのだけれど、なんかモックとかぶちこめて便利だな、ぐらいの理解で、 制御の反転っていう概念がよくわからなかったし、それと DI がどのようにな関係にあるかについては全然考えていなかった。なので、最近いろいろ調べてわかったことを書いてみる。

まず、制御の反転なのだけれど、wikipediaに概念がまとめられている。しかしDI を念頭にこの文章を読んでも、この説明だとよくわからないと思う。

これはなぜかというと、この wiki に載っている例が、Dependency Injection とは直接関係ないからだ。実装技法 の項目になって、ようやく依存性の注入の話が出てくる。この時点で、依存性の注入制御の反転を行うための一つの手段でしかないことがわかる。

それではいったい DI における制御の反転は何の制御を反転しているのか?ということだけど、これは、クラスの管理(制御)の責務を反転している。

この記事からその責務を抜粋すると、

  • 依存関係の置換または更新を行う(a)
  • 依存関係の有効期間の特定(b)

である。DI においては、クラスの管理(制御)の責務を担うのは、利用する側のオブジェクトではなく、フレームワークだ。

これを Angular のユースケースで考えると、(a)は例えばユニットテストのためにモックの注入を行う場合で、 (b)はフレームワーク側の機能としてProviderSingleton serviceを提供している点だろう。

以上を意識してから読むと面白いのが、この記事この記事 だ。

前者では必要な機能を持った関数を引数として渡したり、部分適用を行うことで依存性の注入を実現していて、後者では、 React は props の機能で DI 相当の機能が実現できるから、DI なんて知る必要はない、と言っている。

つまり、OOP の文脈で DI を実現するためには DI コンテナのようなフレームワークが必要だが、FP においては関数が first class であることで、言語機能として制御の反転を担保している、と言えるのかもしれない。(React は FP 側)

google の Peter Norvig のスライドで、「動的言語でのデザインパターン」というものがあって、この中で GoFデザインパターンのうち 16 個は動的言語では不可視化されるかシンプルになると言っている。確かに Python なんかではイテレータは言語に組み込まれているし、頻出するパターンはプログラマの手を煩わせないように言語設計者が上手く取り込んでくれているのだろう。

もし FP が今後もっと台頭すれば、DI の概念もいずれは、すでに言語にビルトインされたものとして特におおげさに言及されることもなくなるのかもしれないと思った。

Hyperapp × TypeScript × herokuで簡単なアプリケーションを作成した

Hyperapp × TypeScript × herokuで簡単なアプリケーションを作成した。

obenkyou.herokuapp.com

tour of goっぽいかんじで、JavaScriptをサイト上で実行することができる。

処理の流れとしては、右のペインに入力 -> inputを拾って随時stateを更新-> 実行ボタン押下次にinputの内容をevalするactionを実行-> actionの結果を右下に表示というようになっている。

この部分についてはHyperappのstate managerとviewが程よく密結合になっていて、書きやすかった。

コンポーネントの定義だけ抜粋すると下のようなかんじ。ここだけ見るとほぼReactと変わんないんだろうなという気がする。

const JsCode: Component<Props> = ({
  title,
  label,
  description,
  code,
  result,
  error,
  onChange,
  onSubmit
}) => (
  <div class="container">
    <div class="columns">
      <div class="column col-6">
        <h2 class={styles.title}>{title}</h2>
        {descriptionFormatter(description)}
      </div>
      <div class="column col-6">
        <div class="columns">
          <div class="column col-12">
            <label class="form-label" for="textare">
              {label}.js
            </label>
            <textarea
              id="textarea"
              class={styles.codeForm}
              value={code}
              oninput={(event: any) => onChange(event.target.value)}
            />
          </div>
          <div class="column col-12">
            <button class={'btn ' + styles.run} onclick={() => onSubmit(code)}>
              JavaScriptを実行
            </button>
          </div>
          <div class="column col-12">
            <p>
              結果: <span class={styles.result}>{result}</span>
            </p>
          </div>
        </div>
      </div>
    </div>
  </div>
)

hyperapp/routerも試しに使ってみたのだが、ルーティング後に別のactionを発行した時、全体のstateが更新されるのでルーティング処理のルートに再度入ってしまい、変更差分の制御を入れないと無限ループになるのが難点だった(書き方の問題かもしれない)。

上の件以外は特にハマった部分は無く、Angularと比べると意味不明なエラーに遭遇する率が低い印象だった。

それに、bundle.jsのサイズが12.3kbという大きさで収まっているのは、Hyperappならでは利点だと思う。1kbとか公式が言っているだけあって、やはりめちゃくちゃ小さい。

TypeScriptとの相性については、まだRouterが型定義が公開されてないとかあって微妙な部分もあるけど、PRは出ているようなので時間の問題っぽい。

自分は業務ではメインでAngularを使っているのだけれど、ロード時の重さや開発時の重さで中々大変な部分があり、結構辛い。でも今回Hyperappぐらい小さいライブラリでもこの位のものは作れちゃうのがわかったので、実はAngularなんて要らないんじゃないかというかんじもしてきた。

(Hyperappと直接は関係ないが、jsxで条件によってタグ・クラスの出し分け〜みたいなのは、参考演算子がjsxの中に混ざってかなり読みにくいので、AngularのngIfほうが良いかも。ということは可読性&バンドルサイズの小ささで結局vueが最強なのか。。。)

入門 React ―コンポーネントベースのWebフロントエンド開発

入門 React ―コンポーネントベースのWebフロントエンド開発

Angularアプリケーションプログラミング

Angularアプリケーションプログラミング

されたくもないのにメンタリングされることに対する気持ち悪さ

先日、最近流行りの『エンジニアリング組織論への招待』を読んで、その中にメンタリングについての章があった。それによるとメンタリングとは、

対話を通じて、メンタリングする人の思考力を一時的に貸し出し、思考の幅を広げていくことで、その人の歪んだ認知を補正し、次の行動を促し、成長させていく手法です。

と書かれている。自分はこの文章を読んで、まず、「きも、。。。これ洗脳じゃん。。。」と普通に思ってしまった。

こんなふうに思った理由はたぶん簡単で、自分がメンタリングする側の立場ではなく、メンタリングされる立場で読んでいるからだ。つまりメンタリングされる側からすると、よくわからないけど自分の精神の状態を把握され、歪みを補正され、成長させられることになる。こんなに恐ろしいことはない気がする。

なお、この本ではメンタリングの手法として「傾聴」「可視化」「リフレーミング」というものが紹介されるが、これはNLPというジャンルの言葉っぽい。これは神経言語プログラミングの頭文字をとったもので、プログラミングとは全く関係がない、心理学畑の用語のようだ(もちろん、自然言語処理とも関係がない)。この言葉のwikipediahttps://ja.wikipedia.org/wiki/%E7%A5%9E%E7%B5%8C%E8%A8%80%E8%AA%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)を見てみると、疑似科学というワードが出てきて、ああ、やばいな、という気持ちにさらになってくる。

たぶんこの気持ち悪さは、メンタリングに対して知識がないせいだと思う。Fear of the Unknownというやつだ。おそらく本当はメンタリングの技術は正当な科学的背景があって、それを用いることの正当性があるのだけれど、それが上のような疑似科学的な文脈で用いられることがあって、それが自分には知識が無くて弁別できず、一緒にまとめて気持ち悪さを感じさせてしまうのだ。

で、気持ち悪いなら気持ち悪いなりにメリットがないと流行らないはずなので、たぶんメンタリングの手法自体は正しいのだろう。雰囲気的に、メンターがまともならメンタリングもまともになる気がする。『エンジニアリング組織論への招待』では、メンターが導く方向性については正しい前提で話が進んでいるように読めるけれど、これはこの本がフォーカスしているのが「ソフトウェア開発」だからで、ゴールが明確で、「成長」させる方向についてもメンターとメンティーの間で一致できるはずなので、あまり実利的な問題はなさそうだ。これでこの本に対する憂いは無くなった。どんどんメンタリングされていきたい!ジョハリの窓を開示しよう!!!

蛇足として、企業で「メンタリング」という言葉が使われる場合、それは離職率を下げる方法の一つとして使われることがあるようだ(https://college.e-jinzai.co.jp/useful/manager/function-mentoring-that-prevent-new-member-from-retiring/)。なんらかの点で会社と社員のミスマッチがあると離職が発生するわけで、「歪んだ認知を補正」することによってミスマッチが無くなれば、離職率も低くなるだろう、ということだと思う。そんなの補正する前に採用時点で判断しろよ、という気もするが、なかなか難しい話なのだろう(カルチャーフィットを数値可するサービスも出てきているみたいだ https://www.wantedly.com/companies/meryeself/post_articles/81208)。素直な人材が欲しい、というベンチャー界隈の採用方面の気持ちの高まりも、この文脈だと理解しやすい。

以上のようにメンタリングの世間的な流行りを感じるので、学んでおくと生きていくうちの要所要所で効いてきそうなかんじがする。そういう意味で、『エンジニアリング組織論への招待』はメンタリングを学ぶための良い本なので、プログラマーなら一度読んで見ると良いと思う。

なお、こんなひねくれた私を導いてくれる人がいたらぜひ連絡をください(絶賛メンター募集中です)。

マンガでやさしくわかるNLP

マンガでやさしくわかるNLP

地方のプログラマーが都内のベンチャーに転職して2年ぐらい過ごして感じたこと

自分は以前群馬のSIer的な企業で働いていて、転職を機に東京に引っ越した。そして働き始めてからいつのまにか2年以上も経っていたので、新卒として群馬で働き始めてから東京に転職して今までに至る流れを、備忘録としてここにまとめてみる。地方から都内に転職しようとしている人がいたら、もしかしたら参考になる部分もあるかもしれない。

前職(SIer的な企業)

自分は大学時代は生物学をやっていたが、就活していた時はちょうどピペド世界がもし100人の博士だったらのような話がキャンパス内に蔓延していた。研究室の先輩を見ても、アカデミックに残るには命と生活を削らないと無理そうだったので、なんとか就職はしたいなと思っていた。生物学を学んでいたら食品業界とか製薬業界とかに就職しそうなイメージだと思うけれど、研究室の同期の就職先は公務員×2SIer×2といったかんじで、非常に生々しかった。自分はそのSIerのほうの1人なのだが、これは研究の実績的にバイオは無理っぽかったとの、研究でCとかMATLABをちょっと触ってたのと、理系っぽい業界で未経験でも入れるのはSIerぐらいだろうな、と雑に思っていたからだった。

就活ではなんやかんや苦労して1個だけ内定をもらい、そこに新卒で入社した。内定先は東京の企業だったが、すぐに群馬の子会社に出向になった。SIerピラミッドでいうと二次受けぐらいの位置の会社で、たぶん世間で言われているようなブラックSIer企業ではなかった。研修もたっぷり3ヶ月はあったし、配属された部署はほとんど残業もないし、仕事も急いでやらないとヤバイやつは新人には回ってこなかったし、家賃補助もボーナスもあった。完全にホワイト企業だった。ドキュメント書きやテストの仕事が多かったので、どっちかというとコーディングをたくさんしたいと思っていた自分としては多少不満だったが、まあそれも新人のうちだけだろうと思って素直に働いていた。

ただ、働いていくと次第に、残業がないのが自分の部署ぐらいだということがわかってきた。他の同期は今月もX0時間残業だ、というようなことをよく言っていて、4・5年目ぐらいの他部署の先輩で心が破壊されてしまう人もぼちぼちいた。結局多少プログラムが書けるようになるとすぐに外注管理や協力会社との折衝が仕事のメインになり、社会的ななんやらの板挟みになって壊れてしまうのだ。(壊れてしまった場合、休職したのちに復帰プログラムが組まれ、負荷の少ない職場からリスタートできる)。

そして自分が働き始めて2年目の冬、ぬるま湯だった我が部署に新たな案件が振ってきた。既存のガラケーのアプリをイマドキのタブレットのアプリにリプレイスするという素敵な案件だ。しかも今流行りのオフショア開発を用いているということで、高品質なプロダクトが素早く低価格で顧客に提供できるはずだった。

自分は別のチームで別の作業にしばらくの間従事していたのだが、時間が経つにつれその素敵な案件に先輩がどんどん吸い込まれていった。どうやらオフショアで出していた開発の部分でバグが大量に見つかり、その特定に人員が必要らしかった。ブリッジSEのための席が新しく増え、協力会社の方々が常駐するようになり、ついに自分も客先でテスト作業をするために駆り出されてしまった。この適度に炎上した案件はそれなりの時間と人員をかけて鎮火されたけれど、わかったのはこの部署は決して安全なわけではなく、他の部署と同じようにいつ誰が病んでもおかしくないということだった。自分はまだ病んではいなかったが、きっとそれは今自分がただのプレイヤーだからで、未来の自分についてはなんの保証もできなかった。

転職活動

それで約2年前、転職活動を始めた。これまでの知見として、マネジメントは心を破壊されるということがわかっていたので、コーディングをメインで働けるほうが良いかなと思った。CodeIQとpaizaをやってみて、CodeIQのほうはほぼ人材紹介会社からしかリアクションがなかったので、paizaのほうが良さそうに感じた。skypeで面談したり実際に東京まで言って話を聞いたりすると、どこの仕事も楽しそうだった。ある1社で給料を前職から維持してくれるというところがあり、入社を決めた。新卒で就活していたのと比べるとはるかにあっけなく決まったので、かなり拍子抜けしたような覚えがある。

つまり自分は、都内のベンチャーに入りたいから都内のベンチャーに転職したのではなく、コーディングでまともに仕事できそうな企業が都内のベンチャーだったので、というかpaizaに登録している企業がそういうかんじだったので、今の職場に転職したということになる。だから、もし群馬県の企業や他の土地でSIer的なやばさから遠い職場環境があったら、そのような企業に入っていたかもしれない。今思うとpaizaのSIer煽りに完全に乗せられた形だが、転職後に前の職場の同僚に話を聞くと、すでに前の職場の部署は解体され存在せず、そしてチームの先輩どころか役職持ちの方々まで新しい部署で精神を破壊させられりたりしているようなので、結果的にはpaizaに乗せられて良かったと思う。

都内のベンチャーで就職

就職先は山の手線沿いの西側の駅の職場だった。家は安そうなところで板橋区東上線沿いのアパートにした。家を出て職場まで1時間程度で、今は耐えられているが、満員電車に遭遇した時など死にそうになるので(東上線は遅延からの満員電車コンボはよくある)、かなり家選びは悪手だったかなと思う。いずれ引っ越ししたい。

仕事自体はかなり良かった。入った頃はPythonを書いていて、今はその他にNode.jsだったりAngularだったりも使って仕事している。同僚も自分よりレベルが高い人ばかりで学ぶことが多いし、新しい技術が好きな人が多いので自分もいろいろ勉強しなきゃなという気持ちになる。

物理的には、夏場に短パンサンダルで出社できるのがめちゃくちゃ良い。群馬では徒歩通勤で近かったのは良かったが、夏にスーツと革靴で出社させるのは端的に頭がおかしかった。近年の夏はスコールが発生したりして、実質熱帯雨林気候なのだから、それに合わせてライフスタイルも変革する必要がある。

もちろん今の職場も100%良い会社なわけではなくて、ささいな不満もないわけではない。そういう影響で、同僚では他の会社に転職していってしまう人もいる。でもそれはこのweb業界が他の業界と比べてプログラマーに対する環境がかなり良いからで、働いている中で感じる不満が、相対的に大きく感じてしまうのだと思う(常に隣の飯は白いし、東京はが本当に歩いて1分くらいしか離れてない会社だったりする)。

最近不安なのは、自分のバックボーンが生物系なこと、自分のプログラミング経験が周りと比べて短いことだ。中学とか高校からプログラミングをやっている人間と、大学1年のCの授業をほぼコピペで乗り切って20才すぎてからようやく研究でプログラミングし始めたのとでは、やはり決定的に知見が違う気がする。自分は仕事がある程度できている状態だと自分でも思っているが、そのある程度が、ちょっとSQL書けて、ちょっとサーバーサイド書けて、ちょっとフロントエンド書けるというかんじで、特に誇りを持って自慢できるなにかがあるかんじじゃない。今の同僚や、転職していった人たちに較べて、2分の1かそれ以下ぐらいのパフォーマンスしか出ていないのではないか?と思うことがある。自分がこれからどれだけ学んでも、周りと比べて誇れる技術力が持てるか、見通しが立たない。

でもそんなこと不安に思っててもたぶん意味はないし、自分の技術力の未熟さを言い訳しているだけなので、気にせずに今後も淡々と好きなことを勉強していきたい。その結果が誇れるような技術力に跳ね返ってくればかなり嬉しいが、それは5年後だったり10年後だったりするかもしれないので、それまではその時その時の現状で出せる全力のパフォーマンスで会社には貢献していきたいと思っている。

さいごに

ほぼ悩み相談みたいな文章だし、似たようなことを以前も書いている気もするが、いったん今の段階で自分が働いてきてこれまでに感じている感情の流れをまとめてみた。とりあえず、生物学専攻の人でもプログラマーで就職はできるということと、東京のベンチャーにはいつでも入れるということは言えた。似たような境遇の人がもしいたら、少しでも参考になれば良いなと思う。

JavaScriptでforの二重ループからforを一個削除する方法

プログラマのためのコードパズル」を読んでいたところ、かなり始めのほうに、for文の二重ループから forを一個削除することによりプログラムを短くするコードゴルフの技法が載っていた。 しかし、簡単な説明のみで式変形され、すぐには理解できなかったので、 理解しがてらその方法を紹介していく。

まずは以下のような二重ループがあったとする。

function solve() {
  for (var a = 0; a < 10; a++) {
    for (var b = 0; b < 10; b++) {
      if (a * b === 81) {
        console.log("solve!");
      }
    }
  }
}

solve()

このとき、変数aとbがそれぞれ0から9までインクリメントされ、a*b9*9=81となる場合が発生するので、"solve!"というログを見ることができるだろう。

これをfor一個で書く方法として以下のようなものがある。

function solve() {
for(a=0,b=-1;a<10;b<9||(b=-1,a++))b++,a*b==81&&console.log("solve!")
}
solve()

確かにコードからはforが一個消えている。しかし、消えた分のforの処理はどこで行われているのだろう?

これではわからないので、まずは読みやすくフォーマットしてみる。

function solve() {
  for (var a = 0, b = -1; a < 10; b < 9 || (b = -1, a++)) {
    b++;
    if (a * b == 81) {
      console.log("solve!");
    }
    // ※
  }
}

forの加算式の、b < 9 || (b = -1, a++)が目につくと思う。 ここで、※の部分にconsole.log(a, b)を仕込んでaとbがどのように増えるか見てみる。

0 0
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
1 0
1 1
1 2
.
.
.

普通にforを二重にした場合と同じように、内側のループの変数がインクリメントされ、 その後外側のループの変数がインクリメントされている。

インクリメントしている部分はb++の箇所だ。

それでは、なぜこの箇所でaのループが一回しか回っていないのにもかかわらず、b++が10回も実行されるのだろうか...?

ここで、b < 9 || (b = -1, a++)をもう一度見てみる。これはfor文の加算式ではあるけれど、もっと重要な点がある。それは、a++b < 9の場合は実行されないという点だ。

つまり、このfor文は変数aについてだけのループではない。bが9より小さい場合はbのループを回し、そうでない場合にaのループを回す役目があるのだった。

(b = -1, a++)を式(x), b++を式(y)として、 logの結果にコメントをつけてみると、

0 0  // b == -1 < 9なので式(x)は実行されない。式(y)のみ実行でb == 0になる
0 1  // b == 0 < 9なので式(x)は実行されない。式(y)のみ実行でb == 1になる
0 2  // 上記と同様...
0 3  // 上記と同様...
0 4  // 上記と同様...
0 5  // 上記と同様...
0 6  // 上記と同様...
0 7  // 上記と同様...
0 8  // 上記と同様...
0 9  // 上記と同様...
1 0  // b == 9 < 9ではないので式(x)が実行。aがインクリメントされ1, bが-1になる。さらに式(y)が実行されb == 0になる。
1 1
1 2
.
.
.

ということだとわかる。ひとつひとつ処理を追ってみて、ようやく仕組みを理解できた。

コードゴルフでは、forの([初期化式]; [条件式]; [加算式])の部分で、式で可能なあらゆることをするようなので、そのあたりを注意して本のほうを読み進めていきたい。

AMP対応のためのnpmモジュール作った

www.npmjs.com

ampは全てのcssを外部ファイルではなくhtmlに埋め込まなければならないので、直書きしたくない場合は、 なんらかの手段でhtmlにcssを持ってくる必要がある。

github.com

が良さそうだったが、ampタグには対応していなかったので、PRを出した。だが、よく見るとこのリポジトリはPR放置されるかんじのやつだったので、 amp対応したやつを別に公開しておいた。

使い方

例えば以下のように,

index-amp.html

<html>
  <head>
    <style amp-custom href="./yo-amp.css"></style>
  <body>
    <h1 class="hey">
        Hey!
    </h1>
  </body>
</html>

yo-amp.css

body {
  background-color: cyan;
}

.hey {
  color: red;
}

というようなファイルがあったとき、

yarn add html-inline-amp
./node_modules/html-inline-amp/bin/cmd.js -i index-amp.html -o ./_index-amp.html -b ./

すると、

<html>
  <head>
    <style amp-custom>body {
  background-color: cyan;
}

.hey {
  color: red;
}</style>
  <body>
    <h1 class="hey">
        Hey!
    </h1>
  </body>
</html>

というように、cssがamp-customタグに埋め込まれたhtmlファイルが出力される。

webpackとか使うまでもないときに便利かもしれない。