blog.syfm

徒然なるままに考えていることなどを書いていくブログ

就活を終えた

はじめに

この記事はポエムです。

f:id:ktr_0731:20181029161538j:plain


先日、内定承諾をして就活が終わった。
就活を始めたのが去年の 9 月くらいだったので、だいたい 1 年くらい就活をしていたことになる。
とはいえ、内定承諾をしたのが最近だっただけで実質的な就活は去年の年末で終わっていた。
それからは頂いた内定を 1 つずつ断り、残った 1 つだけ承諾せずに残していた。残していた明確な理由は特になくて、ただ内定承諾期間が長いからというだけだった。

ついに社会人になるのか、と思うと感慨深いものがあるので、今までなにをしてきたか・なにを思ってきたかを鮮やかに思い出せる間に書いておきたいと思う。

高校

高校は工業高校の情報技術を扱う学科だった。第 1 志望は高専で、それに落ちて第 2 志望のこの学校に行くことになった。高専では電気科志望だったのでそちらに行かなくてよかったと今では思っている。
高等教育機関ではないので当たり前だけど、高校ではコンピュータサイエンスというより、就職するために必要な知識を学ぶような感じだった。C 言語の文法を 3 年間かけて学び、ハードウェア・ソフトウェアともに浅く狭く学んだ。
一応プログラミング歴はその頃から始まっていたことになるけど、当時は Linuxコマンドラインといった環境も全く使っていなかったし、知らなかった。

大学

大学は会津大学という福島の公立大学に通っている。大学に行くということは、それだけで実家に負担がかかるので、公立かつ県内出身の人は入学費が半額になる会津大学を選んだ。工業高校から推薦を使わずに大学に行くということは、めちゃくちゃ難しくて、うちの高校ではセンター試験は受けない前提のカリキュラムなので当然普通科の高校生より圧倒的に学力が劣っていたと思う。会津大学の偏差値は高くないけど、自分も受験期は地獄を見た。

この大学は、コンピュータ理工学部しかないことで有名で、大学の規模は大きくないけど通っているすべての学生がコンピュータサイエンスを学んでいる。残念なことに、会津大学国公立大学の滑り止めに使われることが多く、落ちてきた人がかなりの割合を占めている。結構そういう人はコンピュータサイエンスを学ぼうという意識も低いように感じるし、そういった人に影響を受けやすい環境であることは間違いない。
ただ、毎年一定数異常にコンピュータに精通している人たちが入学しているので、そういった人たちと関わっていると良い刺激を受けることができると思う。

授業の質は普通という感じで、特に良いと思ったのはオートマトンと言語理論、言語処理系論、離散系論くらいしかなかった気がするけど、UNIX 環境があり、広く浅くコンピュータサイエンスを学べる大学は日本にはあまりなさそう。

ベンチャーアルバイト

会津大学発のベンチャーが市内には多くある。ただし、実際にはベンチャーではなくただの零細企業であるところがほとんどというのが現状な気がする。
それでも比較的まともな企業には大学の先輩が多く在籍していて、そういったところでアルバイトとして働くことで色んな技術的なことを教えてもらえると思う。
自分も学部 1 年から 4 年の春頃まで計 2 社の企業で働いていた。一社目は JavaScript (Node.js 含む) とか PHP とかを使う業務をいろいろやっていて、二社目ではバックエンドエンジニアとして Go で Web API サーバを書いていた。

ただ、会津大学のある会津若松市は他にコンピュータサイエンスの大学もなく、遊ぶ場所もなく、山に囲まれた良くも悪くも閉鎖的な環境なので気をつける必要がある。 大学に入ったばかりのときは、意識が高いのでどんな企業も魅力的に見えるけど、実際にはひどい企業もたくさんある。なにかおかしいなと気がついたらその会社はやめるべきだと思う。世の中にはたくさんの企業があり、わざわざ怪しい企業で働く必要はない。自分も辞めた。

今は学生ニートをしつつ、やりたいことをやってるような感じ。会津若松は、なにもないけど自然豊かで静かなので余生を過ごしている感が得られて便利。

インターン

インターンにもいくつか行った。ここで書いていない企業もいくつかある。

リクルート

2 年の時にインターンに応募した。実際には技術面接で落とされた。このときの評価は未だに納得がいっていなくて根に持っている。

