Friday, May 17, 2013

Dependency inversion principle where one depend abstractions

The Dependency Inversion principle is part of the SOLID Principles and is an important principle for among other things, to promote testability and reuse of the higher-level algorithm.
Background: As indicated on Uncle Bob's web page, Dependency Inversion is about depending on abstractions, not on concretions.
In practice, what happens is that some places where your class instantiates another class directly, need to be changed such that the implementation of the inner class can be specified by the caller.
For instance, if I have a Model class, I should not hard code it to use a specific database class. If I do that, I cannot use the Model class to use a different database implementation. This might be useful if you have a different database provider, or you may want to replace the database provider with a fake database for testing purposes.
Rather than the Model doing a "new" on the Database class, it will simply use an IDatabase interface that the Database class implements. The Model never refers to a concrete Database class. But then who instantiates the Database class? One solution is Constructor Injection (part of Dependency Injection). For this example, the Model class is given a new constructor that takes an IDatabase instance which it is to use, rather than instantiate one itself.
This solves the original problem of the Model no longer references the concrete Database class and uses the database through the IDatabase abstraction. But it introduces the problem mentioned in the Question, which is that it goes against Law of Demeter. That is, in this case, the caller of Model now has to know about IDatabase, when previously it did not. The Model is now exposing to its clients some detail about how it gets its job done.
Even if you were okay with this, there's another issue that seems to confuse a lot of people, including some trainers. There's as an assumption that any time a class, such as Model, instantiates another class concretely, then it's breaking the Dependency Inversion principle and therefore it is bad. But in practice, you can't follow these types of hard-and-fast rules. There are times when you need to use concrete classes. For instance, if you're going to throw an exception you have to "new it up" (eg. threw new BadArgumentException(...)). Or use classes from the base system such as strings, dictionaries, etc.
There's no simple rule that works in all cases. You have to understand what it is that you're trying to accomplish. If you're after testability, then the fact that the Model classes references the Database class directly is not itself a problem. The problem is the fact that the Model class has no other means of using another Database class. You solve this problem by implementing the Model class such that it uses IDatabase, and allows a client to specify an IDatabase implementation. If one is not specified by the client, the Model can then use a concrete implementation.
This is similar to the design of the many libraries, including C++ Standard Library. For instance, looking at the declaration std::set container:
template < class T,                        // set::key_type/value_type
           class Compare = less<T>,        // set::key_compare/value_compare
           class Alloc = allocator<T> >    // set::allocator_type
           > class set;
You can see that it allows you to specify a comparer and an allocator, but most of the time, you take the default, especially the allocator. The STL has many such facets, especially in the IO library where detailed aspects of streaming can be augmented for localization, endianness, locales, etc.
In addition to testability, this allows the reuse of the higher-level algorithm with entirely different implementation of the classes that the algorithm internally uses.
And finally, back to the assertion I made previously with regard to scenarios where you would not want to invert the dependency. That is, there are times when you need to instantiate a concrete class, such as when instantiating the exception class, BadArgumentException. But, if you're after testability, you can also make the argument that you do, in fact, want to invert dependency of this as well. You may want to design the Model class such that all instantiations of exceptions are delegated to a class and invoked through an abstract interface. That way, code that tests the Model class can provide its own exception class whose usage the test can then monitor.
I've had colleagues give me examples where they abstract instantiation of even system calls, such as "getsystemtime" simply so they can test daylight savings and time-zone scenarios through their unit-testing.
Follow the YAGNI principle -- don't add abstractions simply because you think you might need it. If you're practicing test-first development, the right abstractions becomes apparent and only just enough abstraction is implemented to pass the test.

Thursday, August 12, 2010

Brain-dead simplistic logger

var message = "message that gets logged goes here";
System.IO.File.AppendAllText(System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "log.txt"), string.Format("{0}\r\n", message));



Then type:
    %localappdata%
from the Run dialog to display the folder containing log.txt.
Or type:
    %localappdata%\log.txt

Now make a method out of it

....and have work like the Format command:

private static void Log(string format, params object[] parameters)
{
System.IO.File.AppendAllText(System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "log.txt"), string.Format(format + "\r\n", parameters));
}

If you want to clear the log file, put this in the appropriate place:

System.IO.File.Delete(System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "log.txt"));

Friday, January 15, 2010

Brain Dead Hash Function

I love things that are brain-dead simple.   Here's a very old C function that hashes a string:

int
HashFunction(char *string, int size)
{
   int hashkey = 1;

   while (string[0])
   {
      hashkey  = hashkey<<1^string[0];
      string++;
   }

   return hashkey%size;
}

