<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="Content-Script-Type" content="text/javascript" />
    <meta http-equiv="Content-Style-Type" content="text/css" />
    <title>アプリケーションアーキテクチャ標準</title>
    <link rel="stylesheet" href="/css/style.css" type="text/css" media="all" />
    
    
  </head>
  <body>
    <div class="header">
      <div id="pane.left-header" class="pane left">
        <div id="org.seasar.kvasir.cms.toolbox.customPop-2" class="pop org.seasar.kvasir.cms.toolbox.customPop">
          <div class="body"><div class="wiki">
<ul>
<li><a href="/" class="pageNotFound">（サイトトップ）</a></li>
<li><a href="/download">ダウンロード</a></li>
<li><a href="/news/" class="pageNotFound">新着情報</a></li>
<li><a href="/docs/" class="pageNotFound">ドキュメント</a></li>
</ul>
</div>
</div>
        </div>
      </div>
      <div id="pane.right-header" class="pane right">
        <div id="org.seasar.kvasir.cms.toolbox.loginPop-1" class="pop org.seasar.kvasir.cms.toolbox.loginPop">
          <div class="body">
<form method="post" action="/plugins/toolbox/login.do/docs/1.0.x/ref/standardArchitecture">
    <div class="row">
      <span class="label">Name</span>
      <span class="textinput"><input type="text" name="name" size="12" value="" /></span>
    </div>
    <div class="row">
      <span class="label">Password</span>
      <span class="textinput"><input type="password" name="password" size="12" value="" /></span>
    </div>
    <div class="row">
      <span class="submit"><input type="submit" value="Login" /></span>
    </div>
</form>
</div>
        </div><div id="org.seasar.kvasir.cms.pop.loginUserPop-1" class="pop org.seasar.kvasir.cms.pop.loginUserPop">
          <div class="body"></div>
        </div>
      </div>
    </div>
    <div class="page-frame">
      <div id="pane.left-sidebar" class="pane sidebar-frame sidebar subcontent">
        <div id="org.seasar.kvasir.cms.toolbox.searchPop-1" class="pop org.seasar.kvasir.cms.toolbox.searchPop">
          <h2 class="title">Search</h2>
          <div class="body"><form class="simple" method="get" action="/plugins/toolbox/search.do">
  <input type="text" name="query" size="12" />
  <input type="submit" value="Go!" />