はてな

3 年の夏。はてなは昔一番好きだった Web サービスを作っていた会社で、ここでインターンとして働けて本当に良かったと思った。
Scala や Angular を使って Mackerel の機能開発をがんばっていた。
詳しいことは別の記事で書いているのでそちらを。

syfm.hatenablog.com

Wantedly

3 年の夏、はてなインターン終わりの翌週から。2 年の冬頃に Wantedly に遊びに行ったことがあって、気になっていたのでインターンに参加した。
Go のバックエンドを希望していたのに、なぜか未経験の Rails を使っているプロダクトに入ることになった。
採用面接の技術試験は一番難しかった気がする。

Fringe81

3 年の夏、Wantedly の次に行った。ここは年齢層が割と高く他の Web 系の企業とは雰囲気が少し異なる。
ここでは DDD の戦術的設計を行うインターンをして、かなり悩んで苦しかったけどすごくいい経験になったのを覚えている。

就活要素

就活をするにあたって、ある程度内部が分かる企業を選ぼうと思っていた。 あとは、インターン先からも分かるように、Web 系企業を前提に考えていた。

大学

特に Web 系の企業に行きたい人の場合、大学の就職課は完全に当てにしないほうが良い。学部 3 年になると進路についての面談をさせられるけど、自分の挙げた企業名がほぼわからなかったらしく、適当な雑談をして終わった。
最近だと大学経由で一部のインターンを応募できるようになったらしいけど、レポートなりが必要で面倒なので自分で直接応募したほうが間違いなく良い。

交通

面接を受ける最低限の基準として、交通費を全額支給してくれるか否かというのがある。 自分みたいな地方の学生だと交通が悪かったり遠かったりで、東京への参勤交代は肉体的にも精神的にもかなり消耗することになる。 自分の場合だと、東京 ⇔ 会津若松 で、新幹線を使う場合は 3 時間、高速バスを使う場合は 5 時間ほどかかる。 一番多い時期だと週に 1 度は東京へ行っていたので、交通費支給 + 新幹線じゃないと金銭・肉体・精神がマッハで消耗されていく。
自分が面接を受けた企業からは、どこも交通費を支給していただいたので本当にありがたかった。

逆求人

逆求人にも一度行った。アカウントつくって、それなりにプロフィールを充実させておくと早い段階で逆求人の招待が来る。逆求人の開催時期が早いほど企業の質も良い気がしていて、自分が行ったときも興味のある企業ばかりだった。
ただ、異常に疲れるし二回目は一回目と被る企業も出てくるので一度だけ行けば十分だと思う。

資格

一応、就活が始まる前までに情報処理技術者試験の FE / AP / SC / DB を持っていたけど全く役に立たなかった。
そもそも、ソフトウェアエンジニアならこの程度の試験問題なら絶対に解けなければいけないと思って勉強していたので、自分もこれらを武器にしようと思っていなかったし、話題に出すこともなかった。

基準

自分の選んだ企業を選んだ理由はいくつかある。
一緒に働きたい人がいる、使っている技術・興味のある技術がある程度一致している、事業領域に興味があるといった点が大きいかなと感じる。
それぞれのインターンでメンターとなったエンジニアはどの方も本当に尊敬できて、そのたびに一緒に働きたいと思った。 メンターだけではなく、インターンの同期やアルバイト先の学生ともそう思ったときが度々あった。 正直かなり悩んだのも事実だけど、自分も他のエンジニアもずっと同じ企業に属するわけでもないのでいつか一緒に働けるときが来れば良いなぁと思っている。

まとめ

振り返ってみると、それなりに就活っぽいことをやっていたことに気づいた。

企業の性格を見たいならその企業で働いてみるのが一番良いと思う。一週間だと微妙だけど二週間くらいいると大体わかってくる。
自分は、自分の実力に自信が持てない性格なので、企業で働いているエンジニアは全知全能の神のような存在に思える。ただ、一緒に働いていると実は自分のほうが得意、知っている知識があったりして、こんなにすごいエンジニアでも人間なのかー。と実感することができると同時に頑張ろうと思えるようになってくる。

