我正在实现一个类似于{/ p>的ITracker
界面
public interface ITracker
{
void Track(ITrackerEvent trackerEvent);
}
我最初创建了这个包装Mixpanel.NET的接口的实现。然后我创建了另一个包装Application Insights的程序。但是,Application Insights需要Flush()
将数据发送到服务器。
我不想仅仅因为其中一个实现需要使用ITracker
方法来污染Flush()
接口。它会感觉像是一个漏洞的抽象。
但是,我需要在某个时候(可能是关闭应用程序时)调用此方法,并且每次调用Track
时都不想这样做。
当会话结束时对Tracker进行垃圾回收时,是否可以调用方法?这甚至是一个好方法吗?
我觉得我在这里错过了一招!
答案 0 :(得分:5)
我要使ITracker
使用与事务相似的模式,因为可能存在您可能想要丢弃跟踪器事件,回滚或修改它们的情况:
public interface ITracker
{
void Track(ITrackerEvent trackerEvent);
void Commit();
}
然后按实施方式:
Flush
内拨打Commit
了解应用洞察。List<ITrackerEvent>
方法内写入内存中集合中的跟踪器事件(BlockingCollection<ITrackerEvent>
或Track
,如果涉及并发),然后使用当前逻辑调用{{1在Mixpanel.NET
的{{1}}方法实现中的api。 建议: Commit
也应该实施Mixpanel.NET
,因为跟踪器通常会使用需要处理的资源。
答案 1 :(得分:5)
在Leri的基础上,我会更多地考虑跟踪器可能需要做的事情。
我倾向于做这样的事情:
public interface ITracker {
void BeginTracking();
void Track(ITrackerEvent trackerEvent);
void EndTracking();
}
然后所有跟踪器都能了解它们何时开始以及何时完成。这很重要,因为跟踪器可能持有的资源不应超过必要的时间。如果跟踪器不需要使用BeginTracking
或EndTracking
,则实现操作非常简单。一个简单的实现不是漏洞的抽象。漏洞抽象是一种不适用于所有实现的抽象。
现在假设你在每个跟踪器中都有两个额外的方法(为什么?)。您可以改为使用带外的ITrackerEvents并涵盖Begin和End的语义含义。我不喜欢这个。它要求每个跟踪器都有特殊的代码来处理带外事件。
您还可以拥有单独的界面
public interface IDemarcatedTracker : ITracker {
void BeginTracking();
void EndTracking();
}
要求您在调用代码中包含特殊案例代码,以检查ITracker是否也是IDemarcatedTracker:
public void BeginTracking(ITracker tracker)
{
IDemarcatedTracker demarcatedTracker = tracker as IDemarcatedTracker;
if (demarcatedTracker != null)
demarcatedTracker.BeginTracking();
}
而不是过度夸大事物,但我也想知道当追踪器失败时会发生什么?只是盲目地抛出异常?而这里的抽象实际上是漏洞。跟踪器没有让您知道它无法跟踪的过程。
在您的情况下,您可能希望返回布尔值(有限信息),错误代码(更多信息)或错误类/结构。或者您可能希望获得抛出的标准异常。或者您可能希望Begin()方法包含在跟踪中发生错误时调用的委托。
答案 2 :(得分:3)
我只是从ITracker
派生IDisposable
。实现此接口的类可以选择在Dispose
方法中执行某些操作,例如你的Flush
,或什么都不做。
public interface ITracker : IDisposable
{
void Track(ITrackerEvent trackerEvent);
}
此外,请查看Observable pattern,ITracker
名称表示您可能希望在更改对象状态时执行某些操作。
答案 3 :(得分:1)
听起来你正在缓冲某些东西 - 被跟踪的东西需要不时刷新。你的界面隐藏了这种行为,这很好 - 当你的界面被刷新或者它被缓冲时,你不应该从该界面告诉你。
如果它是高容量我想设置两个参数 - 最大刷新间隔和最大缓冲区大小。 第一个使用计时器定期刷新。第二个在达到容量时触发刷新。然后,当物品被丢弃或收集时,我再次冲洗。
我将缓冲区分离到自己的类中,因此我可以重复使用它并单独对其进行单元测试。我会看是否能找到它,但写的代码不多。