開発、テスト、運用を問わず、すべての技術者には多かれ少なかれ技術の達人になりたいという夢がある。「夢は持つべきだ、叶うかもしれないからね」ということだ。技術への夢の追求こそが、私たちを絶えず努力し、自分を高めさせているのだ。


しかし「夢は美しく、現実は残酷だ」。多くの人は実際に働き始めると、夢は達人になることなのに、やっていることは達人とは全く関係ないように見えることに気づく。例えば、プログラマーは「毎日業務コードを書いて残業までしているのに、どうすれば技術の達人になれるのか」と言い、テスト担当者は「毎日やり切れないテストケースがある」と言い、運用担当者は「サーバーを運び、ケーブルを繋ぎ、shellコマンドを叩く。こんな運用人生は望んでいない」と言う......。知乎にも似たような質問「毎日業務コードを書くプログラマーは、どうすれば技術の達人になり、技術コードを書き始められるのか?」があり、フォロワーは6K以上、回答は120以上あった。当時私も回答し、最も多くの「いいね」を獲得した。その後、キャリアの等級昇進の面接評価やコミュニケーションを行う中で、新たな発見や考えが生まれ、体系のに記事をまとめたいと思った。より多くの人が技術の達人への道で遠回りを少しでも減らせるようにしたい。


私はプログラマーなので、以下の例はソフトウェア開発に基づいているが、根本的な道理は共通しており、テストや運用の担当者も参考にできる。


いくつかの典型的な誤解


1. 達人を師と仰ぐ


知乎では、技術の達人になる最も簡単で直接的かつ迅速で効果的な方法は「チームの技術の達人を師と仰ぎ、彼らに普段から特別に指導してもらい、難易度の高いタスクを割り当ててもらうこと」だと考える人もいる。


私は個人的にこの方法には反対だ。主な理由はいくつかある:


  • 達人は忙しく、あなただけに特別指導をする余裕はまずない。ましてや毎日1時間の特別指導などあり得ない。また、チーム内で達人があなたに頻繁に特別指導をしていたら、他のチームメンバーの疑惑を招くのは避けられない。私は、チームの達人が本当にその気があるなら、チームへの研修を増やすのが最善だと思う。しかし研修を行ったことがある人なら分かるだろうが、研修の準備は非常に時間がかかる。教材と資料だけで少なくとも2時間(しかも断片的な時間ではだめ)、説明に1時間。達人たちが月に1回研修を行うだけでも、すでに頻度が高い方だ。
  • 最初の理由から、達人に会う必要がある場合は、たいてい問題を抱えて教えを請うか議論することになる。質問や議論に答えるにはそれほど時間は必要なく、むしろ経験と蓄積に依存するからだ。そういう場合、達人たちは喜んで応じてくれる。影響力は達人にとって重要な指標だからね。ただし、特に注意すべき点がある。本やGoogleですぐに調べられるような知識を頻繁に尋ねると、達人たちもひどく不機嫌になる。時間は貴重だからだ。よくネットユーザーから「JVMの-Xmnパラメータの設定方法」のような質問を受けるが、私はいつも「直接Googleで検索してください」と答える。なぜなら、そういう質問はあまりにも多すぎて、自分で体系のに学ばずに毎回人に聞いていたら、自分と相手の時間を大幅に無駄にしてしまうからだ。
  • 達人は多くない。すべてのチームに技術の達人がいるとは限らない。せいぜいチームの中に自分よりレベルの高い人がいる程度だ。仮にその人が毎日特別指導してくれたとしても、最終的に自分の実力はその人の水準までしか上がらない。一方、チームをまたいだ技術の達人の場合、仕事の割り当てや体制の都合上、直接教えを乞い指導を受ける機会は比較的少ない。達人の研修に何度か参加しただけで技術の達人になれる可能性は低い。

以上の理由を総合すると、ほとんどの人にとって、技術の達人になるには、まず「主に自分次第」という道理を理解すべきであり、武術の師匠のような達人が一から十まで手取り足取り教えてくれることを期待してはいけない。適切なタイミングで達人に教えを乞い、達人と議論することで自分を高めることはできるが、大部分の時間は自分で体系的かつ的を絞ってレベルアップしていくべきだ。