インターンに行くか否かっていうのは人の好き嫌いがあるのでどちらとも言えなさそう。研究や CS の勉強、OSS 活動のほうが好きであればそういうところに割いたほうが良いかもしれない。どちらにせよ、何かに打ち込んでいてそれを伝えられれば、ちゃんとした企業であれば評価してくれるはず。

あとは特に大きなイベントもなく、淡々と春になるまで雪に埋もれているだけなので、卒業できるように卒論がんばりながら、学生の間にやりたいことをやっておきたいなと思う。

技術書典 5 で Go & Kotlin 本を頒布します

技術書典 5 の「う11」で「Go & Kotlin Playground」というタイトルの本を頒布します。 以下のような本です。表紙は入稿 1 時間前につくりました。

f:id:ktr_0731:20181003230047j:plainf:id:ktr_0731:20181003230056p:plain
Go & Kotlin Playground

ホームページもつくりました。 gcf.syfm.me

割とニッチな章ばかりかなぁと思います。
自分は第 1 章「gRPC Web Internals」と第 2 章「やはり俺の Go アプリケーション設計はまちがっている。」を担当しました。

第 1 章で取り上げている gRPC Web は gRPC を Web ブラウザ上で使うための gRPC ベースのプロトコルです。
gRPC と比べて具体的に何が異なっているのか?実用的なものなのか?将来的な目的はなんなのか?そういったことに触れています。
また、gRPC Web プロトコルの実装である improbable-eng/grpc-web での通信を読み解いて、どういうリクエスト・レスポンスが行われているのかを覗いてみたりもします。

github.com

gRPC Web を触ったことのない人も興味があればぜひ手に取ってみてください。

第 2 章「やはり俺の Go アプリケーション設計はまちがっている。」は Go アプリケーションの設計に関する章です。 Go を書く時に、パッケージをつくるべきか?一つのパッケージにまとめるべきか?どういうパッケージ構成にするか?といったことに悩んだ方も多いかと思います。
この章では、Go アプリケーションを開発するときに、どういう方針で構築していけばいいかを Go の標準パッケージの特徴や、Go 自体の設計思想などから考えていきます。
この章は、先日行われた Go の学生コミュニティによるイベント、Student Go #1 で発表した内容です。

speakerdeck.com

ここでの内容をベースに、その時の発表で話せなかったことや、補足、文章の再構成を行っています。
「Go アプリケーション設計」と銘打っていますが、実際にはすべてのソフトウェア開発共通で言える設計原則なので、Go をあまり書いたことのない人でも設計に興味がある方はぜひ手に取っていただければと思います。

このサークルの出展は今回が初めてとなります。色々至らない点があるかもしれませんが、少しでも興味があったら、ぜひ立ち寄ってください!

techbookfest.org

GopherCon 2018 に Mercari BOLD Scholarship で参加・発表してきた

今年の 8 月 26 日から 9 月 1 日の間、Mercari BOLD Scholarship で Go 最大のカンファレンスである GopherCon へ参加していました。

tech.mercari.com

GopherCon 2018 は希望者のみ参加できるワークショップ、3 日間に渡って行われるトークセッション、最終日に行われるライトニングトーク (LT) や Go チームコミュニティにより行われる Go コントリビューションワークショップなどで構成されていました。その他にも Welcome Party などをはじめとする色々なイベントが用意されていました。 実際のスケジュールは以下のページから見ることができます。

www.gophercon.com

自分はワークショップを含む全ての日程に参加していました。以下では参加したワークショップと、特に興味深かったセッション、LT について書いていきたいと思います。

Pre-Conference Workshop: Testing

自分は Go のテスト手法に関するワークショップに参加しました。このワークショップの講師は Mat Ryer 氏で、stretchr/testify の作者です。
Testify は自分がテストコードを書く時に、非常に良く使っているライブラリです。Testify を作った方が、普段どのようにテストについて考え、どういったテストコードを書いていて、どういった思想で Testify を作ったのかが気になったのがこのワークショップに参加した理由です。

github.com

ワークショップの内容は非常に丁寧に作られていて、testing パッケージの testing.Ttesting.M について、go test の実行方法などの Go の初学者向けの話から始まり、Go のテストに関する基本的な知識はほぼ網羅されていたように思います。他のプログラミング言語とは異なり、基本的に Go はテストフレームワークを使わずにテストコードを書くため、このあたりの話は常に役に立ちます。また、一日でテスト技法を学べるくらいの仕様の小ささも Go の良い点だと思います。

