この記事は「こちら」に移動しました。


連載

Javaオブジェクトモデリング

第4回
静的モデル:クラスにおけるUMLとJavaのマッピング(2)

8.マッピング例

■■8.1 具象クラス■■

 Javaによる具象クラスの実現例はリスト6のようになります

リスト6 Account.java(リストのダウンロード)
public class Account {
     private String id;
      private String name;
      private long balance;
  

       public Account(String id, String name) {
            this.id = id;
            this.name = name;
        this.balance = 0;
    }   

    public void setBalance(long balance) {
    this.balance = balance;
    }   
  
    public long getBalance() {
    return (balance);
    }   

    public void deposit(long balance) {
    this.balance += balance;
    }   

    public void withdraw(long balance) throws IllegalArgumentException {
    
        if (this.balance < balance) {
      
            throw (new IllegalArgumentException("insufficient balance"));
        }  
        this.balance -= balance;  
    }
}

 このJavaクラスAccountは典型的な具象クラスです。インスタンス変数はすべて可視性をprivateにして、外部からの不用意なアクセスを不可能にしています。インスタンス変数に対するアクセスはオペレーションを通して行うようになっています。

 具象クラスAccountをUMLで表現したものが図13です。

図13 具象クラスAccountをUMLで表現したもの

 Accountはコンストラクタを1つ定義しています。これをUML上で表現しているのが、ステレオタイプcreateを設定したオペレーションAccountです。

 withdrawメソッドはthrows句で送出する可能性のある例外としてIllegalArgumentExceptionを宣言しています。このようなオペレーションと例外の関係はsendディペンデンシィで表現されます。

 例外はステレオタイプexceptionを設定したクラスとして表現されます。IllegalArgumentExceptionはjava.lang.RuntimeExceptionの子孫クラスであり、検査なし例外と呼ばれているものです。この点をプロパティruntimeで表現しています。

■■8.2 抽象クラス■■

 抽象クラスの実現例はリスト7のようになります。

リスト7 AbstractItem.java
public abstract class AbstractItem {
    private String id;
    private String name;
  

    protected AbstractItem(String id) {
    this.id = id;
    }
  

    public final String getId() {
    return (id);
    }
  

    public void setName(String name) {
    this.name = name;
    }
  

    public String getName() {
    return (name);
    }
  

    public abstract long getPrice() throws java.io.IOException;
}

 このJavaクラスAbstractItemは典型的な抽象クラスです。抽象クラスはクライアントオブジェクトから直接生成されることはないので、コンストラクタの可視性をprotectedにしています。

 抽象クラスにつきものの抽象メソッドであるgetPriceを定義しています。また、getIdメソッドがfinalとなっており、サブクラスでのオーバーライドを許さないことが明示されています。抽象クラスAbstractItemをUMLで表現したものが図14です。

図14 抽象クラスAbstractItemをUMLで表現したもの

 クラス名AbstractItemがイタリック体で表示されており、AbstractItemが抽象クラスであることを示しています。抽象メソッドgetPriceもイタリック体で表示されています。

 コンストラクタはステレオタイプcreateのオペレーションで表現されています。可視性protectedもそのままUMLで表現されています。

 getIdメソッドのfinalは、プロパティfinalとして表現しています。ここを標準プロパティleafで表現することも可能です。

■■8.3 インターフェイス■■

 インターフェイスの実現例はリスト8のようになります。

リスト8 IItem.java
public interface IItem {
    String getId();
    String getName();
    String getPrice() throws java.io.IOException;
}

 インターフェイスIItemをUMLで表現したものが図15です。

図15 インターフェイスIItemをUMLで表現したもの

 図15は、ステレオタイプinterfaceを用いてインターフェイスであることを表現しています。インターフェイスは、それ自身がインスタンス化されることはなく、また定義してあるオペレーションはすべて抽象オペレーションとなります。通常のクラスであればインターフェイス名やオペレーションは、プロパティabstractを明記するか、オペレーションをイタリック体で表示するところですが、インターフェイスの場合は、通常の表示のままでよいことになっています。

■■8.4 インターフェイスと定数■■

 定数を使ったインターフェイスの実現例はリスト9となります。

リスト9 IScheduleable.java
public interface IScheduleable {
    int PRI_HIGH = 1;
    int PRI_MIDDLE = 2;
    int PRI_LOW = 3;

    void setPriority(int priority);
    int getPriority();
}


 setPriorityメソッドやgetPriorityメソッドで扱うint型のデータに用いる定数としてPRI_HIGH、PRI_MIDDLE、PRI_LOWの3つを定義しています。このインターフェイスIScheduleableをUMLで表現したものが図16です。

図16 インターフェイスIScheduleableをUMLで表現したもの

 定数はUMLの仕様外です。属性で表現することもできなくはありませんが、ここでは定数用のオプションの並び区画を設け、そこにJavaの文法の文字列を記述するという方法を用いています。

■■8.5 ユーティリティ■■

Javaによるユーティリティの実現例はリスト10となります。

