POSTD PRODUCED BY NIJIBOX
POSTD PRODUCED BY NIJIBOX

ニジボックスが運営する
エンジニアに向けた
キュレーションメディア

2016年4月4日

プログラミング面接を突破する方法 (前編)

Ammon Bartram

本記事は、原著者の許諾のもとに翻訳・掲載しております。

本稿は本来、当サイト会員にお渡しする資料として作成したものですが、このたび公開することにしました。

プログラマとして腕が立つということが、その職で入社面接を受けた時の合否にどれほど影響するかというと、意外なほど重要性は低いのです。生産性の高いプログラマならば必ず、何週間も何カ月も広範囲に拡大し続ける問題を解決する力を持っているはずです。これに対して面接での質疑応答は、1つのトピック当たりせいぜい1時間です。そんな面接で成功するためには、緊張する中で小さな問題を素早く解決し、同時にあなたの考えを明確に説明しなければなりません。これはプログラミングとは異なるスキルです ^(1) 。まず断っておきたいのは、面接官の中には往々にして場慣れしておらず、どこか上の空な態度で求職者に接し(そういう面接官は面接よりもプログラミングがしたいのでしょう)、実際の業務とは全く無関係な質問をしてくる人がいます。そういう面接官は独断と偏見の塊で、客観的な視点は持ち合わせていません。

就職サイト「Triplebyte」を運営している立場として、私はこのことを強く実感します。私たちが、ベンチャーキャピタルであるY Combinatorから支援を受けるようなスタートアップ企業でエンジニアに面接する場合、話している間に履歴書を見ることはありません。直近の9カ月間に、私たちは面接で1000人のプログラマに会いました。私たちは極力実務的なプログラミングについて話すことを心がけ、求職者の評価方法について求職者自身に選択肢を幾つか提示して、その中から求職者が好むものを選んでもらっています。私たちは面接で、数多くの(非常に才能あふれる)プログラマと出会いましたが、学校などでコンピュータサイエンスを学んだことのない人も少なくありませんでした。そういう人々は、面接では散々な評価となります。広範囲に拡大する問題を収束させるのは朝飯前なのに、45分のアルゴリズムのテストを受けると立往生するのです。

ここで1つ朗報があります。面接は一種のスキルで、コツを身に着ければ上達できます。私たちには面接での上手な応対を求職者に伝授して成功した実績があります。実際に、当サイト「Triplebyte」の会員である求職者がスタートアップ企業の採用面接を突破した場合、その決め手となった資質は、純粋な才能というより熱意です。

私は本来、優秀なプログラマでも面接をうまく乗り切るためなら、面接のスキルを学ぶ必要があると考えているわけではありません。 しかし現実には必要なのです。そこで当サイト「Triplebyte」は、この現状を変えるための取り組みを続けています。私たちのその活動に興味を持たれた方はぜひ、 当サイトの活動をここからチェックしてください 。そして、真剣に面接のスキルを身に着けたいと考えている人のために、効率よく学ぶ方法を以下で説明します。

1. やる気をアピールする

意欲あふれる態度は、面接の評価に大きく影響します。当サイト「Triplebyte」会員の求職者で、面接の結果企業での採用を見送られた人のうち約50%は、不採用の理由が技術力以外のところにありました。企業の採用担当者がよく言う「当社の社風に合わない」という理由です。しかしこんな場合は十中八九、「社風に合う」とは、その企業の事業に対する熱意を求職者が見せた、という意味です。人材を募集する企業は、募集中の職務を是が非でもやりたい、という熱意を見せる応募者を求めています。この「熱意」を技術力に負けず劣らず重視する企業は多いものです。これは納得できます。やる気満々の社員なら進んで熱心に働くからです。

問題は、そんな採用企業の心理をくんで、熱意のあるふりをする求職者がいることです。どこの面接に出かけても毎回必ず「御社の募集ポジションは私にとって夢のような仕事です」とアピールし、全ての会社で面接官の心をつかむ求職者がいますが、その結果、他の者(本物の熱意の持ち主)が割を食う結果になります。私たちはそんな状況を何度も何度も見てきました。そこで、全ての求職者の皆さんに有効なソリューションは、熱意を見せるテクニックを磨くことです。これは「ウソをついても構わない」という意味ではありません。面接はいわばデートのようなものです。初めてのデートで、「あなたはたくさんいる候補者の中の1人に過ぎない」と相手に言われて喜ぶ人はいません。たとえそれが世の中の常であったとしても。同様に、プログラマは大抵、なるべく多額の給与を求めて、より有利な仕事を探すものです。だからと言って、面接でいきなり給与の希望額から話し始めるのは正しくありません。最善のアプローチは、その会社で働くことを自分がどれほど熱望しているか、面接で自分が言う予定のセリフを事前にまとめておくことです。そしていざ面接で「何か質問は?」と面接官に聞かれたら、その場の面接官全員に1人ずつ、その話題で語り掛けることです。セリフをまとめるときの参考資料として私たちが勧めたいのは、その企業の公式ブログの直近の記事やプレスリリースです。その資料の中で、自分が興味を引かれた部分をノートに書きだしてみましょう。

この対策は簡単そうに思えるでしょう。皆さんがこの記事を読みながらうなずいているのが目に見えるようです。ところが(面接官の経験を持つ人間として、確信をもって言いますが)実際にこれを実行する求職者はびっくりするぐらい少ないものです。その企業の職務をなぜ志望するのか、じっくりと時間をかけて自分の話すセリフをまとめると、面接の合格率は本当に上がります。志望理由をまとめたメモを面接会場に持ち込んで、それを見ながら話しても構いません。メモを持ち込むのは、「きちんと準備をして面接に臨んでいる」ことのアピールにもなります。

2. 面接で聞かれそうなトピックの知識を再確認する

面接ではかなりの確率で、データ構造とアルゴリズムについての質問が面接官から投げかけられます。良くも悪くも、それが真実なのです。スタートアップ企業の面接を受けたことのある、当サイト会員の求職者からの聞き取り結果を集計したところ(このデータを深堀りした分析は別の機会に記事としてまとめる予定です)、アルゴリズムに関する質問は、面接官が求職者に対して投げかけた質問の70%を占めるという結果が出ました。この分野のエキスパートになる必要はありませんが、アルゴリズムとデータ構造について、以下のトピックを確認しておけば、ほとんどの企業での面接に役立つでしょう。

  • ハッシュテーブル
  • 連結リスト
  • 幅優先検索、深さ優先検索
  • クイックソート、マージソート
  • 2分探索
  • 2次元配列
  • 動的配列
  • 2分探索木
  • 動的プログラミング
  • ビッグオー記法

皆さんが本来得意とする分野が何であるかによって、上記のリストはつまらないと思う人もいるでしょうし、恐いと思う人もいるかもしれません。しかし私たちは皆さんを動揺させたくて、リストを掲載したのではありません。上記の概念は、ウェブプログラミング開発の現場よりも、面接で非常によく尋ねられるテーマです。独学でプログラミングを身に着けたか、学校を卒業してから大分時間が経った人で、上記の概念についてあまり詳しくない場合は、この機に勉強すれば、皆さんの面接の評価が以前よりもぐっと上がるでしょう。一通り分かっているつもりでも再確認すると、面接に楽に臨めます。 面接で聞かれる頻度が極めて高い質問は、つまるところ幅優先検索またはハッシュテーブルを使って一意の要素を数える方法です。 手元にマシンがなくても幅優先検索を書く能力が必要です。また、ハッシュテーブルの実装方法についても理解しておかなければなりません。

上記のテーマについて学ぶのは、私たちが日ごろ接している会員の皆さんが恐れているほど、難しいことではありません。アルゴリズムは通常、学術論文のようなスタイルで記述されているために、その表現だけで敬遠してしまう人もいます。しかし実際のところ、上記のリストの内容よりも、現在利用されているモダンなウェブアプリのアーキテクチャの方がよほど複雑です。ウェブアプリを1本(まともに動くものを)構築してみれば、ここで私が書いたことが実感できるはずです。参考資料として私が勧めたい本は、Steven Skiena著『 The Algorithm Design Manual 』(アルゴリズム設計マニュアル)です。この本の第3章から第5章までは、このテーマを簡潔かつ明快に説明している、すばらしい参考文献です。C言語と数学的な構文を使っていますが、それでもこのテーマについては実に分かりやすく書かれています。またCourseraにも、アルゴリズムの優れたコースが幾つかあります。特に このコース は、面接でとても重視される概念に焦点を当てているのでお勧めです。

アルゴリズムとデータ構造について再度学ぶことをここで皆さんに勧めている理由は、面接で話題に上るテーマだからというだけではなく、アルゴリズムのコースで問題解決に当たる際のアプローチは、面接に応用すると非常に効果が高いものだからです。アルゴリズムをしっかり研究すれば、求職者である皆さんに向き合う面接官の気持ちが分かるようになるでしょう。

3. 面接官に手助けしてもらう

面接官は、求職者を手助けします。彼らはヒントを与え、アイデアに対して反応を示し、大抵、面接のプロセスを誘導します。しかし、全ての求職者を同じように手助けするわけではありません。 プログラマの中には、面接官からかなり手助けしてもらいながらも、そのことで不利にならない人もいれば、 ヒントをもらったことで厳しく評価されてしまう人もいます。誰でも手助けしてもらいたいと思うでしょう。

これは、プロセスとコミュニケーション次第です。あなたのプロセスが面接官に気に入られ、面接官とうまくコニュニケーションできれば、面接官は手助けしても構わないと思うでしょう。慎重なプロセスに従うことによって、そうなる可能性を高めることができます。推奨する手順は次のとおりです。

  1. 質問をする。
  2. 総当たりの解決法を詳しく説明する。
  3. 最適化された解決法を詳しく説明する。
  4. コードを書く。