2. 業務コードも同じようにすごい


知乎の回答には、業務コードを書くことも同じようにすごくなれる、というものがある。その理由は、業務コードにもさまざまなテクニックがあり得るからだ。例えば、カプセル化や抽象化を使って業務コードをより拡張可能にできるし、プロダクトと多くコミュニケーションすることで業務をより深く理解して実装できるし、ログをしっかり記録しておけば問題の特定効率を10倍に上げられる......などなど。


業務コードにも技術のな価値があることは間違いない。業務コードの中の技術はすべてのプログラマーの基礎だ。しかし、それらのテクニックを身につけただけでは技術の達人にはなれない。それはゲームのレベル上げと同じで、最初は雑魚モンスターを倒すと経験値が高いが、後半になるほど経験値は少なくなり、雑魚を倒しても経験値が稼げなくなる。そうなると、もっと強いモンスターを倒したり、やりがいのあるダンジョンに挑戦する必要がある。雑魚だけ倒し続けて最高レベルまで上がれるゲームは見たことがない。技術の達人への道も似ている。絶えず自分のレベルを高め、さらに大きな挑戦に直面し、その挑戦を乗り越えることでさらに一段上のレベルに上がり、それを繰り返して最終のに技術の達人、さらには業界の達人に到達する。業務コードを書くことは、そのレベル上げの道のりの中の一つの挑戦に過ぎず、しかも比較の初級の挑戦だと思う。


したがって、私はこう考える。業務コードさえうまく書けないプログラマーは確実に技術の達人にはなれないが、業務コードをうまく書けるだけのプログラマーもまだ技術の達人にはなれない。


3. 仕事が忙しすぎて自分の学習時間がない


多くの人は、技術の達人になれないのは自分が賢くないからでも努力していないからでもなく、中国という環境では技術者の残業が多すぎて、追加で学習する時間がないからだと考えている。


この理由には一定の客観性がある。実際、欧米と比べれば私たちの残業は確かに多い。しかしこの要因は克服すべき問題に過ぎず、越えられない隔たりではない。なぜなら、身の回りにはやはり大勢の達人がいて、彼らも同じ中国という環境で成長してきたからだ。


このような考え方が生まれる原因には、いくつかの誤解があると思う。


1) 仕事でやっているのは繰り返しの作業ばかりで、レベルアップするには自分で追加の学習が必要だ


この誤解が生まれる主な原因は、「業務コードを書くことに技術的価値はない」という考えにある。そして、自分は今まさに業務コードを書いているので、仕事の中でレベルアップできない、と考えるのだ。


2) 学習にはまとまった連続した時間が必要だ


多くの人は、学習するには学校の授業のように一日中時間が与えられて初めて学習だと思っている。しかし普段の残業が多いため、週末は疲れて寝坊したいだけ、映画を見たりゲームをしたりしてリラックスしたいだけになり、学習する時間がない。


実際のやり方は正反対だ。まず、私たちは仕事の中で学び、レベルアップすべきだ。学んだことを実践できたり、実例を参考にできたりするので、学習効果が最も高いからだ。次に、仕事を始めてからの学習にはまとまった時間は必要ない。時間を捻出し、断片的な時間を利用して学ぶことが大事だ。


正しいやり方


1、Do more


もっと多くのことをやる。上司があなたに与えたタスクよりも多くのことをやる。


私がHWにいたとき、あるバージョンの開発を担当した。このバージョンの作業量は約2000行だったが、私はこの機能を完成させるだけでなく、関連する機能もすべてを握し、コード(約10000行)もすべて読んだ。このバージョンが完了した後、このバージョンに関連する一連の業務全体に非常に詳しくなった。会議を1、2回経た後、皆が私がこの分野を最もよくを握していることに気づいた。その後は面白くなった。製品の要件検討は私に、テストの問題も私に、上からの対外支援の依頼も私に来るようになった。さらに後には、私の担当ではない機能でも皆が私に尋ねてきた。その場で分からなくても、コードを読んだりドキュメントを探したりして答えた......。最終のに、私はこのシステムの「専門家」になった。その頃もまだ業務をやっていて、業務コードを書いていたが、すでにビジネス全体に詳しくなっていた。


