kenu / solid star
dboyliao 2015-11-25
Add code for DIP. Update README.md
@34dda4f85d8e4c686e9e0f342ec8533c7305edc5
README.md
--- README.md
+++ README.md
@@ -1,7 +1,7 @@
 ## SOLID - Principles that Apply
 
 This page is destinated to collect some good resources (IMHO) in order to give
-an overview over good priciples that should apply to software designe.
+an overview over good priciples that should be applied to software design.
 
 - [Intro to `SOLID`](http://www.wikiwand.com/en/SOLID_(object-oriented_design))
     - `S`: Single Responsibility Principle.
@@ -17,16 +17,21 @@
     - `I`: Interface Segregation Principle
         - [link](http://www.oodesign.com/dependency-inversion-principle.html)
         - [Wiki](https://en.wikipedia.org/wiki/Interface_segregation_principle)
-    - `D`:
+    - `D`: Dependency Inversion Principle
+        - [link](http://www.oodesign.com/dependency-inversion-principle.html)
+        - [Code Tutorials](http://code.tutsplus.com/tutorials/solid-part-4-the-dependency-inversion-principle--net-36872)
+        - **Program to an interface, not an implementation.**
 
 ## Running the Code
 
 All the submodules are managed in the same way, which means you can run the code using the same syntax. For example, if you want to see the result of the sample code for Open/Close principle, just run:
 
 ```
-python -m python_code.bad.open\_close   # See the result of bad implementation
-python -m python_code.good.open\_close  # See the result of good implementation
+python -m python_code.bad.open_close   # See the result of bad implementationgi
+python -m python_code.good.open_close  # See the result of good implementation
 ```
+
+Or, you can run `python -m python_code --list` or `python -m python_code -l` to see all the available submodules.
 
 However, it is recommanded to see the source code and get an understanding of what the issue is and possible way to solve it.
 
@@ -37,3 +42,5 @@
 - [Programming Done By Superstition](https://utcc.utoronto.ca/~cks/space/blog/programming/ProgrammingViaSuperstition)
 - [Object Mentor](http://www.objectmentor.com/resources/publishedArticles.html)
 - [Clean Coder](http://cleancoders.com/category/fundamentals)
+- [Code Tutorials](http://code.tutsplus.com/series/the-solid-principles--cms-634)
+- [搞笑談軟工](http://teddy-chen-tw.blogspot.tw/2012/01/5dependency-inversion-principle.html)
 
python_code/__main__.py (added)
+++ python_code/__main__.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from good import __all__ as all_submodules
+import sys
+
+def main(argv):
+    if len(argv) > 1 and argv[1] in ["-l", "--list"]:
+        print "Available submodules: "
+        for i, submodule in enumerate(all_submodules, 1):
+            print "{}. good.{} / bad.{}".format(i, submodule, submodule)
+
+if __name__ == "__main__":
+    
+    main(sys.argv)(No newline at end of file)
 
python_code/bad/DIP.py (added)
+++ python_code/bad/DIP.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+class Worker(object):
+
+    def work(self):
+        print "I'm working!!"
+
+
+class Manager(object):
+
+    def __init__(self):
+        self.worker = None
+
+    def set_worker(self, worker):
+        assert isinstance(worker, Worker), '`worker` must be of type {}'.format(Worker)
+
+        self.worker = worker
+
+    def manage(self):
+        if self.worker is not None:
+            self.worker.work()
+            # And some complex codes go here....
+
+class SuperWorker(object):
+
+    def work(self):
+        print "I work very hard!!!"
+
+# OK... now you can see what happend if we want the `Manager` to support `SuperWorker`.
+#  1. The `set_worker` must be modified or it will not pass the type-checking.
+#  2. The `manage` method should be re-test, which means you may or may not have to 
+#     rewrite the testing code.
+
+def main():
+
+    worker = Worker()
+    manager = Manager()
+    manager.set_worker(worker)
+    manager.manage()
+
+    # The following will not work...
+    super_worker = SuperWorker()
+    try:
+        manager.set_worker(super_worker)
+    except AssertionError:
+        print "manager fails to support super_worker...."
+
+if __name__ == "__main__":
+    main()
python_code/bad/__init__.py
--- python_code/bad/__init__.py
+++ python_code/bad/__init__.py
@@ -1,0 +1,4 @@
+#/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+__all__ = ['DIP', 'ISP', 'LSP', 'open_close', 'single_responsibility']
(No newline at end of file)
 
python_code/good/DIP.py (added)
+++ python_code/good/DIP.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Here we solve the issues in the design in `python_code.bad.DIP` with an interface
+# (implemented with abstract class).
+
+from abc import ABCMeta, abstractmethod
+
+class IWorker(object):
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
+    def work(self):
+        pass
+
+# `IWorker` defines a interface which requires `work` method.
+
+class Worker(IWorker):
+
+    def work(self):
+        print "I'm working!!"
+
+
+class Manager(object):
+
+    def __init__(self):
+        self.worker = None
+
+    def set_worker(self, worker):
+        assert isinstance(worker, IWorker), '`worker` must be of type {}'.format(Worker)
+
+        self.worker = worker
+
+    def manage(self):
+        if self.worker is not None:
+            self.worker.work()
+            # And some complex codes go here....
+
+class SuperWorker(IWorker):
+
+    def work(self):
+        print "I work very hard!!!"
+
+# Now, the manager support `SuperWorker`...
+# In addition, it will support any worker which obeys the interface defined by `IWorker`!
+
+def main():
+
+    worker = Worker()
+    manager = Manager()
+    manager.set_worker(worker)
+    manager.manage()
+
+    # The following will not work...
+    super_worker = SuperWorker()
+    try:
+        manager.set_worker(super_worker)
+        manager.manage()
+    except AssertionError:
+        print "manager fails to support super_worker...."
+
+if __name__ == "__main__":
+    main()
python_code/good/__init__.py
--- python_code/good/__init__.py
+++ python_code/good/__init__.py
@@ -1,0 +1,4 @@
+#/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+__all__ = ['DIP', 'ISP', 'LSP', 'open_close', 'single_responsibility']
(No newline at end of file)
Add a comment
List