From dee038490f39755b8836110fcba2c2aebd188360 Mon Sep 17 00:00:00 2001 From: "Damith C. Rajapakse" Date: Mon, 12 Sep 2016 17:50:58 +0800 Subject: [PATCH] Add LO-DIP --- doc/Diagrams.pptx | Bin 52381 -> 52929 bytes doc/LearningOutcomes.md | 18 ++++++++++++++++++ doc/images/LogicStroageFileDIP.png | Bin 0 -> 5368 bytes 3 files changed, 18 insertions(+) create mode 100644 doc/images/LogicStroageFileDIP.png diff --git a/doc/Diagrams.pptx b/doc/Diagrams.pptx index 6e9071e2f2b926fd90e3232d8d6e5731683db2cb..45171f705ac84388cae6ed4d7453a99e1c7f0fca 100644 GIT binary patch delta 4723 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 DWoyUi delta 4348 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 YSxihoK=V%)#}w*-Wb9Rv*Nu4fzxb1w{r~^~ diff --git a/doc/LearningOutcomes.md b/doc/LearningOutcomes.md index 1cb2e4b01..0847cd234 100644 --- a/doc/LearningOutcomes.md +++ b/doc/LearningOutcomes.md @@ -8,6 +8,7 @@ After studying this code and completing the corresponding exercises, you should 1. [Use abstract classes/methods `[LO-Abstract]`](#use-abstract-classesmethods-lo-abstract) 1. [Follow Liskov Substitution Principle `[LO-LSP]`](#follow-liskov-substitution-principle-lo-lsp) 1. [Use Java-FX for GUI programming `[LO-JavaFx]`](#use-java-fx-for-gui-programming-lo-javafx) +1. [Apply Dependency Inversion Principle `[LO-DIP]`](#apply-dependency-inversion-principle) 1. [Use Dependency Injection `[LO-DI]`](#use-dependency-injection) @@ -90,6 +91,16 @@ Covered by `[LO-Polymorphism]` ------------------------------------------------------------------------------------------------------ +## Apply Dependency Inversion Principle `[LO-DIP]` + +#### Exercise: Invert dependency from Logic to Storage + +* Note how `Logic` class depends on the `StorageFile` class. This is a violation of DIP. +* Modify the implementation as follows so that both `Logic` and `StorageFile` now depend on the abstraction + `Storage`.
+ + +------------------------------------------------------------------------------------------------------ ## Use Dependency Injection `[LO-DI]` @@ -98,9 +109,16 @@ Covered by `[LO-Polymorphism]` * Note how `Logic` class depends on the `StorageFile` class. This means when testing the `Logic` class, our test cases executes the `StorageFile` class as well. What if we want to test the `Logic` class without getting the `StorageFile` class involved? + * Now, change the implementation as follows so that we can inject a `StorageStub` when testing the `Logic` class.
+ + > If you did the exercise in [`LO-DIP`](#apply-dependency-inversion-principle) + already but those changes are in a different branch, you may be able to reuse some of those commits + by cherry picking them from that branch to the branch you created for this exercise.
+ Note: *cherry picking* is simply copy-pasting a commit from one branch to another. In SourceTree, you can + right-click on the commit your want to copy to the current branch, and choose 'Cherry pick' * Implement the `StorageStub` to ignore calls to the `save` method. Update the `LogicTest` to work with the `StorageStub` instead of the actual `StorageFile` object. diff --git a/doc/images/LogicStroageFileDIP.png b/doc/images/LogicStroageFileDIP.png new file mode 100644 index 0000000000000000000000000000000000000000..6733e7c2d870a5776370da61b4992e51998b994f GIT binary patch literal 5368 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 V9)Fho0Y6j%2T@K)ioNfZ{{ah+WYz!x literal 0 HcmV?d00001