</form>
</div>
        </div><div id="org.seasar.kvasir.cms.toolbox.customPop-1" class="pop org.seasar.kvasir.cms.toolbox.customPop">
          <h2 class="title">メニュー</h2>
          <div class="body"><ul>
  <li><a href="/" class="pageNotFound">（サイトトップ）</a></li>
  <li><a href="/download">ダウンロード</a></li>
  <li><a href="/news">新着情報</a></li>
  
    
    
      <li>
        <a href="/docs/1.0.x/user">ユーザマニュアル</a>
        <ul>
          <li>
            <a href="/docs/1.0.x/user/description">Ymirとは</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/processFlow">Ymirの処理フロー</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/projectStatus">動作ステータス</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/generator">自動生成機能</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/vili">Eclipseプラグイン「Vili（ヴィリ）」</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/ve">Eclipseプラグイン「Ve（ヴェー）」</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/setUp">セットアップ</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/skeleton">空のアプリケーション</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/example">サンプルアプリケーションの作成</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/development">開発における注意点</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/faq">FAQ</a>
            
          </li>
        </ul>
      </li><li>
        <a href="/docs/1.0.x/ref">リファレンスマニュアル</a>
        <ul>
          <li>
            <a href="/docs/1.0.x/ref/pageClass">Pageクラス</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/pathMapping">リクエストパスとPageクラスのマッピング</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/response">レスポンス</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/fileupload">ファイルアップロード</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/typeConversion">型の自動変換</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/zptTemplate">ZPTテンプレート</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/constraintCheck">制約チェック</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/validation">バリデーション</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/transactionToken">トランザクショントークン</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/permissionCheck">権限チェック</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/objectScope">オブジェクトスコープ</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/i18n">国際化</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/exceptionHandler">例外処理</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/include">インクルード</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/conversation">カンバセーション</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/appProperties">アプリケーションの設定</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/dicon">diconファイルの扱い</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/standardArchitecture">アプリケーションアーキテクチャ標準</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/ymirJson">JSON連携</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/batch">バッチプログラムの作成</a>
            
          </li>
        </ul>
      </li><li>
        <a href="/docs/1.0.x/dev">Ymir開発者マニュアル</a>
        <ul>
          <li>
            <a href="/docs/1.0.x/dev/build">Ymirのビルド</a>
            
          </li><li>
            <a href="/docs/1.0.x/dev/release">Ymirのリリース</a>
            
          </li><li>
            <a href="/docs/1.0.x/dev/update-ymir-fragment-dbflute">DBFluteフラグメントの更新</a>
            
          </li>
        </ul>
      </li><li>
        <a href="/docs/1.0.x/etc">その他</a>
        
      </li><li>
        <a href="/docs/1.0.x/glossary">用語集</a>
        <ul>
          <li>
            <a href="/docs/1.0.x/glossary/Vili">Vili</a>
            
          </li><li>
            <a href="/docs/1.0.x/glossary/ve">Ve</a>
            
          </li>
        </ul>
      </li>
    
  
  <li><a href="/roadmap">ロードマップ</a></li>
  <li><a href="https://www.seasar.org/issues/browse/YMIR">既知の不具合を閲覧する・不具合を報告する</a></li>
  <li><a href="https://www.seasar.org/svn/ymir/">SVNリポジトリ</a></li>
  <li><a href="http://svn.seasar.org/browse/?root=ymir">SVNリポジトリを閲覧</a></li>
</ul>
</div>
        </div>
      </div>
      <div id="pane.main" class="pane main">
      
        <div id="org.seasar.kvasir.cms.toolbox.breadcrumbsPop-1" class="pop org.seasar.kvasir.cms.toolbox.breadcrumbsPop">
          
          <div class="body"><ul>
  <li class="first"><a href="/">(TOP)</a></li><li><a href="/docs">ドキュメント</a></li><li><a href="/docs/1.0.x">ドキュメント（1.0.x系）</a></li><li><a href="/docs/1.0.x/ref">リファレンスマニュアル</a></li><li>アプリケーションアーキテクチャ標準</li>
</ul>
</div>
        </div><div id="org.seasar.kvasir.cms.pop.contentPop-1" class="pop org.seasar.kvasir.cms.pop.contentPop">
          <h2 class="title">アプリケーションアーキテクチャ標準</h2>
          <div class="body">
<ul class="information">
  
  <li>2010-02-25 17:27:34</li>
