Можно ли считать такой объект неизменным? - PullRequest
2 голосов
/ 25 июня 2011

Я разработал класс, содержащий некоторую информацию о данном объекте, которая будет зарегистрирована в базе данных SQL Server. Я хотел бы сделать этот объект (глубоко) неизменным, но я также должен заверить, что он регистрируется только один раз. Если этот объект реализует следующий шаблон, можно ли его считать неизменным?

public class NewClass
{
    private bool registered;

    public string SomeProperty { get; private set; }

    public NewClass Register()
    {
        if (registered)
        {
            throw new NotImplementedException(/*arguments*/);
        }

        /* Register on DB here... */
        registered = true;
        return new NewClass(somePropertyFromDB);
    }

    public NewClass(string someProperty)
    {
        registered = false;
        SomePropery = someproperty;
    }
}

Я бы сказал, что кроме логического поля registered объект неизменен, но эти поля оставляют у меня некоторые сомнения, потому что он действительно изменится при первом запуске метода Register ... Может кто-нибудь сказать мне, как я могу решить эту проблему и при этом сделать объект неизменным?

1 Ответ

3 голосов
/ 25 июня 2011

Нет, это определенно не неизменный.Значение registered изменяется в течение всего времени жизни объекта.

Чтобы сделать его неизменным, нельзя разрешать изменению поля registered в течение всего времени жизни объекта - вместо этого сделайте Register returnновый объект, который имеет true значение для registered

Я бы также удалил приватный установщик для SomeProperty, просто имея геттер и переменную только для чтения.

Так что-токак это:

public class NewClass
{
    private readonly bool registered;
    private readonly string someProperty;

    public bool Registered { get { return registered; } }
    public string SomeProperty { get { return someProperty; } }

    public NewClass Register()
    {
        // Note the change of exception here
        if (registered)
        {
            throw new InvalidOperationException("Already registered");
        }

        return new NewClass(somePropertyFromDB, true);
    }

    // You may want to have a public constructor with just someProperty
    // which calls this one, which you could make private
    public NewClass(string someProperty, bool registered)
    {
        this.registered = registered.;
        this.someProperty = someproperty;
    }
}

Некоторые примечания:

  • Другой вариант будет иметь два отдельных класса, RegisteredFoo и UnregisteredFoo;это может облегчить понимание кода с использованием этого класса
  • Нет ничего, что могло бы помешать кому-либо дважды вызывать Register, поэтому его неизменность не очень помогает с точки зрения идемпотентности.Поскольку есть естественный побочный эффект (общение с базой данных), трудно сделать его действительно функциональным.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...