需要 .Net SOLID 设计方面的帮助
我第一次尝试坚持罗伯特·马丁的 SOLID 设计原则,但我并不擅长。
本质上,我需要一个“Node”对象的层次结构。有些节点是 NodeHosts,有些是 NodeChildren,有些是 Both。每个人以前都做过这个,但我不知道如何在不过度复杂化设计或在节点子类型中做类似事情的情况下做到扎实:
INodeHostType node;
public INodeType NodeType
{
....
set
{
node = (INodeHostType)value;
}
}
这违反了里氏替换原则,对吗?有什么更好的办法呢? 这就是我现在所拥有的。
I'm trying to stick fast to Robert Martin's SOLID design principles for the first time, and I am not good at it.
In essence, I need a hierarchy of "Node" objects. Some nodes are NodeHosts, some are NodeChildren and some are Both. Everybody's done this one before, but I can't figure out how to do it SOLID without over-complicating the design or doing something like this in the node subtypes:
INodeHostType node;
public INodeType NodeType
{
....
set
{
node = (INodeHostType)value;
}
}
This violates Liskov Substitution Principle right? What's a better way?
Here's what I have now.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
伙计,这个答案确实很丰富,但很有趣。我们开始吧:)
我同意这是一个相当复杂的设计。当您使用接口来“抽象变化的内容”时,接口会很有帮助,但在该示例中,所有内容都是抽象的。这个例子确实很难遵循,所以这应该是一个重要的指标,表明出现了问题。与 Spaghetti 代码相反的是 Lasagna 代码(多层),这正是该图的内容。
据我所知,你们有 3 个小组。
让我们从节点开始,SOLID 确实告诉您对接口进行编码,但这并不一定意味着它必须是一个实际的接口。将常规旧继承与扩展基节点的子节点一起使用是完全可以接受的。这仍然是可靠的,并且在这种情况下是有意义的。
对于节点类型,节点确实具有不同的类型,但它们仍然具有类型。我认为这不足以使其成为单独的抽象。我刚刚将类型移动到你的基节点中。
对于渲染,现在您正在做一些事情。由于 ChildNode 和 ParentNode 的渲染方式不同,因此对其进行抽象是有意义的。虽然,我看到 IRenderer 中的所有属性都在 IRenderContext 中重复,所以我只是将它们折叠成 1。
类图看起来像这样。
好的,这一切都很好,但是为什么还要做所有额外的工作 Solid 呢?让我们看看最终的实现。
Man this answer really grew, but it was fun. Here we go :)
I agree that is a pretty complicated design. Interfaces are helpful when you use them to "abstract what varies", but in that example everything is abstracted. This is example was really difficult to follow, so that should be a big indicator that something is wrong. The opposite of Spaghetti Code is Lasagna Code (to many layers) and thats exactly what this diagram is.
From what I can see you have 3 groups.
Lets start with Nodes, its true that SOLID tells you to code to an interface, but that doesn't necessarily mean it has to be an actual interface. It's perfectly acceptable to use regular old inheritance with a childnode that extends a basenode. That is still Solid and makes sense in this case.
For Node Type, its true that the nodes have different types but they both still have a type. I don't think this qualifies it for a separate abstraction. I have just moved type into your basenode.
For Render, now you are on to something. Since ChildNodes and ParentNodes are rendered differently it makes sense to abstract it. Although, I see is that all the properties in IRenderer are duplicated in IRenderContext so I'm just going to collapse them into 1.
And the Class Diagram would look something like this.
Ok so thats all well and good, but why do all the extra work solid requires. Lets look at the final implementation.