Freitag, 11. November 2011

Dependency Injection vs Encapsulation

When trying to show coworkers of the advantages of Dependency Injection I often encounter the argument, that it hurts one of the major object-oriented principles – encapsulation.

Let us consider the following basic example of class that has two dependencies, created in the constructor:

public class SomeClass
{
IWriter writer;
ILogger logger;

public SomeClass()
{
this.writer = new StreamWriter();
this.logger = new RegistryLogger();
}
}

Client code:

SomeClass someClass = new SomeClass();
SomeClass has direct dependencies and can’t be used without them and is clearly not testable. Let us see a implementation with dependency injection:


public class SomeClass : ISomeClass
{
IWriter writer;
ILogger logger;

public SomeClass(IWriter writer, ILogger logger)
{
this.writer = writer;
this.logger = logger;
}
}
This is clearly much better, but is considered to be violating the encapsulation principle form some developers. Encapsulation principle tells us to hide the class inner workings form the user. This is important in order to allow us to change the class implementation without changing all of its clients. This is a valid point, that I respect, we all strive to the “low maintenance road” (Ayende) - the most important thing in software development.

However let us look at the client code and see if it actually breaks the encapsulation principle:

ISomeClass someClass = Container.Resolve();
What we see here is that, the client code does not even know a damn thing about the class dependencies!
We just let the dependency injection container do the heavy lifting for us and don’t worry how to create all of the class dependencies.
In practice we actually do not even have the possibility to use the constructor!
That’s true – in production code instantiating a class from the constructor would require creating all of its dependencies, which would require instantiating their dependencies and so on. It would be safe to say, that the developers can’t even use the constructor and must instantiate their objects using the dependency injection container, which is so much easier.

So the user of the code does not actually even know what kind if dependencies a class has – all of this because of the dependency injection container. So actually instead of breaking encapsulation we are driving it to a whole new level – each individual class does not get to decide what kind of object it needs – everything gets configured in the configuration of the container. This definitely does not break the encapsulation principle. It makes it hold even stronger.

As a side note I want to point out, that I am definitely against the point of view “If you let the developers to bad things, then they will”. If you don’t trust your developers you shouldn’t hire them in the first place. Treat all the of the developers as stars and they will be.

Happy dependent less programming!

Sonntag, 30. November 2008

Blog moved

My blog has moved to word press
http://devdimi.wordpress.com

Older posts can be found there.

Dienstag, 26. Februar 2008

Delphi/C++ Builder vs .NET and C#

Lately I was looking for a nice GUI front-end for MySql and also for Sqlite. MySql now comes with several GUI Tools, including MySql Query Browser which is supposed to do exactly what I need - except, that it doesn't.
Some features simply aren't just there - what about clicking in data cell to edit its value? Too advanced to be required from a application being developed for at least two years or even more? And I was thinking that Database GUI editors were all about editing data.

Than I tried the open source HediSql. It is truly awesome! Given the enormous competition in the field, and official GUI from MySql itself these guyes just rock!
It gives you everything that you need; it is fast, responsible and nice to work with. Keep up the good work! What about Sqlite support?

It was clear that it is native application - it just worked too smooth and had too small memory footprint to be developed with .NET.
A wanted to look at the source and to my surprise it wasn't in C++, it was Delphi!
That really got me thinking - some of the best software products, that I have used - BSPlayer, Skype, HeidiSql, TestComplete- just to name a few, aren't developed in a mainstream language like C++ or C#, but in Deplhi. I even was told, that the initial version of the eBay ISAPI was also developed in Delphi.
But there is more - a lot of bussines applications, that really make a lot of money for their developers are also developed also in Delphi.

We had a presentation at work from a partner software company, which product works with ours. He talked all day long and he could show us just a small part the application features. It was really good and he developed it all by himself. Guess what development platform he is using - Delphi.

Well I don't know why Microsoft can't pull this off with all the billions they are putting in to their development platform. .NET is really good, I love developing software with it, but I hate using .NET products, because they are slow. Not too slow if the developers did a good job, but a lot slower than anything native.

I know that there is no market for Delphi developers and I know that Java and .NET jobs are all around the place, but Delphi and C++ Builder are better for developing user software.

So if you are looking for career opportunities - go .NET or J2EE. But if you want to develop a software product and sell it successfully - Deplhi and C++ Builder are the way to go.

I wish I had the courage to use this platform way myself.

