自分を攻略していく記録

自分がやりたいことを達成するには何をすればいいのか、その攻略していく過程をつらつらと

シンガポールのGO-JEKとGrabのエンジニア求人を受けた話

はじめに

11~12月あたりにシンガポールのGO-JEKとGrabのiOSエンジニア求人を受けてみたのでその時のことを書いていく。これらはそれぞれインドネシアシンガポール発のユニコーンである。

f:id:ngo275:20181231211330p:plain:w400
GO-JEKとGrab

シンガポールのエンジニア転職情報はまだまだ少ないが、アメリカに比べビザも圧倒的に取りやすいしアリだと思う。

結論は、GO-JEKとGrabではない、他のアーリーステージのスタートアップ※にジョインすることにしたので、GO-JEKは後半の方で辞退、Grabは普通に途中で落ちた。

※ ここでは触れていない会社です。

英語やビザの話はここでは触れずに、実際にどういうことが聞かれたのか日程感はどんな感じなのか、という話にフォーカスする。海外で働いてみたいけど面接ってどんな感じなんだろう、どういう準備をすればいいのだろうという人の参考になれば良いなと思う。LinkedInのプレミアム機能で、求人に応募している人がどのエリアから来ているのか見ることができるのだが、インドからの応募がめちゃくちゃ多いのが分かった。シンガポールの求人に対して一番応募しているのがインドなことが多い。日本からもっとガツガツそういうところに出ていく人が増えるといいなと思った。

TL;DR

  • 英語はコミュニケーションできるくらいには必要だけど、営業できるレベルまで求められない。
  • アメリカ英語のような慣れ親しんだ英語ではないと思ったほうが良い。
  • 時間がかかる。平気で1ヶ月とかかかる。シンガポールに限った話ではないと思うが、思ったより時間がかかるのだなと実感した。面接はどれも平日の日中に行われたが、正社員で働きながらだとかなり大変そう。
  • アルゴリズムというよりは、アーキテクチャやテストといった実践的なことが重視されているように感じた。

GO-JEKを受けた記録

⬇参考までに、ここに一般公開されているGO-JEKの採用フローが書いてある。

blog.gojekengineering.com

11月中旬 応募する

LinkedInの求人からGO-JEKの採用ページに飛んで、そこで自分でペイメントのiOSエンジニアを応募してみた。

Resume(履歴書)はこのサイトで作成した。ちゃんと作っておくべき。

11月23日 最初の返信が来る

応募の返信が23日に返ってきた。応募してから返信が来るまでに一週間もかかってないとは思うが記録がなくて正確にはわからない。

Hi Shuichi,

Greetings from GO-JEK Group! I was hoping I could set up a 30-minute call between you and our team, to discuss the opportunity a bit. Would you mind letting me know some times you're available over the next few days?

We usually have the call through Google Hangouts / WhatsApp call, but kindly let us know if you have preferences.

We're looking forward to speaking with you. 

軽く30分くらいコールしましょう、ということだったので、いついつが開いてるよ、と20分後に返信した。

その日のうちに、Googleカレンダーで招待が来て27日にコールすることになった。

11月27日 最初のコールをする

エンジニアではなく採用担当と思われる女性の方とコールをした。お互い自己紹介をした後、会社や求人のポジションの説明を受けた。それに関して質問をしたり、という感じ。これで落ちることはないと思われる。

この後、2日間かけてやってほしい課題を送るので時間を確保できる時にメールをしてくれ、と言われた。多分何かを作る課題だろう...。

11月30日 技術課題を行う

この日とその翌日はまるまる時間が確保できそうだったので、朝9時半過ぎに、課題を送ってくれと催促した。その30分後くらいに以下のような返信が来た。

Hi Shuichi,
Good morning, thanks for the reminder. 

Before we move forward to the next process, allow us to present you with a challenge. Please find attached in this e-mail a problem statement for you to solve.

...中略

Ideally, it should take you 2 days to solve this. So if you can send it to us no later than Sunday, 2 December 2018, we would really appreciate it so that we can begin the review process faster. 

Please let us know if you have any urgent matter and need more time for complete the test or have any question regarding the test. We will be more than happy to help you out.
Can't wait to see your great work. 

添付されていたPDFに仕様とデザインが書いてあり、それに従ったアプリを作る、というものだった。その仕様やデザインについてはここでは伏せるが、iOSアプリを好きにMVVMなりMVPなりで設計して実装、それに関連してUIテスト、ユニットテストを書きなさいという感じ。APIについては彼らがHerokuで立てたものを利用する。

