日用品のストック管理ツール Stokk を作った
日用品のストックを管理出来るツール「Stokk」を公開しました。
以下はポエムです。
技術選定
- サーバをわざわざ建立するほどの機能はない
- mBaaSと親和性が高そう
- フロントエンドを書きたい
ということで、SPA + mBaaSで作ることにしました。
使ったもの
- ツール
- 言語
- TypeScript
- フレームワーク
- その他ライブラリ
- mBaaS
ツール: Adobe XD
初使用。無料の「スタータープラン」があり、アカウントさえあればシュッと使えます。
プロトタイプは作らず、ちょっと便利な図形描画ツール程度に使いました。事前にデザインや要件を整理でき、その後データやイベントの流れを練り練りするのにも大いに役立ちました。
言語: TypeScript
JavaScriptを操れる自信はなかったのでTypeScriptで書きました。エディタはVisual Studio Code。
ただ、厳格に型付けをするのは諦めました。動く状態で、「thisはVueだからお前が定義したプロパティなぞ存在せんわ!」などと言われていました。「ぐ、Gradual Typingだから…」と意味不明な言い訳をしつつキャストしたりanyにしたりしました。
フレームワーク: Vue.js + Vue Router, Bootstrap + BootstrapVue
ふわっと書きたかったのとReactは仕事で書く機会があるのとでVue.jsにしました。Vue CLIでTypeScriptも含めて一括で初期設定でき、とても楽でよいです。
デザインは安定のBootstrap。BootstrapVueも入れましたが、「BootstrapのListってBootstrapVueでどう書くんだっけ」と毎回マッピングしつつ書いていました。効率的に書けたかは分かりません。
その他ライブラリ: Lodash, Font Awesome
Lodashはdebounceに、Font Awesomeはアイコンに。
mBaaS: Cloud Firestore, Firebase Hosting, Firebase Authentication + FirebaseUI
作るサービスと親和性高そうなので全面的に依存しました。
FirebaseUIについては、 Firebase 6.6.1 と FirebaseUI 4.2.0 でドキュメント通りに書いたつもりで動作せず(firebase.auth()
と書くとfirebase
がないと怒られる)。
メジャーバージョンを1つ落として FirebaseUI 3.6.1 を使用することで落ち着きました。何故なんだ。
そのほか
命名: Stokk
当初「にちまね!(日用品在庫マネージャ)」で けいおん!風にしようと思っていました。が、サブドメインを割り当てるタイミングで nichimane
は無いな… と思って在庫(stock)を意図的に誤字らせました。
アニメーション
「動いているんだけど動いている感がない」という印象を受けたため、「小気味よく動いている」感を演出するべくアニメーションを設定しました。
- アイテム追加、削除、並び替え時
- 読み込み・保存時(スピナー表示)
ソースコード
ページの好き嫌いを学習・分類するChrome拡張を作った
ネタです.
ベイジアンフィルタで,ページの好き嫌いを学習・分類するChrome 拡張機能を作りました.
動作サンプル
ページが自分好みかどうかベイズ推定するやつ、Chrome拡張に昇華させた pic.twitter.com/RIsdR3ReMg
— たいぷらいたー (@no_clock) 2019年6月29日
構成
学習・分類サーバがあり,Chrome拡張はそのクライアントとして機能します.
全文ではなくURLを送っているのは,認証が必要なエリアのコンテンツをうっかり学習させないためです.学習データに個人情報が混ざっているとか怖くて扱えない.
学習・分類サーバ
- 考えるのが面倒だったので GCE (Debian 9), nginx, Ruby, Sinatra, Unicorn
- ベイジアンフィルタとして jekyll/classifier-reborn ,日本語の分かち書きにはMeCabとIPA辞書を使用
ソースファイルと利用方法
Chromeウェブストアから拡張機能を追加するか,上記リポジトリをcloneしてデベロッパーモードで拡張機能を読み込んでください.
URLがサーバに送信されますので,気になる方は自前でサーバを立ててください.
Oracle Code Cardを触ってみる (触っただけ編)
Oracle Code Cardという謎のカードを譲ってもらった.「イベントでもらったけど使わない」「ボタン電池が高い(500円)」という情報も付属していた.
観察
赤い基板に電子ペーパーが載っている.イベントで配布するにしては贅沢だ.いくら掛かっているんだろう.
裏面には「Live for the Code」との記述がある.
ボタン電池のホルダがあるが,LIR2450 3.6V,という珍しい電池のようだ.なんと RECHARGEABLE の記述がある.充電池.
よく見ると,ESP-12Fチップが搭載されている.これはArduino互換のような気がする.調べてみるとどうやら確からしい.
あっちこっちのページを探索していると,USB-シリアル(UART)変換チップも載っていて,シリアル接続で通信出来るとのこと.確かに載っている.
というか,リポジトリがある.
通信
リポジトリの記述に従って接続し,スイッチON/OFFを切り替えたが何も起きない.
Aボタンを押すと,どうやらWi-Fiに接続しようとしている旨のメッセージが流れる.Type 'help' for more info.
と表示されるが,直後にシャットダウンしていて反応はない.
詰んだ,と思った.とりあえず適当にA/Bボタンを同時押ししてみた.
…すると,なんと当たりだったようで,電子ペーパーにORACLEのロゴが現れた後,シャットダウンしなくなった.
そのままhelpと入力すると,期待通りヘルプが出てきた.うまくいったようだ.
さて,どう調理しようかな.つづく.
参考
死活監視をFirebase Realtime Databaseでお手軽にやってみる
死活監視といえば,たとえば Mackerel や Uptime Robot などが使えます.
ただし,こうしたサービスは「エージェントをインストールする」か「外部からサービスにアクセスできる」必要があるほか,無料版に制限があるなど少々ネックがあります.
そこで,Firebase Realtime Databaseで死活監視チャレンジしてみました.
監視対象の条件
- インターネットに到達できる(外部公開は不要)
- cron または 任意の定期実行可能なジョブ管理システム がある
- cURL または 任意のHTTPクライアント がある
監視対象: REST APIを定期的に叩く
監視対象のホストから,定期的にハートビートを送信します. データの保存 | Firebase に記載されている Realtime Database の REST API を用います.
crontab -e
でcrontabに定義を追加します.
*/10 * * * * curl -X PUT -d "\"`date '+\%Y-\%m-\%d \%H:\%M'`\"" https://examples.firebaseio.com/heartbeats/`hostname`.json
Realtime Databaseにデータが追加されます.
アラート: Cloud FunctionsからSlackに通知する
アラートも作ります.Cloud Functionsで定期実行するようにします.
Node.jsですが普段あまり書かないのでクオリティはお察しです.
export const scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) => { request.get({ url: "https://examples.firebaseio.com/heartbeats.json", }, function(error: any, response: any, body: any) { const info = JSON.parse(body) for (let hostname in info) { const diff = Date.now() - Date.parse(`${info[hostname]}+09:00`) if (diff < 1000 * 60 * 30) { continue; } const options = { url: 'https://hooks.slack.com/services/<fugafuga>', form: `payload={ "text": "${hostname}: ${info[hostname]} 以降 heartbeatがありません." }`, json: true } request.post(options) } }); return 1 });
ためしにしきい値を1分とかにして毎分実行させると,ちゃんとSlackに通知されます.
注意事項
- うまくいったら認証処理入れましょう. 参考: REST リクエストの認証 | Firebase
おわりに
Realtime Databaseとは… という感じですが,Realtime Databaseは課金対象がストレージとトラフィックのみで,リクエスト数に制限がないため,少量のデータを高頻度にやり取りするケースによく合います.もっとも,今回の規模であればFirestoreでも無料枠で済みますが…
めでたしめでたし.
SIerから自社サービス系に転職して半年ちょっと経過した
2018年9月にSIerから自社サービス企業に転職した.会社の宣伝ではないので社名は伏せる(たどれば出るが).
退職エントリは書かなかったが,半年ちょっと経ったので考えを整理してみようとポエムにした.
学生時代
小学生でVisual Basic 6.0に触れ,中学生でソフトウェアを公開して自宅サーバも立てていた.今も続いている.
SIer時代
就職活動は熱心に行わなかった.「親を安心させたかった」というもっともらしい理由で大手グループのSIerに入った.
闇
世の中には不気味なSIerのdis記事があふれていて,残念なことに私がかかわった現場の大半もその通りだった.
メモリは4GBで,Eclipseに統合された謎の静的コード解析ツールはファイル保存のたびに1分間フリーズした.3年前の話で,今は違うかもしれない.
なぜそんな闇が残り続けるのかというと,私は「効率化するメリットが(会社に)ないから」と勝手に解釈している.効率化してもお金にならない,そんな不思議な世界だったように思う.
何を得たか
と言っても,無だったわけではない.得たものはあったし,転職して初めて「あの経験役立ってる」と気づくこともあった.
- 品質意識とバランス感覚.バグが損害に直結する.趣味のモノづくりとは何もかも違う世界で,意識は大きく変わった.また,人的リソースと期間が限られているなかで,どうバランスを取るか,という点は常にトライ&エラーで工夫していた.
- OJTトレーナーやレビュア経験.コミュニケーション面で,どうすれば相手に伝わるのかひたすら苦心した.技術面(?)では,何をレビューしなくても大丈夫かという勘所(手の抜きどころ)を得たような気がする.
- 会社はそう簡単には変わらないという感触.会社の技術推進部門に異動させてもらって,「さて,会社全体で技術重視の方向に舵を切ってもらいますか」とイキったが特に何も出来なかった(一番悲しいのはその障壁が部門内にあったことだった).
何を得なかったか
一方,得たいと思っていたものはあまり得られなかったように思う.
- 技術力.趣味で培った以上のことを何も得なかった.配属直後から「チームで一番技術に詳しいのはお前だから」と言われていた.
- 顧客が本当に求めるもの.本当に顧客が欲しているものを作っている,という感触は得られなかった.これ以上の言及は控えたい.
なぜ転職しようとしたか
「得なかったもの」の裏返しである.技術力を活かして,顧客が本当に求めるものを作りたかった.
より根底には,3つの事柄が関係している気がする.
- 小学生の頃から続く「プログラミングって楽しい」とか「プログラミングなら何でも出来る」という感覚
- 作ったものを誰かに使ってもらったときの「嬉しい」という感情
- 「やりたいこと」「できること」「求められること」が合致するとベターだという大学の講義で聴いた話
ずっと転職を考えていたが,最後のひと押しは同僚の転職だった.
なぜ転職まで6年強在籍していたか
2点ある.
- 限界を見たかった.自分が現場や会社をどれだけ変えられるか,一通り試しておきたかった.
- 漠然とした不安.Web系はSIerよりハードワークなのだろうという偏見と,SIerから転職出来るだろうかという不安があった.
限界を見たという納得感と,SIerに残り続けることの不安にかられ,転職に至った.
なぜ今の会社に決めたか
先に非礼を詫びておく.
情熱プログラマに「一番の下手くそでいよう」という節があるが,これを最も実現できそうだったから,というのが理由である.
言い訳がましいが,このフレーズに甘えるつもりはなく,相応の成果を出すようには努めている.
転職活動の思い出
転職活動は大変だったが楽しかった.面接の技術的な質問は腕試し感覚だったし,何より「サービスを作ってる人が目の前にいる」のがとても眩しかった.
印象的な問答はよく覚えている.
私「今の会社だと,そもそも『理想の開発環境』にこぎつけるまで10年単位で掛かる.待っていられない」
面接官「その『理想の開発環境』というのは具体的には」
私「CIが回っているとかそのレベル」
面接官「えっ(笑)」
私「えっ(笑)」
SIerから自社サービス,で異世界転生モノが書けるのではないだろうか.私は書かないが.
今の会社はどうか
自分のスタイルとの合致度は大きく上がったと思っている.
会社固有のものか,自社サービス系なら当たり前のものか,という区別はついていない.
合っているところ
- 自由.「成果を出す」という一点が満たせれば,いつ来ていつ帰ってもよいし,技術選定に制限はないし,周辺機器や書籍も手に入る.
- 技術スタックの分散が大きい.新しい技術に触れやすいし,どの技術も誰かが詳しいので困ったときもなんとかなる.
- コミュニケーションがいい意味で雑.相互のリスペクトが前提となるが,オブラートや遠慮みたいなところに脳のリソースを割かなくて良い.これはエンジニアに限った話ではない.
- チームリーダでもコードが書ける.SIerだとリーダはリーダ業に徹していたが,現職はメンバの自走力(?)が高くて,リーダリーダする必要はない(そっと背中を押す感覚でいる).メンバと同じく作業していることが多い.
合っていないところ
- 申請方法どこに載ってんだみたいなことが多い.相手の時間を奪いたくなくて聞くのは避けたい人間なのだけど,結局初回は聞くことになりがち.個人的にちょっと相性が悪い.
そのほかの感想
- みんなすごい(こなみかん).インターンの学生がめちゃくちゃ成果出したりもする.正直劣等感に苛まれることもあるが,隣の芝生は何とやら,自分は自分なりに成果を出せるポイントを見つけてやっていくしかないのではと感じている.
今何をやっていて,今後どうしたいか
今は,後述する「やりたいこと」に掲げたことをやっている.
今後については,「5年後にXX」といった明確な目標はまったくない.これには,大学生の頃に聴いた 計画的偶発性理論 (Planned Happenstance Theory) に従っている,という背景がある.
ただし,やりたいこととやりたくないことは持つようにしている.内容は変化するとしても,やりたいことが出来て,やりたくないことを極力やらなくていい,そんな場所を今後も漂っていくのだと思う.
やりたいこと
- コーディング.ソフトウェアアーキテクチャの設計等も含む.何らかの形で「自分が書いたコード」がプロダクトに入っていてほしいと常に思っている.
- プロダクトの成長.「より多くのユーザにより良いプロダクトを届ける」ことで満たされた気持ちになるような気がしている.これはここ半年で強く思うようになった.
- プライベートでのサービス開発.既に14年半続けているが,アイデンティティとして昇華させたい.
やりたくないこと
- マネジメント中心の仕事.人をどうこうする,というのは最も苦手な部分であるし,精神的に疲弊するため.
- 兼務.マルチタスクは疲弊する.
おことわり
これはポエム.一個人の意見に過ぎない.
変数名などの命名のお供に.Webサービス "Zenrei" を公開しました
Webサービス "Zenrei" を公開しました. GitHubのスター数上位のリポジトリから,クラス名・メソッド名・変数名の使用実績を検索できるサービスです.悩ましい命名のお供にご活用ください.
機能
- 使用実績 … GitHubスター数上位リポジトリから,入力したクラス名/メソッド名/変数名の使用頻度・使用箇所を表示
- 類語 … "calculate" - "estimate" のように,各単語の類語を表示
- betaにつきRubyのみ対応
活用例
"calculate" にするか "calc" にするか
"data" が複数形なので、 "datas" は使われていない
ソースコード
GitHubに公開しています.あまり綺麗ではないです.
技術要素
言語・フレームワーク等
- フロントエンド: Vue.js + Bootstrap
- サーバサイド: Go (Echo framework)
- データベース: MongoDB, SQLite3(日本語WordNetのみ)
- その他: Docker, Ruby(データ解析)
Vue.jsとGoは初でしたが,意外とすんなり出来ました.
クラス名/メソッド名/変数名の解析
ripper
ライブラリを使用しました.Ruby標準ライブラリで,ソースコードを与えるとS式にして返却してくれたりします.
類語の検索
日本語 WordNetを使用しました.SQLiteデータベースとして配布されており,synset(概念)というグループ化によって,類似する単語を探し当てることが出来ます.
なお,複数形・過去形などは原形(lemma)に戻して類語を調べています.これにはgolemライブラリを使用しました(GitHub: aaaton/golem).当初はwink-lemmatizerを用いてフロントエンド側で対応する予定でしたが,辞書サイズが大きくjsファイルが肥大化するためサーバサイドで対処しました.