There are some rules for us when applying functional programming techniques to our applications. The first one was “same argument same response” that we learned in our previous tutorial. The second important rule is “method signature honesty”.
Method Signature Honesty
In C#, method signature honesty refers to how a method's signature communicates its behavior. An honest method signature makes it easy for developers to understand what the method does and what to expect from it, without needing to delve into the implementation details.
The method signature should define all the expected input parameters and their data types. Similarly, it should specify the return type, if any. This helps developers understand what kind of data the method needs and what kind of data it produces.
Ideally, methods should be pure functions. This means they produce the same output for the same input every time without modifying any external state. In practice, some side effects might be necessary. But if a method modifies external data or has other side effects, these effects should be documented clearly, either in the method name or comments.
Let's check a simple code example:
public static int Divide(int a, int b)
{
return a / b;
}
So, what is the problem? Yes, from the first glance, we have specified all input parameters, but the problem occurs when you specify ‘0’ for the second argument.
The signature that accepts ‘int’ as a second argument indicates that it is allowed to provide any integer value, but in the given context, ‘0’ is not a valid argument. The user of the current function can’t guess it. So, in the signature, we should somehow specify the exact range for the second argument.
Let’s change our implementation:
public class NonZeroInteger
{
public int Value { get; init; }
public NonZeroInteger(int value)
{
if (value == 0)
throw new ArgumentException("0 is not a valid argument");
Value = value;
}
public static implicit operator NonZeroInteger(int value)
{
return new NonZeroInteger(value);
}
}
public static int Divide(int a, NonZeroInteger b)
{
return a / b.Value;
}
static void Main(string[] args)
{
Divide(3, 0);
}
NonZeroInteger clearly defines the borders and providing zero will fail not in the method, but in the object itself.
In the above context, we have an honest signature for the Divide method, but not everything simple as a given method.
Method signature honesty plays a crucial role in functional programming because functional programming emphasizes predictability and composability of functions. Here's how:
- Referential Transparency: Functional programs rely heavily on referential transparency, which means calling a function with the same arguments always produces the same result. Honest signatures help achieve this by clearly stating what the function does and potential outcomes for different inputs.
- Reasoning about Programs: With honest signatures, developers can reason about program behavior just by looking at the function definition. The signature encodes information about what the function can and cannot do, reducing the need to examine the implementation details.
- Composable Functions: Functional programming encourages building complex programs by composing smaller, well-defined functions. Honest signatures make functions easier to understand and integrate into larger programs, promoting reusability and reducing errors.
Conclusion
Applying functional programming in your C# projects adds a lot of advantages. It helps you to divide huge methods into smaller ones, define clear signatures for them, and help other developers easily understand your code without diving into documentation. Signature honest methods let your code be a clear "documentation" for the given method.