2日間でこれを実装できる人いるのか?という量だったが、とりあえずざっくりと機能を実装して、QuickNimbleを使ってドメイン周りとバリデーションに関してユニットテストを書いた(UIテストは画面数も少なかったので気持ち書いたくらい)。時間が足りず、デザインは一部断念した箇所もあったが、12月1日の日付が変わる頃(12月2日の0時過ぎ)にメールで提出した。

機能で言うと一応仕様通りにできてはいるが、デザインが一部当てれていなかったり、実装ミスでネットワークエラーの表示がうまくいかない状態だったので少々不安...。

12月7日 技術課題の結果が来る

コードを提出したのが土日で、コード見るから少し待っててね、と3日月曜の朝に言われて、7日にメールが来た。技術面接に進むので日程を教えて欲しいということだった。どうやら技術課題はパスしたらしい

この後、技術面接の日程調整の連絡をして11日に行うことになった。

技術面接はしたことがない + 馴れない英語での説明、ということだったので以下のようなリンクを参考にして勉強をした。

Glassdoor

Glassdoorというサイトで他の人が実際に受けた面接内容とか色々見れる。

ソートや探索のアルゴリズム

このGitHubのリンクがiOSエンジニアのアルゴリズム勉強には最強だと思う。クイックソートバブルソートの実装、バイナリツリーの実装など良く耳にするアルゴリズムはできるようにしておいた。このリンクにはたくさんの情報が載っているが、その中でも聞いたことあるが不安というところだけ確認した。

iOS開発について

iOS自体のライフサイクルと、ViewControllerのライフサイクルは以下のリンクで確認した。なんとなく分かっていたが、英語でちゃんと説明はできなかったのでいい復習になった。

以下で、普段なんとなく利用しているパッケージマネージャについても一応確認しておいた。Static LibraryとDynamic Libaryの違いとか。

12月11日 技術面接のコールをする

シンガポール人とインドネシア人がそれぞれリモートで参加して自分を含めて3人でコールをした。英語はシンガポールなまりとインドネシアなまりで結構辛かった。

以下iOSエンジニア前提で質問されたこと

日本語で見ると普通の内容に見えるけど英語でやると結構難しく感じた

  • 参照型と値型について教えて
    • 変数がポインタであるか、値そのものを持つか。たとえば、クラスは参照型なのである箇所で中身を変更すると、同じモノを参照している他の箇所の変数の値が変わってしまう。一方で、構造体は値型なので同じモノを参照していた他の変数に何も影響がない、的な話をした。Reference type just has its reference, while value type has value itselt instead of reference. みたいな英文になってしまい説明になってなくね?って自分で思って少々焦り、クラスと構造体を引き合いに出して説明した。
  • 強参照・弱参照について教えて
    • 強参照はReference Counterにカウントされるが、弱参照はカウントされない。ViewControllerがお互い参照する時は、弱参照を使わないとお互い参照しあってメモリリークする、みたいな話をした。
  • 先の技術課題で採用したアーキテクチャ(ここではMVP)について説明して
    • Viewはユーザからのイベントを受け付けてPresenterに伝え、Presenterからの通知を受けて描画する。重要なのはロジックを持たないようにすること。PresenterはUIロジックを主に担当する。ビジネスロジックは持たないようにして、必要に応じてモデルに処理を移譲する。Modelはビジネスロジックを主に担当し、API通信や端末のキャッシュアクセスとかはこの階層で行う。といった説明をした。
  • クリーンアーキテクチャの経験あるならそれについても教えて
    • MVPの特にモデルについてUseCase、Repository、Datastore、Entityと細かく分けることによってそれぞれの責務を明確にした感じ。UseCaseはビジネスロジックに集中し、データアクセスの詳細については関与しない。こうすることによって、モック化しやくなり、ビジネスロジックについてのユニットテストが容易になる。というフワッとした説明をした。
  • クリーンアーキテクチャでデータはどう扱うの?(具体的にどう聞かれたかは覚えていない...)
    • domain層からpresentation層にデータを渡す時はトランスレータを噛ましてUIが扱いやすいように変換する。また、APIからのデータはEntityを使ってマッピングするが、Entity自体はメソッドを持たないただのイミュータブルなオブジェクトとして扱う方が好き、という話をした。
  • (先の技術課題のコードを見ながら)この部分(Presenterが保持しているModelをセットする関数をPresenterのinit以外で実行可能になっている箇所)の意図を教えて
    • イニシャライザ以外で変更可能なのは嫌だったけど、Presenterについてのユニットテストを書く時にモデルのモックをセットする用にやむを得ずそうした。時間があったらそこの部分を直したかったんだよね。と話した。時間的制約から仕方がない、と思ってさぼっていたところを突かれた。コメントくらいつけておけば良かった。
  • (先の技術課題のコードを見ながら)この部分(Protocolで重複している箇所)をBaseProtocolみたいにして抽象化するのは考えなかった?
    • 可能ではあるけど、Base〇〇という親クラスみたいなものを作る方針が好きじゃなかったからそうしなかった。重複量が多いなら考えるけどここはそこまで大きくならないところなのでこのままにした、これは好みの問題かもしれない、と話した。
  • (先の技術課題のコードを見ながら)この部分(PresenterやModel用にそれぞれProtocolを宣言している箇所)の意図を教えて
    • PresenterやModelに対してユニットテストを書く時に、Presenter・ModelのProtocolを採用したモックを使うことで、ユニットテストを簡潔に書けるようになるから。DIをしたかった。という回答をした。

