商业应用程序中的c#Immutable类
为什么以及何时我们在业务或数据库应用程序中需要不可变(即只读)类(我不是在谈论字符串
。我在谈论业务对象)?
谁能给我一个真实场景的例子?
Why and when do we need immutable (i.e. readonly) classes (I am not talking about string
. I am talking about Business Objects) in business or database applications?
Can anyone give me a real-world example of a scenario?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不可变类型比可变类型更容易推理 - 当您获得对实例的引用时,您知道您可以依赖它不变。您可以建立一种功能性的工作方式,其中您想要执行的任何突变都会成为创建新实例的操作(就像处理字符串一样) - 这些功能性操作可以安全地组合,而不必担心如果发生变化会发生什么操作以特定方式更改对象,这会损害其他操作。
一旦您根据不可变值的状态做出决定,您就知道该决定对该值仍然有效,因为该值本身无法更改。
此外,不变性对于线程很有用 - 当您想跨多个线程使用单个对象时,不变性可以避免很多有关数据争用等的问题。
其中许多好处对于业务对象可能很有用,但您确实需要以不同的思维方式处理问题。特别是,如果您的数据库行不是不可变的(即您将修改行而不是总是创建行的新“版本”),那么您需要注意任何给定值可能不再代表该行的数据库状态。
Immutable types are easier to reason about than mutable ones - when you've got a reference to an instance, you know you can rely on it not changing. You can build up a functional style of working, where any mutation you would want to perform becomes an operation creating a new instance (just as it does with string) - those functional operations can be composed safely, with no concerns around what happens if one of the operations changes the object in a particular way which would harm the other operations.
Once you've made a decision based on the state of an immutable value, you know that decision will remain valid for that value, because the value itself won't be able to change.
Additionally, immutability is useful for threading - immutability avoids a lot of the concerns around data-races etc when you want to use a single object across multiple threads.
A lot of these benefits can be useful for business objects, but you do need to approach problems with a different mindset. In particular, if your database rows aren't immutable (i.e. you will be modifying rows rather than always creating new "versions" of rows) then you need to be aware that any given value may no longer represent the database state for that row.
一旦您打印出发票并将其发送给客户,该发票就会被永久冻结。任何调整都需要应用于后续发票。
Once you have printed out an invoice and issued it to the customer, that invoice is frozen in time forever. Any adjustments would need to be applied on a subsequent invoice.
尽管乔恩确实为不可变对象的好处提供了令人信服的案例,但我会采取稍微不同的策略。
当您在代码中对业务流程进行建模时,显然您想要做的是使用代码中的机制来表示有关模型的事实。例如,如果客户是一种人,那么您可能会有一个 Person 基类和一个 Customer 派生类,等等。
不变性只是其中的另一种机制。因此,在您的业务流程中,请考虑哪些事情发生一次后就永远不会改变,而不是随着时间的推移而发生变化。
例如,考虑“客户”。客户有一个名字。客户的姓名会改变吗?当然。客户的姓名一直在变化,尤其是在结婚时。那么,Customer 应该是一个不可变的类吗?可能不会。从逻辑上讲,当客户更改姓名时,您不会从旧客户中创建新客户;而是创建新客户。老客户和新客户是同一个对象,只是name属性变了。
现在考虑“合同”。合同会改变吗?不会。对现有合同的修订会产生一份不同的新合同。特定合同中的日期、当事人、条款等都被及时冻结。合约对象可以是不可变的。
现在有趣的问题是,当合同提到客户并且客户更改了姓名时该怎么办。可变对象和不可变对象之间的交互使得这成为一个棘手的设计问题。
Though Jon certainly makes a compelling case for the benefits of immutable objects, I'd take a slightly different tack.
When you're modeling a business process in code, obviously what you want to do is to use mechanisms in the code to represent facts about the model. For example, if a customer is a kind of person, then you'd probably have a Person base class and a Customer derived class, and so on.
Immutability is just another one of those mechanisms. So in your business process, think about what things happen once and then never change, in contrast with what things change over time.
For example, consider "Customer". A customer has a name. Does the name of a customer ever change? Sure. Customer names change all the time, typically when they get married. So, should Customer be an immutable class? Probably not. Logically, when a customer changes her name, you do not create a new customer out of the old one; the old customer and the new customer are the same object, but the name property has changed.
Now consider "contract". Does a contract ever change? No. An emendation to an existing contract produces a new, different contract. The dates, parties, clauses, and so on in a particular contract are frozen in time. A contract object could be immutable.
Now the interesting question is what to do when a contract mentions a customer, and the customer changes their name. It's the interactions between mutable and immutable objects that make this a tricky design problem.