以上は単純な例に過ぎないが、言いたいことは、チャンスを得るためには、まず群衆の中から頭角を現さなければならない。頭角を現すには、他の人とは違うことをしなければならない。他の人と違うことをするには、もっと多くのことをやらなければならない、ということだ。


もっと多くのことをやるにはどうすればいいか?以下のいくつかの側面から始められる。


1) 担当かどうかに関わらず、より多くの業務に詳しくなる。自分が書いたかどうかに関わらず、より多くのコードに詳しくなる。


そうすることには多くの利点がある。簡単な例をいくつか挙げる。


  • 要件分析がより正確になり、要件段階でリスク、影響、難点を特定できる。
  • 問題対応がより迅速になる。関連する業務とコードに詳しいので、問題の考えられる原因を素早く判断し、調査・対処できる。
  • 設計の際に考慮がより周到になり、全体の業務への理解があるので、より良い設計案を作り出せる。

エンドツーエンドをを握する


例えば、あなたがWebバックエンド開発を担当しているとする。実際にはユーザーがHTTPリクエストを発信してから、あなたのサーバーに到達するまでに多くの中間ステップ(ブラウザキャッシュ、DNS、nginxなど)を経る。サーバー側でも通常、多くの処理を経てから、あなたが書いた部分のコード(ルーティング、権限など)に到達する。この一連の流れの中の多くのシステムやステップに、ほとんどの人がコードを書く形で関わることは不可能だ。しかし、これらの知識を身につけることは、あなたの総合のなスキルに大きく役立つ。例えば、ソリューション設計や本番障害対応のような、より価値の高い技術業務には総合のな技術力が必要だからだ。


「体系的」「全体的」「総合的」といった言葉は漠然と見えるかもしれないが、実はこれらはすべて技術の達人に必要な素質だ。その境地に達するには、より多くのシステム、業務、コードに詳しくなることが必須だ。


3) 自主学習


一般のに、成熟したチームでは、フレームワークやコンポーネントが大量にカプセル化されているため、業務コードを書くのに使う技術は確かに少ない。しかし、「唯一変わらないものは変化だけ」であることを理解すべきだ。フレームワークは改良が必要になるかもしれないし、コンポーネントは置き換えられるかもしれない。あるいは転職した先の会社にはコンポーネントもフレームワークもなく、ゼロから作らなければならないかもしれない。これらはすべてチャンスであり、挑戦でもある。そしてチャンスと挑戦は準備ができている人にしかとえられない。だからこそ、私たちはより多くのことを自主学習する必要がある。実際に使うときになってから学び始めたのでは、もう時間がないからだ。


Javaを例にとると、ほとんどの業務コードはif-elseとデータベース操作だけだ。しかし、私たちは完全に自分でJavaに関するより多くの知識を学ぶことができる。例えば、ガベージコレクション、チューニング、ネットワークプログラミングなどだ。これらは今は役に立たないかもしれないが、実際に使う必要が生じたとき、Googleで検索するだけでは済まない。そのときに、関連する知識とスキルをすでに身につけている人こそがチャンスをつかむのだ。


ガベージコレクションを例に挙げると、私自身は普段から時間を捻出してこれらの知識を学んできた。1年間は使う機会がなかったが、その後数回使うことがあり、そのたびにシステムが止まるような大きな問題を解決した。一方で、数年Javaのコードを書いてきた人でも、stop-the-worldという概念さえ知らず、ましてや最適化など論外だ。


2、Do better


