将派生值公开为属性是否是一种好的形式?

发布于 2024-07-27 22:22:11 字数 2042 浏览 1 评论 0原文

我需要在给定 7 个潜在输入的情况下得出一个重要值Uncle Bob 敦促我避免使用带有这么多参数的函数,所以我提取了类。 现在所有参数都是属性,我只剩下一个没有参数的计算方法。

我想,“那个”可能是一个属性,但我不确定这是否是 C# 惯用的。

我应该将最终结果公开为属性,还是不带参数的方法? 一般的 C# 程序员会觉得属性令人困惑或令人反感吗? Alt.Net 人群又如何呢?

decimal consumption = calculator.GetConsumption(); // obviously derived
decimal consumption = calculator.Consumption; // not so obvious

如果是后者:我还应该将临时结果声明为[私有]属性吗? 感谢大量的方法提取,我得到了几个临时结果。 其中许多不应该成为公共 API 的一部分。 不过,其中一些可能很有趣,如果我可以将它们作为属性访问,我的表达式会看起来更清晰:

decimal interim2 = this.ImportantInterimValue * otherval;

快乐实验部:

在 VS2008 中调试代码时,我注意到我一直将鼠标悬停在鼠标上在计算临时结果的方法调用上,期望将鼠标悬停在其返回值上。 将所有方法转换为属性后,我发现将中间结果公开为属性极大地有助于调试。我对此非常满意,但对可读性一直存在担忧。

临时值声明看起来更混乱。 然而,如果没有括号,表达式会更容易阅读。 我不再觉得有必要以动词开头方法名称。 相比之下:

// Clean method declaration; compulsive verby name; callers need
// parenthesis despite lack of any arguments.
decimal DetermineImportantInterimValue() {
    return this.DetermineOtherInterimValue() * this.SomeProperty;
}

// Messier property declaration; clean name; clean access syntax
decimal ImportantInterimValue {
    get {
        return this.OtherInterimValue * this.SomeProperty;
    }
}

我也许应该解释一下,我已经用 Python 编写了十年的代码。 我倾向于花费额外的时间让我的代码更容易调用而不是编写。 我不确定 Python 社区是否会将这种面向属性的风格视为可接受的“Pythonic”,但是:

def determineImportantInterimValue(self):
    "The usual way of doing it."
    return self.determineOtherInterimValue() * self.someAttribute

importantInterimValue = property(
    lambda self => self.otherInterimValue * self.someAttribute, 
    doc = "I'm not sure if this is Pythonic...")

I need to derive an important value given 7 potential inputs. Uncle Bob urges me to avoid functions with that many parameters, so I've extracted the class. All parameters now being properties, I'm left with a calculation method with no arguments.

“That”, I think, “could be a property, but I'm not sure if that's idiomatic C#.”

Should I expose the final result as a property, or as a method with no arguments? Would the average C# programmer find properties confusing or offensive? What about the Alt.Net crowd?

decimal consumption = calculator.GetConsumption(); // obviously derived
decimal consumption = calculator.Consumption; // not so obvious

If the latter: should I declare interim results as [private] properties, also? Thanks to heavy method extraction, I have several interim results. Many of these shouldn't be part of the public API. Some of them could be interesting, though, and my expressions would look cleaner if I could access them as properties:

decimal interim2 = this.ImportantInterimValue * otherval;

Happy Experiment Dept.:

While debugging my code in VS2008, I noticed that I kept hovering my mouse over the method calls that compute interim results, expecting a hover-over with their return value. After turning all methods into properties, I found that exposing interim results as properties greatly assisted debugging. I'm well pleased with that, but have lingering concerns about readability.

The interim value declarations look messier. The expressions, however, are easier to read without the brackets. I no longer feel compelled to start the method name with a verb. To contrast:

// Clean method declaration; compulsive verby name; callers need
// parenthesis despite lack of any arguments.
decimal DetermineImportantInterimValue() {
    return this.DetermineOtherInterimValue() * this.SomeProperty;
}

// Messier property declaration; clean name; clean access syntax
decimal ImportantInterimValue {
    get {
        return this.OtherInterimValue * this.SomeProperty;
    }
}

I should perhaps explain that I've been coding in Python for a decade. I've been left with a tendency to spend extra time making my code easier to call than to write. I'm not sure the Python community would regard this property-oriented style as acceptably “Pythonic”, however:

def determineImportantInterimValue(self):
    "The usual way of doing it."
    return self.determineOtherInterimValue() * self.someAttribute

importantInterimValue = property(
    lambda self => self.otherInterimValue * self.someAttribute, 
    doc = "I'm not sure if this is Pythonic...")

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

誰認得朕 2024-08-03 22:22:11

这里的重要问题似乎是这样的:

从长远来看,哪一个会为您生成更清晰、可维护的代码?

在我个人看来,将单独的计算隔离为属性比单独的计算有几个明显的优势:单个单一方法调用:

  • 无论您使用哪种类方法,您都可以看到在调试器中执行的计算。这在您调试类时可以提高工作效率 em>。

  • 如果计算是离散的,属性将执行得非常快,这意味着(在我看来),它们遵守属性设计的规则。 认为设计指南应该被视为束缚的想法是荒谬的。 请记住:没有灵丹妙药。

  • 如果计算被标记为私有或内部,它们不会给类的使用者增加不必要的复杂性。

    如果计算被标记为私有或内部,则它们不会增加不必要的复杂性

  • 如果所有属性都足够离散,编译器内联可能会为您解决性能问题。

    如果

  • 最后,如果返回最终计算的最终方法由于您可以阅读它而更容易维护和理解,那么这本身就是一个完全令人信服的论据。

