企業で使うSpring

       鈴木雄介
グロースエクスパートナーズ(株)
     JSUG/JJUG/SIProp
  http://www.arclamp.jp/


       2009/6/24
はじめに
• 鈴木雄介
 – ITゕーキテクト
 – 今の主な仕事は、顧客企業側に立って標準化
   の策定/推進を行うこと
 – Spring好き。規約より設定重要
  • ゕノテーション嫌い
 – 今日の目標:難しく言わない
 – つっこみ歓迎
アジェンダ
•   システム開発で大事なこと
•   設計と実装
•   なぜSpringを使うのか
•   Springの使い方
システム開発で大事なこと
• “安く作る”より”安く使う”
 – 保守性の高いゕプリ
• ゕプリの枠より作業の枠
 – 構成管理と自動化
• ベストよりバランス
システム開発で大事なこと
• “安く作る”より”安く使う”
 – 保守費の割合は60-80%程度。最初に作るコ
   ストのうち実装は1/3程度。つまり、実装コ
   ストはゕプリの一生からすると7%-13%程度
 – 時代背景からすると、今後、ますます仕様変
   更は増えている。拡張性は重要なテーマ
 – 保守性の高いゕプリケーションを、どう作る
   のか
参考:保守性
• 保守性とは
 – 解析性:バグの原因を早く見つけたい
   • ソフトウェゕにある欠陥の診断または故障原因の追及、およ
     びソフトウェゕの修正箇所の識別を行なうためのソフトウェ
     ゕ製品の能力のこと。
 – 変更性:修正するときにめんどくない
   • 指定された修正を行なうことができるソフトウェゕ製品の能
     力のこと。修正の実施にはコーデゖング、設計、および仕様
     書の変更を含みます。
 – 安定性:デグレや他影響が少ない
   • ソフトウェゕの修正による、予期せぬ影響を避けるソフト
     ウェゕ製品の能力のこと。
 – 試験性:テストするのが楽
   • 修正したソフトウェゕの妥当性確認ができるソフトウェゕ製
     品の能力のこと。
    JIS X 0129-1 ソフトウェゕ製品の品質-第1部:品質モデルより
システム開発で大事なこと
• ゕプリの枠より仕事の枠
 – 個別のゕプリケーションは最適化されていく
   べき。”平均的”なゕプリケーションは存在し
   ない=標準フレームワークって意味あるの?
  • 意味ないことはないけど、緩めに設計する必要が
    ある
 – 仕事の仕方を合わせた方が効果は高い
  • 構成管理重要。ソースコード、課題
  • 自動化重要
システム開発で大事なこと
• バランス、バランス、バランス
 – すべての利害関係者(未来含む)の調整が重
   要
 – 個別最適と全体最適
 – “判断は遅く”でも”早く決める”
設計と実装
 • コンポーネントの集約は大事
   – ただし、機能とクラスは必ず直交するので矛
     盾が生じやすい。もう、これは運命
          クラスA   クラスC         クラスD   クラスG

同じ機能は、同
じクラスに集約                 機能A

                              クラスE
                        機能B
もし変更があれ
ば、すべての機
能に影響が出
てしまう                    機能C

          クラスB                クラスF   クラスH
設計と実装
• コンポーネントの分離は重要
 – 実装要件の違いで切れる
  • トランザクションの切れ目、ゕーキテクチャの切
    れ目、UIとデータとロジック
 – 分業のための分離と、その統合
  • 互いの作業が、なるべく影響し合わないように、
    コンポーネントに分離する
  • ただし、コンポーネントの統合がビッグバンにな
    らないように注意する
   – ゗ンターフェース定義、カプセル化、責務、ロール
設計と実装
• コンポーネントの適切なデザ゗ンが要
 – ただし、要件分析/概要設計段階で織り込む。
   実装/詳細設計段階でデザ゗ンを変えることは
   難しいし、そんなコストはかけられない
  • 再利用=抽象化は設計段階で検討するべき内容
 – コードこそ矛盾のない「真の設計書」
  • 早くコードにするほど矛盾が分かる。プロトタ゗
    プは設計の仕事
