- Message retrieval
- Reading user input
- Printing message and program output
- Handling user-interactions via a lame read-eval-print (aka REPL) loop
- Create a class per responsibility
- Make the Magic8BallSimulator class depend on those classes
- Inject those dependent classes into Magic8BallSimulator (you'll laugh when you see how simple this turns out to be).
- and finally, make you sad by exposing a new problem with the code
MessageService - gets messages
ConsoleInputService - reads user input from the console.
ConsoleOutputService - prints output to the console.
Magic8BallSimulator - Simulates a Magic 8 Ball via a lame read-eval-print (aka REPL) loop.
Oh there's a bit of Dependency Injection - MessageService, ConsoleInputService, and ConsoleOutputService are dependencies of Magic8BallSimulator, which is to say that Magic8BallSimulator cannot do its job of simulating a Magic 8 Ball without them. These dependencies are given to this class (or injected) as simple constructor parameters.
SimulationRunner - Runs the simulator class, and injects new instances of the dependent classes into Magic8BallSimulator.
Hmm, there's still a problem with this code
Let's have one more look at the Magic8BallSimulator constructor.
Notice how we're injecting instances of MessageService, ConsoleInputService, and ConsoleOutputService? What this does is, for example, couple Magic8BallSimulator to ConsoleOutputService which is a specific class printing output in a specific way (to the console). This coupling exposes us to 2 threats:
- If we want to change, say, ConsoleOutputService we risk breaking Magic8BallSimulator too, since it depends directly on ConsoleOutputService (and changing the output on the console really shouldn't break our entire application).
- If we get a requirements change to alter how we output messages, say, to send them as Instant Messages or via Email, we'll have to rip out ConsoleOutputService and change Magic8BallSimulator as well. This makes our application less maintainable because changes to one section break and cascade to other parts of our application making the whole thing a pain in the ass to work on.
Luckily there's a simple way out.
We need to alter Magic8BallSimulator to depend upon abstractions instead of concrete implementations, making Magic8BallSimulator loosely coupled to the classes it depends on.
(Awfully coupled) source code for this post, witness the bad design first hand!
We'll explore this way out in the next post
1 comments:
this is so informative...i cant wait for the next post
Post a Comment