ハウテレビジョン開発者ブログスマートフォン用の表示で見るハウテレビジョン開発者ブログ『外資就活ドットコム』を日夜開発している技術陣がプログラミングネタ・業務改善ネタ・よしなしごとについて記していきます。今回は副業のはなしです。(TOP画像だと1週間休み無く毎日働いてる感がありますが、そんなことはないです)話題のツイート友人が副業禁止されてる会社に副業がバレて二度と副業をしないよう上司に言われた。言われた通り翌日から会社に行くのを辞めたら鬼電が止まらなかったとか。友人いわく、何が副業かは俺が決めること。二度と副業をしないように言われたのでそうしたのだと。前に副業禁止の会社に関するtweetがバズってましたが、ハウテレビジョンでは副業を全面的に推奨しています。事業的に競合する会社はダメとか、体を壊すような無茶な働き方はダメとか一定の基準はありますが、あらかじめ申請した上で副業しているメンバーは結構います。いう会社で副業エンジニアとして働いており、主にGoで書かれたWebアプリ開発のお手伝いをしています。(厳密にはheyの100%子会社のコイニー社と業務委託契約しています)開発をお手伝いしていたのは新たな決済サービスで、簡単にいうと「スマホがあれば、リアル店舗でツケ払いで買い物できる」というサービスです。去る5月にようやくプレスリリースも出て世間にお披露目されたので、副業エンジニアをやってみて分かったことなどをお話していきたいと思います。副業をはじめたのはEMとしての経験値不足を補うためハウテレビジョンに入社してから丸3年たった2018年9月頃、僕は開発部長に正式に任命されました。世にいうエンジニアリングマネージャー(EM)というやつです。EMになって一番大きな変化は他のエンジニアメンバーの評価、あけすけにいうと給料を決める立場になったことでした。その時点で僕はエンジニアになって(=プログラミングを初めて)4年半。前職は受託やSESをやっている会社におり、いわゆるWeb系ベンチャーでの経験はハウテレビジョン1社しかない状態。開発チームの中には自分より年上でエンジニアとしての業務経験も豊富なメンバーもいる中で、そんなエンジニアの評価についてメンバーや経営陣が納得する判断をできるかが不安が募ります。副業を考え始めた最大の理由は、「EMとして自信を持てるためにより多くの経験値を獲得したいから」でした。EMの役割とは何か?少し話は逸れますが、EMの役割について私見を述べます。EMに求められるものはチームごとに異なるかもしれませんが、僕が考えるEMの役割はエンジニアメンバーの給料を上げることに集約されます。エンジニアメンバーの給料を上げるためには開発チームが事業インパクトの高い開発をして成果を出す成果の出る開発をスピーディーに進められる開発チームを作る個々人の技術スタックが増え、技術レベルが上がるなどが必要で、これらを実現することで最終的に事業成長に貢献できると考えています。EMとは開発チームに働きかけることで事業成長に貢献する人、という定義です。いう本の第6章中で紹介されている「技術部長」のジョブディスクリプションが近しいイメージです。heyとの出会い副業の話に戻ります。heyとの出会いは、2018年夏にWantedlyでスカウトを貰ったことからでした。僕は転職するつもりが無くても面白そうな会社からメッセージを貰ったらカジュアル面談しに行くことがあります。冷やかしのようで気が引けますが、他社の開発チームの内情を聞くこと自体が自分の糧になったりすんですよね。そんなこんなでheyに話を聞きに行った所、Goで開発してる新規事業をやろうとしてるチームメンバーが優秀な人ばかりで、雰囲気もめちゃくちゃ良いオフィス内にタダで飲めるお酒が大量に置いてある(!?)と、自分にとって魅力的な条件が揃っていました。いえ当時は転職という状況にはならなかったため、ダメ元で「副業という形でチームに入れてくれないか」とコイニー代表の佐俣さんにお願いしたところお許しを頂けることになりました。どんな感じで副業してるか?まず、ハウテレビジョンでの仕事は引き続き週5フルコミットでやっています。晴れて東証マザーズに上場したハウテレビジョンですが僕が副業を始めた2018年11月時点はまさに上場が決まるか決まらないかという大事なタイミングでした。UXの改善、新商品の開発、セキュリティ課題への対応、上場に備えてのコーポレートサイトのリニューアル、エンジニアメンバーの採用...などの仕事が山ほどある上に、EMとしてメンバーを評価するという重責も担うようになったので副業をするからといって本業を疎かにしてよい状況では全くありませんでしたし僕もそうするつもりはありませんでした。平日の早朝や帰宅後にもやるようにしました。開発マシンは私物のMacで自宅作業。完全にフルリモートの副業という感じです。使って10分程度のオンラインミーティングをして開発進捗やプロジェクトの状況シェアをしています。(これは平日の昼休憩の時間でやってます)あと、ハウテレビジョンのオフィスからheyのオフィスまで歩いて12分くらいなので新しいメンバーが増えたときなどには一緒にランチに行ったり、リリース後の打ち上げに参加させてもらったりしてます。業務委託費用について。始めは稼働開始と終了をSlackで報告する方式にして実働時間分を請求するスタイルにしていたのですが、スキマ時間で開発することも多く報告が煩雑になってきたので、最近は担当するIssueごとに事前に見積もり工数を出してその月にPRを出したIssueの工数分を請求するスタイルに変更しました。どんな開発をしてるか?「ツケ払い」はWebアプリケーションで、お店で買物をする購入者向けのスマホ画面や、お店のスタッフが決済を登録する画面、運営側が使う管理画面などがあります。技術スタックは、GoVue.jsDockerMySQLTravisCIなどを使っています。運営向けの管理画面でページングのコンポーネントを実装するGoのErrorハンドリングでerrorsパッケージでWrapするようにするなどがあり、やや大きなものから細かいものまでやっています。↑は自分が担当したIssueがリリースされた時のSlackの様子です。副業をやってよかったことGoと言えば並列化ですが、2つの開発チームに所属することで得られる経験値も倍増しました。技術面での経験値が増えたGoは外資就活ドットコムの開発でも使っていますが、使っているフレームワークやライブラリ、アーキテクチャなどは異なるため、自分の中の引き出しが増えました。知らなかったGoの挙動を発見したこともありました。決済という事業ドメインも外資就活ドットコムというメディア事業・人材事業とはまったく異なり、その裏側に登場する技術も普段触れることがないものが多くあります。ツケ払いではSMS送信の機能があるのですが、外資就活の開発では今の所SMSを使う場面はなかったので、もし今後SMSを使って何かしたくなった時に役立ちそうです。副業エンジニアとの付き合い方どんなIssueをお願いできるかどのくらいの頻度でコミュニケーションが必要かなどを学ぶことができました。実際、7月に就業体験目的で副業エンジニアの方を1ヶ月だけ受け入れる機会が発生したのですが、その時にも自分が副業をしていて得た知見を活かすことができました。まとめ実際、エンジニアとしてもEMとしてもまだまだ修行が足りませんが、副業をすることで経験値を増やせることは間違いないように思います。最近では転職する前に副業してミスマッチを防ぐようなやり方をしている人も増えてきました。募集しているポジション一覧は以下をご覧ください。求人一覧もっとライトに質問や相談したいという方はtwitterのDMでも受け付けております。Botを作るこんにちは、Go2のReleaseを楽しみにしているymgytです。Botの作り方について書いていきます。Botを作って見たい方に向けた記事です。codeはこちらで公開しています。以下のTopicを扱います。作成するbotの名前はgobotとしました。ReviewのSlackへの通知とUserのCRUD処理を行います。Userの対応はgobotが独自に管理しています。URLに登録するdomainが必要です。packageを利用してCertificateを取得するので、明示的なTLS設定は必要ありません。Kuberneteskubectlが実行できる状態にしておきます。Engine(GKE)を利用しました。GCPまわりの設定についてふれると長くなってしまうので本記事では、詳しくはふれません。gcloudコマンドをinstallしたうえで以下のコマンドにてclusterを作成しました。Datastoreを利用しております。formatで取得してください。Tokenの値を確認します。このTokenは実行時にgobotに渡してやる必要があります。GithubPullRequestの通知を実施したいRepositoryにてWebhookを設定します。Webhookから設定をおこないます。typeにはapplication/jsonを指定し、Secretはgobotに渡してやる必要があります。reviewsを指定します。codeをみていきます。imageのpushまでについて述べます。imageがpushできたら、kubernetesにdeployして完成です。開発環境gobotのsorceをpullしてある前提で話をすすめます。fileを作成しておくと便利です。GO111MODULEmoduleは明示的にonにしておきます。vendorコマンドでvendoringができます。GOBIN$(pwd)/binの値をセットしておきます。して、Versionを定義したfileを利用します。User用のtokenを指定します。API接続時に必要になります。GOBOT_MONGO_DSNlocalではmongodb://localhost:27017を指定します。GOBOT_MONGO_DATABASEgobot-localを指定しておきます、なんでもよいです。依存ツールの管理Goで開発していると、gomockやlinterといった、go製のtoolのversionを固定したくなります。tagを設定しておきます。github.com/google/wire/cmd/wire実行時に、go.modで指定されたversionのbinaryが${GOBIN}以下に配置されます。API開発環境も整ったので、codeをみていきます。APIはgithub.com/nlopes/slackを利用しています。Userの名前とIDが取得できるので、以降はこの名前でmentionされた際に、処理を起動するようにします。初期化時に、Githubへの通知用channelが取得できるかも確かめています。Goらしく、SlackのEventはchannelから取得できます。gobotでは、slack.MessageEventを処理の対象にしています。Eventを拾えば、Channel作成の通知処理なんかも行えそうですね。isDirect})}Bot自身が発言したMessageも取得してしまうのですが、判別できるようになっているので、無視します。Messageで話しかけられたかどうか、発言者の情報等のコンテキストを取得して、MessageHandlerに処理を委譲します。Eventの処理をみていきます。eventのbindingにはgopkg.in/go-playground/webhooks.v5/githubを利用しています。w.WriteHeader(http.StatusOK)}github.Webhook.Parseでpayloadの検証とbindingまでおこなってくれるので、必要な情報だけ抽出して、slackに通知します。slackへの通知する際に、概要にあったようなmessageを送るためにattachmentを設定します。Eventが複数発火するので、素直に処理すると通知が重複して飛んでしまいます。そこで、DuplicationCheckerを定義して、確認処理をいれています。興味がある方はsourceのほうで実装をみてみてください。Userのmentionslackの仕様でmentionを飛ばすには、対象Userのslack上のUserIDが必要です。UserIDの変換が必要です。この変換のために、gobotでは独自にUserをmongoで管理しています。Emailを使う必要は必ずしもないのですが、slackの管理している情報で全ユーザが必ずもっていて、変化しにくいのでemailを使うようにしました。このあたりの変換処理は以下のような感じでおこないました。interfaceここまででPRを通知できるようになったので、githubとslackのuserをマッピングする設定のInterfaceを作成します。個人的な構想として、gobotはあくまで、slackとのinterfaceやwebのendpointの提供にとどめ、kubernetes上の他のserviceとgrpcでやりとりしていこうと考えております。Likeなinterfaceにしようと考えました。そのあたりを以下の処理で行っております。appのような処理を開始します。packageとして自作のgithub.com/ymgyt/cliを利用しています。channelへの通知なのでそこをwrapしている点です。UserのCRUDようやく、UserのCRUD処理までたどり着きました。}}mongo側の処理はこのようになりました。}mongo-dirver/bsonの扱いがまだわかっていない点があり、もっとよい方法があると思っています。imageにしてpushします。Dockerfile上では、moduleをoffに指定してvendoringを利用しています。Registryにimageがpushされます。Kubernetespushしたimageを動かすためにKubernetesの環境を作成していきます。Mongoまず、Kubernetes上にMongoを作成します。3つのResourceを作成します。ConfigMapServiceStatefulSetConfigMapにmongoの初期化scriptを定義します。clientから接続できて便利です。2GiDeployMongoを設定したので、いよいよgobotをdeployします。configこれをみておかしいと思われる方もいらっしゃるかもしれません。Credential情報をConfigMapで管理しています。KubernetesにはCredential情報を管理するResource(Secrets)があるので、ConfigMapには、Token情報は格納すべきではありません。ConfigMapの変更を確実に反映するために、nameにversion情報をいれておいたほうがよいと思います。LoadBalancerにmappingするために、ひとつIPを確保しておいて、DNSに設定してあります。nameをaliasとして登録できるのですが、GCPで同じことをやる方法がわかりませんでした。<resource.yaml>で適用すれば完了です。まとめ前回に続いて2本目の開発者ブログいかがだったでしょうか。誤りのご指摘やご意見等あればtwitterまでいただけるとうれしいです。golangci-lintについても書きたかったのですが、断念しました。ハウテレビジョンでは現在、エンジニア採用を積極的に進めています。Missionである"全人類の能力を全面開花させ、世界を変える"は、多少宗教的いろあいがあることは否めませんが、5つのValueとして掲げているChallengeTransparencyOwnershipUserfirstRespectは真っ当なので、大丈夫です!特にこの記事を読んでくれる方には、是非インフラエンジニア募集にご応募していただきたいです。Developingしましょう。冨樫先生を見習い、堂々と長期休載してゆく覚悟です。ブログ枠で参加させてもらいましたので、せっせとレポします。いう新サービスをリリースしました。平たく言うと今流行りの質問箱のようなサービスですが、回答者は運営側で厳選しているため普段なかなか会うことの出来ないすごい社会人(+内定者)に誰でも気軽に質問できるよー、というのが好評を博しています。質問箱系のサービスで必須なのがOGP画像ですね。↓のように、「質問」を画像で、「回答」をTweetの本文で表現したりします。言われていますが、ソフトウェア開発を労働集約的産業と捉えているから、というのが理由の1つであるように思います。2018年10月25日このOGP画像はgoで生成してるのですが、開発にあたり色々と苦労があったので、レポの後にその辺の話もチョロっと書きます。Gunosy社は六本木ヒルズ森タワー内にあります。入館の仕方を忘れます。着くの早すぎ、ほぼ一番乗り。青鬼があるあたり心憎いですね。LTのタイムアップを知らせる用と思われる銅鑼(ドラ)。鳴らすと近所迷惑にも程があるらしく、主催者さんの首が飛ぶらしいです。今回は懇親会パートなどは無く、ドリンクを飲みながら発表を聞く、というスタイルでした。タメになったこと、気になったことなどザッと記していきます。(@timakinさん)speakerdeck.com相談室の開発で自分が経験したことととても近い内容の発表でした。自分のやってたことが世間と大きくズレていなかったぽい、ということを確認できました。Goにおける画像ファイル処理(@harukasanさん)speakerdeck.comそもそも「画像とは何か?」「人間とは画像をどのように認識するか?」という話。人間は色情報より輝度情報に敏感なので、色情報は多少サンプリングしてもOKらしい。JPEG、GIF、PNG、WebPなど、それぞれの画像フォーマットの歴史。どのフォーマットでも表現できるように上手いこと抽象化してくれてるぽい。フォーマットの異なる画像を合成することができる。普通に実装しているとなかなかここまで深く知る機会は無いので勉強になりました。画像を扱うプロ集団のPixivさんですね。Go画像と東京アメッシュ(@otiai10さん)ターミナル上に画像を出す話。熱量が高く、会場の笑いをさらってました。goのimagemagickを使ってレンチキュラー写真を作ったハナシ(@junpaymentさん)docs.google.comドット単位で打ち込み位置を計算すれば、2つの画像をマージしたレンチキュラー写真(見る角度によって絵が変わるアレ)も作れる、というアイデア作。やろうと思えばマジで何でも出来るんだなと勇気をもらいました。「デジタルの世界と紙の世界は違う」という深い示唆を頂きました。使った事例を紹介されていて、トラウマが開く音がしました。とあるライブラリをGoに移植した結果......(@makki_dさん)speakerdeck.com移植駆動学習すごい、の一言。golangにまだ無いサードパーティ製のライブラリを見つけては他言語の実装に倣って移植すると学習が捗る。ついでに既存ライブラリのバグを見つけて修正PRを送るチャンスまである。移植元のライブラリを叩けば入出力のペアを簡単に得られるのでテストを書きやすい。テストカバレッジを測るとどこが理解できてないか可視化出来る。とあるgopherがOpenCVをさわってみた話(@usk81さん)CERNでPython→golangの乗り換えがあったらしい。機械学習系でgoの機運?もれなくシュタゲを連想するなど。GoCVを使うと、集合写真を認識して個々人の顔だけ切り出したりできる。「画像生成」だけじゃなくて「画像認識」もgoでできる、という啓示を得られた気分でした。先述の通り、外資就活相談室のOGP画像をgoで実装しましたので、こぼれ話をいくつか紹介します。パッケージでしょ?」と、今なら言えます。夏頃に「よっしゃ実装や!」と張り切っていた時、「golangでImageMagickを触りたい」という記事を発見。使って実装を始め一通り完成に至りました。この時、完全にデプロイのことを考えていませんでした。コンテナ内にクロスコンパイルした実行ファイルをポンと置く、というシンプルな手順でデプロイしています。して依存するライブラリをインストールしておく必要があるのですが、これでは「クロスコンパイルして実行ファイル置くだけ良い」というgolangの旨味をまったく享受できません。alpineイメージをと使い分けているため、開発環境と本番環境で動作が異なる可能性も出てきてしまいます。追い打ちのように「ImageMagickに脆弱性があるかも!!」というNEWSが飛び込んだため、ImageMagickとの訣別を決めました。さよならっ!!!!読みやすく改行するため禁則処理をライトに実装Webページであれば文字の折返しはブラウザが良い感じにやってくれますが、画像に文字を埋め込むとなると画像から文字が溢れないように改行する処理も自前で実装する必要があります。画像に対する文字サイズや余白の広さ、使用するフォントなどは仕様次第で変わるため、この辺はトライアンドエラーを繰り返してマジックナンバーを探し出す必要がありました。そんなこんなで改行を実装した結果が↓左側です。「ャ」や「、」などの文字が行頭に来てしまい読みづらいでです。英文に至っては英単語の途中で改行されてしまうため、とても読める状態ではありません...。ブラウザやワープロ系のソフトウェアに実装されているアレです。(このとき禁則処理という言葉を初めて知りました)さすがにこんなニッチなライブラリをgoで見つけることは出来なかったため、自前で実装することにしました。試行錯誤の末、以下の様なアルゴリズムで文章を改行可能な単位の文字列(ブロック)に分割しスライスに格納。今度はこのブロックごとに行を組み立てていき、文字幅を計算して溢れそうになったら次の行を追加してまた結合...、を繰り返します。画像にレンダリングした後の文字列の正確な幅を取得するのは骨が折れますが、全角/半角を考慮して大体の文字列幅を計算し、試行錯誤を繰り返して係数をチューニングしていけば、そこそこの精度で文字を置くことができます。