</ul>
<div class="content"><div class="document">
<p>この文書では、<a class="reference" href="/docs/1.0.x/glossary/vili">Vili</a>で作成した空のYmirプロジェクトを基にアプリケーションを開発する際の標準的なアプリケーションアーキテクチャについて説明します。なお以下の内容はあくまで標準であり、他の規則に従ってアプリケーションを作ることももちろんできます。</p>
<div class="section" id="e382a2e38397e383aae382b1e383bce382b7e383a7e383b3e381aee6a78be68890e382afe383a9e382b9">
<h3><a name="e382a2e38397e383aae382b1e383bce382b7e383a7e383b3e381aee6a78be68890e382afe383a9e382b9">アプリケーションの構成クラス</a></h3>
<p>アプリケーションの構成クラスには以下のものがあります。</p>
<dl class="docutils">
<dt>Page</dt>
<dd>
<p>リクエストを処理するクラスです。通常Pageの<tt class="docutils literal"><span class="pre">_</span></tt>で始まるメソッド（アクションメソッド）がリクエストの処理のエントリポイントとなります。アクションメソッドからはServiceクラスのメソッドが呼び出されます。</p>
<p>インスタンスは1リクエストにつき1つ生成されます。</p>
</dd>
<dt>Service</dt>
<dd>
<p>プレゼンテーションと関連の強いロジックを記述するためのクラスです。通常Pageと1対1対応します。ServiceクラスのメソッドからはLogicクラスのメソッドが呼び出されます。</p>
<p>アプリケーションの規模によっては、Serviceクラスを省略してServiceクラスに書くべき処理をPageクラスに記述しても構いません。</p>
<p>インスタンスはシングルトンです。</p>
</dd>
<dt>Logic</dt>
<dd>
<p>画面と直接結びつかないビジネスロジックを記述するためのクラスです。LogicクラスのメソッドからはHelperクラスのメソッドまたはDaoクラスのメソッドまたはDBFluteのBhvクラスのメソッドが呼び出されます。</p>
<p>インスタンスはシングルトンです。</p>
</dd>
<dt>Helper</dt>
<dd>
<p>ビジネスロジックのうち、データベースアクセスを行なわないロジックを記述するためのクラスです。</p>
<p>アプリケーションの規模によっては、Helperクラスを省略して処理をHelperクラスに書くべき処理をLogicクラスに記述しても構いません。</p>
<p>インスタンスはシングルトンです。</p>
</dd>
<dt>Dao</dt>
<dd>
<p>データベースにアクセスするためのクラスです。S2Daoを直接利用する場合に使用します。DBFluteを利用する場合は基本的に使用することはありません。</p>
<p>インスタンスはシングルトンです。</p>
</dd>
<dt>Entity</dt>
<dd>
<p>データベースのテーブルの行に対応するクラスです。</p>
<p>インスタンスの生成は通常DIコンテナの外で行なわれます。</p>
</dd>
<dt>Dto</dt>
<dd>
<p>画面で指定されたリクエストパラメータを保持したり、画面の動的な表示要素を保持するためのクラスです。</p>
<p>インスタンスの生成は通常DIコンテナの外で行なわれます。</p>
</dd>
<dt>Converter</dt>
<dd>
<p>DtoとデータベースのEntityとの値の変換を行なうためのクラスです。</p>
<p>インスタンスはシングルトンです。</p>
</dd>
<dt>Dxo</dt>
<dd>
<p>リフレクションベースのデータ変換を行なうためのクラスです。リフレクションベースのデータ変換は挙動をカスタマイズしにくい、リファクタリングに弱いという特徴があるため、Ymirの標準アプリケーションアーキテクチャでは使用を推奨しません。</p>
<p>インスタンスはシングルトンです。</p>
</dd>
<dt>Handler</dt>
<dd>
<p>例外がスローされた場合の処理を記述するためのクラスです。</p>
<p>インスタンスは1リクエストにつき1つ生成されます。</p>
</dd>
<dt>Constraint</dt>
<dd>
<p><a class="reference" href="/docs/1.0.x/ref/constraintCheck">制約チェック</a>を行なうためのクラスです。</p>
<p>インスタンスはシングルトンです。</p>
</dd>
<dt>Interceptor</dt>
<dd>
<p>S2Containerのインターセプタクラスです。</p>
<p>インスタンスはシングルトンです。</p>
</dd>
<dt>Bhv</dt>
<dd>
<p>データベースにアクセスするためのクラスです。DBFluteを利用する場合に使用します。</p>
<p>インスタンスはシングルトンです。</p>
</dd>
</dl>
<table border="1" class="docutils">
<colgroup>
<col width="10%" />
<col width="8%" />
<col width="14%" />
<col width="10%" />
<col width="10%" />
<col width="5%" />
<col width="5%" />
<col width="18%" />
<col width="20%" />
</colgroup>
<thead valign="bottom">
<tr>
<th>種類</th>
<th>サフィックス</th>
<th>パッケージ名</th>
<th>ライフサイクル</th>
<th>HOT Deploy対応</th>
<th>自動登録</th>
<th>自動生成</th>
<th>インタフェースと実装の分離</th>
<th>備考</th>
</tr>
</thead>
<tbody valign="top">
<tr>
<td>Bhv</td>
<td>Bhv</td>
<td>ROOT.dbflute.exbhv</td>
<td>singleton</td>
<td>×</td>
<td>○</td>
<td>○</td>
<td>しない</td>
<td>DBFluteと組み合わせた場合のみ</td>
</tr>
<tr>
<td>Constraint</td>
<td>Constraint</td>
<td>ROOT.constraint</td>
<td>singleton</td>
<td>○</td>
<td>○</td>
<td>×</td>
<td>しない</td>
<td>対応するアノテーションはROOT.constraint.annotationパッケージに置かれる</td>
</tr>
<tr>
<td>Converter</td>
<td>Converter</td>
<td>ROOT.converter</td>
<td>singleton</td>
<td>○</td>
<td>○</td>
<td>○</td>
<td>しない</td>
<td></td>
</tr>
<tr>
<td>Dao</td>
<td>Dao</td>
<td>ROOT.dao</td>
<td>singleton</td>
<td>○</td>
<td>○</td>
<td>×</td>
<td>しない</td>
<td></td>
</tr>
<tr>
<td>Dto</td>
<td>Dto</td>
<td>ROOT.dto</td>
<td>prototype</td>
<td>○</td>
<td>×</td>
<td>○</td>
<td>しない</td>
<td></td>
</tr>
<tr>
<td>Dxo</td>
<td>Dxo</td>
<td>ROOT.dxo</td>
<td>singleton</td>
<td>○</td>
<td>○</td>
<td>×</td>
<td>しない</td>
<td></td>
</tr>
<tr>
<td>Entity(S2Dao)</td>
<td>(なし)</td>
<td>ROOT.entity</td>
<td>prototype</td>
<td>×</td>
<td>×</td>
<td>×</td>
<td>しない</td>
<td></td>
</tr>
<tr>
<td>Entity(DBFlute)</td>
<td>(なし)</td>
<td>ROOT.dbflute.exentity</td>
<td>prototype</td>
<td>×</td>
<td>×</td>
<td>○</td>
<td>しない</td>
<td>DBFluteと組み合わせた場合のみ</td>
</tr>
<tr>
<td>Handler</td>
<td>Handler</td>
<td>ROOT.handler</td>
<td>request</td>
<td>○</td>
<td>○</td>
<td>×</td>
<td>しない</td>
<td></td>
</tr>
<tr>
<td>Helper</td>
<td>Helper</td>
<td>ROOT.helper</td>
<td>singleton</td>
<td>○</td>
<td>○</td>
<td>×</td>
<td>しない</td>
<td></td>
</tr>
<tr>
<td>Interceptor</td>
<td>Interceptor</td>
<td>ROOT.interceptor</td>
<td>singleton</td>
<td>○</td>
<td>○</td>
<td>×</td>
<td>しない</td>
<td></td>
</tr>
<tr>
<td>Logic</td>
<td>Logic</td>
<td>ROOT.logic</td>
<td>singleton</td>
<td>○</td>
<td>○</td>
<td>×</td>
<td>しない</td>
<td></td>
</tr>
<tr>
<td>Page</td>
<td>Page</td>
<td>ROOT.web</td>
<td>request</td>
<td>○</td>
<td>○</td>
<td>○</td>
<td>しない</td>
<td></td>
</tr>
<tr>
<td>Service</td>
<td>Service</td>
<td>ROOT.service</td>
<td>singleton</td>
<td>○</td>
<td>○</td>
<td>×</td>
<td>しない</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="e383aae382afe382a8e382b9e38388e381aee587a6e79086e381aee6b581e3828c">
<h3><a name="e383aae382afe382a8e382b9e38388e381aee587a6e79086e381aee6b581e3828c">リクエストの処理の流れ</a></h3>
<p>リクエストを受け取った場合、処理はPage (→Service) →Logic→ (Helper, ) Dao, Bhvのように呼び出されます。</p>
</div>
<div class="section" id="e38388e383a9e383b3e382b6e382afe382b7e383a7e383b3e5a283e7958c">
<h3><a name="e38388e383a9e383b3e382b6e382afe382b7e383a7e383b3e5a283e7958c">トランザクション境界</a></h3>
<p>デフォルトのトランザクション境界はPageクラスのGETまたはPOSTリクエストに対応するアクションメソッドです。具体的には名前が「<tt class="docutils literal"><span class="pre">_get</span></tt>」または「<tt class="docutils literal"><span class="pre">_post</span></tt>」で開始されるpublicメソッドです。</p>
<p>それ以外の処理、例えば制約チェック等のフレームワークによって自動的に実行される処理についてはトランザクションが開始されませんので、必要に応じて明示的にトランザクションを開始する必要があります。</p>
<p>ある種別のクラスについてトランザクション境界をまとめて設定するには、ymir-customizer.diconの設定をオーバライドして下さい。例えばLogicクラスが持つ全てのpublicメソッド（Objectクラスに属しているものを除く）についてトランザクションを開始したい場合は次のようなファイルをsrc/main/resources/ymir-customizer+logicCustomizer.diconとして追加して下さい:</p>
<pre class="literal-block">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!DOCTYPE components PUBLIC &quot;-//SEASAR//DTD S2Container 2.4//EN&quot;
  &quot;http://www.seasar.org/dtd/components24.dtd&quot;&gt;
