Изменение аргумента установки – это взломать или нет?

StackOverflow https://stackoverflow.com/questions/433678

  •  10-07-2019
  •  | 
  •  

Вопрос

Нормально ли изменять аргументы установщика?Давайте представим, что у нас есть метод setString.И нам очень хочется сохранить обрезанную форму строки.Таким образом, строка с конечными пробелами недействительна, но мы не хотим создавать исключение.

Какое лучшее решение?Чтобы обрезать значение в установщике, например.

public void setString(String string) {
    this.string = string.trim();
}

Или обрезать его в вызывающем абоненте (более одного раза), например.

object.setString(string.trim());

Или, может быть, что-то еще?

Это было полезно?

Решение

Да.В конце концов, сеттеры созданы для таких вещей!Для контроля и очистки значений, записанных в поля;)

Другие советы

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

public double UserTemperature
{
  get
  {
    return Units.Instance.ConvertFromSystem(UnitType.Temperature, temperature);
  }
  set  
  {
    double v = Units.Instance.ConvertToSystem(UnitType.Temperature, value);
    if (temperature != v)
    {
      temperature = v;
      Changed("SystemTemperature");
      Changed("UserTemperature");
    }
  }
}

Да, конечно. Просто будьте внимательны и проверяйте NULL перед применением любого метода (например, trim ()).

Существует две школы: одна говорит, что можно проверять параметр в setter (стиль школы), а вторая говорит, что bean-компоненты не должны содержать никакой логики и только данные (стиль предприятия).

Я верю больше во второй. Как часто вы смотрите на реализацию ваших бинов? getUser должен выбросить любое исключение или просто вернуть null?

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

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

Другой (лучше?) альтернативой является изменение имени метода на trimAndSetString. Таким образом, не удивительно поведение обрезать ввод.

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

Именно поэтому вы используете сеттеры, а не выставляете поля объектов всему широкому миру.

Рассмотрим класс с целочисленным углом от 0 до 359 включительно.

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

С сеттером вы можете сделать несколько вещей. Один из них - вызвать исключение, чтобы указать, что было передано неверное значение, но, на мой взгляд, это было бы неправильно (в данном случае). Вероятно, это будет более полезно, если вы измените входное значение на что-то между 0 и 359, например с помощью:

actualVal = passedValue % 360;

Пока это указано в вашем интерфейсе (API), оно совершенно корректно. На самом деле, даже если вы не укажете это, вы все равно можете делать все, что захотите, так как вызывающая сторона нарушила контракт (передав значение за пределы диапазона). Я склонен следовать правилу «очистить ваш вклад как можно скорее».

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

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

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

Если кто-то желает разрешить клиенту каким-либо образом изменять состояние объекта, не отвечая приведенному выше описанию, следует использовать метод, а не свойство. Если вызвать Foo.SetAngle (500) , можно разумно ожидать, что метод будет использовать указанный параметр при установке угла, но свойство Angle может не возвращать угол в той же форме, в которой он был установлен (например, он может вернуть 140). С другой стороны, если Angle является свойством чтения-записи, можно ожидать, что запись значения 500 будет либо запрещена, либо вызовет обратное чтение значения 500. Если кто-то хочет иметь объект хранит угол в диапазоне от 0 до 359, объект также может иметь свойство только для чтения с именем BaseAngle , которое всегда будет возвращать угол в этой форме.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top