設計と実装
• デザ゗ンパターン
 – “デザ゗ン”パターンは”設計”段階で使うもの
 – 設計方法論は難しい。美しい方法論は、基本
   的にあやしい(象牙の塔)
  • DDDは、特に難しいと思う。相当、ドメ゗ンのビ
    ジネス知識がないと無理。
設計と実装
• 未来への対応
 – 5年後の誰かが悲しまないために
  • 「なんだよ、この設計/実装!ありえん」
 – 今後、拡張性や柔軟性がもっと求められる
  • 小規模は作りなおせばいいじゃんでもOK
 – 可変性分析
  • 拡張の方向性や手段について、きちんと確定して
    おく
なぜSpringを使うのか
• Springはフレームワークのフレームワー
  ク
 – 個別ゕプリのためにフレームワークを構築す
   るためのフレームワーク
 – 開発効率よりもSpringらしい”スタ゗ル”を重
   視
 – さまざまな3rd Partyプロダクトに対応し、中
   立性を重んじる。なるべく個性を削らない
 – EAIやSOAなどに連携可能
なぜSpringを使うのか
• Springを使う上では、
 – オススメのプラクテゖスはあまりないので、
   自分で決めてからやる
   • 実装フレームワークもコンポーネント分割も
 – 設定は確かに複雑になるので担当者を明確に
   する。あと設定フゔ゗ルの分離重要
 – 使いこなすとすごいけど、設定が難しいプロ
   ダクトがある
   • WebFlow、Security
なぜSpringを使うのか
• なぜSeasarを使わないのか
 – Seasarは優秀なWebゕプリフレームワーク
 – 開発の効率化、エンジニゕの能力向上に注力
 – プラクテゖス(実践)や規約を重視
 – 適切な部分には、ぜひ使うべき
Springの使い方
• というわけで、非機能の話を中心に
 – コンポーネント化
  • 外部リソースゕクセスの分離
  • 横断的関心事の分離
 – ロギング
 – Maven2のプロフゔ゗ル機能
外部リソースアクセスの分離
• 例:ログ゗ン処理
 – 1.ログ゗ン情報を受け取る
 – 2.LDAPで認証
 – 3.DBからユーザー情報を獲得
 – 4.ログ゗ン履歴を保存
 – 5.認証認可情報を返却する
• 2,3,4は外部リソースゕクセスなので分離
  するように作る
外部リソースアクセスの分離
• シーケンス図

                                              Login
         LoginBL       LDAP認証      UserDao
                                             Logger
ログイン(ログイン情報)

               認証フラグ:認証(認証情報)




               ユーザー情報:検索(ユーザーID)



               ログ(ユーザー情報)


:ユーザー認証情報
外部リソースアクセスの分離
• メリット
 – テストがしやすい、デバッグもしやすい
 – 個別に実装が遅れても逃げられる。たいてい
   は要件確定が遅れる
横断的関心事の分離
• ゕスペクト指向=見地
• 横断的関心事って?
 – 「メソッドの最初や最後に必ず書く」みたい
   なもの
 – ログ、トランザクション、セキュリテゖ
  • ServletFilterは、AOP的

               ア
               ス
               ペ          クラス
               ク
               ト
横断的関心事の分離
• 実装の考え方
 – 基本はProxyパターンで理解する
                                LoginBlImpl
           <Interface>
                                Implements
             LoginBl
                                  LoginBl




                                              LoginBlImpl
  <Interface>         LoginInterceptor
                                              Implements
     MyBl            implements MyBL
                                                LoginBl
横断的関心事の分離
• SpringのAOPを使う
 – ポ゗ントカット:どこに挟むのか
 – ゕドバ゗ザー:何を挟むのか
• 使いどころ
 – 性能検証
 – ゕクセスログ(内部統制で)
 – 更新日や更新者の自動設定
ロギング
• ロギングはSLF4JとLogbackがオススメ
 – Log4jの作者の新作
• 使い方
 – ログ出力:org.slf4j.Logger;
 – 設定: appenderとlogger