一部覚えていないが概要としては上記のような感じだった。自分の回答に対して深ぼるような感じだった。ここではライブコーディングはなかった。

こっちから質問したこと

  • ストーリーボードは使う?使わない?
    • これは本当にチームによる。ストーリーボードを使わないところもあるね。
  • 開発スタイルはアジャイルなの?
    • そう、チームによるけど俺は2週間のスプリントだよ。
  • タスク管理はどうしているの?
  • デザイナーとはどういうコミュニケーションをするの?
    • (たしかZeppelinでもらってやってると言っていた気がするが、)とりあえず普通だった記憶だけある。
  • 2日間の課題って結構仕様重かったけどみんな終わるの?

あとは少し雑談をしつつ計1時間弱のコールで終わった。

12月12日 技術面接の結果が来る

技術面接の結果に関するメールが来た。パスしたようだ。

そして次の技術面接のラウンドを行うから開いてる日を教えてくれ、と。技術面接はあと1~2回あるらしい。長い...。この時点で最初に応募してからすでに一ヶ月が経とうとしている...。

12月18日 技術面接2ラウンド目を行う

ネットの調子がめちゃくちゃ悪かったのと家のすぐ隣で工事をしていて騒がしかったこともあり、開始して10分程でリスケすることになった。

この時の相手はインド人2人だったのだが、マジなインド英語は初めてだったので最初ホントに何を言っているのか分からなかった。

10分程度だったが、質問されたのはこんな感じ。

  • UIのライフサイクルについて教えて
  • 描画の流れについて説明して
  • UIWindowとUIViewの違いは
  • LayoutIfNeededの呼ぶタイミングは?

前回と違って今回はライブコーディングもあるようだったがネット環境がひどすぎてその前に終了した。

辞退の連絡

他で並行していたスタートアップからオファーをもらっており、そちらに行くことにしたので、リスケの日付が確定する前にGO-JEKの方を辞退することにした。小さいスタートアップを選ぶことにした。

Grabを受けた記録

11月28日 応募する

Stackoverflowで見かけてGrabのiOSエンジニアの求人に応募してみた。

12月4日 最初の返信が来る

完全に忘れた頃にメールが来て、とりあえずコールをするので開いてる日を教えてくれという趣旨だった。その2日後の12月6日にコールをすることになった。

12月6日 軽いコールと技術課題と行う

お互いの自己紹介とポジションの説明とかとりあえずそんな感じのコール。GO-JEKの時と同様に軽い感じのコールだった。

その後にコードテストのリンクを送るからやってみて欲しいとのこと。

Codilityというサイトで行う。

app.codility.com

ちょうどこの日は時間があったのでそのまま受けてみた。

Swiftを使って、設問があってその条件を満たすコードを書く、というもので2問で制限時間は45分だった。GO-JEKより全然軽い課題だったが、2問目が意外と難しくて途中で力尽きた。簡単な引数だとうまくいくけど、エッジケースではfailする感じの出来栄え。

12月7日 技術課題の結果が来る

普通にできなかったから終わりかと思っていたが、次の技術面接に進む、というメールが来た。こちらの予定の確認なしに13日にカレンダーの招待が来ていた。まあ空いてたわけだけど。

12月13日 技術面接をする

