Question On ‘Give Types Meaningful Names’

 

 

Yesterday’s blog article on ‘Give Types Meaningful Names’ attracted an exciting question from Andy:

“If I have a bunch of String functions or Utility Functions, where do I put these. For example:

  1. safeString – ensures a string is “safe” i.e. either has a value or is a fallback
  2. isNullOrEmpty – checks if an object is undefined/nil/empty object”

 

Let’s get into it!

The string utility methods would be great to have on the string object. C# has a way to add additional methods to a type for which we lack access to the source code: Extension Methods. Using the magic of extension methods, we can add Andy’s two string utility functions to the string type:

  public static class StringExtensions
  {
     public static string safeString(this string input)
     {
        // TODO: Check safety of the string

        return input;
     }

     public static bool isNullOrEmpty(this string input)
     {
        // Something like this:
        return input == null || input == "";
     }
  }

Now we can call 

var safeString = string.safeString(inputString);
var hasValue = string.isNullOrEmpty(inputString);

Because extension methods must be declared static, we can perform null checks inside them, as we did for isNullOrEmpty(). Instance methods do not allow that – calling a method on a null would cause a NullReferenceException.

We can use extension methods to put utility functions on other data types for which we can’t change the definitions: DateTime, int, object, ReadOnlyCollection, SqlConnection, and all types.

OK, what about other types of utility functions? 

Routinely we need to convert from one type to another. Say, transform a CustomerRegistration object into a Customer object. IMO this kind of conversion qualifies as a utility function. 

At first glance, it’s not apparent which object should own this behaviour. Should we have a specific converter class? Maybe.

  var customer = CustomerConverter.Convert(custReg);

That works. 

I feel that introducing CustomerConverter is not the simplest, best way of performing the conversion.  

What if CustomerRegistration knew how to transform itself into a Customer? Eh?!

Like so:

var customer = custReg.ToCustomer();

ToCustomer() is an instance method on the CustomerRegistration class that will take the internal state of the CustomerRegistration and transform it into a Customer object. 

Pretty cool, right?! The registration knows how to convert itself to a Customer!

A note of caution: Not all types can be converted this way. Sometimes one type should not know about another type. Why? Because it would set up a dependency that goes the ‘wrong’ way. I’ll address this next week.

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply