我的应用程序有InstrumentFactory
- 我创建Instrument
实例的唯一地方。每个工具实例都包含多个字段,例如Ticker=MSFT
和GateId=1
以及唯一Id =1
。
现在我意识到我几乎不需要Instrument
个实例。在90%的情况下,我只需要Id
。例如,现在我有这样的方法:
public InstrumentInfo GetInstrumentInfo(Instrument instrument)
{
return instrumentInfos[instrument.Id];
}
我们知道我们不应该传递参数多于所需的信息。所以这段代码可能应该重构为:
public InstrumentInfo GetInstrumentInfo(int instrumentId)
{
return instrumentInfos[instrumentId];
}
我的代码中有90%现在可以重构为使用instrumentId
代替Instrument
。
Instrument
改为instrumentId
将使其成为一项艰难的要求(每个工具应该只有一个唯一的ID)。但是我会有什么好处?作为“硬性要求”的回报,我想为此获得一些好处......(速度,可读性?)但我没有看到它们。
答案 0 :(得分:4)
在任何地方使用ID代替对象都是错误的方法,这违背了OOP的精神。
使用对象本身有两大优势:
Person
之类的内容传递给第一个版本,但您可能会意外地将person.Id
传递给第二个版本。long
ID或其他方式来识别唯一的Instrument
,则无需更改主叫代码。你应该更改你的字典,它应该像Dictionary<Instrument, InstrumentInfo>
,而不是Dictionary<int, InstrumentInfo>
,就像你现在一样。这样,您也可以获得两种优势。要使其有效,您需要在Instrument
中实现相等性,这意味着正确覆盖Equals()
和GetHashCode()
,理想情况下还要实施IEquatable<Instrument>
。
答案 1 :(得分:1)
在对象方面工作总是比整数这样的原始值更好。如果明天您的要求发生变化并且您需要的不仅仅是ID,那么很容易将其添加到Instrument
对象而不是更改所有代码。
答案 2 :(得分:1)
GetInstrumentInfo(int instrumentId);
这可能意味着客户端代码必须具有:
GetInstrumentInfo(instrument.Id);
不要让您的方法的用户担心这样的小细节。让他们只传递整个对象,让你的方法完成工作。
看不出任何重大的性能劣势。无论是传递Int还是引用实际对象。
假设您想要更多地开发GetInstrumentInfo,它更容易访问整个对象而不仅仅是Int。
答案 3 :(得分:1)
你需要问自己的第一件事是:
“如果我有两个ID == 53的乐器,那么这是否意味着它们绝对是同一乐器,无论如何?或者是否有一个有意义的案例,它们可能会有所不同?”
假设答案是“它们都是相同的。如果任何其他属性不同,那就是一个错误,或者因为一个这样的对象是在另一个之后获得的,并且很快就会自行解决(当任何处理线程使用时)旧仪器,停止使用它)“然后:
首先,在内部,只需使用你发现的任何东西。您很可能会发现这一直是int
,尽管您通过坚持将Instrument
传递给该方法获得了一些类型安全性。如果所有Instrument
构造都发生在通过工厂方法访问的internal
或private
构造函数中,并且代码的用户无法创建伪造{{1} id与系统中的任何内容都不匹配。
如此定义相等:
Instrument
现在,特别是当我们考虑到上述内容很可能在大多数情况下被内联时,关于我们是否在相等性方面使用ID或对象几乎没有实现差异,因此也就是用它们作为关键。
现在,您可以通过以下任何方式定义所有公共方法:
public class Instrument : IEquatable<Instrument>
{
/* all the useful stuff you already have */
public bool Equals(Instrument other)
{
return other != null && Id == other.Id;
}
public override bool Equals(object other)
{
return Equals(other as Instrument);
}
public override int GetHashCode()
{
return Id;
}
}
或者:
public InstrumentInfo GetInstrumentInfo(Instrument instrument)
{
return instrumentInfos[instrument];
}
或者:
public InstrumentInfo GetInstrumentInfo(Instrument instrument)
{
return instrumentInfos[instrument.Id];
}
无论您采用哪种方式,性能影响都是相同的。呈现给用户的代码将是类型安全的,并保证它们不会传递虚假值。选择的实现可以是您发现更方便的其他原因。
由于在内部使用仪器本身不会再花费你的成本,我仍然建议你这样做(上面三个选项中的第一个)作为类型安全并且难以通过然后,伪造的值也将适用于您的内部代码。另一方面,如果你发现一组调用仍然只使用id(例如,他们正在与只有ID意味着什么的数据库层交谈),那么改变这些地方对你来说变得快捷方便,隐藏在用户之外。
您还可以让您的用户使用您的对象作为键,并进行快速的相等比较(如果适合他们的话)。
答案 4 :(得分:-1)
你可以重载每个函数,一个拿一个乐器,一个拿一个id:
public InstrumentInfo GetInstrumentInfo(Instrument instrument)
{
// call GetInstrumentInfo passing the id of the object
return GetInstrumentInfo[instrument.Id];
}
public InstrumentInfo GetInstrumentInfo(int instrumentId)
{
return instrumentInfos[instrumentId];
}
这将为您提供足够的灵活性,以便当您通过调用GetInstrumentInfo
的任何地方将其更改为传递ID时,当前代码仍将起作用。
至于你是否“应该”纯粹取决于你。您需要权衡更改它所需的时间与在代码中进行更改的好处。