基本的な内容にもかかわらず、自分が知らなかった機能や仕様も多くありました。 例えば、パッケージ名が foo のとき、そのテストコードのパッケージは同じ名前にする場合が多いですが、foo_test とすることができるという仕様です。このように変更すると、非公開な型、関数、変数へアクセスすることができなくなるため、ブラックボックステストを行うことができます。 自分は、公開された API の仕様をテストすべきで、非常に変化しやすいロジックには極力テストを書くべきではないと考えています。変化しやすいロジックに対してテストを書くと、そのテストは非常に脆いものになります。

他にも、スタブを書く時に、メソッドのシグネチャを表現した関数フィールドを用意することで期待するレスポンスを簡単に差し替えることのできるテクニックも紹介されていて、これは現在書いているテストでも非常に良く使っています。

例えば、以下のような key-value store のインターフェースが定義されているとして、

type KVS interface {
    Set(k string, v interface{})
    Get(k string) (v interface{}, ok bool)
}

スタブでは各メソッドと同じシグネチャを持つ関数フィールドを定義し、実装の詳細をそちらのフィールドの方で持つことで任意の実装を差し込めるようになります。

type kvsStub struct {
    set func(k string, v interface{})
    get func(k string) (v interface{}, ok bool)
}

func (s *kvsStub) Set(k string, v interface{}) {
    if s.set == nil {
        panic("set field is nil")
    }
    s.set(k, v)
}

func (s *kvsStub) Get(k string) (interface{}, bool) {
    if s.get == nil {
        panic("get field is nil")
    }
    return s.get(k)
}

また、このようなコードを自動生成する Ryer 氏自作のライブラリが紹介されていました。

github.com

テストの基本的な手法が紹介されたあとは、実際に簡単な Web アプリケーションに対してテストを書くハンズオン形式になりました。
この Web アプリケーションは、簡単な KVS で、値の書き込みは非同期で行われます。
Web アプリケーションはテストの実行時間を見積もるのが難しいものの一つです。
書き込んだ値が正しく取得できるかをテストしたい場合、まず第一に考えるのは、書き込んだあと一定時間 time.Sleep をしてから値を取得するような実装です。
しかし、 time.Sleep はブロックするためタイムアウトができません。データベースへの書き込みや読み込みにかかる時間は環境などにより左右されやすいので、適切にタイムアウトができなければいけません。
これを解決するためにチャネルと for + select を使ってタイムアウトを設定するテクニックが紹介されていました。

ticker := time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
timeout := time.NewTimer(5 * time.Second)
defer timeout.Stop()

var testErr error

for {
    select {

    case <-timeout.C:
        t.Fatalf("test timed out waiting for success.  last error: %s", testErr)
        return
    case <-ticker.C:
        testErr = test()
        if testErr == nil {
            // test successful
            return
        }
    }
}

その他にも、この Web アプリケーションのインテグレーションテストや、モックするためのテクニックなどが紹介されていました。
全体の流れとしては、愚直に実装した Web アプリケーションとそのテストはあらゆるコンポーネントが密結合しているため、それらを疎結合にしつつ、よりテストしやすくリファクタリングしていく、といった感じでした。

gRPC reflection and grpcurl

トークセッションでは "gRPC reflection and grpcurl" というセッションが面白かったです。
スピーカーの Joshua Humphries 氏 (GitHub: jhump) は gRPC クライアントのデファクトスタンダードである fullstorydev/grpcurl の作者で、GitHub の gRPC オーガニゼーションのメンバーです。また、自分が今回の GopherCon の LT で発表した gRPC クライアントを作るために必要不可欠だった jhump/protoreflect の作者でもあり、今回の彼の発表を非常に楽しみにしていました。

Humphries 氏が働いている FullStory 社では、サーバ間の通信に gRPC を使用しているそうです。また、各バックエンドサーバのアグリゲータとなるサーバがあり、ここの API エンドポイントは非常に変化しやすいものになっていました。
このサーバの API を叩くために CLI ツールを作っていましたが、API のインターフェースが変わるたびに修正・追加が入ったり、ほとんどすべての API へのリクエストが同じようなロジックになっていました。ここで、Humphries 氏は、動的に gRPC API を取得し、動的にリクエストを送信できないかを考え、protoreflect と gRPCurl が生まれました。

