模型的哪一部分应该处理数据库插入?
标题可能没有很好地描述我的问题,如果有人可以将其编辑为更合适的内容,我会很高兴。无论如何:
我得到了一个组件,根据其id
,该组件应该返回产品价格。它实现了这样一个接口:
interface IProductPriceFetcher
{
double GetPrice(int id);
}
现在,可以从 3 个不同的来源获取价格:
- 的 Web 服务
- 直接从网站源代码(抓取)
- 作为最终后备(Web 服务和网站都无法访问),返回本地数据库的最新价格
为了解决这个 3 个不同来源的问题,我实现了这样的类:
class MainFetcher : IProductPriceFetcher
{
public double GetPrice(int id)
{
var priceFetcher = this.factory.GetWebServiceFetcher()
?? this.factory.GetWebsiteFetcher()
?? this.factory.GetLocalDatabaseFetcher();
return priceFetcher.GetPrice(id);
}
}
工厂中的每个方法当然都会返回 IProductPriceFetcher ,附带说明前两个可能会失败和返回空
;我假设 GetLocalDatabaseFetcher 总是会返回有意义的对象。
我的“一般疑问... ment”
在成功的网络服务/网站调用后,我希望将获取的价格插入到本地数据库中,作为未来的后备案例。现在我的问题是:上面代码的哪一部分应该负责?它应该是返回价格的具体网络获取器之一吗?或者“聚合器”获取器(MainFetcher
),因为它也知道价格来源是什么?我应该提出一些事件吗?通过数据库调用注入另一个接口?改变设计更好?
为什么它对我来说是一个问题?好吧,我试图保持代码干净(不用担心,这只是我业余时间的宠物项目 - 正是为了解决这样的问题)可能考虑到了 SRP/SoC。现在我似乎在摆脱这种思维方式方面遇到了问题 - 我的意思是,获取网页的东西怎么可能也进行数据库插入?哦,来吧! :)
Title probably doesn't describe my problem too well, I'll be glad if somebody could edit it to something more appropriate. Anyways:
I got a component that is supposed to return product price given its id
. It implements an interface like this one:
interface IProductPriceFetcher
{
double GetPrice(int id);
}
Now, the price can be fetched from 3 different sources:
- web service
- directly from website source code (scrapping)
- as a final fallback (both webservice and website are inaccessible), most recent price from local database is returned
To play around this 3-different-sources issue I've implemented class like this:
class MainFetcher : IProductPriceFetcher
{
public double GetPrice(int id)
{
var priceFetcher = this.factory.GetWebServiceFetcher()
?? this.factory.GetWebsiteFetcher()
?? this.factory.GetLocalDatabaseFetcher();
return priceFetcher.GetPrice(id);
}
}
Each method from factory returns IProductPriceFetcher
of course, with side note that first two can fail and return null
; I assumed GetLocalDatabaseFetcher
will always return meaningful object tho.
My "general wondering... ment"
Upon successful webservice/website call, I want fetched price to be inserted into local datbase, as a future fallback case. Now my question is: which part of code above should be responsible for that? Should it be one of the concrete web fetchers that returns price? Or "aggregator" fetcher (MainFetcher
), as it also has knowledge over what's the source of price? Should I raise some event? Inject yet another interface with DB calls? Change design to better?
Why did it even occur as an issue to me? Well, I tried to keep the code clean (worry not, it's only pet project for my spare time - exactly for solving problems like this) possibly with SRP/SoC in mind. Now I seem to have problems switching from this mindset - I mean, how could possibly something that fetches webpages also be doing database inserts? Oh, come on! :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果你想要一个超级解耦的设计,我会实现一个 Decorator 类,例如下面并使用它来包装 WebServiceFetcher 和 WebsiteFetcher:
然后您的工厂将实现以下方法:
此设计将实际的获取器与缓存机制分离。
编辑:我对这个答案的设计略有误解,因为我假设如果无法获取价格,GetPrice 方法将返回某种 NULL 值,而不是工厂返回 NULL 值。我认为返回 NULL 的工厂有点味道,因为工厂的责任是可靠地返回对象。我会考虑更改您的
GetPrice
方法接口以返回double?
也许,以允许“未找到价格”。If you want to have a super-decoupled design, I would implement a Decorator class like the following and use it to wrap both the WebServiceFetcher and the WebsiteFetcher:
Then your factory would implement the following methods:
This design decouples your actual fetchers from your caching mechanism.
EDIT: I misread your design slightly with this answer, as I assumed that the GetPrice method would return some sort of NULL value if the price couldn't be fetched, rather than the factory returning a NULL value. I think the factory returning NULL smells a bit, since a factory's responsibility is to reliably return objects. I would consider changing your
GetPrice
method interface to return adouble?
perhaps, to allow for "price not found".在我看来,这就像你需要一个“缓存”。缓存通常作为一种方面或依赖项实现,您可以将其注入到
Fetcher
实现中。下面我假设IPriceCache
具有某种IDictionary
接口,但您当然可以插入您需要的任何抽象。我还建议抽象出价格获取者的数据源......:It sounds to me like if you needed a "Cache". Caching is typically implemented either as a kind of aspect or dependency which you inject into your
Fetcher
implementation. Below I assumeIPriceCache
with sort ofIDictionary
interface, but you could of course insert whatever abstraction you require. I also suggest to abstract away the data sources for price fetchers...: