    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: OOD and Testing using the Dependency Inversion
Principle</title>
        <link>https://members.accu.org/index.php/articles/1079</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + CVu Journal Vol 12, #6 - Dec 2000</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c123/">126</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-123/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+123/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;OOD and Testing using the Dependency Inversion
Principle</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 03 December 2000 13:15:41 +00:00 or Sun, 03 December 2000 13:15:41 +00:00</p>
<p><strong>Summary:</strong>&nbsp;<p>I learned one of the most important OOD techniques 10 years ago on an OOD workshop. It has since become known as the Dependency Inversion Principle.</p></p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e18" id="d0e18"></a>Design</h2>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e21" id="d0e21"></a>The Dependency
Inversion Principle</h3>
</div>
<p>I learned one of the most important OOD techniques 10 years ago
on an OOD workshop. It has since become known as the Dependency
Inversion Principle (see <a href=
"http://www.objectmentor.com/publications/dip.pdf" target=
"_top">www.objectmentor.com/publications/dip.pdf</a>). It
eliminates most of the dependencies between classes, which yields
three major advantages:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>The impact of design changes is minimised; the design is thus
both more flexible and more robust</p>
</li>
<li>
<p>The scope for re-use of classes is increased</p>
</li>
<li>
<p>Unit testing of classes is facilitated</p>
</li>
</ul>
</div>
<p>This Principle pervades many of the latest OO technologies, e.g.
the use of <tt class="type">interface</tt> and <tt class=
"type">class</tt> in Java, the use of interfaces and co-classes in
COM. The Principle can be realised in C++ by means of abstract
classes.</p>
<div class="sect3" lang="en">
<div class="titlepage">
<h3><a name="d0e47" id="d0e47"></a>A simple
class</h4>
</div>
<p>Consider a C++ class that simply stores a floating-point number.
We can declare its interface in an abstract class as follows:</p>
<pre class="programlisting">
#ifndef ASTORE_H
#define ASTORE_H
class Astore {
public:
    virtual void Put(double d) = 0;
    virtual double Get() const = 0;
    virtual ~AStore() {}
};
#endif // ASTORE_H
</pre>
<p>This corresponds to an interface in Java and COM. I have used
the convention of prefixing the class name with A to indicate that
it is an abstract class. There are no data members or constructors.
The methods which make up the abstraction, Put and Get, are
declared pure virtual. The standard virtual destructor is also
provided (note that this must be implemented, not pure).</p>
<p>We can then implement this abstraction by inheriting from it.
For the purposes of illustration, a trivial implementation is shown
below (using such a <tt class="classname">CStore</tt> object would
be no different from using a <tt class="type">double</tt> so it is
an unnecessarily complicated abstraction). Examples of more
realistic implementations are when the value needs to be protected
against concurrent access, or when the value needs to be mapped to
a hardware address.</p>
<pre class="programlisting">
#ifndef STORE_H
#define STORE_H
#include &quot;AStore.h&quot;
class CStore : public Astore {
protected:
   CStore() : m_d(0.0) {}
public:
   static AStore *New() { return new CStore; }
   static int main();
   virtual void Put(double d) { m_d = d; }
   virtual double Get() const { return m_d; }
   virtual ~CStore() {;}
private:
   double m_d;
};
#endif // STORE_H
</pre>
<p>This corresponds to a class in Java and a co-class in COM.
Implementations are provided for the abstract methods <tt class=
"methodname">Put</tt> and <tt class="methodname">Get</tt>, together
with the standard virtual destructor. The <tt class=
"methodname">main</tt> method is used for testing and is discussed
later.</p>
<p>Because this realisation of the Dependency Inversion Principle
depends upon the use of <tt class="type">virtual</tt> functions, it
only works if pointers to objects of this class are used. Hence
there are no public constructors; a <tt class="type">static</tt>
function provided will construct an object of the class and return
a pointer to it. I have used the convention of naming this function
<tt class="methodname">New</tt>, by analogy with the C++ keyword
<tt class="literal">new</tt>. For each constructor declared by the
class there should be a corresponding New with the same arguments
as the constructor.</p>
</div>
<div class="sect3" lang="en">
<div class="titlepage">
<h3><a name="d0e91" id="d0e91"></a>A class depending
upon another class</h4>
</div>
<p>Now consider a class that depends upon this class, for example
we might use the store to hold the value of a simple pocket
calculator memory. Again we abstract the interface from the
implementation:</p>
<pre class="programlisting">
#ifndef AMEMORY_H
#define AMEMORY_H
class Amemory {
public:
   virtual void Save(double d) = 0;
   virtual void Add(double d) = 0;
   virtual void Subtract(double d) = 0;
   virtual void Cancel() = 0;
   virtual double Recall() const = 0;
   virtual ~AMemory() {;}
};
#endif // AMEMORY_H

