I focus a lot on making my software design flexible and reliable, and one of the key concepts to achieve this is encapsulation. Lately I have faced a special design problem and I can't argue (with myself) what is the best solution.
A concrete example illustrating the problem: A device has an address (on a bus). The device has multiple registers. A register also has an address (inside the device - aka. virtual address/mapp开发者_Go百科ed address), so for example to write to a register on the device, you have to write (registerAddress, value) to the address of the device. I can't decide where to put the functionality of reading/writing registers:
1) a register should be able to read write itself, meaning it needs to know about the communication channel between the device and itself. This seems strange/wrong somehow, I can't explain why though..
2) The device reads/writes to/from registers. A register is just a placeholder for information (data, access rights etc) that the device can query/alter. This also seems wrong because the responsibility of reading/writing a register should really be in the register (like a file knows how to read/write itself).
What solution makes most sense and why? Maybe there is a completely different solution that makes more sense?
Solution 1
class Device
{
private CommChan chan;
private Register register1;
private Register register2;
...
public Device(int deviceAddress)
{
chan = new CommChan(deviceAddress);
register1 = new Register(0x01, chan);
...
}
public void DoSomething()
{
register1.Write(0x22);
byte b = register1.Read();
}
}
class Register
{
private int address;
...
public Read()
{
chan.InitTransfer(address)
... // Other setup
return chan.Read(address);
}
public Write()
{
chan.InitTransfer(address)
... // Other setup
chan.Write(value);
}
}
Solution 2
class Device
{
private CommChan chan;
public Device(int address)
{
chan = new CommChan(address);
}
public void DoSomething()
{
WriteRegister(0x01, 0x22);
byte b = ReadRegister(0x01);
}
private byte ReadRegister(int address)
{
chan.InitTransfer(address)
... // Other setup
return chan.Read(address);
}
private void WriteRegister(int address, int value)
{
chan.InitTransfer(address)
... // Other setup
chan.Write(value);
}
}
Driven to the logical extreme, a bus is an object by itself. Reading or writing a register is a bus operation, different busses have different ways to access a register. Create a bus interface with methods ReadRegister and WriteRegister.
Overdoing this is certainly a consideration, I imagine the odds that you'll ever run this code on another type of bus are small.
The question is really about "should Register be a separate entity?". Well it's up to you. You need to answer question: why it's necessary a Register to be a class?
精彩评论