英文:
When to use static over passing reference in constructor for things I want to share?
问题
一个主题不太清晰,我将尝试用一个简单的例子来解释我的问题。我们知道银行的所有客户共享银行的钱。所以如果银行破产了,没有客户可以贷款。基于这一观点,我将尝试制作一个简单的程序。
方法1:
class Client {
private static int sharedMoney = 100;
void takeLoan(int amount) {
sharedMoney = sharedMoney - amount;
}
}
方法2:
class Client {
private SharedMoney sharedMoney;
public Client(SharedMoney sharedMoney) {
this.sharedMoney = sharedMoney;
}
void takeLoan(int amount) {
sharedMoney.setAmount(sharedMoney.getAmount() - amount);
}
}
class SharedMoney {
private int amount;
public SharedMoney(int amount) {
this.amount = amount;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
当然,逻辑没有完全覆盖,但我认为我表达了我的观点。有没有人有一个编码时应该遵循的经验法则?在共享某些东西(钱)时应该何时使用静态,何时应该在构造函数中传递引用以再次共享相同的东西(钱)?
英文:
A topic is not so clear I will try to explain my question in an easy example. We know what all clients of a bank share money from a bank. So if the bank is bankrupt, no client could take a loan. Based on that point of view I will try to make a simple program.
Approach 1:
class Client {
private static int sharedMoney = 100;
void takeLoan(int amount) {
sharedMoney = sharedMoney - amount;
}
}
Approach 2:
class Client {
private SharedMoney sharedMoney;
public Client(SharedMoney sharedMoney) {
this.sharedMoney = sharedMoney;
}
void takeLoan(int amount) {
sharedMoney.setAmount(sharedMoney.getAmount() - amount);
}
}
class SharedMoney {
private int amount;
public SharedMoney(int amount) {
this.amount = amount;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
Of course, logic is not 100% covered, but I think I showed my point. Does anyone have a rule of thumb I should follow when coding? When should I use static when sharing something (money) and when should I pass reference in the constructor when again sharing the same thing (money)?
答案1
得分: 1
在几乎所有情况下,方法2被认为是首选。这相比方法1有许多重要优势:
- 测试方法2要容易得多。您可以传入一个模拟的
SharedMoney
,在测试中其行为与所需完全一致(例如具有特定金额的货币)。 - 它允许您向
SharedMoney
类添加与这些对象相关的方法,而不是在Client
中拥有与该类责任无关的静态方法。 - 静态变量包含全局状态。全局状态是任何程序状态,可能可供任何代码访问或更改。每当有全局状态时,就引入了无关的方法改变该状态,从而产生了意外副作用,使代码变得不可预测,并容易出现难以检测的错误。尽量避免使用全局状态。另一种常见的方法是依赖注入,您的方法2是一个很好的例子。
这些主题在https://stackoverflow.com/questions/7026507/why-are-static-variables-considered-evil的答案中得到了详细讨论。但要注意,那里的许多讨论实际上是关于可变的静态变量。常量值(通常声明为private static final
并且按约定使用大写名称)没有相同的缺点,因为可以依赖于它们的值不会更改。
英文:
In almost all cases approach 2 is preferred. This has a number of significant advantages over approach 1:
- It is much easier to test approach 2. You can pass in a mocked
SharedMoney
that behaves exactly as required for your test (such as having a specific amount of money). - It allows you to add methods to the
SharedMoney
class that are related to those objects rather than end up with static methods inClient
that aren't really related to that class's responsibilities - Static variables contain global state. Global state is any program state that is potentially available to any code to access or change. Any time you have global state you introduce the possibility of an unrelated method changing that state with unexpected side effects which makes code unpredictable and prone to bugs that are difficult to detect. Try to avoid global state whenever possible. The alternative is generally dependency injection, of which your approach 2 is a good example.
These topics are dealt with at some length in the answers to https://stackoverflow.com/questions/7026507/why-are-static-variables-considered-evil Note, however, that at lot of the discussion there is really about mutable static variables. Constant values (generally declared as private static final
and, by convention, given uppercase names) don't have the same disadvantages as their values can be relied upon not to change.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论