你能做的最好的事情之一就是独立思考,敢于挑战我们的同行和前辈先入为主的一刀切观念。 每条规则都有例外。 这个案例很可能就是其中之一。

后记:
我不认为在绝大多数情况下我们应该放弃标准的属性设计。 但在某些情况下,需要偏离标准(TM),因为这样做是有意义的。

The important question here seems to be this:

Which one produces more legible, maintainable code for you in the long run?

In my personal opinion, isolating the individual calculations as properties has a couple of distinct advantages over a single monolothic method call:

  • You can see the calculations as they're performed in the debugger, regardless of the class method you're in. This is a boon to productivity while you're debugging the class.

  • If the calculations are discrete, the properties will execute very quickly, which means (in my opinion), they observe the rules for property design. It's absurd to think that a guideline for design should be treated as a straightjacket. Remember: There is no silver bullet.

  • If the calculations are marked private or internal, they do not add unnecessary complexity to consumers of the class.

  • If all of the properties are discrete enough, compiler inlining may resolve the performance issues for you.

  • Finally, if the final method that returns your final calculation is far and away easier to maintain and understand because you can read it, that is an utterly compelling argument in and of itself.

One of the best things you can do is think for yourself and dare to challenge the preconceived One Size Fits All notions of our peers and predecessors. There are exceptions to every rule. This case may very well be one of them.

Postscript:
I do not believe that we should abandon standard property design in the vast majority of cases. But there are cases where deviating from The Standard(TM) is called for, because it makes sense to do so.

謌踐踏愛綪 2024-08-03 22:22:11

就我个人而言,我更愿意将公共 API 作为方法而不是属性。 C# 中的属性应该尽可能“快”。 有关此讨论的更多详细信息:属性与方法

在内部,GetConsumation 可以使用任意数量的私有属性来获取结果,选择是你的。

Personally, I would prefer if you make your public API as a method instead of property. Properties are supposed to be as 'fast' as possible in C#. More details on this discussion: Properties vs Methods

Internally, GetConsumption can use any number of private properties to arrive at the result, choice is yours.

给妤﹃绝世温柔 2024-08-03 22:22:11

我通常遵循方法或属性的作用。 如果这件事需要一点时间,我会使用一种方法。 如果它非常快或者在幕后进行的操作数量很少,我会将其设为属性。

I usually go by what the method or property will do. If it is something that is going to take a little time, I'll use a method. If it's very quick or has a very small number of operations going on behind the scenes, I'll make it a property.

↙厌世 2024-08-03 22:22:11

我过去常常使用方法来表示对对象的任何操作或更改对象状态的操作。 因此,在这种情况下,我将该函数命名为CalculateConclusion(),它计算其他属性的值。

I use to use methods to denote any action on the object or which changes the state of an object. so, in this case I would name the function as CalculateConsumption() which computes the values from other properties.

风启觞 2024-08-03 22:22:11

您说您正在从七个输入中派生一个值,您已经实现了七个属性,每个输入一个,并且您有一个用于结果的属性获取器。 您可能需要考虑的一些事情是:

  • 如果调用者未能设置七个“输入”属性中的一个或多个,会发生什么情况? 结果还有意义吗? 会抛出异常(例如除以零)吗?

  • 在某些情况下,API 可能不太容易被发现。 如果我必须调用一个带有七个参数的方法,我知道我必须提供所有七个参数才能获得结果。 如果某些参数是可选的,则该方法的不同重载会明确哪些参数。

    相比之下,在访问“结果”属性之前我必须设置七个属性,这可能不太清楚,而且很容易忘记其中一个。

  • 当您的方法具有多个参数时,您可以更轻松地进行更丰富的验证。 例如,如果“参数 A 和参数 B 都为空”,则可以抛出 ArgumentException。

    如果您对输入使用属性,则每个属性都将独立设置,因此您无法在设置输入时执行验证 - 仅当结果属性被取消引用时才执行验证,这可能不太直观。

You say you are deriving a value from seven inputs, you have implemented seven properties, one for each input, and you have a property getter for the result. Some things you might want to consider are:

  • What happens if the caller fails to set one or more of the seven "input" properties? Does the result still make sense? Will an exception be thrown (e.g. divide by zero)?

  • In some cases the API may be less discoverable. If I must call a method that takes seven parameters, I know that I must supply all seven parameters to get the result. And if some of the parameters are optional, different overloads of the method make it clear which ones.

    In contrast, it may not be so clear that I have to set seven properties before accessing the "result" property, and could be easy to forget one.

  • When you have a method with several parameters, you can more easily have richer validation. For example, you could throw an ArgumentException if "parameter A and parameter B are both null".

    If you use properties for your inputs, each property will be set independently, so you can't perform the validation when the inputs are being set - only when the result property is being dereferenced, which may be less intuitive.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文