Чистый код. Создание, анализ и рефакторинг (Мартин) - страница 91

>• clear() void – Map

>• containsKey(Object key) boolean – Map

>• containsValue(Object value) boolean – Map

>• entrySet() Set – Map

>• equals(Object o) boolean – Map

>• get(Object key) Object – Map

>• getClass() Class – Object

>• hashCode() int – Map

>• isEmpty() boolean – Map

>• keySet() Set – Map

>• notify() void – Object

>• notifyAll() void – Object

>• put(Object key, Object value) Object – Map

>• putAll(Map t) void – Map

>• remove(Object key) Object – Map

>• size() int – Map

>• toString() String – Object

>• values() Collection – Map

>• wait() void – Object

>• wait(long timeout) void – Object

>• wait(long timeout, int nanos) void – Object

Рис. 8.1. Методы Map


Если в приложении требуется контейнер Map с элементами Sensor, его можно создать следующим образом:

>Map sensors = new HashMap();

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

>Sensor s = (Sensor)sensors.get(sensorId );

Причем видим его не только в этом месте, но снова и снова по всему коду. Клиент кода несет ответственность за получение Object из Map и его приведение к правильному типу. Такое решение работает, но «чистым» его не назовешь. Кроме того, этот код не излагает свою историю, как ему положено. Удобочитаемость кода можно было бы заметно улучшить при помощи шаблонов (параметризованных контейнеров):

>Map sensors = new HashMap();

>...

>Sensor s = sensors.get(sensorId );

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

Свободная передача Map по системе означает, что в случае изменения интерфейса Map исправления придется вносить во множестве мест. Казалось бы, такие изменения маловероятны, но вспомните, что интерфейс изменился при добавлении поддержки шаблонов в Java 5. В самом деле, мы видели системы, разработчики которых воздерживались от использования шаблонов из-за большого количества потенциальных изменений, связанных с частым использованием Map.

Ниже представлен другой, более чистый вариант использования Map. С точки зрения пользователя Sensors совершенно не важно, используются шаблоны или нет. Это решение стало (и всегда должно быть) подробностью реализации.

>public class Sensors {

>  private Map sensors = new HashMap();


>  public Sensor getById(String id) {

>    return (Sensor) sensors.get(id);

>  }


>  //...

>}

Граничный интерфейс (Map) скрыт от пользователя. Он может развиваться независимо, практически не оказывая никакого влияния на остальные части приложения. Применение шаблонов уже не создает проблем, потому что все преобразования типов выполняются в классе Sensors.