<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>kamolog &#187; 設計</title>
	<atom:link href="http://www.mkamo.org/blog/category/dev/design/feed" rel="self" type="application/rss+xml" />
	<link>http://www.mkamo.org/blog</link>
	<description>mkamo&#039;s blog ．．．．． mkamo&#039;s memo?</description>
	<lastBuildDate>Tue, 13 Jul 2010 12:07:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>エラー内容の流し方</title>
		<link>http://www.mkamo.org/blog/20080728/83.html</link>
		<comments>http://www.mkamo.org/blog/20080728/83.html#comments</comments>
		<pubDate>Mon, 28 Jul 2008 12:04:50 +0000</pubDate>
		<dc:creator>mkamo</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[設計]]></category>

		<guid isPermaLink="false">http://www.mkamo.org/blog/20080728/83.html</guid>
		<description><![CDATA[J2EEで開発しているプロジェクトで，EJB層で検出したエラーチェック内容をvalue objectのプロパティとして流しているのを見かけた．問題点と改善案を示してみる．

まずは現状の説明から．EJB層からの戻り値とな [...]]]></description>
			<content:encoded><![CDATA[<p>J2EEで開発しているプロジェクトで，EJB層で検出したエラーチェック内容をvalue objectのプロパティとして流しているのを見かけた．問題点と改善案を示してみる．</p>
<p><span id="more-83"></span>
<p>まずは現状の説明から．EJB層からの戻り値となるvalue objectでは，EJB層で検出するひとつのエラーに対して，ひとつの～Flgというvalue objectのプロパティを定義している．</p>
</p>
<div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:431d4a64-d2ef-4542-970b-e24ffc2f547e" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="java:nogutter:nocontrols">public class FooResult {
    private boolean hogeCodeErrorFlg;
    private boolean gehoCodeErrorFlg;

    public boolean getHogeCodeErrorFlg() {
        return hogeCodeErrorFlg;
    }
    public void setHogeCodeErrorFlg(boolean value) {
        this.hogeCodeErrorFlg = value;
    }

    public boolean getGehoCodeErrorFlg() {
        return gehoCodeErrorFlg;
    }
    public void setGehoCodeErrorFlg(boolean value) {
        this.gehoCodeErrorFlg = value;
    }
}</pre>
</div>
</p>
<p>EJB層ではメソッドの戻り値として返すFooResultに対して，エラーがあった場合はそれぞれのプロパティにfalseを，なかった場合にはtrueを設定している．</p>
<div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:bf6ce2a3-22dd-4341-8b0d-d984ca8ee1a5" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="java:nogutter:nocontrols">public FooResult foo(...) throws Exception {
    FooResult result = new FooResult();

    if (validateHogeCode(...)) {
        result.setHogeCodeErrorFlg(true);
    } else {
        result.setHogeCodeErrorFlg(false);
    }

    if (validateGehoCode(...)) {
        result.setGehoCodeErrorFlg(true);
    } else {
        result.setGehoCodeErrorFlg(false);
    }

    /// do something...

    return result;
}</pre>
</div>
<p>JSP/Servlet層では，このvalue objectのget～Flg()をそれぞれ調べて，falseの場合はエラーを表示している．以下の例ではstrutsのタグを使ってエラーを表示している．</p>
</p>
<div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:a380b143-5e36-4c3b-8e0d-fc4405425a27" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="xml:nogutter:nocontrols">&lt;logic:equal name="fooResult" property="hogeCodeErrorFlg" value="false"&gt;
    &lt;%= "hogeコードがおかしいですよ．" %&gt;
&lt;/logic:equal&gt;

&lt;logic:equal name="fooResult" property="gehoCodeErrorFlg" value="false"&gt;
    &lt;%= "gehoコードがおかしいですよ．" %&gt;
&lt;/logic:equal&gt;</pre>
</div>
<p>このコードにはいくつかの問題点がある．</p>
<p>まず大きな問題として，エラーの追加という変更に対して非常に弱いということである．EJB層のfoo()メソッドで行うエラーチェックをひとつ増やすと，上で示した3つのコードのすべての箇所で修正が必要である．データ・ロジック・表示の修正が必要と，まさにダメ三冠王である．例えばFooResultではエラー内容をListなどに格納しておき，JSP/Servlet層ではそのListの中身を順番に表示する，といった形にすればデータと表示に関してはエラーの追加による影響を減らすことができる．</p>
<p>次に気になるのはプロパティ名である．boolean型のプロパティ名に～Flg，～Flagなどと名づけるのは基本的にはご法度である．hogeCodeErrorFlgといわれても，エラーがあった場合の値がtrueなのかfalseなのかわからない．実際私は上のコードを書いていて何度かtrueとfalseを間違えてしまった．boolean型のプロパティ名は，is～，has～，can～のどれかの名前にしないといけない，と思っておけば問題ない．例えばisValidHogeCodeやisNotValidHogeCodeといったプロパティ名にしておけば，エラーがあった場合の値がtrueなのかfalseなのかはプロパティ名だけから推測できる．</p>
<p>改善案の一例を以下に示しておく．エラー情報保持用のValidationErrorクラスを定義し，FooResultがリストでエラーを保持できる形にする．なお，この例では簡単のため，エラーメッセージをValidateionErrorのプロパティとして持たせているが，idとエラーの原因となった入力値だけをプロパティに持たせておいて，JSP/Servlet層でそれらの値からメッセージを組み立てるようにした方がよいこともある．</p>
</p>
<div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:4e792726-b45e-47c1-aab5-5ea3ab508299" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="java:nogutter:nocontrols">/// なにかしらのエラー情報を持つクラス
public class ValidationError {
    /// エラーの種別を表すID
    private String id;
    /// エラーメッセージ
    private String message;

