7

It seems like whenever I use the Command Pattern, it always leads to a significantly larger number of classes than when I don't use it. This seems pretty natural, given that we're executing chunks of relevant code together in separate classes. It wouldn't bother me as much if I didn't finish with 10 or 12 Command subclasses for what I might consider a small project that would have only used 6 or 7 classes otherwise. Having 19 or so classes for a usual 7 class project seems almost wrong.

Another thing that really bothers me is that testing all of those Command subclasses is a pain. I feel sluggish after I get to the last few commands, as if I'm moving slower and no longer agile.

Does this sound familiar to you? Am I doing it wrong? I just feel that I've lost my agility late in this project, and I really don't know how to continuously implement and test with the speed that I had a few days ago.

Mike
  • 19,267
  • 11
  • 56
  • 72

2 Answers2

6

Design patterns are general templates for solving problems in a generic way. The tradeoff is exactly what you are seeing. This happens because you need to customize the generic approach. 12 command classes does not seem like a lot to me, though, personally.

With the command pattern, hopefully the commands are simple (just an execute method, right?) and hence easy to test. Also, they should be testable in isolation, i.e. you should be able to test the commands easily with little or no dependencies.

The benefit you should be seeing are two-fold:

1) You should have seen your specific, complicated approach simplified by using the pattern(s) you chose. i.e. something that was getting ugly quickly should now be more elegant.

2) Your should be going faster, due to the simplified approach and the ease of testing your individual components.

Can you make use other patterns, like composite, and use good OO design to avoid duplicating code (if you are duplicating code...)?

hvgotcodes
  • 118,147
  • 33
  • 203
  • 236
  • I'm not duplicating code. They're pretty simple execute methods that perform distinct tasks. It was just the large number of classes that bothered me - given I only have about 4 or 5 domain classes. – Mike Feb 05 '11 at 17:52
  • @mike yeah 12 classes are not a lot. If they are simple, you should be able to test them easily. I also think once the pattern is in place and you get used to it you'll go faster – hvgotcodes Feb 05 '11 at 17:54
  • Also, it's not meaningful to test them in isolate. At that layer in my architecture, they're subject to the full set of business rules. That also, is an area that's quite annoying. – Mike Feb 05 '11 at 17:55
  • @mike you are supposed to test in isolation. You should also test the classes that use the commands too – hvgotcodes Feb 05 '11 at 17:56
  • @mike, where specifically are you slowing down? Testing? Implementing the commands? Something else? – hvgotcodes Feb 05 '11 at 17:59
  • Hm. Let me rephrase. I've Unit tested all of the domain classes. My Command classes use those, and I therefore wrote Integration Tests for them. Do you think it would have been better if I only Unit tested the Command classes, and not Integration tested? – Mike Feb 05 '11 at 17:59
  • Testing is slowing down significantly, I would say. – Mike Feb 05 '11 at 17:59
  • why is testing slowing down? You should unit test the commands as you write them in the spirit of TDD, and you should also integrate to make sure the logical units the commands encapsulate are correct. – hvgotcodes Feb 05 '11 at 18:05
  • I'm not sure why I didn't Unit test them to be honest. Integration tests are what are taking the longest amount of time. I'm just not sure anymore. – Mike Feb 05 '11 at 18:07
  • I think it might help to describe what I'm doing. First, I use TDD and write a Unit test for the domain object, if I need one. Then, I again use TDD and add to a Facade, while producing an integration test for the Facade and domain object. Finally, I TDD an Integration test for Command, stretching from the Command, to the Facade, to the domain object. Where did I go wrong in there? – Mike Feb 05 '11 at 18:11
  • @mike let me ask this: how fast are you going? Are you delivering features on time? things take time to do correctly...if you hadnt used the command pattern, do you think you would be going faster? Is the code cleaner with the command pattern? Software development can be frustrating -- keep with it – hvgotcodes Feb 05 '11 at 18:15
  • I'm implementing a 2-4 small features a day, putting in 1-4 hours per day. Maybe I just feel that I'm going slow because some of my classmates burned through the assignment without tests. (It's a college SE project, so you understand that it's reasonably small). I think it's just demoralizing to see someone finish so fast - even though I know theirs is riddled with bugs and mine is bullet proof. Your last comment made me feel a lot better, though. – Mike Feb 05 '11 at 18:19
  • @mike -- ahh a college project. You are going to be a good software developer if you start off now doing it the right way. If your project were ongoing you would see the benefits down the line in terms of maintainability and code simplicity. – hvgotcodes Feb 05 '11 at 18:37
  • 1
    @hvgotcodes Thanks for the encourage. It really got me over the wall I'd been having for the last 24 hours. I backed up, reverted my non-tested code, planned some more, TDDed and succeeded with another feature. :) – Mike Feb 05 '11 at 20:29
4

That doesn't seem like a lot of command classes, but I agree with you that it smells a little if they make up more than 60% of your classes. If the project is complex enough to merit the use of the command pattern, I suspect you'll find some classes begging to be split up. If not, perhaps the command pattern is overkill.

The other answers here have great suggestions for reducing the complexity of your commands, but I favor simplicity where I can find it (ala the bowling game).

Tyler Holien
  • 4,791
  • 2
  • 19
  • 14
  • I'm afraid to drop the Command pattern. It's where I parse text input, match it against regexes, and execute the work. It's a small amount of work, but has meaningful, cohesive functionality. Do you think that merits dropping the pattern? – Mike Feb 05 '11 at 18:03
  • I think that sounds like a great argument for using the command pattern! I would take a look at the rest of your classes and make sure they all have that same sense of meaningful, cohesive functionality, but it sounds like you're on the right track. – Tyler Holien Feb 05 '11 at 18:32
  • I decided to stick with it and finished the project today. Turned out better than I thought yesterday - especially when I stepped back and executed 120 automated tests over those commands. :) – Mike Feb 06 '11 at 18:25