Go でも Protocol Buffers はサポートされていますが、JavaC++ 等とは異なり、 dynamic message (メッセージを動的に組み立てるための API) が提供されていません。
また、Protocol Buffers の descriptor (メッセージの構造を表す識別子) も限定的なサポートとなっていました。
彼が開発した protoreflect には、よりリッチな descriptor を提供する desc パッケージ、dynamic message を Go でも使えるようにするための dynamic パッケージが含まれています。また、同じく protoreflect に含まれる protoparse パッケージを使うと protoc へ依存することなく Protocol Buffers ファイルをパースできるようになります。

これらのライブラリと、 gRPC が提供しているリフレクション機能を使って gRPC サーバが提供している API を動的に取得できることを利用し、 gRPCurl が誕生しました。
gRPCurl は、curl と同じようなインターフェースを持つ gRPC クライアントで、前述の gRPC リフレクションと protoreflect を使うことで Protocol Buffers ファイルを読み込まずにサーバとやりとりができます。

自分がよく使っている protoreflect が、どういう目的で、どういう思想で生まれたかを聞くことができたので非常に興味深いセッションでした。

Lightning Talks

GopherCon では毎年 Lightning Talk (LT) 枠があり、開催直前に募集を募っています。
今回 GopherCon に BOLD Internship に参加するにあたり、その条件として LT 枠に応募することになりました。
時間帯ごとに募集枠が設定されていて、そのどこかの枠を選び、審査が通れば確定となります。
どういう LT をするか迷いましたが、自分がつくった gRPC クライアントの Evans について発表することにしました。Evans については春に開催された Go 1.10 リリースパーティーで発表していたので、その時の内容をベースに再構成することにしました。
LT は 7 分以内に収めなければならず、当然英語で喋らなくてはいけません。自分は英語のスキルが乏しいため、とにかく練習するしかない!と思い、限られた時間でスライドとトークスクリプトをつくり、そのあとはひたすら練習していました。
自分たちと同じく GopherCon に参加したメルカリの tenntenn さんと deeeet さんは GopherCon でトークをした経験があったため、二人に発表の際に気をつけることを聞いたりしていました。
また、LT 前日あたりからは tenntenn さん、deeeet さん、osamingo さん、morikuni さん、codehex さんの前で発表練習を行い、スライドの構成や話すスピードなどをチェックしてもらいつつ、安定して話すことができるようになってきました。

f:id:ktr_0731:20180913192522j:plain

LT の発表者へのいつ頃集合すれば良いかなどの連絡は口頭でしかないので注意したほうが良いと思います。自分の場合、余裕を持って 1 時間前くらいに会場入りをしたらすでに発表者席があり、ある程度のスピーカーが集まっていたので非常に焦りました。また、スタッフに自分が発表者であることを伝えると、マイクの準備をしてくれ、このときに PC のミラーリングの設定をしているかどうか聞かれますが、念の為ちゃんと確認しておいたほうが良いと思います。自分の場合、発表練習の際には確実にミラーリングになっていたにもかからわず、本番ではミラーリングが解除されていました…。(謎)

自分の発表の前には Brad Fitzpatrick 氏をはじめとするレベルの高い Gopher だらけで、自分の番が来る前はひたすら緊張していましたが、いざ始まってしまえば後は練習したことをやるだけです。英語が喋れなくても練習すれば喋りたいことは喋れるようになるし、スタッフの英語が聞き取れなくても英語が苦手なことを伝えればゆっくり喋ってくれます。発表したいという気持ちさえあれば、そういったことはどうにでもなると思います。
自分は人前で喋るのがあまり得意ではなく、非常に苦しかったのも事実ですが、終わってみればものすごい経験になったし、発表してよかったと心から思っています。

f:id:ktr_0731:20180913194537j:plain

今回のスカラシップでは、渡航費や一週間分の宿泊費がすべてサポートされていました。自費だと莫大な費用がかかるので、学生だと (社会人でも) 個人で海外のカンファレンスへ行こうとしてもなかなか難しいと思います。しかし、こういったスカラシップを利用することで学生のうちから非常に貴重な機会を得ることができます。
ぜひその機会を無駄にせずどんどん挑戦して欲しいなと思います!