ロギング:APIの使い方
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SampleLogic {
  private static Logger logger
    = LoggerFactory.getLogger(SampleLogic.class);

    public void execute() throws Exception {
      if (logger.isTraceEnabled()) {
        logger.trace("trace level");
      }
      if (logger.isDebugEnabled()) {
        logger.debug("debug level");
      }
      logger.info("info level");
      logger.warn("warn level");
      logger.error("error level");
    }
}
ロギング:設定ファイル
<?xml version="1.0" encoding="UTF-8" ?>
 <configuration debug="true">
  <appender name="STDOUT" class="ch.qos.logback.core.Console
    <Target>System.out</Target>
    <layout class="ch.qos.logback.classic.PatternLayout">
     <Pattern>
      %d{HH:mm:ss.SSS} [%thread] %-5level %logger{10} - %msg
     </Pattern>
    </layout>
  </appender>
  <logger name="org.springframework" level="WARN" />
  <logger name="org.apache" level="WARN" />
  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>
ロギング:マーカー
• マーカー
 – マーカーを付けると、出力先を分けることが
   できる。
 private IMarkerFactory markerFactory;

 @Override               マーカーを指定
 public void logging(User user) {

     logger.info(markerFactory.getMarker("login"),
     “user loged in “ + user.getName());

 }
ロギング:マーカー

<appender name=“LOGIN" class="ch.qos.logback.core.ConsoleApp
 <Target>System.out</Target>
 <layout class="ch.qos.logback.classic.PatternLayout">
   <Pattern> LOGIN %logger{10} - %msg%n </Pattern>
 </layout>
 <filter class="jp.arclamp.jsug.sample.log.MarkerFilter">
  <marker>login</marker>
  <OnMismatch>DENY</OnMismatch>
  <OnMatch>ACCEPT</OnMatch>
 </filter>
</appender>

         フィルターを適用して、出力を制御
ロギング:コンバーター
• コンバート
 – 要素conversionRule
   • 属性conversionWord:キーワード
   • 属性converterClass:出力クラス
• パターンのところで出力が可能
 – %{conversionWord}%
• 使いどころ
 – ログへのログ゗ンユーザー情報出力
ロギング:コンバーター
                                              キーワード
<?xml version="1.0" encoding="UTF-8" ?>       の設定
 <configuration debug="true">
  <conversionRule conversionWord="user"
    converterClass=" jp.arclamp.jsug.sample.user.UserInfoCon
                             コンバータークラスの指定
 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleA
  <Target>System.out</Target>
  <layout class="ch.qos.logback.classic.PatternLayout">
   <Pattern>
%d{HH:mm:ss.SSS} [%thread] [%user] %-5level %logger{10} - %m
   </Pattern>
  </layout>
 </appender>                       ここが置換される
 <root level="DEBUG">
  <appender-ref ref="STDOUT" />
 </root>
</configuration>
ロギング:コンバーター
                                             継承してコンバー
package jp.arclamp.jsug.sample.user;         ターを作成

import jp.arclamp.jsug.sample.log.LogConverterTest;
import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.LoggingEvent;

public class UserInfoConverter extends ClassicConverter {
  @Override
  public String convert(LoggingEvent event) {
    return UserInfoHolder.get();
  }
}

         出力する文字列を返却
Maven2のプロファイル機能
• 環境毎に設定フゔ゗ルの切替を実施
 – DB接続設定やログ設定などの切替
 – ローカル、IT、本番…など、プロフゔ゗ルを
   カスタマ゗ズ可能
• コマンドラ゗ン(-P{プロフゔ゗ル名})
 – mvn eclipse:eclipse –Plocal
 – mvn package -Pproduction
Maven2のプロファイル機能
<profiles>          プロファイル名の指定
 <profile>
  <id>local</id>
  <build>
   <resources>                 プロファイルで有効になる
    <resource>                 ディレクトリの指定。
     <directory>src/main/resources/local</directory>
     <includes>
      <include>*.properties</include>
      <include>*.xml</include>
     </includes>
    </resource>
   </resources>
  </build>
</profile>
Maven2のプロファイル機能
• フォルダ側



            他のモノは無視




              クラスパスに通る
サンプルコード
• ブログエントリ

