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:
- safeString – ensures a string is “safe” i.e. either has a value or is a fallback
- 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.
Leave a Reply
Want to join the discussion?Feel free to contribute!