所以我有一个计算折扣的类(让我们称之为“A”类)。它有一个价格获取类作为依赖项(构造函数注入)(类"B")。返回的价格(按“B”类计算)用于计算折扣。但是,除非您深入到"A“类中函数calculateDiscount
的实现中,否则使用"B”类来获取价格并不明显。
在框架中有多种方法可以获取产品价格;其中之一是通过使用类"B“。但是"B“类可以做更多的事情,而不仅仅是返回价格,它还有其他一些功能(不是由我构建的,所以我可以说它有多重责任)。
我的目标是修改"B“级退货的价格。为了实现这一点,我可以创建另一个类(类"C"),它继承自"B“(它没有接口)并注入它。
问题是,我知道我依赖于代码中的实现细节。如果代码发生了变化,并且使用了另一种获取价格的方法,那么整个过程将停止工作。我对此并不满意。而且这个类("B")是在类"A“中显式注入的,所以它不一定只是实现细节,它也是某种抽象(因为它是在构造函数中注入的)。然而,我从来不确定它是否以我希望的方式使用;正如我前面所说的,它具有多个功能,如果它不再用于"A“类来获取价格,但仍然使用(在同一类”A“中)来做其他事情怎么办?这意味着用"C“类替换它不会实现获取修改后的价格(因为使用了另一种获取方法)。要使它起作用,我必须有一个承诺,那类"B“将被用来标价。
我不确定我是否解释得很好。我正在寻找一种简洁的方法来修改功能;但同时,我希望确保我不依赖于实现细节。
我的回退解决方案只是将整个方法复制/粘贴到另一个类中,并实现一些更改。它可以工作;它不依赖于任何实现细节;但缺点是代码重复(折扣计算功能本身相当大)。
我很困惑,因为我觉得这就是使用DI的全部目的--允许扩展性。但是,如果这个DId项能够执行多个任务,并且您永远不知道它是如何在类中使用的,那么会发生什么呢?查看类以验证依赖关系是否以您想要的方式使用--当然,其他人可能会在其他任务上工作,并更改代码,它将用于新任务,但我的部分可能因此而失败;我希望避免这种情况。
有什么想法吗?
更新:我冲了个澡,意识到DI并不像拥有方法/函数的DI那样好。如果方法请求另一个方法而不是对象,那就太酷了。对象可能有各种各样的东西,但是方法是明确的。但在这种情况下我做不到。
让我举一个例子(没有税的产品价格是500;加上税是600)。根据数据库税收设置的不同,获取的价格将返回500或600:
function calculateDiscount($item, $discountPercentage) {
return $priceFetcher->getPrice() * $discountPercentage
}
我想改变它,使它不依赖于数据库税收设置:
function calculateDiscount($item, $discountPercentage) {
return ($includeTax ? $item->getPriceExclTax() : $item->getPriceInclTax()) * $discountPercentage
}
我可以直接去构造函数,用另一个函数替换我的价格获取器,这样第一个实现就可以工作了!问题是,如果有一天有人改变了这个实现并使用了另一个服务?我正在calculateDiscount
函数的范围内工作。我不能相信价格获取器方法会被使用,是吗?My的想法是确保我的修改对 calculateDiscount
该方法中发生的事情产生影响;就像它对读者完全隐藏一样!
为了实现这一点,我觉得我需要的只是另一个折扣计算器,它将有一个复制/粘贴的实现与一些修改。但这也不好。我希望有第三种解决办法。我想出了一个关于注入方法而不是对象的想法,并想知道关于这个主题是否有某种程度的文字或一些好的例子。也许这是函数式编程的东西;不确定。
发布于 2022-06-30 15:49:34
我很困惑,因为我觉得这就是使用DI的全部目的--允许扩展性。但是,如果这个DId项能够执行多个任务,并且您永远不知道它是如何在类中使用的,那么会发生什么呢?查看类以验证依赖关系是否以您想要的方式使用--当然,其他人可能会在其他任务上工作,并更改代码,它将用于新任务,但我的部分可能因此而失败;我希望避免这种情况。
那就别说了。你在与抽象的概念作斗争。当你设计一些东西来使用某种东西(依赖)时,你应该清楚地表达你的需求。您不应该寻求微观管理您所使用的,以确保这样和这样的是被称为。只管满足你的需要。你怎么使用它的工作不关你的事。
function calculateDiscount($item, $discountPercentage) {
return $priceFetcher->getPrice() * $discountPercentage
}
该函数以正确的DI样式完成,类似于如下所示:
function calculateDiscount($price) {
return $price * $discountPercentage
}
现在的税收问题是一个构成问题,而不是一个实施问题。
calculateDiscount(calculateTax($price))
你不需要通过控制里面的布尔人来控制它的功能。你一眼就能看到发生了什么。
发布于 2022-06-30 14:55:28
在我看来,这是通过简单地区分包括税在内的价格和税前价格来解决的。
通常你会在发票上单独征税。
Type , Price
Item 1, £1.50
item 2, £3.00
tax , £0.50
total £5.00
有了这个级别的详细信息,我可以计算出多种折扣类型。
x% off total
-£1.00 on all "item 1"s
free "item 3" if you also buy two "item 2"s etc
我也可以为不同的项目计算不同的税收,并确保税额包括任何折扣。
这不是DI问题,而是您的价格计算,包括税收和折扣,依赖于您运行各种流程的顺序。
如果您删除了该订单依赖项,或者至少跟踪应用了哪些流程,那么您的问题就会消失,您的代码将更加可靠。
..To展开,如果你不想去完整的“发票是需要打折扣”的路线,或者你有一个大对象与多重责任。分割界面。
IPriceCalcWithTax //indicates that the internals will calc the price with tax
{
decimal GetPriceWithTax(order o)
}
IPriceCalcWithoutTax //indicates that the internals will calc without tax
{
decimal GetPriceWithoutTax(order o)
}
MyPriceCalculator : IPriceCalcWithoutTax, IPriceCalcWithTax, IWhateverElseTheObjectsResponsiblitiesAre //one or both
{
...
}
MyDiscountCalc(IPriceCalcWithoutTax pricecalc) //indicates that it will need the price calculated without tax
https://softwareengineering.stackexchange.com/questions/439569
复制相似问题