Working with Design Patterns: Command Los Angeles CA

It's always possible to slowly refactor toward a better design. The improved version of the code demonstrates the Command Pattern, one of the more useful recognized software design patterns. In this example, your need to test proved to be in alignment with good design concepts!

Local Companies

Moyea Software
92295612365
Hot building, ring street
LA, CA
Interneer Inc.
8005586832 x85
6101 W. Centinela Ave.
Culver City, CA
Cornerstone Concepts Inc
818-247-3909
600 W Broadway
Glendale, CA
Greene Computer Corporation
(818) 956-4961
200 S. Louise Street
Glendale, CA
Corticalx Inc Software Solutions & Technology
818-500-0881
425 E Colorado St
Glendale, CA
Alphatier Systems
818-409-8920
517 Griswold St
Glendale, CA
TimeTECH - Customizable Time and Attendance / Workforce Management Solutions
905-677-7009
7420 Airport Rd 203
Mississauga, CA
Hutchinson & Bloodgood, LLP
(818) 637-5000
101 N. Brand Blvd. #1600
Glendale, CA
Telsoft Solutions
818-545-8680
100 N Brand Blvd
Glendale, CA
Abraxas Technologies Inc
818-502-9100
450 N Brand Blvd
Glendale, CA

provided by: 
Originally published at Internet.com


Do you have any methods in your system that look like the service method in Listing 1? I've seen them in many systems. Regardless of how they got there, I often have to change code within them, or add support for new request types. To have enough confidence to make changes, I try to get these methods under the control of unit tests.

How do I even begin to write a test for this code?

Listing 1. A messy method.

public class LibrarySystem { ... public void service(Request request) { String command = request.getParameter("command"); if (command.equals("return")) { String barCode = request.getParameter("barCode"); Date date = new Date(); String branchName = request.getParameter("branch"); Branch branch = findBranch(branchName); checkIn(barCode, date, branch); } else if (command.equals("checkout")) { String barCode = request.getParameter("barCode"); Date date = new Date(); String patronId = request.getParameter("id"); checkOut(patronId, barCode, date); } else if (command.equals("newBranch")) { String branchName = request.getParameter("branch"); addBranch(branchName); } else if (command.equals("addBook")) { String branchName = request.getParameter("branch"); String author = request.getParameter("author"); String title = request.getParameter("title"); String classification = request.getParameter("classification"); String year = request.getParameter("year"); Book book = new Book(author, title, classification, year); String copyNumberParm = request.getParameter("copyNumber"); int copyNumber = 1; if (copyNumberParm != null) { copyNumber = Integer.parseInt(copyNumberParm); } addNew(branchName, book, copyNumber); } else if (command.equals("addPatron")) { String name = request.getParameter("name"); String id = request.getParameter("id"); Patron patron = new Patron(name, id); add(patron); } } public void add(Patron patron) { ... } ...

I could talk about how switch statements and if/else statements represent an opportunity to exploit polymorphism. Instead, I'll take a more test-driven approach: I'll look to slowly and safely refactor, moving the code into forms that are more easily unit-tested.

I'll start with the addPatron command functionality. An initial unit test for this chunk of code is shown in Listing 2. The test truly attempts to isolate code as a standalone unit: It verifies that code in the service method calls the LibrarySystem method add(Patron) with a properly-populated Patron argument. Long-term, this is perhaps not the best way to approach the test. Short-term, it's just fine!

Listing 2.

public class LibrarySystemTest { @Test public void addPatron() { final List added = new ArrayList(); LibrarySystem system = new LibrarySystem() { @Override public void add(Patron patron) { added.add(patron); } }; Request request = new Request(); request.setParameter("command", "addPatron"); request.setParameter("name", "patronName"); request.setParameter("id", "patronId"); system.service(request); assertEquals(1, added.size()); assertEquals("patronName", added.get(0).getName()); assertEquals("patronId", added.get(0).getId()); } }

After proving the unit test works, I now can change addCommand code in the service method, wwith high levels of confidence that I'm not breaking anything. The new else leg now looks like this: } else if (command.equals("addPatron")) { AddPatronCommand addPatron = new AddPatronCommand(request, this); addPatron.execute(); }

The AddPatronCommand class is simply bits of code I moved across to a new class (see Listing 3). Short-term, I passed in the LibrarySystem reference to the constructor of this class. The result is tight coupling: LibrarySystem knows about AddPatronCommand, and AddPatronCommand knows about LibrarySystem. That's almost always a bad idea, but it's something I'll resolve before I check in the code.

Listing 3. AddPatronCommand

public class AddPatronCommand { private String name; private String id; private final LibrarySystem system; public AddPatronCommand(Request request, LibrarySystem system) { this.system = system; name = request.getParameter("name"); id = request.getParameter("id"); } public void execute() { Patron patron = new Patron(name, id); system.add(patron); } }

I next rename LibrarySystemTest to AddPatronCommandTest, and then change it to operate directly on AddPatronCommand. See Listing 4 for the modified test. Relevant changes appear in bold.

Listing 4. AddPatronCommandTest

public class AddPatronCommandTest { @Test public void execute () { final List added = new ArrayList(); LibrarySystem system = new LibrarySystem() { @Override public void add(Patron patron) { added.add(patron); } }; Request request = new Request(); request.setParameter("command", "addPatron"); request.setParameter("name", "patronName"); request.setParameter("id", "patronId"); AddPatronCommand command = new AddPatronCommand(request, system); command.execute(); assertEquals(1, added.size()); assertEquals("patronName", added.get(0).getName()); assertEquals("patronId", added.get(0).getId()); } }

Renaming the LibrarySystemTest class leaves me with no tests against LibrarySystem. I'll revisit that problem shortly. First, however, I'll eliminate the tight coupling between LibrarySystem and AddPatronCommand. That involves moving methods and fields across as appropriate. Obviously, I must move the add(Patron) method. After moving it, I let the compiler tell me what other methods and fields I need to move along with it. It turns out that in the case of add(Patron), I also have to copy across a data access field.

The resulting test and code aren't much different (see Listings 5 and 6).

Listing 5. AddPatronCommandTest, revised.

public class AddPatronCommandTest { @Test public void execute() { Request request = new Request(); request.setParameter("command", "addPatron"); request.setParameter("name", "patronName"); request.setParameter("id", "patronId"); final List added = new ArrayList(); AddPatronCommand command = new AddPatronCommand(request) { @Override public void add(Patron patron) { added.add(patron); } }; command.execute(); assertEquals(1, added.size()); assertEquals("patronName", added.get(0).getName()); assertEquals("patronId", added.get(0).getId()); } }

Listing 6. AddPatronCommand, revised.

public class AddPatronCommand implements Command { private String name; private String id; ... public AddPatronCommand(Request request) { name

By using this refactoring pattern, I can incrementally put such command classes in place. As I tackle the second command class, I recognize that both commands support the common method execute. I introduce an interface, Command (see Listing 7), and alter each command class to implement this interface.

Listing 7. The Command interface.

public interface Command { void execute(); }

I am now able to introduce a factory class whose sole job is to return Command objects (see Listing 8).

Listing 8. The Command interface.

public class CommandFactory { public static Command create(Request request) { String command = request.getParameter("command"); if (command == null) return null; if (command.equals("return")) return new ReturnCommand(request); if (command.equals("addPatron")) return new AddPatronCommand(request); return null; } }

Writing tests for CommandFactory is easy (Listing 9)!

Listing 9. 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() { assertNull(CommandFactory.create(request)); } @Test public void createWithBadCommandParameter() { request.setParameter("command", "badCommand"); assertNull(CommandFactory.create(request)); } private void assertCommandType(String commandArgument, Class commandClass) { request.setParameter("command", commandArgument); assertEquals(commandClass, CommandFactory.create(request).getClass()); } }

I now can change code in the service method to take advantage of the command factory (see Listing 10).

Listing 10. Incremental refactoring.

public void service(Request request) { String command = request.getParameter("command"); if (command.equals("checkout")) { ... } else if (command.equals("newBranch")) { ... } else if (command.equals("addBook")) { ... } else { libraryCommand = CommandFactory.create(request); libraryCommand.execute(); } }

Ultimately, I can refactor all the code in the service method to use the CommandFactory. Here's what it looks like after moving all chunks of service code out to the command framework: public void service(Request request) { Command command = CommandFactory.create(request); command.execute(); }

Not bad! At this point, I want enough unit test coverage to give me the confidence that the service method uses the factory to execute and execute a command. I don't need to re-test each command class. Instead, I only need to prove that the execute method gets called for the created command.

I could choose one representative command and verify that it got executed end-to-end. Or I could introduce a "dummy" Command implementation that did nothing but report back that it got executed: public class NullCommand implements Command { public static boolean wasExecuted = false; public void execute() { wasExecuted = true; } }

Along with this change, I alter the definition of the CommandFactory to never return null, instead returning a NullCommand object (see Listing 11).

Listing 11. CommandFactoryTeest, revised.

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()); } }