面接で質問された後、質問されたことを明確にすることから始めます。これは知識をひけらかす時間です。思い付く限りのあいまいな点を全て明確にします。エッジケースについて質問しましょう。入力の具体例を挙げ、予想される出力が正しいことを確認します。ほぼ確実に質問の答えを知っている場合でも、質問をしてください。そうすれば、エッジケースを思い付き、問題を完全に特定する機会が得られるので有効です(エッジケースをどう扱うかを見るのは、面接官が面接で評価する際の主要な点の1つです)。また、問題を解決する前に、自分の考えをまとめる時間もできます。

次に、問題に対して考え得る最も単純な総当たりの解決法を詳しく説明しましょう。すぐにコーディングを始めるのではなく、まず説明すべきです。なぜなら、話すほうが早く先に進めるし、面接官の注意をより強く引き付けることができるからです。 面接官が関心を持てば、途中で話に割り込んで助言をしてくれます。 しかし、もしコードを書くことに逃げてしまうと、この機会を逃してしまいます。

求職者は大抵、問題に対する総当たりの解決法はあまりにも分かりきったことで、間違っていると決めてかかっているため、その解決法を省略してしまいます。これは間違いです。質問された問題に対する解決策をいつも必ず提示するようにしてください(たとえ指数関数的に莫大な時間や、アメリカ国家安全保障局のスーパーコンピュータ並みの演算能力が必要だとしても)。総当たりの解決法を説明した後、それを実装したほうがいいか、それとも、より効率的な解決法を考え出したほうがいいか面接官に尋ねてください。大抵、もっと効率的な解決法を考えて欲しいと言うでしょう。

より効率的な解決法のためのプロセスは、総当たりの場合と同じです。再び詳しく説明してください。コードを書いてはいけません。面接官にアイデアをぶつけて反応を見ましょう。うまくいけば、これまで経験したものと似たような質問をされるので、答えを知っているはずです。そうでない場合は、今までの経験の中から一番近い問題を考えて、面接官に提示すると効果的です。面接の質問のほとんどは、古典的なコンピュータサイエンスのアルゴリズムがわずかに隠された応用問題です。面接官は、よくこのアルゴリズムに誘導しますが、それはあなたがこのプロセスを開始した場合に限ります。

あなたと面接官の両方があなたには良い解決策があることに同意した後、最後に、コードを書くべきです。企業によっては、コンピュータを使ったりホワイトボードを使ったりします。しかし、既に解決策は考えてあるので、非常に簡単なはずです。追加点を稼ぐために、テストも書いたほうがいいかどうか、面接官に尋ねてください。

4. トレードオフについて話す

プログラミングの面接は、主にプログラミングの質問で構成されており、その内容は私がこれまでお話ししてきたとおりです。しかし、システム設計に関する質問をされる場合もあります。企業は特に、より経験豊富な求職者を採用するために、このような質問を好むようです。システム設計の質問では、求職者は、現実世界の複雑なシステムを設計する方法を尋ねられます。例として、Googleマップを設計する、ソーシャルネットワークを設計する、または銀行システム向けのAPIを設計するなどが含まれます。

まず注目すべきは、システム設計の質問に答えるには、ある程度の専門知識が必要だということです。明らかに、誰も実際に(多くの人と長い時間を要した)Googleマップを設計することなど期待していません。しかし、このような設計に対する見識があることを期待しています。うれしいことに、こういう質問は、通常、ウェブバックエンドに集中していることです。ですから、この領域に関することを読んで自分を大いに向上させることができます。理解しておくべき事柄の未完成リストは、次のとおりです。

  • HTTP(プロトコルレベルで)
  • データベース(インデックス、クエリプラン)
  • コンテンツデリバリネットワーク(CDN)
  • キャッシュ(LRUキャッシュ、memcached、Redis)
  • ロードバランサ
  • 分散ワーカシステム

これらの概念を理解する必要があります。しかし、もっと重要なのは、実際のシステムを構成するために、これらがどう組み合わさっているかを理解する必要があるということです。これを学ぶ最善の方法は、他のエンジニアがどのように概念を利用してきたかについて読むことです。 High Scalability というブログは、このためのすばらしい情報源です。実際の企業のバックエンドアーキテクチャの詳細記事が掲載されています。前述のリストの全ての概念が、実際のシステムでどのように使われているかを読んで知ることができます。

このブログを読み終えたら、システム設計の質問に答えられる知識は得たことになるので、次はプロセスが重要となります。最も概略的なレベルから始めて、詳細なレベルへと話を進めてください。それぞれのレベルで、仕様について面接官に質問してください(簡単な出発点を提案したらいいのか、それとも成熟したシステムがどのようなものであるかについて話したらいいのか? )。そして、オプション(前述のブログを読んで得たアイデアを適用して)も幾つか提示してください。設計上のトレードオフに関して議論することが鍵です。面接官は、設計自体が良いかどうかはあまり気にしません。それよりも、決断した事項のトレードオフ(プラス面とマイナス面)について話すことができるかどうかを気にします。これを実践してください。


  1. プログラミングスキルと面接でのパフォーマンスが関係ないというわけではありません。しかし、多くの会社が想定している以上に関係性は弱く、プログラミングスキル以外の要因がパフォーマンスに影響していると言えるでしょう。