Должен ли я сделать свои свойства объекта обнуляемыми или использовать значения по умолчанию CLR для каждого типа? - PullRequest
8 голосов
/ 27 июня 2011

Я пытался найти лучший способ обработки значений по умолчанию.Установка значения идентификатора в 0 имеет смысл, но если это денежное или иное значение, которое изначально не установлено, при последующем обнаружении этого в вашем коде невозможно определить, было ли оно установлено или было установлено в 0. Еслиденежное значение равно нулю, тогда вы знаете, что оно не было установлено.Кроме того, при работе с базой данных легко узнать, нужно ли записывать нулевое значение в поле, а не пытаться выяснить, предполагается ли оно нулевым или нет.

Каков приемлемый способ справиться с этим?

Class MyModel
{
    public int Id {get;set;}
    public string Title {get;set;}
    public DateTime CreatedDate {get;set;}
    public bool IsActive {get;set;}

    //CLR will automatically set these values
    Public MyModel()
    {
        Id = 0; 
        Title = String.Empty;
        CreatedDate = "1/1/0001";
        IsActive = false;
    }
}

против

Class MyModel
{
    public int? Id {get;set;}
    public string Title {get;set;}
    public DateTime? CreatedDate {get;set;}
    public bool? IsActive {get;set;}

    //CLR will automatically set these values
    Public MyModel()
    {
        Id = null; 
        Title = null;
        CreatedDate = null;
        IsActive = null;
    }
}

Ответы [ 5 ]

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

Вы всегда можете смешивать подходы, в зависимости от вашего домена.

static class ID
{
    public const int Unassigned = -1;
}

class MyModel
{
    public int Id { get; private set; }
    public string Title { get; set; }
    public DateTime CreatedDate { get; set; }
    public bool IsActive { get; set; }
    public bool? IsAwesome { get; set; }

    Model () 
    {
        // you may use "default" constants...
        Id = ID.Unassigned;
    }

    // you may use optional parameters or overloads
    public MyModel (string title,
        DateTime created = DateTime.Now, // default values may be concrete 
        bool? isAwesome = null)          // or nullable as well
        : this ()                        // and you can chain-call constructors!
    {
        Title = title ?? "<no title>";   // you don't always want null to come through
        CreatedDate = created;     
        IsAwesome = isAwesome;    
    }
}

// Possible usages:
var model = new MyModel ("Hello", new DateTime (2001, 1, 1));
var model = new MyModel ("world", isAwesome: true);
var model = new MyModel (null) {
    IsActive = true
};

Может иметь смысл, чтобы некоторые атрибуты имели значения null, например, «не установлено».

В вашем примере, возможно, модель действительно не имеет и Id до ее сохранения в базе данных. Если это так, и модель без идентификатора имеет смысл с точки зрения бизнес-логики , то значение Id, которое можно обнулять, лучше, чем Id = 0. Однако, если ваше приложение никогда не работает с моделями без идентификатора и обычно ожидает, что Id будет равняться чему-либо, было бы безумно писать

if (model.Id != null)

каждый раз, когда вы хотите что-то с этим сделать.

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

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

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

Каков приемлемый способ справиться с этим?

Принято?Это зависит от домена.

Если денежное значение установлено на ноль, то вы знаете, что оно не было установлено.

Не обязательно.Представьте, что я использую банковское приложение, и я хочу найти конкретную транзакцию, и я получаю диалоговое окно, которое выглядит следующим образом:

Enter the fields you know:
Transaction date: 6/26/2011
Payee: Apple
Amount:

Теперь TransactionSearchParameters.Amount должно быть установлено на ноль.Вы не можете отличить это от того, что оно не задано.

Кроме того, при работе с базой данных просто узнать, нужно ли записывать нулевое значение в поле, а не пытаться выяснитьесли он должен быть нулевым или нет.

Вам следует потратить больше времени на правильное моделирование своего домена, а затем позволить ORM выяснить, как правильно добавить этот материал в базу данных.

2 голосов
/ 27 июня 2011

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

0 голосов
/ 28 июня 2011

Хорошо ... «лучший» ответ (очень самоуверенный, но у меня есть право), когда вам не нужно проводить различие между двумя, потому что существует только одно возможное состояние, которое является действительным:

class MyModel
{
    public int Id {get; private set;}
    public string Title {get; private set;}
    public DateTime CreatedDate {get; private set;}
    public bool IsActive {get; private set;}

    Public MyModel(int Id, string Title, DateTime CreatedDate, bool IsActive)
    {
        this.Id = Id; 
        this.Title = Title;
        this.CreatedDate = CreatedDate;
        this.IsActive = IsActive;
    }
}

Я знаю, что это не всегда возможно, например, Query by Example.

Использование «магических чисел», таких как «Установка значения идентификатора в 0, имеет смысл ...», как правило, избегается.Как только вы сделаете это сейчас, каждый код, который вы пишете, должен быть закодирован, чтобы знать, что это за магическое число и что они значат.Это редко достигается и полно неприятного кода и кода, подверженного ошибкам.

Если вы просто ДОЛЖНЫ иметь различие между полем, имеющим значение, и нет, ваш более поздний пример немного лучше.По крайней мере, здесь вы типы значений явно допустимы или недействительны.Однако использование Nullable означает, что вы должны использовать другое средство, чтобы определить, является ли класс, строка или другой ссылочный тип недопустимым.

ИМО, вам лучше со следующим, хотя, как вы увидите, оно становится очень многословным.

class MyModel
{
    private int _id;
    public bool HasId { get; set; }
    public int Id
    {
        get
        {
            if (!HasId) throw new System.InvalidOperationException();
            return _id;
        }
        set
        {
            HasId = true;
            _id = value;
        }
    }

    private string _title;
    public bool HasTitle { get; set; }
    public string Title
    {
        get
        {
            if (!HasTitle) throw new System.InvalidOperationException();
            return _title;
        }
        set
        {
            if (value == null) throw new System.ArgumentNullException("Title");
            HasTitle = true;
            _title = value;
        }
    }

    private DateTime _createdDate;
    public bool HasCreatedDate { get; set; }
    public DateTime CreatedDate
    {
        get
        {
            if (!HasCreatedDate) throw new System.InvalidOperationException();
            return _createdDate;
        }
        set
        {
            HasCreatedDate = true;
            _createdDate = value;
        }
    }

    private bool _isActive;
    public bool HasIsActive { get; set; }
    public bool IsActive
    {
        get
        {
            if (!HasIsActive) throw new System.InvalidOperationException();
            return _isActive;
        }
        set
        {
            HasIsActive = true;
            _isActive = value;
        }
    }
}

Наконец, если вы идете по этому маршруту, генератор кода будет вам полезен.

0 голосов
/ 27 июня 2011

Зависит от того, как вы собираетесь использовать свой код.Если свойства являются простыми типами, такими как целые числа и строки, значения по умолчанию лучше, если свойства являются объектами сами по себе, я использовал нули, потому что в C # / Java / PHP ссылки на объекты действительно являются указателями на объекты и их лучше использовать.

Но если ваши свойства являются коллекциями, такими как списки или карты, рекомендуется создать коллекцию и оставить ее пустой вместо нуля.

Приветствия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...