开发者

Immutable class appropriate when instances are used in a "what-if" tool?

开发者 https://www.devze.com 2023-02-17 07:03 出处:网络
I have a class that basically represents the parameters of a model, and encapsulates the logic to calculate values of the model with those parameters. I\'m trying to decide if this class should be imm

I have a class that basically represents the parameters of a model, and encapsulates the logic to calculate values of the model with those parameters. I'm trying to decide if this class should be immutable. In practice, instances of the model will be generated by fitting to some data set, so in that sense it makes sense (to me at least) for that instance to be immutable since it's tied to external data.

On the 开发者_如何学运维other hand, there will be a GUI to let a user do a "what-if" wherein they can change the parameters to see how it changes model values. So I could make the model mutable to make this easy, or create new copies every time a parameter is changed. The latter seems awkward, especially if there are e.g. 5 parameters that could be ticked up and down individually...seems like I would have to implement a SetX() method for each parameter which returns a copy, right?

Am I overthinking this, or is there a proper pattern to use here? (This is C# code, though I guess not really language-specific)


Consider carefully how the object is going to actually be used for your speculative analysis. For straightforward, one-off, let's-mutate-the-field-try-something-and-change-it-back scenarios, sure, just make it mutable. But suppose you want to pull out the big guns; then it becomes much nicer to have an immutable model.

Data d = whatever;
// What if we mutate X and Y? Which one maximizes the value of Foo(d) ?
var query = from x in Range(0, 100)
            from y in Range(0, 100)
            let mutated = data.MutateX(x).MutateY(y)
            orderby Foo(mutated)
            select mutated;

var max = query.First();

And so on. With an immutable pattern it becomes much easier to write speculative queries, it becomes much easier to parallelize those queries across multiple cores, and so on.


The latter seems awkward

Well that's your answer. The goal of API design is to make writing code as easy as possible. If a particular pattern makes it more difficult or awkward than the alternative, the alternative is probably correct.


I think you're probably overthinking this a little bit. While there is probably a very elegant design pattern for this that uses eight classes and four interfaces, I think the simplest route forward would be to make it a normal, mutable class. Think about your intention: you want a Model that can be loaded from external data (perhaps a static method returning a Model instance) with parameters that can change according to user input. This seems like a use case for your everyday, garden variety Class.

You may also choose to separate your classes into a Data class and Strategy class, the second which contains the changeable parameters and uses something like a Strategy pattern to calculate the results.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号