Another way: although the following routine returns the crc16 for the string that's passed in, it can also be used as a way to hash a string:

/*    crc16 - crc16 routine
 *
 *    R.K. Irvine
 *
 *    This routine returns the crc16 for the string pointed
 *    to by "in".
 *    crc16 is given by:  x^16 + x^15 + x^2 + 1
 */
unsigned short
crc16(register char *in)
{
   register unsigned int n, crc;

   static unsigned short
   crc16l[]
   =
   {
      0x0000,0xc0c1,0xc181,0x0140,
      0xc301,0x03c0,0x0280,0xc241,
      0xc601,0x06c0,0x0780,0xc741,
      0x0500,0xc5c1,0xc481,0x0440,
   };

   static unsigned short
   crc16h[]
   =
   {
      0x0000,0xcc01,0xd801,0x1400,
      0xf001,0x3c00,0x2800,0xe401,
      0xa001,0x6c00,0x7800,0xb401,
      0x5000,0x9c01,0x8801,0x4400,
   };

   crc = 0;
   while(n = (unsigned char)(*in++))
   {    
      n ^= crc;
      crc = crc16l[n&0x0f] ^ crc16h[(n>>4)&0x0f] ^ (crc>>8);
   }

   return crc;
}

Monday, December 29, 2008

Tetris in Microsoft Small Basic

Tetris for Small Basic: link

(if that link doesn't work, try this: link)

Wiki page: link

Online version: link

Friday, December 12, 2008

Idea for Design by Contract and Unit Testing

One attribute of DbC that would be nice to have in the Unit Testing world is the localization of the test to the method it's testing. ...

click here for article

Thursday, January 3, 2008

How to use NUnit to test native C++ code


Article published: <link>

Old article link, in case the above doesn't work: <link>

Friday, December 14, 2007

Dependency Injection

Dependency Injection is a method of wiring up classes externally to the definition of the class.

click here for article

Tuesday, November 27, 2007

Tuesday, November 6, 2007

Automatically backup your computer for free

Automatically backup up to 2 gigs worth of data for free. Or as much data as you want, for only $4.95 a month. Goto mozy.com.

Update: Some people are concerned about their data going to mozy.com, no matter how much the vendor says they're careful with our data. If this is a concern, I think the best thing to do is to encrypt the data that gets sent there. A free tool from truecrypt.org should do the job.

How to convert .NET DateTime to Variant Time in VBA

Article published May 18, 2007: article link.

Thursday, November 1, 2007

Object Oriented C

Article published January, 2004: link.

(older link in case the above doesn't work: link.)

Monday, October 31, 2005

Copy Constructors and Assignment Operators


Article published August, 2005: link


(Original article: link)

Wednesday, May 19, 2004

Zapped -- Lasik surgeory

Article published may 19th, 2004: article link.

Saturday, October 7, 2000

Variant Streaming Code


Article published October, 2000: link.

Saturday, April 29, 2000

Thursday, April 1, 1999

True Inheritance with JavaScript


Latest version:
 link

History:
  • As originally published in April, 1999: link.
  • As referenced by the Computer Science Department at the Rochester Institute of Technology, see section titled "Some resources for doing OO programming in JavaScript" under "10.3.1. Core language", at http://www.cs.rit.edu/~mjh/base/resources/languages.xml

Saturday, August 15, 1998

Calculating fibonacci series at compile-time


#include <stdio.h>

// The following code prints out the first five elements of the
// fibonacci series without calculating the values at runtime.

template <int param>
struct CFibonacci
{
    static const value;
};

template <int param>
const CFibonacci<param>::value = 
CFibonacci<param - 2>::value + CFibonacci<param - 1>::value;

const CFibonacci<0>::value = 0;
const CFibonacci<1>::value = 1;


void main( void )
{
    printf( "%d\n", CFibonacci<1>::value );
    printf( "%d\n", CFibonacci<2>::value );
    printf( "%d\n", CFibonacci<3>::value );
    printf( "%d\n", CFibonacci<4>::value );
    printf( "%d\n", CFibonacci<5>::value );
}

Wednesday, March 1, 1995

Saturday, November 30, 1985

My early antics pre-internet.


It was 1985, and I was reading my favorite computer magazine, Antic and was floored to see my name mentioned in print.  I had forgotten, but apparently I wrote a "letter" to the magazine describing some programming trick.   I remember seeing the text, "Kudos to Kenny Ksajikian".

My English wasn't so good, so I had to look up "Kudos", which made the phrase stuck in my mind.   Decades later I google that term, and ouala --> Kudos' to Kenny Ksajikian.