    public ValidationError(String id, String message) {
        this.id = id;
        this.message = message;
    }
    public String getId() {
        return id;
    }
    public String getMessage() {
        return message;
    }
}

/// エラー情報をリストで保持
public class FooResult {
    private List&lt;ValidationError&gt; errors;
    public FooResult() {
        errors = new ArrayList&lt;ValidationError&gt;();
    }
    public List&lt;ValidationError&gt; getErrors() {
        return errors;
    }
}</pre>
</div>
<p>EJB層では，エラーがあったときにValidationErrorオブジェクトを生成して，FooResultのerrorsプロパティに追加する．</p>
<div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b310f955-db54-4149-b496-bd6801c61e44" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="java:nogutter:nocontrols">public FooResult foo(...) throws Exception {
    FooResult result = new FooResult();

    if (!validateHogeCode(...)) {
        result.getErrors().add(
            new ValidationError("error.isNotValidHogeCode", "hogeコードがおかしいですよ．");
        );
    }

    if (!validateGehoCode(...)) {
        result.getErrors().add(
            new ValidationError("error.isNotValidGehoCode", "gehoコードがおかしいですよ．");
        );
    }

    /// do something...

    return result;
}</pre>
</div>
<p>JSP/Servlet層では，FooResultのerrorsプロパティに格納されているValidationErrorのmessageプロパティを順次表示する．</p>
<div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:fd807049-1a5f-4741-bc20-26da8267f20a" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="xml:nogutter:nocontrols">&lt;logic:iterate id="error" name="fooResult" property="errors"&gt;
    &lt;bean:write name="error" property="message"/&gt;
&lt;/logic:iterate&gt;
</pre>
</div>
<p>これでエラーチェックを追加する場合でも，EJB層のfoo()メソッドのコードの修正だけで対応できるようになる．</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mkamo.org/blog/20080728/83.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>親が消されたときに子をどうするか</title>
		<link>http://www.mkamo.org/blog/20080721/67.html</link>
		<comments>http://www.mkamo.org/blog/20080721/67.html#comments</comments>
		<pubDate>Mon, 21 Jul 2008 08:06:38 +0000</pubDate>
		<dc:creator>mkamo</dc:creator>
				<category><![CDATA[設計]]></category>

		<guid isPermaLink="false">http://www.mkamo.org/blog/20080721/67.html</guid>
		<description><![CDATA[親子関係にあるオブジェクトやテーブルで親が消されるときに子をどうするべきか．典型的なものを以下に示す．


子があるときは親を削除できない
親を削除したければすべての子を先に削除しておく必要がある．利用者の負荷は高いが， [...]]]></description>
			<content:encoded><![CDATA[<p>親子関係にあるオブジェクトやテーブルで親が消されるときに子をどうするべきか．典型的なものを以下に示す．</p>
<p><span id="more-67"></span></p>
<ul>
<li>子があるときは親を削除できない<br />
親を削除したければすべての子を先に削除しておく必要がある．利用者の負荷は高いが，意図しない子の削除が行われにくい．</li>
<li>すべての子を削除する<br />
親を削除されたときに自動的に子も巻き込んで削除する．利用者の負荷は低くなるが，意図しない子の削除が行われる危険性が高い．</li>
<li>すべての子の親への参照をnullにする<br />
子が孤児状態で存在できる場合はこういうやり方も取れる．親を経由せずに孤児を直接管理できるインタフェースが必要になる．</li>
<li>親を実際には消さずに，削除されたことを記録するだけにする<br />
親や子が重要なデータであったり，削除後もなんらかの形で参照できる必要性がある場合は，こうしたやり方にする．親に削除フラグを立てて，親に対する直接的な検索や更新は無効にする．ただし，子からたどって親の情報を参照することは可能にしておく．</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.mkamo.org/blog/20080721/67.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