この世界に完璧なものは存在しないことを知るべきだ。自分が担当するシステムや業務には、必ず不合理な点や改善できる点がある。これらの「不合理」や「改善可能」な点は、よりレベルの高いモンスターであり、倒すとより多くの経験値を得られる。これらの点を見つけ出し、解決策を提示して、上司に提案する。一度だめなら二度、何度も提案し続け、一度でも実現できれば、それがあなたのチャンスとなる。


例:


  • 重複コードが多すぎる場合、デザインパターンを導入できないか?
  • システムの性能が普通レベルだが、最適化できないか?
  • 現在はシングルマシンだが、2台構成にしたほうが良いのではないか?
  • バージョン開発の品質が高くないが、効率的なユニットテストと統合テストの手法を導入できないか?
  • 現在のシステムが大きすぎるが、リファクタリングと疎結合化によって3つのシステムに分割できないか?
  • アリババのミドルウェアには、我々も使えそうなシステムがいくつかあるが、導入できないか?
  • 。。。。。。。。。。。。。。。。。。。

考えようとすれば、実は改善できる点は必ず見つかるものだ。もしシステムに改善できる点がどこにもないと感じるなら、それは自分のスキルがまだ足りないということだ。関連技術をもっと学び、業界の他社がどうやっているか、BATがどうやっているかをよく研究するとよい。


私は2013年に九游(9游)に異動し、最初はシンプルなバックエンドシステムを担当した。毎日フロントエンドに合わせてデータの追加・削除・変更・検索(CRUD)を行うだけの仕事で、まったく面白くなさそうに見えるだろう?確かにこれだけならつまらない。しかし、私たちは引き継いだ後、多くのことを実行した:


  • 疎結合化:1つのバックエンドを2つのバックエンドに分割し、拡張性と安定性を向上させた。
  • 2台構成:シングルマシンを2台構成のシステムに変更し、信頼性を高めた。
  • 最適化:元々5時間かかっていたインターフェースを5分に短縮した。

その他にも多くの最適化を行った。その後、私たちのグループはさらに多くのシステムを担当することになり、最終的にこの5人のチームで6つのシステムを担当した。


3、Do exercise


キャリアレベルに関する面談を行った際、多くの社員が確かに「Do more」「Do better」を試みていることがわかった。しかし実行の過程で、ほぼ全員が同じ問題に直面していた:「見るだけで使わないと効果が非常に悪い、どうすればよいか?」という問題だ。


例:


  • JVMのガベージコレクションを学んだが、本番環境ではFGC(Full GC)によるカクつき問題はめったに発生しない。たとえ発生しても、ビジネスの復旧が最優先で、本番環境で問題が起きたからといって全員が練習できるわけではない。では、どうやってこれらのJVMの知識やスキルを実践すればいいのか?
  • Nettyも読んだし、Reactorの原理も理解した。しかし、Nettyの開発に参加することはできない。どうすればReactor非同期パターンを本当に習得できるのか?
  • 『High Performance MySQL』を読んだが、本番環境のデータベースはすべてDBAが管理しており、テスト環境のデータベースは適当に設定されているように感じる。どうやってこれらの技術を検証すればいいのか?
  • フレームワークがDAL層をカプセル化しており、データベースアクセスについて心配する必要がない。どうやって分庫分表(シャーディング)の実装を理解すればいいのか?
  • 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

このような問題は他にもたくさんある。ここで私の個人的な経験を共有したい。それは簡単に言えば3つの言葉:learning(学ぶ)、trying(試す)、teaching(教える)だ。


1)Learning


これは第一段階だ。本を読む、Googleで検索する、動画を見る、他人のブログを見る、どれでもよい。ただし注意すべき点は「体系化」だ。特にJVMの原理、Javaプログラミング、ネットワークプログラミング、HTTPプロトコルなどの基礎のなものは、Googleやブログだけで学ぶべきではない。私のやり方は、まず1冊の本を完全に読み終えて全体像をを握し、その後にGoogle、動画、ブログを通じて疑問点やテクニックをピンポイントで調べるというものだ。


2)Trying


