ビジネススキルも問うことができるコーディング試験例（面接官向け）

# はじめに
これまで複数の企業でエンジニアの採用面接を担当する機会があり、のべ50人以上の方にお会いしてきました。
エンジニアの採用面接では様々な角度から候補者の評価を行います。評価手法のひとつとして、職務経歴書どおりの技術スキルと経験を実際に持ち合わせているかを計測するため、多くの企業と同様にしばしばコーディング試験を実施してきました。
この記事では私が出題していた設問のひとつを例に、コーディング試験を実施する際に技術力だけでなく、報連相やコミュニケーションなどいわゆるビジネススキルも同時に問うことができるようにするポイントをご紹介します。

# やりがちな失敗
コーディング試験を実施する面接官の立場として、もし縁あって候補者がジョインしたら主体的に周囲の協力を引き出しながらキャッチアップできるかどうか、自律的に同僚や顧客とコミュニケーションを取りながら業務を進められるかどうかといった点を当然評価しなければいけません。
にもかかわらず、面接官は次のような失敗をやってしまいがちです。
1. **知識だけを問う問題を出してしまいがち**
2. **一方通行になってしまいがち**

まず1.に関しては、ポジションに求められる最低限の知識は問われて然るべきですが、それがもし偏った分野の知識だと企業側が自ら候補者とのミスマッチ原因を作りに行くのと同じことになってしまいます。
例えば、ループを含むコードを見せて「この部分の計算量はどれぐらいか？」などを問う質問です。コンピューターサイエンス専攻や勉強した候補者であればいちどは聞いたことのある `O(n)`, `O(logN)` などオーダー記法を使って答えるのが模範解答ですが、実際の開発現場で「この部分はO(n)です」など会話することはごくまれで、ほとんどの人は必要なときに調べ直すことがほとんどはないでしょうか。
この他にも、特定の公式やアルゴリズムを知らないとまったく解けない問題を出すことも、同様の理由で避けた方がよいでしょう。

また2.も非常にやりがちなのですが、しばしば面接官が詳しい技術分野（多いのがアーキテクチャ系）から答えるのが難しい問題を候補者に問い、それを仮に候補者が答えられなかったときに解説を得意げにしてしまうといったことです。得意げな解説をしなかったとしてもピンポイントの知識を問うクイズのような問題を出して答えられなかったら「わかりません...」→「そうですか...」で終わってしまい知識の幅や広がりも評価できません。「これぐらいの知識を持っていなければうちの会社ではやっていけない」という思いを否定はしませんが、候補者とのマッチングの場である面接を一方通行なクイズ大会にしてしまい、双方のコミュニケーションが取れないのは好ましくありません。

こうした面接官が陥りがちなワナにハマらないよう、プログラミング問題やコーディング試験を実施する際は以下のポイントを意識することをお勧めします。

1. 知識だけを問う問題を出してしまいがち
→**基本的な知識を問う質問からはじめ、徐々に幅広く高度な内容も問う**

2. 一方通行になってしまいがち
→**質問力や相談力や論理理解力を問い、双方向コミュニケーションできる構成にする**

# 試験の進め方
前提として、使用するプログラミング言語は自由であり、対面面接ならホワイトボード等に、オンライン面接なら[Collabedit](https://collabedit.com/)などのオンラインエディターにコードを記述してもらうものとします。
また、10分など時間を決めて問題を解いてもらうというより、適宜会話をはさむインタラクティブなコーディング試験を目指すことにします。

# コーディング試験問題例
それでは、早速上記ポイントを踏まえた特に2.の候補者のコミュニケーション力を問うことができる設問の構成例をご紹介します。

```
問題：
ある数nとある数dを引数とし、nをdで割った余りを返す関数（メソッド）を書いてください。
ただし、除算演算子/や剰余演算子%を使用してはいけません。
```
いかがでしょうか？設問が単純すぎると感じるでしょうか？あるいはこれでどうビジネススキルを問えるのか不思議に感じるでしょうか？
ポイントは、この問題には多くの余白が残してあり、この後の問答で評価が行われていく点にあります。

# 質問力を問う
はじめに、面接官が問うべき質問は「**この問題について質問はありますか？**」です。
以下が期待される候補者からの質問例です。
- 「ある数というのは整数ですか？」
- 「main関数は必要ですか？」
- 「剰余演算子ってなんですか？」（新卒などの場合）
- 「剰余演算子がダメということは `divmod()` などもダメですよね？」（中堅・ベテランの場合）

このような質問が出てきたら面接官は喜ぶべきでしょう。なぜなら、候補者は不確定な問題設定を見抜き、あるいは自身の知識経験でわからないことを素直に相手に伝える力を持っていることが判明したからです。

:::note info
ポイント：問題にあえて余白を残し、質問力をチェック
:::

# 相談力を問う
次に面接官が期待すべきことは「**ヒントをいただけませんか？**」という言葉です。
`int func(int n, int d){ ... }` などメソッドの外形が整えられても、そこからペンが止まってしまう候補者の方はしばしばいらっしゃいます。面接の緊張や気負いから落ち着いて考えられないことも当然あるでしょう。
このようなとき、私は候補者からヒントをくださいと求められたら基本的にはポジティブに捉えています。もちろん、まったく考えるそぶりもなくヒントを求められたら考えものですが、実際にそのような方には一度も会ったことがなく、むしろ長考に入ってしまいそこから状況を打開できなかった方が多かったです。
実際の開発業務が始まった場合、同僚や顧客とコミュニケーションを取りながら、協力を引き出しながら主体的に業務を進めて行くことが必須となります。検討したものの、解けずに悔しいので面接中にヒントを求めたことは候補者のガッツ、エンゲージメントの現れであり、何より入社後も何かあれば相談してくれるだけのコミュニケーション力を持っていることの証拠と捉えられるのではないでしょうか。

:::note info
ポイント：助けを求める相談力があるかチェック
:::

# 論理理解力を問う
候補者の方の考えがまとまり、筆が動き始めたらいちど書くのを止めていただき、こう問いかけましょう：「**どのような方針で作っていくか概要を教えていただけますか？**」
ここで一発で「ループでnからdずつ引き算していき、dより小さくなったら抜けてその値を答えとして返します」と正解が返ってきたらそのまま記述を続けて頂きます。仮にあいまいだったり正解には遠い方針が返ってきたら助け舟を出して正解に近づくようヒントを出して誘導しましょう。
ヒントを出してすぐその内容を理解できたらプログラミング知識はあるけれど思いつかなかっただけですし、ヒントに対し自分の理解を述べたり質問が返ってきたらそれは加点対象にして良いでしょう。例えば、ヒントとして次のような言葉をかけます。
- 「10を3で割ったら余り1ですよね？これは3・3・3・1という風に10が分割されたと考えられます」
- 「こうした分割を実現するプログラミングの構造はなんですか？if文ですか？ループですか？」

このようなヒントを候補者がどう理解したか言語化してもらうことは論理理解力の計測につながります。

:::note info
ポイント：考え方を論理的に説明できる論理理解力をチェック
:::


# 徐々に幅広く高度な内容を問う
このプログラミング問題の「素朴な」正解は例えば次のようなコードです。
```Csharp:素朴な正解
public static int func(int n, int d) {
    while (n > d) {
        n -= d;
    }
    return n;
}
```
お気づきのようにこのコードはまだ不完全です。そこで、例えば次のような質問を行うことでコードの欠点について議論しながら幅広い知識を問うことができます。同時に、主体的にどのような仕様にするか提案する提案力のチェックにもなるでしょう。
- 「このプログラムは暴走しませんか？」
    - （暴走というあいまいな表現から問題を発見し、述べてもらう）
- 「dが0のときはどうしましょうか？」
    - ◎「ゼロ除算なので不能であり、それに相当する結果を返すか例外をスローする必要があります」
    - ◯「無限ループになってしまうのでエラーにする必要があります」
    - ✕「わかりません」
- このプログラムはnが0のときに正しいですか？
    - （0に限っては正しいが、負の数のときはその限りでない）
- nが負の数のときはどうしますか？
    - ◎「[負の数の割り算](https://sugaku.fun/negative-number-multi-divi/)を考慮するかどうかによって方針が変わってきます」
    - ◯「やはりエラーにした方がいいと思います」（自分の意見を述べているので）
    - ✕「わかりません」
- この機能のテストはどのような方針で行いますか？
    - （ソフトウェアテストの基本的な考え方、テストコード、境界条件、などについての知識を本例に絡めて説明していただく）
- もしnが非常に大きい数値でdが2の累乗のとき、高速化する手法があります。どのような方法でしょうか？
    - （ビット演算による[2のn乗の剰余](https://qiita.com/shr_em/items/e03d9a541c31edbee1d5)高速化などについて知っていれば話していただく）

:::note info
ポイント：エラー処理、テストなど幅広いソフトウェアの知識や提案力をチェック
:::

# まとめ
面接官が陥りがちな失敗とその回避方法を、具体的なコーディング試験を例に問答とチェックすべき観点を交えて紹介しました。
取り上げた例は剰余をループで計算するという非常に単純な問題であるにも関わらず、質問の構成を工夫することによって、幅広い知識を問いながらビジネススキルを評価できるようになることが理解いただけたと思います。
この記事がエンジニア採用面接の品質向上に取り組まれている面接官の方々のヒントになれば幸いです。また、面接を受ける方々にも企業がエンジニアに求められるビジネススキルとはどのような観点であるかの一例として参考になれば幸いです。

# 参考
- 負の数の掛け算・割り算
 https://sugaku.fun/negative-number-multi-divi/
- %(剰余)の最適化について
 https://qiita.com/shr_em/items/e03d9a541c31edbee1d5