Смешанная и разделенная изменчивость классов

В частично изменяемом классе лучше ли смешивать изменяемые поля с его неизменяемыми или создавать новый класс (или классы), которые их инкапсулируют? Вот пример на С# того, о чем я говорю:

interface IBedroom
{
    int Volume { get; }

    string Color { get; }

    void Paint(string newColor);
}

Вот реализация со смешанной изменчивостью в полях:

class MixedMutabilityBedroom : IBedroom
{
    readonly int volume;
    string color;

    public MixedMutabilityBedroom(int volume, string color = "")
    {
        this.volume = volume;
        this.color = color;
    }

    public int Volume
    {
        get { return volume; }
    }

    public string Color
    {
        get { return color; }
    }

    public void Paint(string newColor)
    {
        color = newColor;
    }
}

И один с отдельной изменчивостью:

// first, a fully mutable helper class
class RoomColor
{
    string value;

    public RoomColor(string value)
    {
        this.value = value;
    }

    public string Value
    {
        get { return value; }
    }

    public void Change(string newValue)
    {
        value = newValue;
    }
}

и реализация разделенной изменчивости:

class SeparatedMutabilityBedroom : IBedroom
{
    readonly int volume;
    readonly RoomColor color;

    public SeparatedMutabilityBedroom(int volume, RoomColor color)
    {
        this.volume = volume;
        this.color = color;
    }

    public int Volume
    {
        get { return volume; }
    }

    public string Color
    {
        get { return color.Value; }
    }

    public void Paint(string newColor)
    {
        color.Change(newColor);
    }
}

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

Что вы думаете? Я забыл некоторые моменты для рассмотрения?


person xofz    schedule 01.10.2010    source источник
comment
С какой стати вы помечаете что-то как неизменное, а затем меняете это? Независимо от того, где может быть изменчивость, конечно, ни одна из вещей, которые вы собираетесь изменить, не должна быть помечена как неизменяемая, равно как и любая из вещей, которые инкапсулируют эти вещи. Говорите об ошибках, ожидающих своего появления и не сообщающих о намерениях! Эй, эта штука сказала, что она неизменна, а потом она изменилась на мне. ВТФ?   -  person dash-tom-bang    schedule 01.10.2010
comment
@dash-tom-bang, не могли бы вы пояснить, пожалуйста? Что я пометил как неизменное, а затем изменил?   -  person xofz    schedule 02.10.2010
comment
RoomColor помечен как readonly, но метод Paint изменяет его.   -  person dash-tom-bang    schedule 03.10.2010


Ответы (1)


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

Однако, если предположить, что вы находитесь в ситуации, когда существует большое количество параллелизма с несколькими авторами для этого объекта, то создание объекта частично неизменяемым на самом деле не принесет вам многого, поскольку вы все равно можете столкнуться с проблемами.

В этом случае либо используйте какой-то примитив синхронизации, либо используйте полностью неизменяемый объект.

Этот ответ рассказывает о некоторых приемах использования полностью неизменяемых объектов.

person Matthew Manela    schedule 01.10.2010