The corresponding CommandFactory implementation is shown in Listing 12.

Listing 12. CommandFactory, revised.

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(); } }

The changes to CommandFactory ensure that it cannot possibly return null. My test for service is very simple: @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); }

Yes, this introduces a NullCommand class into production. It does no harm there, and otherwise it's a small price to pay for the value provided by better test coverage.

It's always possible to slowly refactor toward a better design. The improved version of the code demonstrates the Command Pattern, one of the more useful recognized software design patterns. In this case, your need to test proved to be in alignment with good design concepts!

About the Author

Jeff Langr is a veteran software developer with a score and more years of experience. He's authored two books and dozens of published articles on software development, including Agile Java: Crafting Code With Test-Driven Development (Prentice Hall) in 2005. You can find out more about Jeff at his site, http://langrsoft.com, or you can contact him directly at

Author: Jeff Langr

Read article at Internet.com site

Featured Local Company

Moyea Software

92295612365
Hot building, ring street
LA, CA

Related Local Events
Automation Technology Expo West (ATX West)
Dates: 2/9/2010 - 2/11/2010
Location: Anaheim Convention Center
Anaheim, CA
View Details

SOLAR POWER - Exhibition and Conference
Dates: 10/12/2010 - 10/14/2010
Location: Los Angeles Convention & Exhibition Center
Los Angeles, CA
View Details

REAL-TIME & EMBEDDED COMPUTING CONFERENCE - LONG BEACH 2009
Dates: 10/1/2009 - 10/1/2009
Location: Marriott Long Beach
Long Beach, CA
View Details

2009 IEEE Petroleum and Chemical Industry Technical Conference (PCIC 2009)
Dates: 9/14/2009 - 9/16/2009
Location:
Anaheim, CA
View Details

Medical Design & Manufacturing - Trade
Dates: 6/9/2009 - 6/11/2009
Location: CANON COMMUNICATIONS LLC
Los Angeles, CA
View Details