&lt;components&gt;
  &lt;component name=&quot;logicCustomizer&quot;
    class=&quot;org.seasar.framework.container.customizer.CustomizerChain&quot;&gt;
    &lt;initMethod name=&quot;addCustomizer&quot;&gt;
      &lt;arg&gt;
        &lt;component
          class=&quot;org.seasar.framework.container.customizer.AspectCustomizer&quot;&gt;
          &lt;property name=&quot;interceptorName&quot;&gt;&quot;j2ee.requiredTx&quot;&lt;/property&gt;
        &lt;/component&gt;
      &lt;/arg&gt;
    &lt;/initMethod&gt;
  &lt;/component&gt;
&lt;/components&gt;
</pre>
<p>また、Pageクラスにトランザクション境界を設定したくない場合は、次のようなsrc/main/resources/ymir-customizer+pageCustomizer.diconを追加して下さい:</p>
<pre class="literal-block">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!DOCTYPE components PUBLIC &quot;-//SEASAR//DTD S2Container 2.4//EN&quot;
  &quot;http://www.seasar.org/dtd/components24.dtd&quot;&gt;
&lt;components&gt;
  &lt;component name=&quot;pageCustomizer&quot;
    class=&quot;org.seasar.framework.container.customizer.CustomizerChain&quot; /&gt;
&lt;/components&gt;
</pre>
</div>
<div class="section" id="e383a6e3838be38383e38388e38386e382b9e38388">
<h3><a name="e383a6e3838be38383e38388e38386e382b9e38388">ユニットテスト</a></h3>
<p>ユニットテストでは極力モッククラスを作らずに、ユニットテスト用のデータをデータベースに登録して実際にデータベースアクセスすることで実際のロジックを通しで検証するやり方を推奨します。これはモッククラスを使ったテストは思いの他コストがかかるためです。モックを使ったテストを作成したとしても実際のロジックを通すテストはどの道作成する必要があるため、純粋にモックを使ったテスト分の工数を削減することができます。</p>
<p>DBFluteを利用することで、このようなユニットテストの作成と実施は容易になります。</p>
</div>
</div>
</div>
</div>
        </div>
      
    </div>
    </div>
    <div class="footer-delimiter"></div>
    <div id="pane.footer" class="pane footer">
      <div id="org.seasar.kvasir.cms.pop.poweredByPop-1" class="pop org.seasar.kvasir.cms.pop.poweredByPop">
        <div class="body">Powered by Kvasir/Sora</div>
      </div>
    </div>
  </body>
</html>
