整个程序使用的公共静态数据
代码示例是 C#,但这是一个常见的 OO 问题。
我知道根据 OO 规则,类耦合应该最小化,成员应该尽可能保持私有,等等。
考虑这个例子:
您正在编写一个深奥的程序,它具有某种数据集(我不是在谈论System.Data.DataSet),该数据集实际上用于程序的每个方面。事实上,程序的存在基本上只是为了加载、显示、操作和保存数据集。此外,任何时候只能加载一个数据集,并且它是在程序打开时加载的。
如果我们严格遵循面向对象的规则,那么我们可能会
public void ShowSomeGraphs(IData data)
{
// do stuff with data which implements IData
}
例如,
public void ShowSomeGraphs()
{
// do stuff with Program.Data
}
在 Program
中存储一个 public static Data
成员。一方面,我们用稍微短一点的函数签名来换取大大增加的类耦合。另一方面,我们不再将 Data 参数传递给几乎每个函数、每个地方。
正确的答案可能是:尽可能避免类耦合。本地数据变量只是指针,因此内存开销可以忽略不计,并且由于这些类是解耦的,因此它们可以在以后在其他地方使用。
尽管实际上来说,Data 类的结构在不同的应用程序中可能会有显着的不同,所以您不能直接从该程序中提取一个类并将其放在其他地方而不进行任何调整。以可以的方式编写类所需的额外时间和精力可能很难向利益相关者证明是合理的。
我现在正在开发此类程序,并且使用了 OO-canon 方法:数据参数在需要的地方传递。我已经最小化了与 IData 接口的类耦合,以概括数据集以供将来的代码重用。鉴于该应用程序,我几乎可以肯定该代码永远不会被重复使用。如果没有这些额外的接口和抽象,对于最终用户而言,该程序的工作方式将完全相同,但对我来说,这会显着减少麻烦和开发时间。
您对此有何看法?您认为花费所有额外的时间来编写接口和泛化以确保类在可能的情况下解耦是否合理,特别是当您以后看不到这些类在其他地方使用时?
Code examples are C# but this is a general OO question.
I know according to OO rules, class coupling should be minimised and members should be kept private wherever possible, etc.
Consider this example:
You are writing an esoteric program which has some sort of data set (I'm not talking about System.Data.DataSet) which is used in literally every facet of the program. In fact, the program basically exists just to load, display, manipulate, and save the data set. Furthermore, there can only ever be one data set loaded at any time, and it is loaded when the program opens.
If we follow OO rules strictly, we would have
public void ShowSomeGraphs(IData data)
{
// do stuff with data which implements IData
}
however we could potentially store a public static Data
member in Program
, for example.
public void ShowSomeGraphs()
{
// do stuff with Program.Data
}
On one hand, we have traded a slightly shorter function signature for vastly increased class coupling. On the other hand, we are no longer passing a Data parameter to practically every function, everywhere.
The right answer probably is: Avoid class coupling wherever possible. The local Data variables are just pointers so the memory overhead is negligible, and because the classes are decoupled they can be used elsewhere at a later date.
Though realistically speaking, the structure of the Data class will likely be phenomenally different in a different application, so it's not like you can just pull a class from this program and drop it in somewhere else without any tweaks. The extra time and effort required to write the classes in such a way that they can just be dropped in might be difficult to justify to a stakeholder.
I'm working on this sort of program now, and I have used the OO-canon approach: Data parameters are passed around where needed I have minimised class coupling with an IData interface to generalise the data set for future code re-use. Given the application, I'm almost certain this code won't ever be re-used. Without these extra interfaces and abstraction, the program would have worked exactly the same as far as the end user is concerned, but would have represented significantly less headaches and development time for me.
What do you think about this? Do you think it's justifiable to spend all the extra time to write the interfaces and generalisations to ensure classes are decoupled where possible, especially when you can't see the classes being use elsewhere later?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不要为此苦恼。严重地。
软件范式/模式是为了帮助我们,而不是教条地遵循。
您在问题中明确表示您认为松散耦合过度杀伤力,并且您可以证明原因。因此,不要使用它。
Don't agonise over it. Seriously.
Software paradigms/patterns are there to help us and not to be followed dogmatically.
You make it clear in your question that you consider the loose coupling overkill, and you can justify why. Therefore, don't use it.
如何使用单例模式提供获取 IData 接口的方法或只读属性?这样,您只耦合到一个非常薄的单例类,并且与数据集的所有交互都是通过 IData 接口完成的。
(我肯定会避免紧密耦合。即使您不打算对这个应用程序做太多事情,您也有可能在开发过程中遇到问题,这将迫使您接触比通过访问数据要多得多的代码。接口。)
上面提出的单例解决方案的代码示例:
一些注意事项:上面的代码示例被完全剥离以显示单例和共享接口的概念。没有实现线程安全,没有数据对象的初始化等。
How about using the singleton pattern to provide a method or read-only property to get the IData interface? This way you're only coupled to a very thin singleton class and all your interactions with the data set are done through the IData interface.
(I would definitely avoid the tight coupling. Even if you don't plan to do much with this app chances are that you will run into an issue during development which will force you to touch significantly more code than if you accessed the data via an interface.)
Code sample of the singleton solution proposed above:
Some caveats: The code sample above is completely stripped down to show the concept of a singleton and shared interface. There is no thread safety implemented, there is no initialization of the data object etc.
好吧,您的文本中有一个重大假设:程序中始终只有一个数据集。您确定该条件将永远成立吗?曾经有一段时间,文字处理器一次只能保存一篇文本。如今,同时打开多个文件已成为标准。如果第一个网络浏览器一次只能打开一个网页,我也不会感到惊讶。今天,没有人会使用不能同时打开多个页面的网络浏览器。我认为你可以说程序中肯定只有一个的对象是非常罕见的。事实上,我唯一想要创建的全局对象或单例就是对象工厂。
另一方面,为每个函数调用传递对象对我来说似乎也太过分了。因此,我会采取中间立场:让对象记住“全局”对象,这样您只需通过构造函数传递它。这将每个单个对象限制为一个数据对象,但如果您决定的话,仍然允许您轻松地在程序中拥有多个数据对象。
Well, there's one big assumption in your text: There will always only be one data set in the program. Are you sure that condition will hold for all time? There was a time where word processors could only hold one text at a time. Today it's standard to be able to have several files open at once. I'd also not be surprised if the first web browsers could only open one web page at a time. Today nobody would use a web browser which could not have several pages open at the same time. I think the sort of object where you can say there will be for certain only one of it in the program, ever, is quite rare. Indeed, the only thing which I would make a global object or singleton would be object factories.
On the other hand, passing the object around for each function call seems to be overkill to me, too. Therefore I would go for the middle ground: Have the objects remember that "global" object, so you only have to pass it via the constructor. This limits each single object to one Data object, but still allows you to easily have several Data objects in your program should you ever decide to.