SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

デザインパターンの使い方

デザインパターンの使い方: Command

Commandパターンを利用したソースコードのリファクタリング

 代表的なコマンドを1つ選んで、端から端まで実行されていることを確認します。あるいは、実行されたという通知を返す以外は何もしない、次のようなダミーコマンドを実装するという方法もあります。

public class NullCommand implements Command {
   public static boolean wasExecuted = false;
   public void execute() {
      wasExecuted = true;
   }
}

 この変更を加えた後、さらにCommandFactoryに手を加え、CommandFactoryがnullを絶対に返さず、代わりにNullCommandオブジェクトを返すようにしました(リスト11を参照)。

リスト11 変更後のCommandFactoryTest
public class CommandFactoryTest {
   private Request request;

   @Before
   public void initialize() {
      request = new Request();
   }

   @Test
   public void createValidCommands() {
      assertCommandType("return", ReturnCommand.class);
      assertCommandType("addPatron", AddPatronCommand.class);
   }

   @Test
   public void createWithNoCommandParameter() {
      assertEquals(NullCommand.class,
                   CommandFactory.create(request).getClass());
   }

   @Test
   public void createWithBadCommandParameter() {
      assertCommandType("badComment", NullCommand.class);
   }

   @Test
   public void createDummy() {
      assertCommandType("dummy", NullCommand.class);
   }

   private void assertCommandType(String commandArgument,
                                  Class commandClass) {
      request.setParameter("command", commandArgument);
      assertEquals(commandClass, CommandFactory.create(request)
            .getClass());
   }
}

 対応するCommandFactoryの実装をリスト12に示します。

リスト12 変更後のCommandFactory
public class CommandFactory {
   public static Command create(Request request) {
      String command = request.getParameter("command");
      if (command != null) {
         if (command.equals("return"))
            return new ReturnCommand(request);
         if (command.equals("addPatron"))
            return new AddPatronCommand(request);
      }
      return new NullCommand();
   }
}

 このように変更したことで、CommandFactoryがnullを返すことはあり得なくなりました。serviceのテストは非常に簡単です。

@Test
public void service() {
   NullCommand.wasExecuted = false;
   LibrarySystem system = new LibrarySystem();
   Request request = new Request();
   request.setParameter("command", "dummy");
   system.service(request);
   assertTrue(NullCommand.wasExecuted);
}

 お気づきのとおり、この方法ではNullCommandクラスを使うようになりました。これによって不都合が生じることはありません。あったとしても、テスト可能な範囲が広がったメリットを考えれば安いものです。

 より優れたデザインを目指して少しずつリファクタリングすることはどのコードでも可能です。この記事の改良後のコードは、Commandパターンという非常に便利で広く知られたソフトウェアデザインパターンに従っています。今回の場合、テストのニーズを追及したら、優れたデザインコンセプトがついてきたということですね。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
デザインパターンの使い方連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Jeff Langr(Jeff Langr)

本格的なソフトウェアの開発に四半世紀以上携わってきたベテランのソフトウェア開発者。『Agile Java: Crafting Code With Test-Driven Development』(Prentice Hall、2005年)と、他の1冊の著書がある。『Clean Code』(Uncle Bob Martin著、Prentice Hall、2008年8月)にも寄稿している。また、ソフトウェア開発に関する記事を80件以上執筆しており、そのうちの...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/2974 2008/09/12 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー