【发布时间】:2016-06-15 23:47:43
【问题描述】:
我正在尝试找出设计程序功能的最佳方式。
该程序的一个主要组件是一个 Camera 类。这个 Camera 对象代表了一个真实相机的程序用户界面,它通过一个图像采集卡连接到计算机。相机类可以链接到图像采集卡,开始和停止采集,还可以改变/访问许多不同的相机属性。当我说很多时,我指的是超过 250 个独特的命令。每个独特的命令都是通过帧采集器向物理相机发送一个串行字符串来发送给相机的。每个命令都可以被认为是三种类型之一。一个操作、一个查询和一个值。
动作命令是不需要等号的东西,例如“reset”、“open”、“close”
查询是您可以获得但不能设置的东西,通常与一个值相关联。例如“温度=?”、“sernum=?”、“maxframerate=?”命令将导致相机发回信息。这些值不能改变,因此“温度=20”会导致错误。
值是您可以获取和设置的东西,通常与值相关联。例如“framerate=30”和“framerate=?”是两个独特的命令,但我认为基本字符串“framerate”是一种值命令类型,因为它可以被变异和访问。
250 个独特的命令可以减少到 ~100 个 CameraActions、CameraQuerys 和 CameraValues。在我的 Camera 类中没有 250 个方法,我有一个想法来组合命令对象,而不是单独的 setter、getter 和 action。命令字符串可以在构造函数中提供,也可以使用设置器重置。然后我可以编写一个包含所有可用命令的 CameraCommands 对象,并将其作为公共成员提供给我的相机。
//CameraAction.h =============================================
class CameraAction {
public:
CameraAction(std::string commandString, SerialInterface* serialInterface);
void operator()() { _serialInterface->sendString(_commandString); }
private:
SerialInterface* _serialInterface;
std::string _commandString;
};
//CameraValue.h =====================================================
class CameraValue {
public:
CameraValue(std::string commandString, double min, double max, SerialInterface* serialInterface);
void set(double value)
{
if(value > _maxValue) { throw std::runtime_error("value too high"); }
if(value < _minValue) { throw std::runtime_error("value too low"); }
std::string valueString = std::to_string(value);
_serialInterface->sendString(_commandString + "=" + valueString);
}
double get()
{
std::string valueString = _serialInterface->sendString(_commandString + "=?");
return atof(valueString.c_str());
}
private:
SerialInterface* _serialInterface;
std::string _commandString;
double _minValue;
double _maxValue;
};
//CameraCommands.h ===================================================
class CameraCommands {
public:
CameraCommands();
CameraAction reset;
CameraQuery temperature;
CameraValue framerate;
CameraValue sensitivity;
//... >100 more of these guys
};
//Camera.h ===========================================================
class Camera {
public:
Camera();
CameraCommands cmd;
void startAcquisition();
void stopAcquisition();
void setDataBuffer(void* buffer);
void setOtherThing(int thing);
};
以便用户可以执行以下操作:
Camera myCamera;
myCamera.cmd.reset();
myCamera.cmd.framerate.set(30);
myCamera.cmd.sensitivity.set(95);
double temperature = myCamera.cmd.temperature.get();
myCamera.startAcquisition();
等等……
这里的主要问题是我公开了公共成员变量,这应该是一个巨大的禁忌。我当前的对象设计是否合乎逻辑,或者我应该简单地实现 250 个 setter 和 getter 以及 100 多个 setter 和 getter 来改变最小和最大可设置值。
这对我来说似乎很笨拙,因为还有许多与 Camera 对象相关联的 setter/getter 与用户命令无关。用户界面最好提供方法 (cmd) 的范围,以便用户知道某些东西是在相机中发生物理变异,还是只是在编程对象中发生变异(其他方法)。有没有更好的方法来设计我的程序?
【问题讨论】:
-
这似乎主要是界面设计的问题。您必须决定如何编写与
Camera类交互的代码,然后找出一种方法使您的界面尽可能接近。对我来说,camera.cmd.foo语法似乎有多余的cmd部分。我希望能够编写Temperature t = camera.temperature();或camera.setFrameRate(6);甚至camera.frameRate = 6;他们之间的互动。 -
你的前几句话真的很重要。我试图使程序的内部工作变得干净且易于扩展,但我并没有真正考虑用户与 API 交互的最佳方式。到目前为止,很多建议似乎都喜欢 camera.frameRate = 5;这是一个很棒的概念,但可能会让其他查看代码的人感到困惑。我需要更深入地思考。