Lately I've been realizing the benefit of (some would argue overuse of) immutable objects to cut down dramatically on read-write dependency issues in my object model and their resulting conditions and side-effects, to ultimately make the code simpler to manage (kind of functional-programming-esque).
This practice has led me to create read-only objects that are provided values at creation/construction time and then to make available only public getters for external callers to access the properties with. Protected, internal and private setters allow internal control to be maintained over writing to the object model.
When creating interfaces while making an API over my object model, I've started considering the same issues about immutability. For example, by providing only public getters on my interfaces, and leaving it up to implementors to decide upon setters and how to handle that aspect.
An example of a "read-only" interface for implementation that I'm talking about is this Valuable Item (just for demonstration):
public interface IValuableItem {
decimal Amount {get;}
string Currency {get;}
}
However I got to wondering how I should provide a companion interface that allows for writing (and if I should), and not combine those operations within the same interface as to not "taint" its immutability.
The following ideas have come to mind, just off the top of my head. Without providing what I think are pros and cons to each, what do you think the best approach is? Is there a coding methodology common in the industry for managing this concept?
// companion writer
public interface IValuableModifier {
decimal Amount {set;}
string Currency {set;}
}
or
// explicit methods to enforce importance of or deviance in the programming
public interface IValuableModifier {
void SetAmount(decimal val);
void SetCurrency(string cur);
}
or
// companion writer that inherits the original interface
public interface IValuableModifier : IValuableItem { //...
or
// Let a concrete class choose one and/or the other.
class Concrete : IValuableModifer, IValuableItem { //...
or
etc...
What else can help me imbue writing on my otherwise immutable programming model and keep it moderately flexible or at least to separate the concerns for better control over it?
I think I might use a variant of your ideas, something like this:
public interface IValuableItem
{
decimal Amount { get; }
string Currency { get; }
}
public interface IMutableValuable : IValuableItem
{
new decimal Amount { set; get; }
new string Currency { set; get; }
}
class Item : IMutableValuable
{
public decimal Amount { get; set; }
public string Currency { get; set; }
}
This way your mutable interface has full getters and setters (I don't think it makes sense to have an interface that has setters but no getters), but any object that implements it will also have an immutable version of the interface that you can use for any pure-functional code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With