このステップこそ、先ほど挙げた多くの社員の疑問を解決する鍵となるポイントだ。わかりやすく言えば「自分で動かしてこそ、豊かになれる(自給自足)」ということだ。つまり、自分で模擬環境を構築し、自分でテストプログラムを書いてみるのだ。例えば:


  • JVMガベージコレクション:自分で簡単なテストプログラムを書き、メモリを確保して解放せず、さまざまなJVM起動パラメータを調整し、実行中にjstack、jstatなどのコマンドを使ってJVMのヒープメモリの分布やガベージコレクションの状況を確認する。このようなプログラムは簡単に書けて、シンプルなものなら数行、複雑でも数十行程度だ。
  • Reactorの原理:実際に自分でReactorパターンのデモを書いてみること。これは難しいと思わないでほしい。最もシンプルなReactorパターンのコード量(コメントを含む)は200行を超えない(Doug LeeのPPTを参考にできる)。自分で書いた後、Nettyがどう実装しているかを見ると、比較することで理解がより深まる。
  • MySQL:本番環境の設定を参考にできるのであれば、DBAに本番環境の設定を送ってもらえばよい(機密情報を削除することを忘れずに)。それを直接学ぶのだ。そして自分でMySQL環境を構築し、本番環境の設定で起動する。多くの人が何年もMySQLを使っているのに、簡単なMySQL環境すら構築できないものである。
  • フレームワークがDAL層をカプセル化している場合:自分でJDBCを使って分庫分表のシンプルな実装を書いてみて、フレームワークの実装と比較し、どこに違いがあるかを確認する。
  • ブラウザのツールを使ってHTTPキャッシュの実装を確認し、さまざまな種類のウェブサイトやさまざまなタイプのリソースが具体的にどのようにキャッシュを制御しているかを観察する。また、自分でPythonを使ってシンプルなHTTPサーバーを作成し、さまざまなHTTPヘッダーを返してブラウザの反応を観察することもできる。
  • 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

他にも多くの方法があるが、ここでは一つ一つ挙げない。簡単に言えば、学んだことを実際に試してみてこそ、理解がより深まるということだ。インディアンの諺に「I hear and I forget. I see and I remember. I do and I understand.(聞いたことは忘れ、見たことは覚え、行ったことは理解する)」というものがある。しかも「試す」ことは実は簡単で、多くの場合、自分で手を動かしてできるものだ。


もちろん、実際の仕事で使えるのであれば効果はさらに良い。実際の本番環境や業務の複雑さは、模擬プログラムを書くだけで再現できるものではないからだ。しかし、そのような機会はなかなか巡ってこないものであり、ほとんどの場合は自分でシミュレーションするしかない。そして実際に業務で使うときに、すぐに活用できるようにしておくのだ。


3)Teaching


一般的に、LearningとTryingを経て約70%を習得できる。しかし、本当に習得するには、他人に明確に説明できることが必須だと私は考える。説明する際には、知識ポイントを体系化する必要があるだけでなく、さまざまな詳細も考慮する必要があり、それによってさらに思考し学習することが促されるからだ。また、説明した後、見たり聞いたりする人が異なる理解を持ったり、新たな補足を加えたりすることがあり、それは知識・スキル体系全体を継続的に完成させることになる。


このような例は多く、私自身がブログを書くときによく遭遇する。本来は十分に理解しているつもりでも、書いてみると多くの点を考慮していなかったことに気づく。チーム内研修でもよく見られる光景だが、PPTを作成した社員が発表する際、質問や議論が始まると、多くの点がうまく説明できていなかったり、理解を間違えていたりすることが明らかになる。PPTを作成し、発表し、議論するというプロセスを一通り経験すれば、基本的に知識ポイントをかなり包括的に把握できるようになる。


あとがき


技術の達人になるという夢は素晴らしいが、多くの犠牲を払う必要がある。「Do more」であれ「Do better」であれ「Do exercise」であれ、時間と労力がかかる。その過程はとても辛いものかもしれず、退屈かもしれない。ここで特に強調したいのは、先ほど述べたことはすべて方法論に関するものだが、実際に決定的な役割を果たすのは、やはり技術に対する情熱と興味だということだ。