技術面接の案内のメールにTipsに関するYouTube動画のリンクが張ってあった。

www.youtube.com

技術面接の所要時間は、1時間のラウンドが2回で計2時間でアルゴリズムについてと、iOSドメイン知識についてだった。

アルゴリズムについて

  • バイナリツリーのdepth(heightだったかも)の算出方法を教えて
    • ここにあるのを思い出しながら、自分の下に何もノードがない時は1を返して、下にノードがある時は、左側と右側のノードで大きい方と1を足して返す関数を再帰的に呼ぶ、と答えた。
  • [ライブコーディング] じゃそれを実装してみて
    • 以下のように答えた記憶はあるけどdepthとheightを間違えて答えたかもしれない。ちなみに以下のコードはdepthではなくheightの実装。
class BinaryTree {
  var left: BinaryTree?
  var right: BinaryTree?
  var parent: BinaryTree?

  func height() -> Int {
    if left == nil && right == nil {
      return 0
    } else {
      return 1 + max(left?.height() ?? 0, right?.height() ?? 0)
    }
  }
}
  • その計算量はどれくらい?
    • n個のノード全部を走査するからO(n)、と答えた。
  • [ライブコーディング] バイナリツリーのdiameterの実装をしてみて
    • diameterとは、あるバイナリツリーにおける最長距離のことらしいが、初耳だった。あるノードを取った時に左サイドのノードのheightと右サイドのノードのheightを足した値を各ノードで計算しその値が最大の時に最長経路になる、と答えてその実装をした(ここでは厳密に覚えていないので割愛)。でもそうすると計算量が非常に大きくなってしまうよね、という指摘をされた。それに対してどう対応するのかを見られたが、明らかに小さいものは計算しないようにしたいけど具体的な計算方法はその場で実装できない、といった感じだった。

iOSドメイン知識について

  • strong、weak、unownedについて教えて
    • strongはReference Counterにカウントされるが、weakとunownedはカウントされないのでweakとunownedはすぐ解放される。weakは解放されるとnilを返すが、unownedは解放された状態でアクセスするとクラッシュする。と説明した。
  • Retain Cycleについて教えて
    • 恥ずかしながらこれについては英語で分からなくて、ちょっと分からないと返してしまった。循環参照のことだった。Circular Reference的な名前だと思ってたからなんだろうってその場で困ってしまった。循環参照も知らないやつってなってしまったかもしれない...。
  • DIについて教えて
    • コード自体を抽象化しておいて、外から変数とか具体的なものを注入すること。これによってテスト時にモック化が容易になるというメリットがある。と答えた。
  • [ライブコーディング] セクションヘッダーにFruit、Vegetable、Drinkのラベルを入れてそれぞれのセクションには["Apple", "Banana", "Lemon"]、["Carrot", "Lettuce"]、["Beer", "Water", "Tea"]のラベルをUITableViewで描画する時の実装をして
    • 以下から書き始める感じ。正直細かいメソッド名( func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { )とかは覚えていなかったので、うろ覚えで進めた。IDEじゃなかったので補完が一切ない環境でのコーディングだった。普段Xcodeを使っていると、補完で細かいメソッド名までは覚えていない人が多いだろうし、間違っていてもXcodeが教えてくれるが、ここではそれがなかったので何をテストしたかったのかイマイチピンとこなかった。とりあえずオーソドックスな実装をした。
struct Fruit {
  var data = ["Apple", "Banana", "Lemon"]
}
struct Vegetable {
  var data = ["Carrot", "Lettuce"]
}
struct Drink {
  var data = ["Beer", "Water", "Tea"]
}

class ViewController {}

12月17日 技術面接の結果が来る

結果はダメだった。循環参照知らないって言ってしまったくらいだから仕方ないと思おう。

まとめ

  • 英語はコミュニケーションできるくらいには必要だけど、営業できるレベルまで求められない。
  • アメリカ英語のような慣れ親しんだ英語ではないと思ったほうが良い。
  • 時間がかかる。平気で1ヶ月とかかかる。シンガポールに限った話ではないが、思ったより時間がかかるのだなと実感した。面接はどれも平日の日中に行われたが、正社員で働きながらだとかなり大変そう。
  • アルゴリズムというよりは、アーキテクチャやテストといった実践的なことが重視されているように感じた。

とにかくインド人はこういった戦いをひたすらしており、日本人ももっとチャレンジする人が増えるといいなと思っった。