用于实现业务逻辑的代码改进
我之前曾问过这个问题。这与此有关。我们有与此类似的代码库:
IRecipie FindRecipiesYouCanMake(IEnumerable<Ingredientes> stuff, Cook cook)
{
if(stuff.Any(s=>s.Eggs && s.Flour) && cook.DinerCook)
{
if(s=>s.Sugar)
return new Pancake("Yum");
if(s=>s.Salt)
return new Omlette("Yay");
}
/*.....
......
.....
loads of ifs and buts and else*/
}
我想摆脱这种混乱并采取更多的数据结构和面向对象的路线。即使我提供的代码示例也没有那么可怕。我查看了规范模式,发现它适用。关于如何改进代码的任何想法。
编辑:现在我意识到了,我什至可能想实现这个签名的方法:
List<IRecipe> WhatAllCanBeCooked(IEnumerable<Ingredients> stuff, Cook cook);
I had asked this question previously on SO. This is related to it. We have code base similar to this:
IRecipie FindRecipiesYouCanMake(IEnumerable<Ingredientes> stuff, Cook cook)
{
if(stuff.Any(s=>s.Eggs && s.Flour) && cook.DinerCook)
{
if(s=>s.Sugar)
return new Pancake("Yum");
if(s=>s.Salt)
return new Omlette("Yay");
}
/*.....
......
.....
loads of ifs and buts and else*/
}
I want to get rid of this mess and take a more data structure and OO route. Even the code sample i have provided is not as horrendous as it is. I looked at the specification pattern and found it applicable. Any ideas how to improve the code.
EDIT: Now that I realize it, I might even like to implement a method of this signature:
List<IRecipe> WhatAllCanBeCooked(IEnumerable<Ingredients> stuff, Cook cook);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我会将这个逻辑委托给各个 IRecipie 类:
编辑以响应评论
要查找所有可以烹饪的食谱,只需执行以下操作:
编辑 2
或者,如果您在某处存储所有可能配方的列表,则可以将
CanBeMadeBy
转换为实例方法而不是静态方法,然后执行以下操作:I would delegate this logic to the individual IRecipie classes:
Edit in response to comment
To find all the recipes that can be cooked, just do something like this:
Edit 2
Alternatively, if you store a list of all possible recipes somewhere, you can turn
CanBeMadeBy
into an instance method instead of a static, and do this:一些想法:
使用决策表
使用策略模式。这可以帮助您封装一组属于不同具体类的操作或参数。一旦您决定使用哪种策略,您就不再需要在策略之间分配任何“if”。
编辑:一些额外的想法:
开始“小”:大多数情况下,只需简单重构为更小、命名良好、可重用的函数将帮助您减少 if-else-if-else-soup。有时,一个简单的、命名良好的布尔变量就可以解决问题。两者都是重构的示例,您可以在 Fowler 的书“重构” 中找到。
考虑“大”:如果您确实有很多复杂的业务规则,那么构建“特定于领域的语言”是一种选择,有时这可能是降低复杂性的正确方法。只需通过谷歌搜索,您就会找到很多关于该主题的材料。引用 David Wheeler 计算机科学中的所有问题都可以通过另一个间接级别来解决。
Some ideas:
use decision tables
use the strategy pattern. This helps you to encapsulate a group of actions or parameters belonging together in different concrete classes. Once you have decided which strategy to use, you don't need any 'ifs' any more to dispatch between the strategies.
EDIT: some additional ideas:
start "small": most often, just simple refactoring to smaller, well-named, reusable functions will help you to reduce the if-else-if-else-soup. Sometimes, a simple, well named boolean variable does the trick. Both are examples for refactorings you will find in Fowler's book "Refactoring".
think "big": if you have really lot of complex business rules, constructing a "domain specific language" is an option that can sometimes be the right way of getting the complexity down. You will find lots of material on this topic just by googling for it. Citing David Wheeler All problems in computer science can be solved by another level of indirection.
原帖——
Martin Fowler 已经为您解决了这个问题...它称为规范模式。
http://en.wikipedia.org/wiki/Specification_pattern
更新的帖子 -
考虑使用复合规范模式适用于以下情况:
的真正威力在于能够通过 AND、OR 和 NOT 关系将不同的规范组合成复合体。可以在设计时或运行时将不同的规范组合在一起。
Eric Evan 关于领域驱动设计的书有一个关于这种模式的很好的例子(运输清单)
这是 Wiki 链接:
http://en.wikipedia.org/wiki/Specification_pattern
wiki 链接底部是此 PDF 链接:
http://martinfowler.com/apsupp/spec.pdf
ORIGIINAL POST --
Martin Fowler has solved this problem for you... its called the Specification pattern.
http://en.wikipedia.org/wiki/Specification_pattern
UPDATED POST --
Consider using the Composite Specification Pattern when:
The true power of the pattern is in the ability to combine different specifications into composites with AND, OR and NOT relationships. Combining the different specifications together can be done at design time or runtime.
Eric Evan book on Domain Driven Design has an excellent example of this pattern (the Shipping Manifest)
This is the Wiki link:
http://en.wikipedia.org/wiki/Specification_pattern
At the bottom of the wiki link is this PDF link:
http://martinfowler.com/apsupp/spec.pdf
我认为该代码块本质上试图完成的是将食谱与该食谱中的成分链接起来。一种方法是在食谱类本身中包含成分列表,然后将其与传入的成分列表进行比较,如下所示:
这假设您在某个地方拥有所有食谱的集合。然而,设置这些静态列表或从数据库中提取应该足够简单。
所讨论的 Linq 查询会查找任何配方,其中传入 stuff 的所有成分均出现在成分列表中(或者,如前所述,Ingredients 中不存在不在 stuff 中的成分)。这也可能会减少对食谱子类的需求,这似乎有点奇怪(尽管据我所知,还有其他原因你需要这个)
I think what that block of code is essentially trying to accomplish is linking recipes to ingredients within that recipe. One approach would be to include a list of ingredients on the recipe class itself, and then compare that against the list of ingredients passed in, like so:
This assumes that you have a collection somewhere of all your recipes. It should be simple enough to set up a static list of those or pull from a database however.
The Linq query in question looks for any recipes where all ingredients passed in stuff are present in the list of ingredients (or, as it's stated, there are no ingredients in Ingredients that are not in stuff). This also might decrease the need to have subclasses for Recipes, which seems a bit odd (although for all I know there's additional reasons you'll require this)