创建一个具有多个函数的库还是创建类更好?
我正在开发一种与设备通信的软件。
该软件将为设备发送命令。设备必须使用以下协议进行应答:
<STX><STX><COMMAND>[<DATA_1><DATA_2>...<DATA_N>]<CHKSUM><ETX>
其中:
<STX> is the Start of TeXt (0x55);
<COMMAND> can be 0x01 for read, 0x02 for write, etc;
<DATA> is any value;
<CHKSUM> is the checksum;
<ETX> is the End of TeXt (0x04).
因此,我必须验证接收到的数据。
那么,接收到的数据:
- 不能为空;
- 必须有 3 个或更多字符;
- 字符串数据的前两个字符中必须有一个标题;
- 字符串数据的最后一个字符必须有一个“页脚”;
- 必须有一个有效的校验和。
如果答案有效,那么我就可以处理数据。但在此之前我必须从收到的响应中提取这些数据。
好的,这是一个相对容易的任务。以前我会以一种程序的方式来完成它,只使用一个函数并放置许多 if。
现在我正在更多地研究良好的编程实践,事情似乎变得越来越难做了。
要验证设备答案,是否最好创建一个类“ValidateReceivedData”,然后在该类的构造函数中传递接收到的数据?然后创建一个名为“IsReceivedDataValid”的公共方法来检查上面给出的所有步骤?
或者也许更好地创建一个具有多个函数的库来验证接收到的数据?
我也想使用单元测试。
正如我之前所说,我正在学习更多知识以编写更好的代码。但我意识到我现在花在编码上的时间比以前更多了。出现了太多的问题,但在我看来,它们似乎很容易解决,但我却没有得到解决。
I'm developing a software to comunicate with a device.
The software will send commands for the device. The device has to answer using the protocol below:
<STX><STX><COMMAND>[<DATA_1><DATA_2>...<DATA_N>]<CHKSUM><ETX>
where:
<STX> is the Start of TeXt (0x55);
<COMMAND> can be 0x01 for read, 0x02 for write, etc;
<DATA> is any value;
<CHKSUM> is the checksum;
<ETX> is the End of TeXt (0x04).
So, I have to validate the received data.
Then, the received data:
- cannot be empty;
- must have 3 or more characters;
- must have an header in the first two characters of the string data;
- must have a "footer" in the last character of the string data;
- must hava a valid CheckSum.
If the answer is valid, then I can handle the data. But before I'll have to extract this data from the response received.
Ok, this is a relatively easy task. Beforetime I would do it on a procedural way, using only one function and putting many if's.
Now I'm studying more about good programming practices, things seem to be getting harder to do.
To validate the device answer, is better create a class "ValidateReceivedData" for example and pass the received data in the constructor of this class? And then create a public method called "IsReceivedDataValid" that check all steps given above?
Or maybe would be better create a library with with several functions to validate the received data?
I'd like to use unit test too.
As I said before, I'm studying more to make better code. But I realize that I'm spending more time now to code than before. And there are too many questions that are arising, but in my view they seem easy to solve, but I'm not getting.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
无论如何,我在使用面向对象设计之前就做过这类事情。以下是您的设计的高级可能性:
ProtocolParser
类:SerialPort
对象或等效对象,并监听它以获取传入字节OnByteReceived
,它实现特定于协议的状态机(具有诸如Unknown
、Stx1Received
、Stx2Received
等状态,...CkSumReceived
)。Packet
类型的对象,该对象在其构造函数中接受字节列表。然后,它引发一个事件PacketReceived
,并将Packet
作为参数传递。BadDataReceived
并传递坏数据(也许用于日志记录/调试目的)。Packet
类:Command
和Data
属性。上述类足以实现接收协议。您应该能够通过模拟 SerialPort 类来测试它(即,ProtocolParser 实际上可以采用 IDataSource 而不是 SerialPort)。
然后,您可以添加一个更高级别的类来实现特定于设备的函数,该函数将侦听
ProtocolParser
的PacketReceived
事件。For what it's worth, I've done this sort of thing before using object-oriented design. Here's a high level possibility for your design:
ProtocolParser
class:SerialPort
object, or equivalent, in the constructor and listens to it for incoming bytesOnByteReceived
, which implements the protocol-specific state machine (with states likeUnknown
,Stx1Received
,Stx2Received
, ...,CkSumReceived
).Packet
, which accepts a byte list in its constructor. It then raises an eventPacketReceived
, passing thePacket
as an argument.BadDataReceived
and passes the bad data (for logging/debugging purposes, perhaps).Packet
class:Command
andData
properties.The above classes are sufficient to implement the receive protocol. You should be able to test it by mocking a SerialPort class (i.e., the
ProtocolParser
could actually take anIDataSource
instead of aSerialPort
).You could then add a higher-level class to implement your device-specific functions, which would listen to the
PacketReceived
event of theProtocolParser
.当然使用OOP设计会更好。
根据您的解释,我将至少创建 2 个类:
Message
Executer
该消息将接收来自设备的命令,并且执行器将处理该消息。
消息对象将以设备的应答启动。它将解析它,并保存您所描述的字段:
STX
命令
数据
校验和
ETX
然后,执行器对象将接收消息对象并实际执行消息,并保存逻辑代码。
Of course it will better to use OOP design.
By what you explained, I'd make at least 2 classes:
Message
Executer
The message will receive the command from the device, and the Executer will handle the message.
The Message object will initiate with the device's answer. It will parse it, and hold fields as you described:
STX
COMMAND
DATA
CHKSUM
ETX
Then an Executer object will receive the Message object and do the actual execution of the message, and hold the logical code.
我会比 Yochai 的答案更进一步,创建以下类:
通过创建中间表示对象(消息),您可以分离正在执行的各种操作。例如,如果当权者决定消息文本可以作为 XML 或 JSON 发送,您可以创建不同的 MessageParser 类,而不必扰乱决定如何处理消息的逻辑。
这也使得单元测试变得更加容易,因为您可以独立于执行器来测试消息解析器。首先通过调用解析函数并检查生成的消息对象来测试消息解析器。然后通过创建 Message 对象并确保采取适当的操作来测试执行器。
I would go a step further than Yochai's answer, and create the following classes:
By making the intermediate representation object (Message), you make it possible to separate the various actions you're performing. For example, if the Powers That Be decide that the message text can be sent as XML or JSON, you can create different MessageParser classes without having to mess with the logic that decides what to do with the message.
This also makes unit testing far easier, because you can test the message parser independently of the executor. First test the message parser by calling the parse function and examining the resulting Message object. Then test the executor by creating a Message object and ensuring that the appropriate action is taken.