ООП проектная проблема: ответственность за контейнер или контейнер? - PullRequest
3 голосов
/ 08 мая 2011

Я уделяю большое внимание созданию гибкого и надежного проекта программного обеспечения, и одной из ключевых концепций для этого является инкапсуляция.В последнее время я столкнулся с особой проблемой проектирования, и я не могу спорить (с самим собой), что является лучшим решением.

Конкретный пример, иллюстрирующий проблему: устройство имеет адрес (в шине).Устройство имеет несколько регистров.Регистр также имеет адрес (внутри устройства - он же виртуальный адрес / сопоставленный адрес), поэтому, например, для записи в регистр устройства необходимо записать (registerAddress, value) в адрес устройства.Я не могу решить, куда поместить функциональность регистров чтения / записи:

1) регистр должен уметь читать и записывать сам, то есть ему необходимо знать о канале связи между устройством и самим собой.Это кажется странным / неправильным, я не могу объяснить, почему ..

2) Устройство считывает / записывает в / из регистров.Регистр - это просто заполнитель для информации (данных, прав доступа и т. Д.), Которую устройство может запрашивать / изменять.Это также кажется неправильным, потому что ответственность за чтение / запись регистра должна лежать на самом деле в регистре (подобно тому, как файл умеет сам читать / писать).

Какое решение имеет наибольшее значение и почему?Может быть, есть совершенно другое решение, которое имеет больше смысла?

Решение 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);
    }
}

Решение 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);
    }
}

Ответы [ 2 ]

2 голосов
/ 08 мая 2011

Доведенный до логического предела, автобус сам по себе является объектом. Чтение или запись регистра - это операция с шиной, разные шины имеют разные способы доступа к регистру. Создайте интерфейс шины с методами ReadRegister и WriteRegister.

Передозировка - это, безусловно, соображение, я думаю, что шансы, что вы когда-нибудь запустите этот код на другом типе шины, невелики.

1 голос
/ 08 мая 2011

Вопрос действительно о том, «должен ли Регистр быть отдельной сущностью?».Ну, это зависит от вас.Вам нужно ответить на вопрос: зачем нужен Регистр, чтобы быть классом?

...