我正在编写一个 C# 库来包装 Win32 API(waveOut...
函数系列),并且已经到了我不确定如何在不破坏封装的情况下管理代码不同部分之间的交互的地步。到目前为止,我有这样的设置:
public class AudioDevice
{
...
private WaveOutSafeHandle hWaveOut;
...
}
// All native method calls happen in wrapper methods here, providing
// uniformity of access, exceptions on error MMRESULTs, etc.
static class NativeWrappers
{
...
internal static WaveOutSafeHandle OpenDevice(...) { ... waveOutOpen(...) ... }
...
}
// Native methods live in a class of their own, and are only called
// from NativeWrappers
static class NativeMethods
{
...
internal static extern MMResult waveOutOpen(...);
...
}
这段代码中最重要的一点是,被 Device 包裹的句柄对于 Device 之外的任何东西都是不可见的。
现在我想添加一个AudioBlock
类,它将包装原生WAVEHDR
结构和音频样本数据。我遇到的问题是,从现在开始,我感兴趣的几乎所有其他本机函数 ( waveOut[Un]PrepareHeader
, waveOutWrite
) 都需要句柄和WAVEHDR
. 似乎要么设备必须触摸WAVEHDR
,要么块必须有权访问句柄。任何一种方法都意味着某些类与它在概念上不知道业务的事物交互。
当然,有几种方法可以解决这个问题:
使句柄和/或
WAVEHDR
内部而不是私有。创建
AudioBlock
一个嵌套类.Device
有一个第三类(我什至不敢想名字
(foo)Manager
),它维护(例如)从块到标题的映射,给定一个块,设备可以使用它来帮助它播放样本,而无需触及块的内部。
可能还有其他人;我希望如此:)
我对这些方法的反对意见(对或错):
他们可能不是严格意义上的公开,但使用内部成员对我来说似乎是一种逃避。库中不需要它们的部分仍然可以看到有效的实现细节。我一直在想“我想向使用或修改此代码的任何人呈现什么界面?”
这几乎在我脑海中起作用。通过将块视为设备的“实现细节”,允许它依赖设备的内部结构似乎更容易接受。除了一个块真的是一个独立的实体;它不依赖于单个设备,也不用于帮助实现设备的逻辑。
这最接近我想要保持的分离水平,但开始误入过度工程领域,就像我经常做的那样:P 它还引入了一个人为的想法,即必须从某个地方集中分配块以保持映射完整.
那么,是否有人对(重新)构建此代码有任何建议?有效答案包括“你的反对意见#X 是一个热气腾腾的锅”,只要你能说服我 :) ETA:例如,如果你认为通过社交手段(文档、惯例)来强制执行这种事情比技术性的(访问修饰符、程序集边界),请告诉我并指出一些参考资料。