开发者

OOP design problem: responsibility in containee or container?

开发者 https://www.devze.com 2023-03-03 14:11 出处:网络
I focus a lot on making my software design flexible and reliable, and one of the key concepts to achieve this is encapsulation.

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?

0

精彩评论

暂无评论...
验证码 换一张
取 消