5

我的应用程序有- 我创建实例InstrumentFactory的唯一地方。Instrument每个仪器实例都包含多个字段,例如Ticker=MSFTGateId=1以及 unique 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.

我应该这样做吗?到处更改InstrumentinstrumentId使其成为一项硬性要求(每个 Instrument 都应该有一个唯一的 id)。但是我会有什么好处呢?作为“硬要求”的回报,我想为此获得一些好处......(速度,可读性?)但我没有看到它们。

4

5 回答 5

4

到处使用 id 而不是对象是错误的方法,它违背了 OOP 的精神。

使用对象本身有两大优势:

  1. 它是类型安全的。您不能不小心将类似的东西传递Person给第一个版本,但您可能会不小心将其传递person.Id给第二个版本。
  2. 它使您的代码易于修改。如果将来您决定需要longid 或其他方式来识别唯一性Instrument,则无需更改调用代码。

而且您可能也应该更改您的字典,它应该像现在一样Dictionary<Instrument, InstrumentInfo>,而不是Dictionary<int, InstrumentInfo>。这样,您也可以获得这两个优势。要使其工作,您需要在 中实现相等Instrument,这意味着正确覆盖Equals()并且GetHashCode()理想情况下还实现IEquatable<Instrument>.

于 2012-08-12T17:45:18.993 回答
1

在对象方面工作总是比像整数这样的原始值更好。如果明天您的需求发生变化,并且您需要的不仅仅是 ID,那么很容易将它们添加到Instrument对象中,而不是更改所有代码。

于 2012-08-12T17:44:58.680 回答
1
GetInstrumentInfo(int instrumentId);

这可能意味着客户端代码必须具有:

GetInstrumentInfo(instrument.Id);

不要让你的方法的用户担心这样的小细节。让他们传递整个对象并让您的方法完成工作。

看不到任何主要的性能劣势。无论您是传递一个 Int 还是对实际对象的引用。

假设您想进一步开发 GetInstrumentInfo,访问整个对象比访问 Int 更容易。

于 2012-08-12T17:51:27.100 回答
1

您需要问自己的第一件事是:

“如果我有两个 ID == 53 的仪器,那么这是否意味着它们绝对是相同的仪器,无论如何?或者是否存在有意义的案例,它们可能不同?”

假设答案是“它们都是相同的。如果任何其他属性不同,那要么是一个错误,要么是因为一个这样的对象是一个接一个地获得的,并且很快就会自行解决(当任何处理线程使用旧仪器时) ,停止使用它)”然后:

首先,在内部,只使用你觉得更方便的任何东西。int尽管坚持将 anInstrument传递给方法,但您很可能会发现这是一直存在的。如果所有Instrument构造都发生在通过工厂方法访问的构造函数internalprivate构造函数中,则尤其如此,并且代码的用户无法创建具有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;
  }
}

现在,特别是当我们考虑到上述内容可能在大多数情况下被内联时,关于我们是否在相等性方面使用 ID 或对象几乎没有实现差异,因此在将它们用作关键。

现在,您可以通过以下任何方式定义所有公共方法:

public InstrumentInfo GetInstrumentInfo(Instrument instrument)
{
    return instrumentInfos[instrument];
}

或者:

public InstrumentInfo GetInstrumentInfo(Instrument instrument)
{
    return instrumentInfos[instrument.Id];
}

或者:

public InstrumentInfo GetInstrumentInfo(Instrument instrument)
{
    return GetInstrumentInfo(instrument.Id);
}
private InstrumentInfo GetInstrumentInfo(int instrumentID)
{
    return instrumentInfos[instrumentID]
}

无论您选择哪种方式,性能影响都是一样的。呈现给用户的代码将是类型安全的,并保证它们不会传入虚假值。选择的实现可以简单地是由于其他原因您认为更方便的实现。

由于在内部使用仪器本身作为密钥不会再花费您,我仍然建议您这样做(上面三个选项中的第一个)作为类型安全并使其难以传递虚假值然后也将适用于您的内部代码。另一方面,如果您发现一组调用仍然只使用 id(例如,如果他们正在与只有 ID 有意义的数据库层交谈),那么仅更改这些位置对您来说变得快速而容易,并且对用户隐藏。

您还可以让您的用户能够使用您的对象作为键并进行快速的相等比较,如果它适合他们这样做的话。

于 2012-08-12T17:54:58.113 回答
-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 的地方时,当前代码仍将起作用。

至于你是否“应该”完全取决于你。您必须权衡更改它需要多少时间与更改代码的好处。

于 2012-08-12T17:48:33.360 回答