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.
Question On ‘Give Types Meaningful Names’
/by Olaf ThielkeQuestion 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:
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:
Now we can call
Because extension methods must be declared static, we can perform
null
checks inside them, as we did forisNullOrEmpty()
. Instance methods do not allow that – calling a method on anull
would cause aNullReferenceException
.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 aCustomer
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.
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 aCustomer
? Eh?!Like so:
ToCustomer()
is an instance method on theCustomerRegistration
class that will take the internal state of theCustomerRegistration
and transform it into aCustomer
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.