エンジニアのスキルの分類と習熟度について

メリークリスマス！24日に割り当てられていることをすっかり忘れてて、焦っています(ﾉ￣□￣)ﾉ

最近、社内のエンジニアのスキル標準の作成をしていて、詳細はそのうち [nrk_baby](http://qiita.com/nrk_baby,"nrk_baby") がきっと書いてくれると思うので、これまでもやもやと思っていた"エンジニアのスキル"についてまとめてみたいと思います。

前段はスキルの分類について、後段はスキルの習熟度について書いてます。

# 想定読者
このエントリーは、以下のような人を対象にしています。

 - エンジニアのスキルって何があるんだろうと思っている人
 - スキルの評価基準について悩んでいる人

「スキルがある/ない」ってとても曖昧な表現ですが、仕事をしていると明確にスキルがある人とない人がいますね。できる人を正当に評価し、できない人は一歩でもできる人に近づくために、まずはどのようなスキルがあるのか、スキルの段階って何があるのかを整理する必要があると思っています。

# スキルの分類
エンジニアのスキルと一口に言っても色んな分類がありますね。まずどのようなスキルがあるのかを整理してみたいと思います。
自分なりにスキルの分類を大きく分けると、以下のように分かれるのかなと思います。

 - 機能
 - 非機能 
 - 企画
 - 設計
 - テスト
 - プロジェクトマネジメント

## 機能・非機能の実現
システムに求められる機能を構築するために直接的に必要なスキルで、プログラミング言語を用いてプログラムを書いたり、インフラを構築したりすることが相当します。

 - プログラミング言語 (C#, Java, PHP, Ruby, Python, HTML, CSS ...etc)
 - データベース (MySQL, PostgreSQL, Oracle ...etc)
 - インフラ、OS、ミドルウェア、ネットワーク

機能の実現だけでなく [非機能要件](https://ja.wikipedia.org/wiki/非機能要件) を満たすためのスキルやナレッジも必要で、例えばセキュリティや運用監視のスキルは機能の実装スキルとはまた毛色の異なるスキルだと思っています。

 - セキュリティ
 - 運用監視
 - 冗長化、障害
 - パフォーマンス

## 企画、設計、テスト
システムの構築だけでなく、そもそもどのようなものが求められているのか、ユーザーにとって価値あるものは何かを考えることも、エンジニアにとって一定は必須のスキルだと思っています。
更にユーザーの要望をシステム要件に落とし込み、全体のアーキテクチャを考えて各要素の設計に落とし込んでいくことが必要ですし、作ったものの品質をシステム的視点、ユーザー的視点の両面で保障するためのテストを実施する必要があり、それぞれに求められるスキルが異なります。
(この辺は話すと長くなるので、今回はかなり割愛…)

## プロジェクトマネジメント
直接的にシステムの構築に寄与するものではありませんが、システム開発は基本的にプロジェクトであり、プロジェクトマネジメントが必須です。世のエンジニアはなぜかマネジメントというものに抵抗感を示す人が多いですが、一定は必須のスキルだと思っています。
全くマネジメントに対しての知見がない人が一流のエンジニアになれるとは到底思えません。

# スキルの習熟度
開発をしていると、ある技術について「知っている」という状態と「使える」という状態には、隔たりがあることに気づかされます。また単に「使える」という状態と「使いこなせる」という状態にも更に大きな隔たりがあるように思います。

「～～について知ってはいるけど、使えるかと言われると自信ないな・・・」
とか
「○○は一応使えるけど、本当に使いこなしている人からするとまだまだだな」
とか
よく思います。

## 知っているという状態
「知っている」という状態は、単にその領域についての**「知識を持っている」**という状態です。
知識を得る為には

 - 本を読む
 - Webの文献を読む
 - 人に聞く

などの方法があります。種々の文献から情報を収集するだけでなく、必要な場面で引き出せるように自身の中に構造的に記憶しておくことが必要だと思います。

ただ、エンジニアは持っている知識を駆使して課題の解決することが求められる為、「知っている」という状態だけでは不十分なことがほとんどですね。

## 使えるという状態
「使える」という状態を定義するのは難しいですが、**「知識を適用すべき課題や状況および適用方法を理解し課題を解決できる」**ということでしょうか。

「使える」状態に至るためには単に知識を持っているだけでは不十分で、「いつ、どのように」知識を適用できるのか、具体的なイメージを持っていることが重要だと思います。
「ここでああしてこうして…ここをこうしたら……できるな」みたいなイメージをパッと思いつけるかどうかですね。

多くの場合、その技術の適用方法についての基本パターンみたいなものがあるので、まずは基本パターンを抑えておいて、そのパターン通りに使えるようにするというのが一般的な気がします。チュートリアルをやると一応使えるようになるというのがこれでしょうか。

## 使いこなせるという状態
「使いこなす」という状態は更に表現が難しいですが、「使える」という状態で更に以下のようなことができるイメージです。

 - 技術を構成する要素や内部構造までも理解した上で、できることできないことの判断ができる
 - 利用頻度の低いパターンを含めて、多くの活用パターンを熟知している
 - 複合的な事項(非機能面、開発以外の要素)を考慮して、最適解を提案できる

 *「これはそもそもこれ使ってでできるんだろうか…」*
 *「これってやろうと思えばできなくはないけど複雑になるし…本当にこのやり方でいいのかな？」*
 *「同じことを実現するのにいくつか方法があるけど、色々考えるとどのやり方がベストなんだろう？」*

この辺りの問いにパッと答えを出せるかどうかが肝な気がしています。

# どうすればいいのか
で、あーだこーだ書いたものの、どうすればいいの？という話ですが。

よくTの字やπの字(どこかでNの字というのも見かけました)と言われるように、基本的に全ての領域について「知っている」という状態でありつつ、特定領域の専門性を持っているという状態がベストだと思います。
システムが複合的な要素の集合体であることとシステム開発が複数工程で成り立っていることから、自分ひとりの作業で完結するものは一切なく、他の領域との関係性を把握していなければパフォーマンスを発揮することはできません。それに「使いこなせるという状態」のところで書いたように、複合的な要素を考慮することができなければスキルも一定以上は向上しないはずですね。

その為に自分としては

 - 常に広くアンテナを張っておくこと
 - 自分の知らないことに積極的に興味を持つこと

は常に意識するようにしています。
特にエンジニアの人はある領域をマニアックに突き詰めたくなることが多いのではないかと思うので、自分が興味がないことについて、積極的にアプローチする姿勢が一層必要だと思います。


スキルの習得については、結局やってみるしかないと思います。
自分の場合は、

1. 基礎的な書籍とWebの文献を読んで一通り理解する
2. とりあえずやってみる。(チュートリアルとかあるならやってみる)
3. 中級の書籍とリファレンスを漁って知識を体系化する

みたいな感じで進めることが多いです。
頭で理解したつもりでも、自分で手を動かして頭を悩まさないことには結局よくわからんな、と思ってしまいますね。
ただ自分でやるだけでは接する情報も狭く我流になってしまうので、一通りできるなと思ったら再度書籍で知識体系を補強しにいきます。

# おわりに
なんかうまくまとまらずに終わってしまった。最近ますます文章力が落ちている気がする…

皆さん、今年のクリスマスはどうでしたか？
今年も残りわずかですね。良いお年をお迎え下さい！