#ifndef MEMORY_H
#define MEMORY_H
#include &quot;AMemory.h&quot;
#include &quot;AClassFactory.h&quot;
#include &quot;AStore.h&quot;
class CMemory : public Amemory {
protected:
   CMemory() : pStore(0) {;}
   void Create(AClassFactory *pClassFactory){
      pStore = pClassFactory-&gt;CreateStore();
   }
public:
   static AMemory *New(AclassFactory
                               *pClassFactory) {
      CMemory *pMemory = new CMemory();
      pMemory-&gt;Create(pClassFactory);
      return pMemory;
   }
   static int main();
   virtual void Save(double d){pStore-&gt;Put(d);}
   virtual void Add(double d) 
            { pStore-&gt;Put(d + pStore-&gt;Get()); }
   virtual void Subtract(double d){Add(0 - d);}
   virtual void Cancel(){ pStore-&gt;Put(0); }
   virtual double Recall() const 
                        { return pStore-&gt;Get(); }
   virtual ~CMemory(){if(pStore)delete pStore;}
private:
   AStore *pStore;
};
#endif // MEMORY_H
</pre>
<p>The essential point of the Dependency Inversion Principle is
that the classes <tt class="classname">AMemory</tt> and <tt class=
"classname">CMemory</tt> must only depend upon abstract classes.
Hence the member variable <tt class="varname">pStore</tt> is of
class pointer to <tt class="classname">AStore</tt>, the
abstraction, not <tt class="classname">CStore</tt>. This means that
any change to the implementation of <tt class=
"classname">AStore</tt> has no impact at all upon this class.
<tt class="classname">CStore</tt> itself could be modified, or we
could replace it with another class derived from <tt class=
"classname">AStore</tt> (say <tt class=
"classname">CProtectedStore</tt> or <tt class=
"classname">CMappedStore</tt> corresponding to the previously
enumerated more realistic examples). The Principle has exactly the
same benefits if a member function of a class uses abstract classes
for the types of its arguments and return values (not shown in this
example).</p>
<p>This leaves the issue of how classes initialise member variables
that are pointers to objects declared abstract. This can be solved
by means of a class factory that encapsulates all the New static
member functions. The class factory is passed to any <tt class=
"classname">New</tt> <tt class="literal">static</tt> member
function which needs it, and the <tt class="classname">New</tt> in
turn calls a protected member function (conventionally named
<tt class="methodname">Create</tt>) to use the class factory
methods to initialise member variables which are pointers to
objects declared abstract.</p>
<p>The class factory is declared and implemented using the
Dependency Inversion Principle just like the other classes:</p>
<pre class="programlisting">
#ifndef ACLASSFACTORY_H
#define ACLASSFACTORY_H
#include &quot;AMemory.h&quot;
#include &quot;AStore.h&quot;
class AclassFactory {
public:
   virtual AStore *CreateStore() = 0;
   virtual AMemory *CreateMemory(
            AClassFactory *pClassFactory) = 0;
};
class CNullClassFactory : public AclassFactory {
public:
   virtual AStore *CreateStore() { return 0; }
   virtual AMemory *CreateMemory(
       AClassFactory *pClassFactory){return 0;}
};
#endif // ACLASSFACTORY_H

#ifndef CLASSFACTORY_H
#define CLASSFACTORY_H
#include &quot;AClassFactory.h&quot;
#include &quot;Store.h&quot;
#include &quot;Memory.h&quot;
class CClassFactory : public AclassFactory {
public:
   virtual AStore *CreateStore() {
      return CStore::New();
   }
   virtual AMemory *CreateMemory(
               AClassFactory *pClassFactory){
      return CMemory::New(pClassFactory);
   }
};
#endif // CLASSFACTORY_H
</pre>
<p>Hence to change the implementation of a class being used, all
that is required is to modify the implementation of the class
factory; there is no impact at all upon the client classes. The
null class factory is useful when testing and is discussed
later.</p>
</div>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e150" id="d0e150"></a>Testing</h3>
</div>
<div class="sect3" lang="en">
<div class="titlepage">
<h3><a name="d0e153" id="d0e153"></a>A convention for
unit testing</h4>
</div>
<p>The static member functions named main are used for unit
testing. The convention that every class should have such a main
was proposed by Francis Glassborow in EXE magazine (May 1999). An
example implementation for the <tt class="classname">CStore</tt>
class is:</p>
<pre class="programlisting">
#ifdef
      TESTING #include &quot;Store.h&quot; #include &lt;cassert&gt; int CStore::main() {
      AStore *pStore = New(); assert(0.0 == pStore-&gt;Get());
      pStore-&gt;Put(3.0); assert(3.0 == pStore-&gt;Get());
      pStore-&gt;Put(2.0); assert(2.0 == pStore-&gt;Get()); delete pStore;
      return 1; } #endif // TESTING
