Какой вариант дизайна больше подходит для автокоррекции на стройке? - PullRequest
1 голос
/ 01 августа 2009

Попытка расшифровать соответствующий ОО-проект для реализации. Основной сценарий состоит в том, что у вас есть PstnNumber, который по сути представляет собой 10-значный номер телефона, который всегда начинается с 0 (например, 0195550000). Введено правило, позволяющее автоматически корректировать число, если отсутствует начальный 0 (например, 195550000).

НАЧАТЬ РЕДАКТИРОВАТЬ

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

КОНЕЦ РЕДАКТИРОВАНИЯ

Я начал играть с некоторыми предварительными концепциями, а затем подумал, что я спрошу, есть ли более подходящий способ или достаточно одного из них (на каком-то уровне)?

Концепция 1

public class PstnNumber
{
    public virtual string Number { get; set; }

    public PstnNumber() { }

    public PstnNumber(string number)
    {
        this.Number = number;
    }
}

public class AutoFormattedPstnNumber : PstnNumber
{
    public override string Number
    {
        get { return base.Number; }
        set { base.Number = value.PadLeft(10, '0'); }
    }

    public AutoFormattedPstnNumber() : base() { }

    public AutoFormattedPstnNumber(string number)
    {
        this.Number = number;
    }
}

Концепция 2 (удалено)

Концепция 3

public class PstnNumber
{
    public bool AutoCorrect { get; set; }

    private string number;
    public virtual string Number
    {
        get { return (this.AutoCorrect) ? this.number.PadLeft(10, '0') : this.number; }
        set { this.number = value; }
    }

    public PstnNumber() : this(false) { }

    public PstnNumber(bool autoCorrect)
    {
        this.AutoCorrect = autoCorrect;
    }

    public PstnNumber(string number) : this(false)
    {
        this.Number = number;
    }

    public PstnNumber(string number, bool autoCorrect) : this(autoCorrect)
    {
        this.Number = number;
    }
}

Я думаю, что Концепция 1 может нарушать правило подстановки Лискова, потому что подкласс меняет поведение свойства Number (рад узнать, что я неправильно понял).

Любые альтернативные предложения будут приняты с удовольствием.

Ответы [ 8 ]

4 голосов
/ 01 августа 2009

нужно ли выполнять автоформатирование при создании экземпляра объекта? Если не, как насчет:

  public class PstnNumber
  {
    public virtual string Number { get; set; }
    public PstnNumber() { }
    public PstnNumber(string number) { this.Number = number; }
    public AutoFormatNumber { get { return Numer.PadLeft(10, '0'); } }
  }
3 голосов
/ 01 августа 2009

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

if (input.Value != current.Number)
{
   NumberChangedAgain = true;
   current.Number = input.Value;
}

Простым решением было бы сделать PstnNumber неизменным:

 temp = PstnNumber.FromString(input.Value);
 if (temp != current) { ... }

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

различные аспекты
Вам нужно различие между «автоматически отформатированным» и «нормальным» числом, или это просто вопрос ввода и вывода - т.е.

  • Формат отображения (короткий или длинный) зависит от того, как был введен номер или от того, где он отображается?
  • это 0195550000 == 195550000?

Я бы предпочел сложить оба класса в один, если это возможно (т. Е. Когда «введено с или без 0, можно забыть»):

public class PstnNumber 
{  
   private string m_number; // always in long format
   public static PstnNumber(string s)  { ... } // accepts short and long form

   public string Number { get { return m_number; } }
   public string AutoFormatted { { get { ... } }
}

В противном случае я бы выбрал вариант 3, но всегда сохранял длинный формат в m_number.

1 голос
/ 01 августа 2009

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

Так что я бы пошел на № 3 без состояния, что означает окончательное число и избавление от переменной autoFormat.

Для простоты я бы просто получил getNumberRaw и getNumberFormatted

Еще лучше, вы могли бы получить getNumberRaw и getNumber (formatType), где formatType фактически содержит код, который форматирует число, так как формат может снова измениться в будущем, а объединение форматирования (просмотра) с вашим номером телефона (моделью) - нет. оптимальный.

(PS / EDIT): просто тот факт, что номер телефона может измениться, НЕ является хорошей причиной для установки! Создание нового объекта номера телефона и замена старого будет работать почти всегда!

1 голос
/ 01 августа 2009

Я бы спросил, почему ваше имя класса такое загадочное. «Номер» для меня понятен, а «П» предлагает «телефон», но что мне говорит «СТН»? Несколько дополнительных нажатий клавиш сделают этот класс более самодокументированным.

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

Я чувствую, что вариант 1 излишний. Я не думаю, что наследование делает эту модель яснее или лучше. Я не вижу, как это нарушает подстановку Лискова, которая требует, чтобы вы могли использовать подкласс в любой ситуации, которая требует базового класса. Методы отображают 1: 1, насколько я вижу. Как нарушается Лисков?

Вариант 2 говорит, что это два отдельных класса без каких-либо отношений. Мне это не кажется правильным.

Вся эта работа предполагает, что ваша проблема потребует, чтобы вы использовали оба класса. У вас будут ситуации, когда ведущий ноль НЕ требуется, а в других - где он есть. Это правда? Или вы всегда будете требовать ведущего нуля?

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

1 голос
/ 01 августа 2009

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

В соответствии с этим я бы заставил PstnNumber просто удерживать число и создать некую фабрику, которая производит правильное число.

Выполнение обоих в одном классе означает, что вы создаете доменную логику и представление. Я предпочитаю их отделить.

1 голос
/ 01 августа 2009

В Варианте 1 и Варианте 2 вы все равно не сохраняете исходный номер, делая подкласс бесполезным (за исключением того, что знаете, что он был автоматически отформатирован в какой-то момент, что не похоже на полезную информацию). Чтобы сделать эти параметры более полезными, можно использовать форматирование вместо Get вместо Set.

Поэтому вариант 3 является предпочтительным шаблоном из этих трех вариантов, но я также хотел бы спросить - почему PstnNumber также не может просто определять количество цифр и автоматически форматировать соответственно?

0 голосов
/ 02 августа 2009

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

0 голосов
/ 01 августа 2009

Я не знаком с C #, но я бы сделал это:

public class PstnNumber {
  readonly string number;

  public PstnNumber(string number) {
    this.number = number;
  }

  public string getNumber() {
    return number;
  }

  static public PstnNumber createNumber(string number) {
    return new PstnNumber(number.PadLeft(10, '0'));
  }
}

Конечно, если бы я знал, как работают свойства, я бы сделал это по-другому:)

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