понедельник, 15 мая 2017 г.

Инкапсуляция скрывает голые данные


Инкапсуляция - это основной принцип объектно-ориентированного программирования, который делает объекты надежными. Но что же такое инкапсуляция? Защищает ли она только от доступа к private атрибутам из вне? Я думаю, она намного больше. Инкапсуляция данных в принципе приводит к отсутствию голых данных на всех уровнях и во всех формах.



Вот какие голые данные (код C):
int t;
t = 85;
Printf («Температура -% d F», t);

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

Почему это плохо? По одной причине: жесткая и скрытая связь.

Код вокруг t неизбежно делает много предположений о данных. Например, обе линии после int t решили, что температура в градусах Фаренгейта. На момент написания это может быть правдой, но это предположение связывает код с данными. Если завтра мы изменим t на градусы цельсия, код не узнает об этом изменении. Вот почему я называю эту связь скрытой.

Если мы изменим тип t с int на, скажем, double, то строка printf не будет печатать ничего после десятичной точки. Опять же, связь есть, но она скрыта. Позже мы просто не сможем найти все места в нашем коде, где мы делали те или иные предположения о t.

Это серьезно повлияет на поддерживаемость кода.

Казалось бы, можно придумать решение через сеттер и геттер:

Class Temperature {
  private int t;
  Public int getT () {return this.t; }
  Public void setT (int t) {this.t = t; }
}

Такое решение вроде бы выглядит уже как объект, но они все еще голые. Любой может извлечь t из объекта и решить, является ли они градусами по Фаренгейту или по Цельсию, целое ли это число или с цифрой после точки. Это еще не инкапсуляция!

Единственный способ инкапсуляции t - убедиться, что никто не может коснуться его ни напрямую, ни путем извлечения его из объекта. Как мы это сделать? Просто прекратите публикацию данных и начните раскрывать функциональность. Вот как, например:

Class Temperature {
  private int t;
  Public String toString () {
    Return String.format ("% d F", this.t);
  }
}

Мы больше не разрешаем никому возвращать t. Все, что они могут сделать, - преобразовать температуру в текст. Если и когда мы решим изменить t на Celsius, мы сделаем это только один раз и в одном месте: в классе Temperature.

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

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

Эта идея близка к «принтерам вместо геттеров», о которых мы говорили ранее, хотя и с гораздо более широкой точки зрения. Здесь я говорю, что любые элементы данных, которые выходят из объектов, являются голыми и приводят к проблемам поддержки кода.

Вопрос в том, как мы можем работать без голых данных, верно? В конце концов, мы должны позволить объектам обмениваться данными, не так ли? Да, это правда. Но не совсем. Я объясню это в своем следующем посте.

Комментариев нет:

Отправить комментарий