良いコ-ドへの道―普通のプログラマのためのステップアップガイド

第4回 コードの分割―その3 Step1:ベタなコードで書いてみる

この記事を読むのに必要な時間:およそ 2 分

ボトムアップ方式による分割の例

それではいよいよコード分割の過程を見ていきましょう。ここではボトムアップ方式でコードを分割していきます。

例で使用するコードは,クライアントにXMLを返却するWeb APIです。Web APIといっても,組織情報とユーザ情報の一覧をXML形式で返すだけの単純なものですリスト1)。唯一特殊な仕様として,組織(division),ユーザ(user)の要素を通して共通の連番を表すindex属性をセットします(リスト1の太字部分)。

リスト1 生成するXML

<?xml version="1.0" encoding="UTF-8"?>
<data>
  <divisions>
    <division index="1">
      <id>1001</id>
      <name>div1</name>
    </division>
   <division index="2">
      <id>1002</id>
     <name>div2</name>
   </division>
   ...
  </divisions>
  <users>
    <user index="12">
      <name>user1</name>
    </user>
    <user index="13">
      <name>user2</name>
    </user>
    ...
  </users>
</data>

Step1:ベタなコードで書いてみる

まずベタに処理を実装してみます。完成したコードはリスト2図1です。処理の流れを簡単に説明します。

リスト2 Step1:ベタなコード

@Path("api/step1")
public class XmlApiAction extends Action {
    public HttpServletResponse response;
    public UserService userService;
    public ActionResult index() throws Exception {
        List<Division> divs = userService.getDivisions();
        List<User> users = userService.getUsers();
        int rowIndex = 1;
        // XMLを作成するためにDocumentオブジェクトを準備
        DocumentBuilderFactory factory =
            DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.newDocument();
        // ルート要素の追加
        Element rootNode = doc.createElement("data");
        doc.appendChild(rootNode);
        // 組織要素の追加
        Element divisionsNode = doc.createElement("divisions");
        int rowIndex = 1;
        for (Division div: divs) {
            Element node = doc.createElement("division");
            node.setAttribute("index", String.valueOf(rowIndex++));
            Element idNode = doc.createElement("id");
            idNode.setTextContent(div.getId());
            node.appendChild(idNode);
            Element nameNode = doc.createElement("name");
            nameNode.setTextContent(div.getName());
            node.appendChild(nameNode);
            divisionsNode.appendChild(node);
        }
        rootNode.appendChild(divisionsNode);
        // ユーザ要素の追加
        Element usersNode = doc.createElement("users");
        for (User user : users) {
            Element node = doc.createElement("user");
            node.setAttribute("index", String.valueOf(rowIndex++));
            Element nameNode = doc.createElement("name");
            nameNode.setTextContent(user.getName());
            node.appendChild(nameNode);
            usersNode.appendChild(node);
        }
        rootNode.appendChild(usersNode);
        // DocumentオブジェクトをXML文字列への変換
        TransformerFactory transFactory =
            TransformerFactory.newInstance();
        Transformer transformer = transFactory.newTransformer();
        DOMSource source = new DOMSource(doc);
        // レスポンスにXMLを出力
        StreamResult result =
            new StreamResult(response.getOutputStream());
        transformer.transform(source, result);
        return new Direct();
    }
}

図1 Step1のクラス図

図1 Step1のクラス図

でXMLを作成する準備としてDocumentオブジェクトを作成しています。JavaではDOM(注9)のDocumentオブジェクトを使用して,XMLの要素を組み立てます。でルート要素の「data」の追加,③④のブロックは組織要素,ユーザ要素の追加です。それぞれのリストをもとに1件ずつ要素を追加しています。作成したXMLを⑤⑥でXMLの文字列に変換して出力しています。

比較的単純な処理なのでこれでも問題なさそうですが,以下の点は改善の余地があります注10)。

  • 要素を作成する部分など共通的な処理をメソッド抽出することで,可読性が高まる部分がある
  • 一部でしか使用していないのにスコープが長い変数(factory,builder,rootNodeなど)が存在する
  • 1メソッドのコードが長いため,処理の流れや全体像を把握しにくい

それでは,Step2以降でこのあたりを改善していきます。

注9)
W3Cから勧告されている標準的なXML操作用のAPI。DOMはDocument Of Modelの略です。
注10)
実際問題,この例ぐらいのコードであれば分割しなくても問題ありません。限られた誌面での説明の都合上,あえて分割を強調して説明しています。

著者プロフィール

縣俊貴(あがたとしたか)

学生時代にMSXで制限された環境でのプログラミングの楽しさを学ぶ。以来,オープンソースのWiki実装「MobWiki」の開発や受託開発などを経て,現在はプロジェクト管理ツール「Backlog」,ドローツール「Cacoo」など,コラボレーション型のWebサービスの企画と製品開発を行う。また,Webアプリケーションフレームワーク「Cubby」のコミッタを務める。福岡在住。株式会社ヌーラボ所属。

ブログ :http://d.hatena.ne.jp/agt

Twitter:@agata

コメント

コメントの記入