リスト10 Calc.java
public class Calc {
    public static Integer plus(Integer lhs, Integer rhs) {
        return (new Integer(lhs.getIntValue() + rhs.getIntValue()));
    }

    public static Integer minus(Integer lhs, Integer rhs) {
        return (new Integer(lhs.getIntValue() - rhs.getIntValue()));
    }
}


 このユーティリティCalcをUMLで表現したものが図17です。

図17 ユーティリティCalcをUMLで表現したもの

 定義されているオペレーションはすべてクラススコープなので通常のクラスであれば下線を引いて表現するところですが、ユーティリティの場合は、普通のオペレーションと同様の記述でよいことになっています。

■■8.6 ファクトリ■■

 インスタンススコープのオペレーションとクラススコープのオペレーションが混在する例として、ファクトリオブジェクトについて考えます。Javaによるファクトリの実現例はリスト11となります。

リスト11 ItemFactory.java
public class ItemFactory {
    private static ItemFactory factory = null;
    private int numberOfItems = 0;
  

    private ItemFactory() {
    }
  

    public Item getItem(String name) {
        numberOfItems++;
        return (new Item(name));
    }
  

    public int getNumberOfItems() {
    return (numberOfItems);
    }
  

    public static ItemFactory newInstance() {
        if (factory == null) {
            factory = new ItemFactory();
        }
        return (factory);
    }
}

 ファクトリでは、オブジェクトの生成を自分自身のクラスメソッド(この場合はnewInstance)でしか行えないようにすると危険防止になるので、コンストラクタをprivateにしています。

 変数factoryとメソッドnewInstanceはいずれも修飾子staticが指定されており、それぞれクラス変数とクラスメソッドであることが宣言されています。

  ItemFactoryをUMLで表現したものが図18です。

図18  ItemFactoryをUMLで表現したもの

 属性factoryやオペレーションnewInstanceに下線が引かれておりクラススコープの属性やオペレーションであることを示しています。

■■8.7 内部データ■■

 パッケージ内で利用するデータを格納するためのオブジェクトについて考えます。 Javaによる実現例はリスト12となります。

リスト12 ActionValue.java
package sample;

class ActionValue {
    int x;
    int y;
    int width;
    int height;
    String command;
  

    ActionValue(int x, int y, int width, int height, String command) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.command = command;
    }
}

 パッケージ内で利用するデータなのでクラス本体、オペレーションの可視性をパッケージにしています。クラス本体の可視性は、パッケージ外からのアクセスに対する可視性ということになります。また、内部データ用のオブジェクトなので属性をオペレーション経由ではなく、 直接外部から操作できるようにしています。 クラス本体の可視性の表現は、クラス名の前に可視性を示す記号を表示することで行います。「パッケージ内」の可視性を表現するためにUML 1.4から導入された新機能である「~」を使用しています(図19)

図19 内部データ

 “クラス”は、UMLとJavaでほとんど同じ構造になっているので、簡単なクラス図を書くことが目的であればマッピングは比較的簡単に行えます。しかし、CASEツールでの自動マッピングなどをターゲットにして、厳密にマッピングを考えていくと、UMLの複雑な部分も見えてきます。UMLの仕様が膨大であるうえに、UMLとJavaのモデルが微妙にズレている点もあるからです。

 この問題に対応するためには、Javaとのマッピングに使用するUMLの仕様を絞り込んだうえで、UMLの仕様にないJavaの機能をステレオタイプやプロパティなどの拡張メカニズムを使って、拡張していく必要があります。もちろん、このような拡張を行う場合には、用途に応じてプロファイルとしてまとめていくことが必要です。そして、このプロファイルを開発チームの中でのルールとして利用することで、UMLを用いたコミュニケーションを円滑に行うことができるようになります。

 今回は、オブジェクトの核となるモデル要素であるクラスについて、JavaとUMLのマッピングを検討するために必要な論点を明らかにしたうえで、サンプルのプロファイルを作成してみました。このプロファイルは筆者の好みが大きく反映されていますが、一般的な開発ではそのまま利用できるのではないかと思います。もちろん、実際の開発に当たっては、利用するCASEツールとの整合性といった要因を考慮に入れてチューニングしていくとよいでしょう。

5/5

Javaオブジェクトモデリング 第4回
  “クラス”のマッピング
  属性のマッピング
  オペレーションのマッピング
  サンプルプロファイル
マッピング例


Javaオブジェクトモデリング INDEX


IT Architect 連載記事一覧

この記事に対するご意見をお寄せください managemail@atmarkit.co.jp

「ITmedia マーケティング」新着記事

匿名加工情報とは何か、内容まで知っている人はたった3%台――データサイエンティスト協会調査
一定のルールの下であれば本人の同意がなくても利用できる匿名加工情報ですが、現状では...

Googleによる買収で話題の「Looker」は他のBIとどこが違うのか
変化するニーズを捉えたユニークなBI製品を提供して注目を集めるLooker。その特徴をまと...

リテールテックのTraxが日本市場に本格参入 画像認識で店舗の棚を見える化
店舗の商品棚の前で撮影した写真を機械学習で画像認識し、在庫状況や商品棚上のシェア、 ...