• サンプルコード
ライセンスについて
•   JSUGマスコットゕ゗コン(本スラ゗ド左下)が残されている場合に限り、本作品
    (またそれを元にした派生作品)の複製・頒布・表示・上演を認めます。

•   非商用目的に限り、本作品(またそれを元にした派生作品)の複製・頒布・表示・
    上演を認めます。

•   本作品のラ゗センスを遵守する限り、派生作品を頒布することを許可します。

企業におけるSpring@日本springユーザー会20090624

  • 1.
    企業で使うSpring 鈴木雄介 グロースエクスパートナーズ(株) JSUG/JJUG/SIProp http://www.arclamp.jp/ 2009/6/24
  • 2.
    はじめに • 鈴木雄介 –ITゕーキテクト – 今の主な仕事は、顧客企業側に立って標準化 の策定/推進を行うこと – Spring好き。規約より設定重要 • ゕノテーション嫌い – 今日の目標:難しく言わない – つっこみ歓迎
  • 3.
    アジェンダ • システム開発で大事なこと • 設計と実装 • なぜSpringを使うのか • Springの使い方
  • 4.
    システム開発で大事なこと • “安く作る”より”安く使う” –保守性の高いゕプリ • ゕプリの枠より作業の枠 – 構成管理と自動化 • ベストよりバランス
  • 5.
    システム開発で大事なこと • “安く作る”より”安く使う” –保守費の割合は60-80%程度。最初に作るコ ストのうち実装は1/3程度。つまり、実装コ ストはゕプリの一生からすると7%-13%程度 – 時代背景からすると、今後、ますます仕様変 更は増えている。拡張性は重要なテーマ – 保守性の高いゕプリケーションを、どう作る のか
  • 6.
    参考:保守性 • 保守性とは –解析性:バグの原因を早く見つけたい • ソフトウェゕにある欠陥の診断または故障原因の追及、およ びソフトウェゕの修正箇所の識別を行なうためのソフトウェ ゕ製品の能力のこと。 – 変更性:修正するときにめんどくない • 指定された修正を行なうことができるソフトウェゕ製品の能 力のこと。修正の実施にはコーデゖング、設計、および仕様 書の変更を含みます。 – 安定性:デグレや他影響が少ない • ソフトウェゕの修正による、予期せぬ影響を避けるソフト ウェゕ製品の能力のこと。 – 試験性:テストするのが楽 • 修正したソフトウェゕの妥当性確認ができるソフトウェゕ製 品の能力のこと。 JIS X 0129-1 ソフトウェゕ製品の品質-第1部:品質モデルより
  • 7.
    システム開発で大事なこと • ゕプリの枠より仕事の枠 –個別のゕプリケーションは最適化されていく べき。”平均的”なゕプリケーションは存在し ない=標準フレームワークって意味あるの? • 意味ないことはないけど、緩めに設計する必要が ある – 仕事の仕方を合わせた方が効果は高い • 構成管理重要。ソースコード、課題 • 自動化重要
  • 8.
    システム開発で大事なこと • バランス、バランス、バランス –すべての利害関係者(未来含む)の調整が重 要 – 個別最適と全体最適 – “判断は遅く”でも”早く決める”
  • 9.
    設計と実装 • コンポーネントの集約は大事 – ただし、機能とクラスは必ず直交するので矛 盾が生じやすい。もう、これは運命 クラスA クラスC クラスD クラスG 同じ機能は、同 じクラスに集約 機能A クラスE 機能B もし変更があれ ば、すべての機 能に影響が出 てしまう 機能C クラスB クラスF クラスH
  • 10.
    設計と実装 • コンポーネントの分離は重要 –実装要件の違いで切れる • トランザクションの切れ目、ゕーキテクチャの切 れ目、UIとデータとロジック – 分業のための分離と、その統合 • 互いの作業が、なるべく影響し合わないように、 コンポーネントに分離する • ただし、コンポーネントの統合がビッグバンにな らないように注意する – ゗ンターフェース定義、カプセル化、責務、ロール
  • 11.
    設計と実装 • コンポーネントの適切なデザ゗ンが要 –ただし、要件分析/概要設計段階で織り込む。 実装/詳細設計段階でデザ゗ンを変えることは 難しいし、そんなコストはかけられない • 再利用=抽象化は設計段階で検討するべき内容 – コードこそ矛盾のない「真の設計書」 • 早くコードにするほど矛盾が分かる。プロトタ゗ プは設計の仕事
  • 12.
    設計と実装 • デザ゗ンパターン –“デザ゗ン”パターンは”設計”段階で使うもの – 設計方法論は難しい。美しい方法論は、基本 的にあやしい(象牙の塔) • DDDは、特に難しいと思う。相当、ドメ゗ンのビ ジネス知識がないと無理。
  • 13.
    設計と実装 • 未来への対応 –5年後の誰かが悲しまないために • 「なんだよ、この設計/実装!ありえん」 – 今後、拡張性や柔軟性がもっと求められる • 小規模は作りなおせばいいじゃんでもOK – 可変性分析 • 拡張の方向性や手段について、きちんと確定して おく
  • 14.
    なぜSpringを使うのか • Springはフレームワークのフレームワー ク – 個別ゕプリのためにフレームワークを構築す るためのフレームワーク – 開発効率よりもSpringらしい”スタ゗ル”を重 視 – さまざまな3rd Partyプロダクトに対応し、中 立性を重んじる。なるべく個性を削らない – EAIやSOAなどに連携可能
  • 15.
    なぜSpringを使うのか • Springを使う上では、 –オススメのプラクテゖスはあまりないので、 自分で決めてからやる • 実装フレームワークもコンポーネント分割も – 設定は確かに複雑になるので担当者を明確に する。あと設定フゔ゗ルの分離重要 – 使いこなすとすごいけど、設定が難しいプロ ダクトがある • WebFlow、Security
  • 16.
    なぜSpringを使うのか • なぜSeasarを使わないのか –Seasarは優秀なWebゕプリフレームワーク – 開発の効率化、エンジニゕの能力向上に注力 – プラクテゖス(実践)や規約を重視 – 適切な部分には、ぜひ使うべき
  • 17.
    Springの使い方 • というわけで、非機能の話を中心に –コンポーネント化 • 外部リソースゕクセスの分離 • 横断的関心事の分離 – ロギング – Maven2のプロフゔ゗ル機能
  • 18.
    外部リソースアクセスの分離 • 例:ログ゗ン処理 –1.ログ゗ン情報を受け取る – 2.LDAPで認証 – 3.DBからユーザー情報を獲得 – 4.ログ゗ン履歴を保存 – 5.認証認可情報を返却する • 2,3,4は外部リソースゕクセスなので分離 するように作る
  • 19.
    外部リソースアクセスの分離 • シーケンス図 Login LoginBL LDAP認証 UserDao Logger ログイン(ログイン情報) 認証フラグ:認証(認証情報) ユーザー情報:検索(ユーザーID) ログ(ユーザー情報) :ユーザー認証情報
  • 20.
    外部リソースアクセスの分離 • メリット –テストがしやすい、デバッグもしやすい – 個別に実装が遅れても逃げられる。たいてい は要件確定が遅れる
  • 21.
    横断的関心事の分離 • ゕスペクト指向=見地 • 横断的関心事って? – 「メソッドの最初や最後に必ず書く」みたい なもの – ログ、トランザクション、セキュリテゖ • ServletFilterは、AOP的 ア ス ペ クラス ク ト
  • 22.
    横断的関心事の分離 • 実装の考え方 –基本はProxyパターンで理解する LoginBlImpl <Interface> Implements LoginBl LoginBl LoginBlImpl <Interface> LoginInterceptor Implements MyBl implements MyBL LoginBl
  • 23.
    横断的関心事の分離 • SpringのAOPを使う –ポ゗ントカット:どこに挟むのか – ゕドバ゗ザー:何を挟むのか • 使いどころ – 性能検証 – ゕクセスログ(内部統制で) – 更新日や更新者の自動設定
  • 24.
    ロギング • ロギングはSLF4JとLogbackがオススメ –Log4jの作者の新作 • 使い方 – ログ出力:org.slf4j.Logger; – 設定: appenderとlogger
  • 25.
    ロギング:APIの使い方 import org.slf4j.Logger; import org.slf4j.LoggerFactory; publicclass SampleLogic { private static Logger logger = LoggerFactory.getLogger(SampleLogic.class); public void execute() throws Exception { if (logger.isTraceEnabled()) { logger.trace("trace level"); } if (logger.isDebugEnabled()) { logger.debug("debug level"); } logger.info("info level"); logger.warn("warn level"); logger.error("error level"); } }
  • 26.
    ロギング:設定ファイル <?xml version="1.0" encoding="UTF-8"?> <configuration debug="true"> <appender name="STDOUT" class="ch.qos.logback.core.Console <Target>System.out</Target> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> %d{HH:mm:ss.SSS} [%thread] %-5level %logger{10} - %msg </Pattern> </layout> </appender> <logger name="org.springframework" level="WARN" /> <logger name="org.apache" level="WARN" /> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>
  • 27.
    ロギング:マーカー • マーカー –マーカーを付けると、出力先を分けることが できる。 private IMarkerFactory markerFactory; @Override マーカーを指定 public void logging(User user) { logger.info(markerFactory.getMarker("login"), “user loged in “ + user.getName()); }
  • 28.
    ロギング:マーカー <appender name=“LOGIN" class="ch.qos.logback.core.ConsoleApp <Target>System.out</Target> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> LOGIN %logger{10} - %msg%n </Pattern> </layout> <filter class="jp.arclamp.jsug.sample.log.MarkerFilter"> <marker>login</marker> <OnMismatch>DENY</OnMismatch> <OnMatch>ACCEPT</OnMatch> </filter> </appender> フィルターを適用して、出力を制御
  • 29.
    ロギング:コンバーター • コンバート –要素conversionRule • 属性conversionWord:キーワード • 属性converterClass:出力クラス • パターンのところで出力が可能 – %{conversionWord}% • 使いどころ – ログへのログ゗ンユーザー情報出力
  • 30.
    ロギング:コンバーター キーワード <?xml version="1.0" encoding="UTF-8" ?> の設定 <configuration debug="true"> <conversionRule conversionWord="user" converterClass=" jp.arclamp.jsug.sample.user.UserInfoCon コンバータークラスの指定 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleA <Target>System.out</Target> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> %d{HH:mm:ss.SSS} [%thread] [%user] %-5level %logger{10} - %m </Pattern> </layout> </appender> ここが置換される <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>
  • 31.
    ロギング:コンバーター 継承してコンバー package jp.arclamp.jsug.sample.user; ターを作成 import jp.arclamp.jsug.sample.log.LogConverterTest; import ch.qos.logback.classic.pattern.ClassicConverter; import ch.qos.logback.classic.spi.LoggingEvent; public class UserInfoConverter extends ClassicConverter { @Override public String convert(LoggingEvent event) { return UserInfoHolder.get(); } } 出力する文字列を返却
  • 32.
    Maven2のプロファイル機能 • 環境毎に設定フゔ゗ルの切替を実施 –DB接続設定やログ設定などの切替 – ローカル、IT、本番…など、プロフゔ゗ルを カスタマ゗ズ可能 • コマンドラ゗ン(-P{プロフゔ゗ル名}) – mvn eclipse:eclipse –Plocal – mvn package -Pproduction
  • 33.
    Maven2のプロファイル機能 <profiles> プロファイル名の指定 <profile> <id>local</id> <build> <resources> プロファイルで有効になる <resource> ディレクトリの指定。 <directory>src/main/resources/local</directory> <includes> <include>*.properties</include> <include>*.xml</include> </includes> </resource> </resources> </build> </profile>
  • 34.
    Maven2のプロファイル機能 • フォルダ側 他のモノは無視 クラスパスに通る
  • 35.
  • 36.
    ライセンスについて • JSUGマスコットゕ゗コン(本スラ゗ド左下)が残されている場合に限り、本作品 (またそれを元にした派生作品)の複製・頒布・表示・上演を認めます。 • 非商用目的に限り、本作品(またそれを元にした派生作品)の複製・頒布・表示・ 上演を認めます。 • 本作品のラ゗センスを遵守する限り、派生作品を頒布することを許可します。