Javenue logo

Javenue

Программирование на Java

Информационные технологии

Антипаттерны проектирования в Java - Внесенная сложность

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

В одном из своих постов я уже рассматривал Java антипаттерн Интерфейс для констант. На этот раз рассмотрим еще несколько шаблонов, которым следовать не стоит. Итак, в этой статье:

Внесенная сложность (introduced complexity)

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

public interface IConfiguration {
    void someMethod();
}

public abstract class AbstractConfiguration
        implements IConfiguration { }

public class ConfigurationImpl
        extends AbstractConfiguration {
    public void someMethod { /* code */ }
}

Надобности в двух дополнительных сущностях естественно не было. Новые реализации тоже не планировались. А даже если и планировались, почему нельзя сделать extract интерфейса или абстрактного класса именно тогда, когда в этом возникла необходимость? Загадка.

Кроме всего прочего, напрягали эти стандартные префиксы и суффиксы: I, Impl, Abstract. Часто не понимал, зачем их использовать. В подавляющем большинстве случаев, если вы хотите добавить такую приставку или суффикс к своему классу, то нужно задать себе вопрос, а действительно ли этот класс нужен? Может достаточно будет всего лишь одного конкретного класса и часть иерархии просто не нужна?

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

Мягкое кодирование (soft coding)

О хардкоде знают все. Классика заваленных Unit тестов:

...
File file = new File("~/dev/some-file.txt");
...

На ряду с хардкодом есть понятие "мягкое кодирование". Это маниакальное, граничащее с психозом, желание избежать хардкода. Вот что можно встретить в тех же тестах:

public class SomeTestCase {
    public static final String EXPECTED_1 = "result";

    @Test
    public void someTest1() {
        ...
        assertEquals(EXPECTED_1, someCall());
    }
}

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

Так что если вы пишите свой блог, который в единственном экземпляре будет крутиться на вашем сервере, то не нужно выносить константу, а то и конфигурационный параметр, с названием HTTP_PORT :)

Ненужная инициализация

Это скорее что-то среднее между антипаттерном проектирования и кодирования. Рассмотрим следующий программный код:

public class SomeClass {
    private boolean active = false;
    private int counter = 0;
    private Object reference = null;

    public SomeClass {
        ...
    }

    ...
}

Вероятно, разработчик кода хотел быть увереным, что все поля класса проинициализированы. Но в данном конкретном случае это не нужно. В спецификации JLS говорится, что поля классов инициализируются значениями по-умолчанию - null для ссылок, 0 для целых типов и так далее.

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

Хотя можно сделать чуть хуже - после такой явной инициализации полей добавить еще их инициализацию внутри тела констркутора.

Шуточный антипаттерн

Ну а для того, чтобы скрасить рабочие будни, рассмотрим еще один анти-паттерн - Public Morozov. Это класс, который открывает доступ ко всем полям и методам класса-предка, не зависимо от их модификаторов видимости. Такие дела.

А какие антипаттерны проектирования (не кодирования) знаете вы?



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

  Выйти

  * для публикации комментариев нужно  

globus:

и вот такое можно встретить

// инициализируем список
list.add(0);
list.add(1);
list.add(2);
...
list.add(9);

Konstantin Chapiuk:

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

1. Индийское программирование:

  ...
  if (var == true)
      return true;
  else if (var == false)
      return false;
  else
      return (!false && !true);
  ...

2. А эту вещь видел в чужом коде. Наверное под вечер многие могут сделать такую ошибку:

  ...
  if (file == null) 
      System.out.println("File " + file.getName() +
               " is null.");
  ...

3. Еще популярный код касательно булевых значений:

    if (new Boolean(bool).toString().length() > 4)
        return false;
    else
        return true;

Alexandr Ryabuh:

По поводу первого примера соглашусь. Второй это обычная невнимательность, ну и третья это уровень трейни. Обычно после года (+/- лапоть) опыта, такие штуки сразу замечаешь, глаза режут.

Владимир Крючков:

Еще такое встречпал : boolean examl; if(examl == true){ //do something... }