メンバーのスキルアップ、どうしてる? − Java 100本ノックで新加入メンバーを鍛えてみた −

4,631 views

Published on

JJUG CCC Fall 2016 での発表資料です。
Java 100本ノックを用いたトレーニングの実例と、アンチパターンについてご紹介しています。

Published in: Engineering
0 Comments
19 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,631
On SlideShare
0
From Embeds
0
Number of Embeds
726
Actions
Shares
0
Downloads
14
Comments
0
Likes
19
Embeds 0
No embeds

No notes for slide

メンバーのスキルアップ、どうしてる? − Java 100本ノックで新加入メンバーを鍛えてみた −

  1. 1. メンバーのスキルアップ、 どうしてる? -Java 100本ノックで新加入メンバーを鍛えてみた- JJUG CCC Fall 2016 2016/12/03 #jjug_ccc #ccc_f3 #Java100
  2. 2. 自己紹介 • 株式会社ジャストシステム 福嶋 航 • Twitter @fukushiw • Java歴約20年、JavaでWebサービス作っています • #Java100 本ノックの人 https://github.com/JustSystems/java-100practices
  3. 3. 株式会社ジャストシステム • 創業37年、売上182億円、 社員平均年収884万円 • Javaのプロダクト採用は1.0から。 一太郎Ark:1996年開発着手。 • 1999年、2005年、2006年には JavaOne Conferenceに出展 JavaOne画像引用:@IT 「JavaOneで阿波踊りを踊るジャストシステム」 http://www.atmarkit.co.jp/news/200506/30/just.html
  4. 4. 株式会社ジャストシステム 現在、いくつものWebサービスをJavaで作っています。 などなど・・・
  5. 5. 今日お話しすること 1.Java 100本ノックを 用いたトレーニング実例 2.ソフトウェア開発 アンチパターン7つ
  6. 6. 1 Java 100本ノックを 用いたトレーニング実例
  7. 7. Java100本ノックとは? プログラミング言語 Java に関するスキル向 上を目的とした問題集です。 具体的には、 運用環境で安定稼働でき、かつ、保守性・ 拡張性に優れたコードがより多く生産できる ようになることを目指しています。 Javaを初めて使う方から中級者までをメイン ターゲットにしています。
  8. 8. Java100本ノック 目次 001-010:はじめの一歩 011-040:言語仕様 041-060:コアAPI 061-080:複合・Java EE 081-090:ライブラリ 091-099:フレームワーク 100 :Webアプリケーションの作成
  9. 9. Java100本ノック例えばこんなの(1)
  10. 10. Java100本ノック例えばこんなの(1) 解答例 jar cfe ${JARFILE} Answer010 -C ${CLASSES} Answer010.class
  11. 11. Java100本ノック例えばこんなの(2)
  12. 12. Java100本ノック例えばこんなの(2) 解答例 medals.forEach(System.out::println);
  13. 13. Java100本ノック例えばこんなの(3)
  14. 14. Java100本ノック例えばこんなの(3) 解答例 「等価なオブジェクトは等価なハッシュ・コードを保持する必要がある」と いうhashCodeメソッドの汎用規約に従う必要があるため java.lang.Object#equals() java.lang.Object#hashCode() のAPIドキュメント参照
  15. 15. ある日
  16. 16. 新メンバーがあらわれた!       たたかう       じゅもん     ▶どうぐ         にげる  みんな  がんばれ
  17. 17. ふくしまは Java100本ノックを つかった!
  18. 18. トレーニング内容 • 被験者 • Java歴数ヶ月のエンジニア(20代前半) • 課題 • Java100本ノックを001番から順番に実施 • 期間 • 1ヶ月 • サイクル • 帰る前にその日できた分をPull Request • 翌朝Pull Requestの内容について対面レビュー • 指摘反映&再レビュー→新規課題取り組み
  19. 19. トレーニング結果 • 期間 • 19営業日 • 課題進捗 • 001~074のうち、019(JNI)を除く73問を完了 • スキル向上度合い(受講者の感想) • 参考書を見ながらコーディングできるレベル         ↓ Javaを「なんとなく」ではなく、理解しながら実装すること ができるようになった! と同時に実装することが楽しいと まで感じられるようになった!
  20. 20. トレーニング結果 • 期間 • 19営業日 • 課題進捗 • 001~074のうち、019(JNI)を除く73問を完了 • スキル向上度合い(受講者の感想) • 参考書を見ながらコーディングできるレベル         ↓ Javaを「なんとなく」ではなく、理解しながら実装すること ができるようになった! と同時に実装することが楽しいと まで感じられるようになった! 特にnullチェックなどの引数や例外をチェックするクセが身についた
  21. 21. 新メンバーは レベルが あがった!
  22. 22. 進捗 0 10 20 30 40 50 60 70 80 1日目 2日目 3日目 4日目 5日目 6日目 7日目 8日目 9日目 10日目 11日目 12日目 13日目 14日目 15日目 16日目 17日目 18日目 19日目 0 2 4 6 8 10 12 14 16 完了累計 (左軸) 完了 (右軸)
  23. 23. Java100本ノックの進め方 • (再掲) • 帰る前にその日できた分をPull Request • 翌朝Pull Requestの内容について対面レビュー • 指摘反映&再レビュー→新規課題取り組み
  24. 24. Java100本ノックの進め方 • (再掲) • 帰る前にその日できた分をPull Request • 翌朝Pull Requestの内容について対面レビュー • 指摘反映&再レビュー→新規課題取り組み 力をつけるにはレビューが大事 1行ずつ、1文字ずつ意味がある
  25. 25. Java100本ノックを受けてみた感想 • 参考書でJavaの知識を網羅したと思い込んでいたことに恐怖 を感じた • Java API リファレンスを見る癖が付いた • Eclipseの補完機能に頼らず実装できるようになった • 単純に問に対する答えが分からないから難しいのではなく、 使 用するコマンド・クラス・APIなどを正しく理解した上で、 正しく 使用しなければ解けない問題が多いため難しい。 • 問題が難しい分、解けた時には、なるほどといった爽快感が あった。 • 今までJavaを学習してきた中で、100本ノックのような問題集 にもっと早く出会えていたら、Javaの理解スピードは遙かに違っ ていただろうと思った。 ※個人の感想です
  26. 26. Java100本ノックを受けてみた感想 • 参考書でJavaの知識を網羅したと思い込んでいたことに恐怖 を感じた • Java API リファレンスを見る癖が付いた • Eclipseの補完機能に頼らず実装できるようになった • 単純に問に対する答えが分からないから難しいのではなく、 使 用するコマンド・クラス・APIなどを正しく理解した上で、 正しく 使用しなければ解けない問題が多いため難しい。 • 問題が難しい分、解けた時には、なるほどといった爽快感が あった。 • 今までJavaを学習してきた中で、100本ノックのような問題集 にもっと早く出会えていたら、Javaの理解スピードは遙かに違っ ていただろうと思った。 ヨイショォオォォォォ!! ※個人の感想です
  27. 27. どのように活用すべきか • 基本 • 回答→Pull Request→レビューのサイクル • オンデマンドで被験者の相談に乗る • レビューで鍛える • レビューの場=スキルアップの場 • 教える側も本質を正しく理解していないといけない • 指摘だけではなく、よくできたところを伝える • 「コメントがよく書けた!」 • 「1メソッドが短くていいね!」 • 「この命名はわかりやすいね!」
  28. 28. Java100本ノックは基礎を学ぶもの • 次は実践 • 実践では何に気をつけるべきか
  29. 29. 2 ソフトウェア開発 アンチパターン7つ
  30. 30. 社内の複数のプロジェ クトに関わってきたら、 気づいてしまった
  31. 31. ひとつ関われば自分がわかる
  32. 32. ひとつ関われば自分がわかる ふたつ関われば全てが見える
  33. 33. ひとつ関われば自分がわかる ふたつ関われば全てが見える みっつ関われば…アンチパターンが見える
  34. 34. ひとつ関われば自分がわかる ふたつ関われば全てが見える みっつ関われば…アンチパターンが見える 見える見えるー嵌まる様
  35. 35. アンチパターンを作るきっかけ • 複数のプロジェクトに関わるうちに「あそこがイクナイ」 「ここがイクナイ」という事例がたまってきていて、これ をバネに各開発チームのスキルアップが必要と感じて いた。 • そんな折、「SQLアンチパターン」の社内読書会に @t_wada さんにお越し頂く機会があり、そこで、   アンチパターンには名前をつけるとよいです というお言葉を頂戴した。
  36. 36. アンチパターンを作るきっかけ • 複数のプロジェクトに関わるうちに「あそこがイクナイ」 「ここがイクナイ」という事例がたまってきていて、これ をバネに各開発チームのスキルアップが必要と感じて いた。 • そんな折、「SQLアンチパターン」の社内読書会に @t_wada さんにお越し頂く機会があり、そこで、   アンチパターンには名前をつけるとよいです というお言葉を頂戴した。 これ、使えるんじゃないだろうか?
  37. 37. 社内のQiita:Teamで共有してみた
  38. 38. 今日お話しする部分
  39. 39. 1 シャイ・メッセージ 何が起きたかは生ログで
  40. 40. シャイ・メッセージ(何が起きたかは生ログで) 本当にあった怖い話 ログ監視システムからアラートメールが到着。肝心のメッセージ部分には       java.lang.NullPointerException: null とだけ書かれている !? ユーザーへの影響は? 何が起きているのかサッパリ分からん・・・
  41. 41. シャイ・メッセージ(何が起きたかは生ログで) 本当にあった怖い話 ログ監視システムからアラートメールが到着。肝心のメッセージ部分には       java.lang.NullPointerException: null とだけ書かれている !? ユーザーへの影響は? 何が起きているのかサッパリ分からん・・・運用環境に乗り込んでログを確認・・・(初動調査に遅れ)
  42. 42. シャイ・メッセージ(何が起きたかは生ログで) 解決策:例外スロー時・ログ出力時のそれぞれで、       何が起きて何ができなかったかを記載する 例外をスローするときは何が起きたかをメッセージに入れる throw new ApiException("api server did not respond for " + retryCount + " times"); ログ出力時にどこで何の処理ができなかったかを記述する LOGGER.error("Failed to retrieve the score from database.", e);
  43. 43. 2 リ・インベンティング ・ザ・ホイール 無駄な独自ロジック
  44. 44. リ・インベンティング・ザ・ホイール(無駄な独自ロジック) 本当にあった怖い話 渡された日付の前日が所属する年 月を求めて欲しい OK できたよ ・・・2016/01/01入れると 2016年0月ってなるんだけど・・・
  45. 45. リ・インベンティング・ザ・ホイール(無駄な独自ロジック) 本当にあった怖い話 渡された日付の前日が所属する年 月を求めて欲しい OK できたよ ・・・2016/01/01入れると 2016年0月ってなるんだけど・・・ String newMonth = Integer.parseInt(inputString.substring(3,5)) - 1; return newYear + "年" + newMonth + "月";
  46. 46. リ・インベンティング・ザ・ホイール(無駄な独自ロジック) 本当にあった怖い話 渡された日付の前日が所属する年 月を求めて欲しい OK できたよ ・・・2016/01/01入れると 2016年0月ってなるんだけど・・・ String newMonth = Integer.parseInt(inputString.substring(3,5)) - 1; return newYear + "年" + newMonth + "月";ロジック作っちゃってる・・・!
  47. 47. リ・インベンティング・ザ・ホイール(無駄な独自ロジック) 補足:Date and Time API を使えば以下の通り(※例外未考慮) return LocalDate.parse( inputString, DateTimeFormatter.ofPattern("yyyy/MM/dd") ).plusMonths(-1L).format( DateTimeFormatter.ofPattern("yyyy年MM月") ); 解決策:標準SDKやよく使われているライブラリを使用する 今回の場合、標準SDKであるSimpleDateFormatクラスや Calendarクラスを使えばなんのことはなくできる処理です。標準SDK 以外のライブラリを使うまでもありません。 標準SDKが第1の選択肢です。ちまたのユーティリティライブラリが第2 の選択肢です。後者の場合、使用の前にライセンスの確認が必要で す。
  48. 48. 3 リーゾンレス・ トラスト nullチェックしない
  49. 49. リーゾンレス・トラスト(nullチェックしない) 本当にある普通の話 実は、現場で起きている例外で一番多いのが、 NullPointerException
  50. 50. リーゾンレス・トラスト(nullチェックしない) 本当にある普通の話 実は、現場で起きている例外で一番多いのが、 NullPointerException
  51. 51. リーゾンレス・トラスト(nullチェックしない) The Checker Framework の @NonNull や Kotlin を使うという解決策もあります。 解決策:nullチェックを入れる nullチェックを入れない代わりに、nullチェックをしなく てよい理由をコメントしてもよいです。にするのがよい です。
  52. 52. 4 デコイ・コード ソースコードのコピペ
  53. 53. デコイ・コード(ソースコードのコピペ) 本当にある普通の話 機能追加、今あるものに影響が出ない よう、元のコードをコピーして改変せよ 了解しました あ、ここにバグがあるや、 修正しよう あれ? 直したはずがまだバグコードが あるぞ?
  54. 54. デコイ・コード(ソースコードのコピペ) 本当にある普通の話 機能追加、今あるものに影響が出ない よう、元のコードをコピーして改変せよ 了解しました あ、ここにバグがあるや、 修正しよう あれ? 直したはずがまだバグコードが あるぞ? バグA を たおした! バグA の かげから バグB が あらわれた!
  55. 55. デコイ・コード(ソースコードのコピペ) 本当にある普通の話 機能追加、今あるものに影響が出ない よう、元のコードをコピーして改変せよ 了解しました あ、ここにバグがあるや、 修正しよう あれ? 直したはずがまだバグコードが あるぞ? バグAをたおした! バグAのかげからバグBがあらわれた! メンテナンスコスト ∝ ロジックコピペ回数
  56. 56. デコイ・コード(ソースコードのコピペ) 解決策:Once And Only Once コードの重複をしないように工夫します。 例えば、旧ロジックと新ロジックの共通部分 をスーパークラスで実装し、サブクラスで違う 部分だけを実装するようにします。 当然、リファクタリング前にテストコードを書い てデグレ防止対策をする必要があります。
  57. 57. 5 ナム・トゥ・イエロー 警告無視
  58. 58. ナム・トゥ・イエロー(警告無視) 本当にある普通の話 • @SupressWarningsがクラスについてる • 警告は普通に無視。もしくは気づかない。 Eclipseだと黄色になるだけで実行できるし痛くもかゆくもない。
  59. 59. ナム・トゥ・イエロー(警告無視) 本当にある普通の話 • @SupressWarningsがクラスについてる • 警告は普通に無視。もしくは気づかない。 Eclipseだと黄色になるだけで実行できるし痛くもかゆくもない。でもいざDeprecatedのものが消えたりするとそのとき大騒ぎ
  60. 60. ナム・トゥ・イエロー(警告無視) 解決策:コンパイラが出す警告は全て解消する ビルドのログを見て警告が出ていないことを毎回必ず 確認するようにします。一杯たまると大変なので、 ちょっとずつビルドして、警告が出たらすかさずつぶす ようにするのがよいです。
  61. 61. 6 エングリッシュ 奇妙な英語
  62. 62. エングリッシュ(奇妙な英語) 本当にあった怖い話 • public void regist(User user) • public boolean isExist(User user) A:「registでしょ?」 B:「えっ?」 A:「えっ?」
  63. 63. エングリッシュ(奇妙な英語) 本当にあった怖い話 • public void regist(User user) • public boolean isExist(User user) A:「registでしょ?」 B:「えっ?」 A:「えっ?」 「キラキラ変数名」とかいう言葉も世の中にはあるようで・・・ (ノД̀)
  64. 64. エングリッシュ(奇妙な英語) 便利なツール • codic https://codic.jp/ PascalCase, camelCase, snake_caseなど   かゆいところに手が届いているところがニクい • IDE 例:Android Studio →
  65. 65. エングリッシュ(奇妙な英語) 便利なツール • codic https://codic.jp/ PascalCase, camelCase, snake_caseなど   かゆいところに手が届いているところがニクい • IDE 例:Android Studio → • ATOK 日本語入力してF4
  66. 66. 7 ミミック おかしいコードの増殖
  67. 67. ミミック(おかしいコードの増殖) 本当にあった怖い話 リーダー「前担当のソースを参考にしてみて」 メンバー:コピーして必要なところだけ修正 ~レビューにて~ リーダー「なんでthrowするのがRuntimeException?」 メンバー「だって前のコードを参考にしろという指示だったし、 そもそも何やってるのかわからないところはそのままにし ています」
  68. 68. ミミック(おかしいコードの増殖) 本当にあった怖い話 リーダー「前担当のソースを参考にしてみて」 メンバー:コピーして必要なところだけ修正 ~レビューにて~ リーダー「なんでthrowするのがRuntimeException?」 メンバー「だって前のコードを参考にしろという指示だったし、 そもそも何やってるのかわからないところはそのままにし ています」 あなたが書いたコードはコピペであってもあなたのものですから!
  69. 69. ミミック(おかしいコードの増殖) 解決策:最善なコードを生産する 前任者から引き継いだコードがひどいシロモノだった、というの はよくある話です。ひどいコードスタイルをそのまま受け継ぐと 負の遺産が増えるばかりです。自分がコードを書くところは自 分の責任ですから、自分が最善と思えるコードを書き、新し く作るところだけでも清らかにしていくことが重要です。
  70. 70. まとめ
  71. 71. 本日お話ししたこと メンバーのスキルアップ、 どうしてる?
  72. 72. 本日お話ししたこと 1.Java 100本ノックを 用いたトレーニング実例 2.ソフトウェア開発 アンチパターン7つ
  73. 73. We are Hiring!!

×