memccpy considered harmful ( if you don't know how to use it)

Ever heard of the memccpy function?

It is very similar to memcpy, but it will stop copying if given delimiter character is encountered. So that's a nice feature - let's just use it instead of memcpy everywhere!

Except that you must pay extreme attention to what are you actually copying, and what kind of delimiter character are you using. Copying text strings and using line feed '\n' as delimiter is fine, but copying mac addresses, and using '\n' as delimiter, as a coworker did, is not.
But why, you may ask. Well because the '\n' character, 0x0a in hex, is pretty valid byte to come in a mac address. And guess what - if you use memccpy to copy a mac address and use '\n' as delimiter, it is going the get truncated! And because the target buffer is already allocated with certain size and filled with some random data, that may also be valid for mac address, this kind of error may go unnoticed for a long time.

This brings up the question of the data representation, that you are using and how well you understand it, and also the quality of the interface definitions of common C functions and stuff like:

if(strcmp(str1, str2)) {
/*
if you are expecting to get here
if str1 and str2 are the same,
you are in for a surprise
*/
}


Otherwise remember it also very important to always check the return values, that you are getting and event more important also: test, test, test

Montag, 25. Februar 2008

GUIDs, their representation and Base64

Everyone knows what a GUID is - 128 bit number, that is supposed to be global unique and it is used for identifier for different types of objects, COM objects most notably.

Usually they are formatted as hex string like {F7F052A2-8BC7-4b84-8330-228BCA8A6E19}. A tool for creating guids can is guuidgen.exe, there are also System.Guid class and CoCreateGuid API.
Sometimes GUIDs have to be formatted more compactly, for instance in the IFC Specification GUIDs have to be formatted as Base64, making them string with 22 characters length.
Sadly the base64 encoding is non-compatible with the .NET implementation, which makes it a hard task to convert System.Guid object to required format.
IFC Base64 is using 0-9A-Za-z_$ characters and .NET implementation is using something like A-Za-z0-9 for encoding table.
There is some sample C code on the ifc wiki site, so I went for the easy solution - make a dll and call it from .NET.
The problems with this approach kept comming one after another - mostly dll was not always found in Web scenario, due to deployment issues. But there are also other possible hurles - 64bit migration, deployment on Mono and so on.
So I needed a pure managed implementation of Base64 encoding for GUIDs.
Some googleing brought me to sample code, that I adjusted it to the spec and here is the solution:


public class Managed {

public static string GetId(Guid guid) {
return ToBase64String(guid.ToByteArray());
}

public static string GetId() {
return ToBase64String(Guid.NewGuid().ToByteArray());
}

public static readonly char[] base64Chars = new char[]
{ '0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z',
'_','$' };

public static string ToBase64String(byte[] value) {
int numBlocks;
int padBytes;

if ((value.Length % 3) == 0) {
numBlocks = value.Length / 3;
padBytes = 0;
} else {
numBlocks = 1 + (value.Length / 3);
padBytes = 3 - (value.Length % 3);
}
if (padBytes < 0 || padBytes > 3)
throw new ApplicationException("Fatal logic error in padding code");


byte[] newValue = new byte[numBlocks * 3];
for (int i = 0; i < value.Length; ++i)
newValue[i] = value[i];

byte[] resultBytes = new byte[numBlocks * 4];
char[] resultChars = new char[numBlocks * 4];

for (int i = 0; i < numBlocks; i++) {
resultBytes[i * 4 + 0] =
(byte)((newValue[i * 3 + 0] & 0xFC) >> 2);
resultBytes[i * 4 + 1] =
(byte)((newValue[i * 3 + 0] & 0x03) << 4 |
(newValue[i * 3 + 1] & 0xF0) >> 4);
resultBytes[i * 4 + 2] =
(byte)((newValue[i * 3 + 1] & 0x0F) << 2 |
(newValue[i * 3 + 2] & 0xC0) >> 6);
resultBytes[i * 4 + 3] =
(byte)((newValue[i * 3 + 2] & 0x3F));
}

for (int i = 0; i < numBlocks * 4; ++i)
resultChars[i] = base64Chars[resultBytes[i]];

string s = new string(resultChars);
return s.Substring(0, 22);
}
}


So if you have to encode something as Base64 or deal with GUIDs with one way or another - this may be helpful to you.
Original code by James McCaffrey

Hello World!

Hello everyone!

This is my first blog post! This blog is going to be about software development problems that I encounter at work and their solutions. I am mostly working with the .NET platform and C#, but there will also be bunch of other stuff like C++ and its pitfalls, Java, VB, VB.NET and nifty gritty Windows Installer MSI tricks and a lot more.
I hope this will be a nice trip and I will be glad if this is helpful to someone.