Java入門

 Java入門

2017年4~5月開催「ブートキャンプ特別講座」の資料になります。

Eea9a05e6e222a3d50c73f54a49fadf4?s=128

Recruit Technologies

June 02, 2017
Tweet

Transcript

  1. Java・OO入門 TP部 APプロダクト開発グループ 五味 和人

  2. 自己紹介 • 五味 和人 (ごみ かずひと) • 55期10月入社 (3社目) •

    〜57期:主に検索基盤の導入と検索品質改善を担当 • 58期 :APプロダクト開発グループのGM • S53年うまれ (53 → ごみ) • 山梨出身 • サッカーやってます • ポジション:GK (GOMI Kazuhito) ラッキーナンバー です 世間のひとは厳しい
  3. おしながき • Maven基礎 • GC基礎 • レイヤー?抽象化?実装の隠蔽? • バッドコードからプロダクトコードへ •

    オブジェクト指向とUMLモデリング ※Java文法、Java8らしい書き方はやりません
  4. おしながき • Maven基礎 • GC基礎 • レイヤー?抽象化?実装の隠蔽? • バッドコードからプロダクトコードへ •

    オブジェクト指向とUMLモデリング
  5. Maven基礎 • Recruitの多くのサイトはMavenを使用 • Mavenがどんな仕組みかを知ることはとても大切 • [Mavenの基礎を学ぶ.pptx] ※みんなよく知ってるなら端折ります

  6. おしながき • Maven基礎 • GC基礎 • レイヤー?抽象化?実装の隠蔽? • バッドコードからプロダクトコードへ •

    オブジェクト指向とUMLモデリング
  7. GC基礎:ゴール • GCの基本アルゴリズムを理解する • 世代別GCの仕掛けを理解することでメモリー中のオブ ジェクトの動きをイメージできるようになる • GCオーバーヘッドが問題になったとき、どこをどういじ れば良さそうなのか、あたりをつけられるようになる

  8. GC基礎:Copy GC • オブジェクトを探索し、Liveオブジェクトを空き領域にコ ピーする • 同時にCompactionが行われフラグメンテーション防止 • 非常に高速だがコピー先の領域が必要なので2倍のメモ リーが必要

    • Liveオブジェクトの量が実行時間に関係する Copy & Compaction Liveオブジェクト Deadオブジェクト
  9. GC基礎:Mark-Sweep GC • ふたつのフェーズでオブジェクトを破棄する • マークフェーズ • スイープフェーズ • 実装は単純でCopy

    GCとは違い2倍のメモリー量を必要と しないがフラグメンテーションが起きる ◎ ◎ ◎ Mark Sweep
  10. GC基礎:Mark-Sweep-Compact GC • ふたつのフェーズでオブジェクトを破棄する • マークフェーズ (Mark-Sweep) • コンパクトフェーズ •

    フラグメンテーションは起きないが遅い ◎ ◎ ◎ Mark Compact
  11. GC基礎:世代別GC • オブジェクトは生存期間が異なることに着目 • キャッシュオブジェクトは長い • メソッド内でしか使わないオブジェクトは短い • 生存期間が異なるならば、そもそも両者が存在する領域を 分けた方がGC対象を減らせるので効率が高い

    • 世代数をコントロールしてFull GCを抑止
  12. GC基礎:世代別GC • Xms == Xmxにするとメモリー拡張コストが抑えられる • NewRatio = Old /

    New(3を設定するとNewはHeapの1/4) • SurvivorRatio = Eden / {S0 | S1} (6を設定するとS0, S1はNewの1/8) ※ S0をS1は必ず同じサイズにな る JVM Total Memory New(Xmn, NewRatio) Old Metaspace (MaxMetaspaceSize) Eden Survivor (SurvivorRatio) S0 S1 Heap(Xmx, Xms) Non - Heap ※ 重要なポイントだけに絞っています。
  13. GC基礎:世代別GC • New直後のオブジェクトはEdenに割り当てられる New Old Eden Survivor S0 S1 Liveオブジェクト

    Deadオブジェクト
  14. GC基礎:世代別GC • EdenがいっぱいになるとScavenge GC(Copy GC)が動く • マイナーGCとも呼ぶ • LiveオブジェクトはSurvivorにコピーされる New

    Old Eden Survivor S0 S1 Liveオブジェクト Deadオブジェクト
  15. GC基礎:世代別GC • Edenは空っぽになる New Old Eden Survivor S0 S1 Liveオブジェクト

    Deadオブジェクト
  16. GC基礎:世代別GC • またEdenがいっぱいになったらScavenge GCが動く • この間にS0内のLiveオブジェクトにはDeadになるものもある New Old Eden Survivor

    S0 S1 Liveオブジェクト Deadオブジェクト
  17. GC基礎:世代別GC • EdenとS0のLiveオブジェクトをS1にコピーする New Old Eden Survivor S0 S1 Liveオブジェクト

    Deadオブジェクト
  18. GC基礎:世代別GC • EdenとS0は空っぽになる New Old Eden Survivor S0 S1 Liveオブジェクト

    Deadオブジェクト
  19. GC基礎:世代別GC • またEdenがいっぱいになったらScavenge GCが動く • この間にS1内のLiveオブジェクトにはDeadになるものもある New Old Eden Survivor

    S0 S1 Liveオブジェクト Deadオブジェクト
  20. GC基礎:世代別GC • EdenとS1のLiveオブジェクトをS0にコピーする New Old Eden Survivor S0 S1 Liveオブジェクト

    Deadオブジェクト
  21. GC基礎:世代別GC • EdenとS1は空っぽになる New Old Eden Survivor S0 S1 Liveオブジェクト

    Deadオブジェクト
  22. GC基礎:世代別GC • 経験回数が一定数を上回るとそのLiveオブジェクトはOldに移動する • この閾値はTenuringThresholdと呼ばれる • Old領域に移動したオブジェクトはScavenge GCでは回収されない • この閾値は動的に変わるため、これを高い位置で推移させることがメモ

    リー効率が高いと言える New Old Eden Survivor S0 S1 Liveオブジェクト Deadオブジェクト 世代 == Scavenge GCの経験回数
  23. GC基礎:世代別GC • 青字:-XX:MaxTenuringThresholdで指定した値 • あくまで目標値であり必ずしも維持されるわけではない -XX:PrintTenuringDistributionを指定するとGCログが↑のようになり動きがイ メージしやすくなる。 2014-09-16T16:42:15.357+0200: 6.796: [GC

    6.796: [ParNew Desired survivor size 381681664 bytes, new threshold 7 (max 15) - age 1: 16125960 bytes, 16125960 total - age 2: 16259512 bytes, 32385472 total - age 3: 2435240 bytes, 34820712 total - age 4: 17179320 bytes, 52000032 total - age 5: 43986952 bytes, 95986984 total - age 6: 20858328 bytes, 116845312 total - age 7: 31571664 bytes, 148416976 total
  24. GC基礎:世代別GC • Old領域がいっぱいになるとFull GC発動 • Full GC発動中、全てのワーカースレッドは停止し、GCス レッドに全てを支配される • これがStop

    The World (STW) • Full GCを発動させても十分なメモリーが確保できない場 合にOutOfMemoryError(OOME)となる
  25. GC基礎:CMS • 世代別GCはSTWの時間が長いためSTWが及ぼす影響を最 小化するのがConcurrent Mark Sweep GC(CMS) • 初期マークとリマークのときだけワーカースレッドを停止 させることでSTWの時間を短くするもの

    ※ https://goo.gl/gpcBaJ
  26. GC基礎:CMS • CMSInitiatingOccupancyFraction • CMSが発動するOld領域の使用量閾値 • デフォルト値はある計算式に基づいて決定されるが90%近く、アプリ特性に応じて60% 近くまで下げた方が良い JVM Total

    Memory New(Xmn, NewRatio) Old (CMSInitiatingOccupancyFraction) Metaspace (MaxMetaspaceSize) Eden Survivor (SurvivorRatio) S0 S1 Heap(Xmx, Xms) Non - Heap ※ 重要なポイントだけに絞っています。
  27. GC基礎:CMS New Old Eden Survivor S0 S1 Liveオブジェクト Deadオブジェクト ①CMS発動

  28. GC基礎:CMS New Old Eden Survivor S0 S1 Liveオブジェクト Deadオブジェクト ②マーク

  29. GC基礎:CMS New Old Eden Survivor S0 S1 Liveオブジェクト Deadオブジェクト ③この間にもSurvivorからLive

    オブジェクトがPromoteされる
  30. GC基礎:CMS New Old Eden Survivor S0 S1 Liveオブジェクト Deadオブジェクト ③この間にもSurvivorからLive

    オブジェクトがPromoteされる • CMSでSweepされる前にOld領域が不足するとPromoteに失敗したりマーク フェーズに失敗してFull GCが発動する
  31. GC基礎:CMS New Old Eden Survivor S0 S1 Liveオブジェクト Deadオブジェクト ③この間にもSurvivorからLive

    オブジェクトがPromoteされる • CMSでSweepされる前にOld領域が不足するとPromoteに失敗したりマーク フェーズに失敗してFull GCが発動する Stop The World
  32. GC基礎:CMS • CMSはSTWの時間を短くするためのもので、当然OOME が発生することもある • CMSはMark&Sweep方式なのでCompactionは走らない • CMSであろうと実行効率が高いマイナーGCで不要オブ ジェクトは回収すべき基本方針は変わらない •

    CMSを使うとマイナーGCを軽視する傾向があるので注意 • CMSはSTWの時間が短いFull GCと考えるのが賢明
  33. おしながき • Maven基礎 • GC基礎 • レイヤー?抽象化?実装の隠蔽? • バッドコードからプロダクトコードへ •

    オブジェクト指向とUMLモデリング
  34. レイヤー?抽象化?実装の隠蔽?:ゴール • レイヤーアーキテクチャーの基本を理解する • 実装を隠蔽することのメリットを説明できるようになる

  35. • Enterprise領域ではレイヤーアーキテクチャーが基本原則 • PofEAAでもDDDでも根っこは同じ • PofEAA:Pattern of Enterprise Application Architecture

    • DDD:Domain Driven Design (Devlopement) Martin Fowler Eric Evans Layered Architecture
  36. • Presentation (Interface) • Application • Domain • Infrastructure (Data

    Source) Layered Architecture
  37. • Presentation (Interface) • Application • Domain • Infrastructure (Data

    Source) Layered Architecture 大別すると3, 4種類しかない
  38. 守るべき本質的な原則が ひとつ Layered Architecture

  39. Layered Architecture なんでしょう?

  40. Layered Architecture 下位層は上位層に 依存してはならない

  41. Layered Architecture • 下位層、もしくは同位層にしか依存 しないのが基本原則 • 最もあり得る状況なのが、Domainが Applicationに依存したくなる場合 • ドメインが肥大化している予兆なのでそ

    もそも見直す必要がある
  42. ~ from PofEAA ~ Provision of services, display of information

    (e.g., in Windows or HTML, handling of user request (mouse clicks, keyboard hits), HTTP requests, command-line invocatiions, batch API) ~ from ドメイン駆動設計 ~ ユーザーに情報を表示して、ユーザーのコマンド を解釈する責務を負う。外部アクターは人間の ユーザーではなく、別のコンピューターシステム のこともある。 Layered Architecture : Presentation
  43. • HTMLや画面などのビューに近いところに位置 • リクエストハンドラーやREST APIエントリーポイント • 外部世界とアプリケーションの世界を繋ぐグルーコードで あるべき(ビジネスロジックは書かない) • 技術革新の影響を受けやすい

    (BFF部分に該当する) • アーキテクチャーを決めれば実装は機械作業的になる • Java EE:JSP / Servlet • Struts :Action • Spring :Controller Layered Architecture : Presentation
  44. ~ from PofEAA ~ Logic that is the real point

    of the system ~ from ドメイン駆動設計 ~ ビジネスにとって意味があるものか、あるいは他 システムのアプリケーション層と相互作用するの に必要なものである。 このレイヤーは薄く保たれる。ビジネスルールや 知識を含まず、やるべき作業を調整するだけで、 実際の処理は、ドメインオブジェクトによって直 下のレイヤーで実行される共同作業に委譲する。 Layered Architecture : Application
  45. • ドメイン層のコンポーネントを連動させ、単独のドメインだけでは 表現しきれない機能を実現する • 単一のドメインで表現できる機能に対しては右から左に流すレベル • ビジネスロジックに直結しないシステム特有の機能を提供する • データ登録と同時に帳票印刷 •

    システム機能の再利用単位 Layered Architecture : Application
  46. ~ from PofEAA ~ Logic that is the real point

    of the system ※ PofEAAではApplicationとDomainに明確な定義差はない ~ from ドメイン駆動設計 ~ ビジネスの概念と、ビジネスが置かれた状況に関 する情報、およびビジネスルールを表す責務を負 う。 この層がビジネス・ソフトウェアの核心である。 Layered Architecture : Domain
  47. • じゃらんなら「部屋」「宿」「プラン」「予約」など、カーセン サーなら「車」など、タウンワークなら「原稿」「応募」などのビ ジネスを形成する概念ごとの機能や操作を実現する • 概念の抽出が最も難しく、これをしくると全てが破綻するので業界分析、 業務分析が非常に重要 • 巨大なドメイン、貧弱なドメインはドメインモデルとは言わない •

    貧弱なドメイン == ドメインモデル貧血症 「オブジェクトにはわずかな振る舞いしかない」 • ビジネスロジックの再利用単位 Layered Architecture : Domain
  48. 演習:駐車場のコアドメインは?(1min)

  49. ~ from PofEAA ~ Communication with databases, messaging sysetms, transaction

    managers, other packages ~ from ドメイン駆動設計 ~ 上位のレイヤーを支える一般的な技術的機能を提 供する。アプリケーションのためのメッセージ送 信、ドメインのための永続化などがある。 Layered Architecture : Infrastructure
  50. • Application, Domainレイヤーと永続化装置の間を繋ぎ、永続化装 置に依存しがちなロジックを全て隠蔽する • RDBMS? KVS? File System? Other

    System? • Oracle? MySQL? PostgreSQL? • 永続化装置は性能要件や外部連携などの都合で変更が余儀なくされ るケースが多々あるため、隠蔽して変更の影響範囲を局所化する Layered Architecture : Infrastructure
  51. 演習:インフラストラクチャー(5~10min) • java.sql.PreparedStatement#executeQueryを内部で利用して [select * from Employee as e where

    e.組織 = :所属組織コー ド] の結果を返却するメソッドのシグネチャーを考えてください。 • 条件 • :所属組織コードはString型引数でnullと空文字は指定されないものとしま す。 • Employeeテーブルは以下の3つの列で構成されているものとします。 • 社員番号 • 社員名 • 所属組織コード
  52. 実装の隠蔽(抽象化)とは何か • ビジネスとテクノロジーを切り離すこと • ビジネスとテクノロジーはライフサイクルが異なるので疎に保つ • 技術革新が早い現在において、その重要性は非常に高い • コンポーネント内部がどのような実装になっていようとも、呼び出 し元にそれをさらけ出してはならない

    • 抽象化するとテクノロジーの入れ替えはしやすくなるが、コンポー ネントが増えやすい
  53. 実装の隠蔽(抽象化)とは何か

  54. 実装の隠蔽(抽象化)とは何か • ただし、不必要な抽象化はコンポーネントをいたずらに増やすし、 意図が全くわからない自己満足にしかならない

  55. ついでに トランザクション境界はどこに 設定すべきだと思いますか?

  56. トランザクション境界 Presentation? Application? Domain? Infrastructure?

  57. トランザクション境界 Presentation? Application? Domain? Infrastructure?

  58. • HTMLや画面などのビューに近いところに位置 • リクエストハンドラーやREST APIエントリーポイント • 外部世界とアプリケーションの世界を繋ぐグルーコードで あるべき(ビジネスロジックは書かない) • 技術革新の影響を受けやすい

    (BFF部分に該当する) • アーキテクチャーを決めれば実装は機械作業的になる • Java EE:JSP / Servlet • Struts :Action • Spring :Controller Layered Architecture : Presentation 再掲
  59. トランザクション境界 • Presentationがトランザクション境界だとこういうことを 考えないといけない • Presentationはテスト自動化がやりにくいので打鍵任せに なりやすい

  60. トランザクション境界 • Presentationはある意味使い捨て • Applicationは画面やプロトコルに依存しないのでテスト を自動化しやすい

  61. おしながき • Maven基礎 • GC基礎 • レイヤー?抽象化?実装の隠蔽? • バッドコードからプロダクトコードへ •

    オブジェクト指向とUMLモデリング
  62. バッドコードからプロダクトコードへ:ゴール • 先輩社員から刺されるコードは書かないようになる ※ もっともっといっぱいポイントはあって全部は紹介しきれ ません。現場でどんどん学んでいってください。

  63. バッドコードからプロダクトコードへ • このコード、どこかおかしい? public boolean checkNull(Object obj) { if (null

    == obj) { return false; } else { return true; } }
  64. • このコード、どこかおかしい? public boolean isNull(Object obj) { return (obj ==

    null); } バッドコードからプロダクトコードへ
  65. • このコード、どこかおかしい? public void doSomething(Integer arg) { if (arg !=

    null) { if (arg < 0) { do1(); } else if (arg > 0) { do2(); } else { do3(); } } } バッドコードからプロダクトコードへ
  66. • このコード、どこかおかしい? public void doSomething(Integer arg) { if (arg ==

    null) { return; } if (arg < 0) { do1(); } else if (arg > 0) { do2(); } else { do3(); } } バッドコードからプロダクトコードへ
  67. • このコード、どこかおかしい? public List<String> findEmployee(String orgCode) { if (orgCode ==

    null) { throw new NullPointerException(); } if (orgCode.length() != 7) { return null; } String[] result = find...; return (result == null) ? null : Arrays.asList(result); } バッドコードからプロダクトコードへ
  68. • このコード、どこかおかしい? public List<String> findEmployee(String orgCode) { if (orgCode ==

    null) { throw new IllegalArgumentException("orgCode must be not null."); } if (orgCode.length() != 7) { throw new IllegalArgumentException("orgCode length must be 7."); } String[] result = find...; return (result == null) ? Collections.emptyList() : Arrays.asList(result); } バッドコードからプロダクトコードへ
  69. • このコード、どこかおかしい? (lambdaじゃないのは置いといて) public List<DTO> toList(Map<String, String> arg) { List<DTO>

    ret = new ArrayList<DTO>(); for (String key : arg.keySet()) { ret.add(new DTO(key, arg.get(key))); } return ret; } バッドコードからプロダクトコードへ
  70. • このコード、どこかおかしい? (lambdaじゃないのは置いといて) public List<DTO> toList(Map<String, String> arg) { List<DTO>

    ret = new ArrayList<DTO>(arg.size()); for (String key : arg.keySet()) { ret.add(new DTO(key, arg.get(key))); } return ret; } バッドコードからプロダクトコードへ
  71. • このコード、どこかおかしい? public void doSomething() { try { do... }

    catch(Exception e1) { try { rollback(); log(e1); throw new RuntimeException(e1); } catch(Exception e2) { log(e2); throw new RuntimeException(e2); } } } バッドコードからプロダクトコードへ
  72. • このコード、どこかおかしい? public void doSomething() { try { do... }

    catch(Exception e1) { log(e1); try { rollback(); } catch(Exception e2) { log(e2); } finally { throw new RuntimeException(e1); } } } バッドコードからプロダクトコードへ
  73. • このコード、どこかおかしい? public void doSomething() { try { do... }

    catch(Exception e) { } } バッドコードからプロダクトコードへ
  74. • このコード、どこかおかしい? public void doSomething() { try { do... }

    catch(Exception e) { // NOP } } バッドコードからプロダクトコードへ
  75. • このコード、どこかおかしい? public void doSomething() { Integer[] intArray = new

    Integer[10]; Arrays.sort(intArray, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { do... } }); } バッドコードからプロダクトコードへ
  76. • このコード、どこかおかしい? private static final Comparator<Integer> SORTER = new Comparator<Integer>()

    { @Override public int compare(Integer o1, Integer o2) { do... } }; public void doSomething() { Arrays.sort(intArray, SORTER); } バッドコードからプロダクトコードへ
  77. • このコード、どこかおかしい? public String concat(String str, int num) { StringBuilder

    sb = new StringBuilder(); for (int i = 0; i < num; i++) { sb.append(str); } return sb.toString(); } バッドコードからプロダクトコードへ
  78. • このコード、どこかおかしい? public String concat(String str, int num) { StringBuilder

    sb = new StringBuilder(str * num); for (int i = 0; i < num; i++) { sb.append(str); } return sb.toString(); } バッドコードからプロダクトコードへ
  79. • このコード、どこかおかしい? private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); public

    static void doSomething(Date date) { .... String formatDate = sdf.format(date); .... } バッドコードからプロダクトコードへ
  80. • このコード、どこかおかしい? public static void doSomething(Date date) { SimpleDateFormat sdf

    = new SimpleDateFormat("yyyy/MM/dd"); .... String formatDate = sdf.format(date); .... } バッドコードからプロダクトコードへ
  81. • このコード、どこかおかしい? public void isValidFormat(String str) { return Pattern.compile("a.c").matcher(str).matches() }

    バッドコードからプロダクトコードへ
  82. • このコード、どこかおかしい? private static Pattern pattern = Pattern.compile("a.c"); public void

    isValidFormat(String str) { return pattern.matcher(str).matches() } バッドコードからプロダクトコードへ
  83. • このコード、どこかおかしい? public void doSomething() { try { do... }

    catch (Exception e) { throw new RuntimeException(); } } バッドコードからプロダクトコードへ
  84. • このコード、どこかおかしい? public void doSomething() { try { do... }

    catch (Exception e) { throw new RuntimeException(e); } } バッドコードからプロダクトコードへ
  85. • この設定、どこかおかしい? ※ https://logging.apache .org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html <appender name="stdout" class="org.apache.log4j.ConsoleAppender"> <param name="Target"

    value="System.out" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{yyyy MM dd HH:mm:ss,SSS} %C %F %m%n" /> </layout> </appender> バッドコードからプロダクトコードへ
  86. • この設定、どこかおかしい? <appender name="stdout" class="org.apache.log4j.ConsoleAppender"> <param name="Target" value="System.out" /> <layout

    class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %m%n" /> </layout> </appender> バッドコードからプロダクトコードへ
  87. おしながき • Maven基礎 • GC基礎 • レイヤー?抽象化?実装の隠蔽? • バッドコードからプロダクトコードへ •

    オブジェクト指向とUMLモデリング
  88. オブジェクト指向:ゴール • オブジェクトの抽出のコツを知り、できるようになる • 基本的なUMLダイアグラムの読み書きをできるようになる

  89. オブジェクト指向 • オブジェクト指向(Object Oriented)とは オブジェクト同士の相互作用として、 システムの振る舞いをとらえる考え方である ※Wikipediaより

  90. オブジェクト指向:オブジェクトとは 概念をモノとして表現したもの モノ同士がコトを通じて連動する

  91. オブジェクト指向:概念? • じゃらんなら「部屋」「宿」「プラン」「予約」など • カーセンサーなら「車」など • タウンワークなら「原稿」「応募」など • 勤太郎なら「日毎の就業時間」など •

    会社なら「組織」「ヒト」「役割」など 概念は名詞から抽出するのが基本原則 システムの振る舞いをとらえる考え方である
  92. オブジェクト指向:概念? 概念はクラス、操作はメソッドが基本なので クラス名に動詞が入るとかナシ

  93. オブジェクト指向:概念? public class UserCreateService { public boolean submit(String name, String

    password) { ... } } public class UserDeleteService { public boolean submit(String id) { ... } } public class UserService { public boolean create(String name, String password) {...} public boolean delete(String id) {...} }
  94. オブジェクト指向 JavaやC#などの オブジェクト指向言語を使うと オブジェクト指向なのか?

  95. JavaやC#などの オブジェクト指向言語を使うと オブジェクト指向なのか? オブジェクト指向 No

  96. オブジェクト指向 オブジェクト指向と オブジェクト指向プログラミング は全く別物 (OO != OOP)

  97. オブジェクト指向 オブジェクト指向分析 (OOA) オブジェクト指向設計 (OOD) オブジェクト指向 プログラミング (OOP)

  98. オブジェクト指向 オブジェクト指向への近道は OOAができるようになること

  99. オブジェクト指向 でも今日はOOAはやりません

  100. オブジェクト指向 Why?

  101. オブジェクト指向 手法が必要です

  102. 演習:内部構造を説明しよう(10min) • Spring Framework@OSSの AnnotationConfigApplicationContextの継承関係や関連するクラ スをペアを組んで説明してみましょう。 ※ https://goo.gl/PlJKB1 • 条件

    • 手法は問いません。 • コードを使っても良いですし、口頭でも構いません。 • 5分経ったら説明係を交代してください。
  103. 演習:内部構造を説明しよう(10min) もう一度説明してみましょう

  104. コードや口頭ではツラくない? 頭の中で整理できた?

  105. None
  106. 絵だとわかり やすくない?

  107. モデルは人に 説明するだけでなく 自分の考えを整理、 人の考えを理解する のに使える

  108. オブジェクト指向:UML UML (Unified Modeling Language)

  109. オブジェクト指向:UML 主にオブジェクト指向分析や設計のための、 記法の統一がはかられた(Unified) モデリング言語(Modeling Language)である。 仕様記述言語であるなどとされることもあるが、 統一されているのは構文に相当する記法だけで、 仕様を表現するような意味が 形式的に与えられていない図もあるので、 形式仕様記述言語ではない。

    ※Wikipediaより
  110. UML:Three Amigos Grady Booch Ivar Hjalmar Jacobson James Rumbaugh 経緯はどうあれ、みんなRational

    Softwareの中の人 (Rational Softwareは2003年にIBMに買収された)
  111. UML:Structure No Diagram Overview 1 クラス図 オブジェクトの構造やオブジェクト間の関係、役割 を表現 2 オブジェクト図

    特定条件下におけるオブジェクト同士(インスタン ス同士)の関係を表現 3 コンポジット構造図 ※ UML2.0で追加 クラスやコンポーネント等の内部構造と関係を表現 4 コンポーネント図 ソフトウェアコンポーネントの構成を表現 5 配置図 ハードウェア、ソフトウェア、ディレクトリなどを どう配置するかを表現 6 パッケージ図 パッケージ間の関係やオブジェクトがどのパッケー ジに属するかを表現
  112. UML:Behavior No Diagram Overview 1 シーケンス図 オブジェクト間(インスタンス間)のやりとりを時 間系列で表現 2 コミュニケーション図

    (コラボレーション図) 〃 ※ シーケンス図より表現力が乏しいので存在感薄い 3 タイミング図 ※ UML2.0で追加 リアルタイムのような短時間での状態遷移や時間制 約、メッセージ送受信などを表現 4 相互作用概要図 ※ UML2.0で追加 シーケンス図、アクティビティ図などを相互作用図 として概要化し全体を俯瞰して表現 5 ステートマシン図 状態を持つ概念にフォーカスして生成から破棄まで の状態遷移を表現 6 アクティビティ図 システムや業務の活動、データの流れ、条件分岐な どを表現 ※ フローチャートに近い 7 ユースケース図 対象機能と利用者や他システムなどの外部的な関係 を表現
  113. UML:今日やるダイアグラム No Diagram Overview 1 クラス図 オブジェクトの構造やオブジェクト間の関係、役割 を表現 2 オブジェクト図

    特定条件下におけるオブジェクト同士(インスタン ス同士)の関係を表現 3 シーケンス図 オブジェクト間(インスタンス間)のやりとりを時 間系列で表現
  114. UML:クラス図

  115. UML:クラス図

  116. 演習:UML:クラス図(20min) • タウンワークはひとつひとつが原稿という枠で扱われます • ユーザーにはカスタマーとクライアントがいます • 原稿には複数のカスタマーが応募でき、カスタマーは複数の原稿に応募で きます • 原稿を出稿するクライアントは応募先として管理されます

    • クライアント機能として「おうぼうけるくん(UK)」というものがあり、 応募先とUKアカウントはメールアドレスで関連付けられます。 • 応募先が異なっていてもメールアドレスが同じなら同じUKアカウント • UKアカウントにはアカウントごとに固有のUK設定がひとつあります • クライアントには管理者とメンバーがいて、管理者がUKアカウントにひ も付き、管理者アカウントが削除されるとメンバーもUKが使えなくなり ます • メンバーも削除されます • 応募するとチャットが開始され、カスタマーとUKアカウントがチャット ルームに関連付けられます
  117. None
  118. UML:オブジェクト図 • クラス図は概念を静的に表すものであり、概念を具体化したインス タンスごとの関係性は表現できない • オブジェクト図はこれを解消するもので、具体的なインスタンス間 の関係性を表現する

  119. UML:さっきの演習のオブジェクト図 • オブジェクト図ではインスタンスは 「<インスタンス名>:クラス名」で表現する。 • フィールドには具体的な値を設定してイメージしやすくする

  120. UML:さっきの演習のオブジェクト図

  121. UML:シーケンス図

  122. None
  123. UML:シーケンス図 • ビギナーあるある

  124. UML:シーケンス図 • ビギナーあるある

  125. おわり

  126. Appendix

  127. 開放 / 閉鎖原則 (Open Closed Principle:OCP) Carrier carrier = mobile.getCarrier();

    switch (carrier) { case DOCOMO: form.KW = ResponseUtils.encodeURL(form.KW, "windows-31j"); break; case AU: form.KW = ResponseUtils.encodeURL(form.KW, "windows-31j"); break; case SOFTBANK: form.KW = ResponseUtils.encodeURL(form.KW, "windows-31j"); break; case SOFTBANK3G: form.KW = ResponseUtils.encodeURL(form.KW, "UTF-8"); break; case WILLCOM: // 新規キャリアが参画したら case ブロックを追加する必要があるかもしれない // case SPRINT: // case ATT: // case VERIZON: default: form.KW = ResponseUtils.encodeURL(form.KW, "windows-31j"); break; }
  128. 開放 / 閉鎖原則 (Open Closed Principle:OCP) Carrier carrier = mobile.getCarrier();

    CarrierStrategy carrierStrategy = CarrierStrategyFactory.buildStrategy(carrier); form.KW = carrierStrategy.encodeURL(); public class CarrierStrategyFactory { public static CarrierStrategy buildStrategy(Carrier carrier) { switch (carrier) { case DOCOMO: return new DoCoMoStrategy(); case AU: return new AuStrategy(); case SOFTBANK: return new SoftBankStrategy(); case SOFTBANK3G: return new SoftBank3GStrategy(); case WILLCOM: default: return new DefaultStrategy(); } } }
  129. 開放 / 閉鎖原則 (Open Closed Principle:OCP)

  130. 単一責任の原則 (Single Responsibility Principle:SRP) • 凝集度を考えるとき、SRP (Single Responsibility Principle:単 一責任の原則)

    が基本的な考え方になる。 • SRP は「1 つのクラスは 1 つの責務 (だけ) を持つ」を原則とし、 複数の責務を 1 つのクラスに持たせないことに意識を向けている。 • 責務が端的で分かりやすいものであればクラスの境界がはっきりし、 新たな機能を追加するときどこを修正すれば良いのか、何のクラス を追加すれば良いのかが明確になる。 • 「唯一の責務を全うするために属性や操作が集まっている」、これ が凝集しているということである。
  131. 継承と委譲 • 一般的に「継承」は差分プログラミング的なコードの再利用を例に 説明されることが多い。この効用は非常に直感的でわかりやすいた め、多くのプログラマーは「コードの再利用 == 継承」と捉えて 多用する傾向が強い。もちろん継承によるコードの再利用は正しい ことだが、誤用はクラスの凝集度を下げ、結合度を高めることにな りかねないので、用法用量を守って正しく使うことが大切となる。

    • 継承はクラスの関係を密にし、クラスが持つべき本来の責務範囲を 逸脱し肥大化する恐れがあり、「結局このクラスの責務は何?」状 態になる可能性が高い。 • それを回避しつつコードの再利用を実現する手段には何があるか。 「委譲」だ。具体例は後述するが、以下の観点に基づき継承でコー ドの再利用を実現するか、委譲で実現するかを決定すると良いコー ドになる。 • 「型」の再利用は継承 • 「機能」の再利用は委譲
  132. 演習:継承と委譲 • BuiltinTextBoxクラスがSDK標準として存在しているものとして、 以下の機能を提供するクラス群の構成を考えてください。 • 英数字のみを許容するテキストボックス • 数字のみを許容するテキストボックス • 全角のみを許容するテキストボックス

    • 半角のみを許容するテキストボックス
  133. 演習:継承と委譲

  134. 演習:実践モデリング

  135. None