</pre>
<p>This convention makes it trivial to write a test harness for
multiple classes:</p>
<pre class="programlisting">
#include &quot;Store.h&quot; #include &quot;Memory.h&quot;
      #include &lt;cassert&gt; int main(int argc, char* argv[]){
      assert(CStore::main()); assert(CMemory::main()); return 0;
      }
</pre></div>
<div class="sect3" lang="en">
<div class="titlepage">
<h3><a name="d0e167" id="d0e167"></a>The Dependency
Inversion Principle and unit testing</h4>
</div>
<p>The thing I like the most about the Dependency Inversion
Principle is that it facilitates unit testing. Stub versions of
classes that a class under test depends upon are easily
incorporated into the test harness (though writing the stubs is not
always easy, of course). All we need to do is implement a class
factory that will return pointers to stub objects.</p>
<p>Consider unit-testing <tt class="classname">CMemory</tt> with a
stub implementation of <tt class="classname">AStore</tt> named
<tt class="classname">CStoreStub</tt>. Glassborow's convention is
that classes used for unit testing a particular class should be
declared in a file named <tt class="filename"><i class=
"replaceable"><tt>&lt;ClassUnderTest&gt;</tt></i>Tester.h</tt>. So
in <tt class="filename">MemoryTester.h</tt> we could have:</p>
<pre class="programlisting">
#ifndef MEMORYTESTER_H #define MEMORYTESTER_H #include
      &quot;AClassFactory.h&quot; #include &lt;cassert&gt; class CStoreStub : public
      Astore { public: CStoreStub() : m_nTestCase(0) {;} virtual void
      Put(double d) { m_nTestCase++; switch(m_nTestCase) { case 2: assert(d ==
      3.0); break; case 5: assert(d == 5.0); break; case 8: assert(d == 2.0);
      break; case 10: assert(d == 0.0); break; default: assert(0); break; } }
      virtual double Get() const { m_nTestCase++; switch(m_nTestCase) { case
      1: return 0.0; break; case 3: case 4: return 3.0; break; case 6: case 7:
      return 5.0; break; case 9: return 2.0; break; case 11: return 0.0;
      break; default: assert(0); return 0.0; break; } } virtual ~CStoreStub()
      {;} private: mutable int m_nTestCase; }; class CStubClassFactory :
      public CNullClassFactory { public: virtual AStore *CreateStore() {
      return new CStoreStub; } }; #endif // MEMORYTESTER_H
</pre>
<p>The stub class factory is derived from the null class factory so
that we only have to implement the methods we actually need for
these unit tests. In this case it is just the <tt class=
"methodname">CreateStore</tt> method, and we implement this to
return a pointer to a <tt class="classname">CStoreStub</tt> object.
We then use the stub class factory in the unit tests for <tt class=
"classname">CMemory</tt>:</p>
<pre class="programlisting">
#ifdef TESTING
      #include &quot;Memory.h&quot; #include &quot;MemoryTester.h&quot; #include &lt;cassert&gt;
      int CMemory::main(){ CStubClassFactory StubClassFactory; AMemory
      *pMemory = New(&amp;amp;StubClassFactory); assert(0.0 ==
      pMemory-&gt;Recall()); pMemory-&gt;Save(3.0); assert(3.0 ==
      pMemory-&gt;Recall()); pMemory-&gt;Add(2.0); assert(5.0 ==
      pMemory-&gt;Recall()); pMemory-&gt;Subtract(3.0); assert(2.0 ==
      pMemory-&gt;Recall()); pMemory-&gt;Cancel(); assert(0.0 ==
      pMemory-&gt;Recall()); delete pMemory; return 1; } #endif //
      TESTING
</pre></div>
<div class="sect3" lang="en">
<div class="titlepage">
<h3><a name="d0e206" id="d0e206"></a>Editorial
Notes:</h4>
</div>
<p class="c2"><span class="remark">Unfortunately, since having my
article published in EXE it has come to my notice that while main
is not reserved in C it is in C++ and so strictly speaking it
should not be used other than for the entry point to a
program.</span></p>
<p class="c2"><span class="remark">I have taken liberties with the
code format to get this article to fit.</span></p>
</div>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
