Take the following code:
public class ClientCode
public void CallAnOperation()
string fileName = string.Empty;
int lengthOfFile = 0;
Getter get = new Getter();
get.GetFile(ref fileName, ref lengthOfFile);
Doer doGuy = new Doer();
int retValue = doGuy.DoSomething(fileName, lengthOfFile);
if(retValue != 23) //throw an exception, etc.
public class Getter
public void GetFile(ref string name, ref int length)
//Do some work to get file, and then. . .
name = “myFileName.txt”;
length = 98;
public class Doer
public int DoSomething(string fileName, int fileLength)
//Do something with this information. . .
//We’ll pretend the the operation succeeded and return 23;
//If the operation had failed, we would have returned 67.
There are several issues with the above code. Kudos to you if you already know what’s going on.
First, my CallAnOperation() method needs values for fileName, and lengthOfFile. He passes references to these two into a class that initializes them to correct values. This is the first mistake. Now the CallAnOperation() method has to have intimate knowledge of the inner behavior of the GetFile method. This is bad and leads to tightly-coupled code that doesn’t make sense. Instead, the GetFile method should return an object that contains the needed information.
The second issue is with the DoSomething method. This method has custom return codes to signal if things are good or bad. This requires the user code to know that “23” is a good number, and “67” is a bad number. Again, this is forcing knowledge onto the client. The CallAnOperation() method shouldn’t have to know how a component functions. The method names should be descriptive enough, and the return value should be quickly understandable. At most, returning true or false may be acceptable, but a more preferrable approach is: if something unacceptable happened, throw an exception. If validation is in the method and is the cause for a return value instead of an exception, consider refactoring the validation into a separate method.