Javenue logo

Javenue

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

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

Анти-паттерн проектирования в Java: интерфейс для констант

Ошибка, которая будет описана в данной статье, иногда привлекает Java-программистов своей многообещающей простой (я знаю, о чем говорю, так как сам ее допускал).

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

Если описать константу в интерфейсе, назовем его символично Unacceptable, то затем можно декларировать любой класс как реализующий (implements) этот интерфейс (interface) и использовать нашу полезную константу:

public interface Unacceptable {
    public static final int USEFUL_CONSTANT = 0;
    ...
}

public class First implements Unacceptable {
    public void firstMethod() {
        int key = USEFUL_CONSTANT;
        ...
    }
    ...
}

public class Second implements Unacceptable {
    public void secondMethod() {
        int value = USEFUL_CONSTANT;
        ...
    }
    ...
}

Не нужно портить зрение: в этом коде все синтаксически правильно. Но вот идеологически...

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

Поэтому, используйте следующий код:

public final class First {
    public static final int USEFUL_CONSTANT = 0;
    ...
}

public class Second {
    public void usefulMethod() {
        int value = First.USEFUL_CONSTANT;
        ...
    }
    ...
}

Используйте даже тогда, когда кроме констант там больше ничего не будет. Хотя это достаточно сложно себе представить, ведь константы обычно привязаны логически к какой-то сущности из вашего проекта. Главное, чтобы имя класса четко давало понять, что за смысловую нагрузку он несет. Так что можете смело переименовать класс First из второго примера в Unacceptable.

Еще об антипаттернах проектирования читайте - здесь.

Всем удачи.



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

  Выйти

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

stan:

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

1.Анти-паттерн IMHO это решение типовой задачи, которое действительно решает эту задачу (на самом деле только на первый взгляд), но при этом не соответствует принципам ООП.

2.Сравнивать java с такими языками программирования как PHP или С довольно странно (PHP использует оба подхода к программирования, а С вообще не поддерживает ОО-подход).

3.Дело не в ролях тех или иных элементов языка, а в нарушении принципов ООП. Вот пример:

public class UsefulConstants{
  public static final int USEFUL_CONSTANT_0 = 0;
  public static final int USEFUL_CONSTANT_1 = 1;
}

Почему так делать нельзя? Потому что этот подход нарушает принцип инкапсуляции. Следуя логике такого подхода необходимо выделить класс(ы) переменных и класс(ы) методов. Т.е. в данном случае константы является сущностью смоделированной посредством класса. А теперь надо задуматься: а есть ли такие предметные области в которых можно было бы выделить сущность “константы”?

Использование анти-паттернов или говоря проще “неверных с точки зрения ООП решений” приводит к запутыванию и необоснованному усложнению кода.

Что касается использования констант в интерфейсах то (опять же IMHO) это вообще говоря лишнее (а может и вредное) действие. Здесь есть проблемы как принципиального, так и чисто практического характера.

Oleg:

ООП и паттерны будоражат наши умы как красная тряпка возбуждает быка, или модный яркий магазин влечет блондинку. Как… эээ… ну вобщем понятно я думаю.
И что самое интересное, мы теперь начинаем рассуждать: “Это противоречит правилам ООП”. Здрасте приехали… Боже мой! Если всю жизнь следовать правилам - можно никогда ничему не научиться. Пишите как вам взбредет в голову и со временем все встанет на свои места. Ошибки и эти все “антипатерны” проявятся сами собой. А может быть вы выработаете свой, совершенно уникальный стиль, и откроете новые “паттерны”. А заранее вы все равно соломку не подстелите в нужном месте. А все эти “паттерны” - ПРОСТО ЖИЗНЕННЫЕ ВЕЩИ, которые новичкам кажутся чем-то магическим, что (каким-то волшебным образом) они спасут их в будущем, избавят от страданий и разочарований, лишней работы и т.п.

Sergey:

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

Я считаю, что начинающего нужно знакомить с простым линейным программированием, дать ему саму упереться в стенку и задать вопрос: “А нет ли способа реализовать задачу вывода всех чисел от 0 до 100 проще, чем писать:

Writeln(”0″);
Writeln(”1″);
…
Writeln(”99″);

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

Если во время спора о необходимости использования того или иного подхода (паттерна) на вопрос какие преимущества в нем заключаются, оппонент дает заученную формулировку. А после вопроса, как он к этому пришел, говорит, одну из следующих фраз:

1. Мне лид сказал так делать.

2. Мы так всегда дели.

3. Так в книжке “Н” написано.

Сразу становится понятно, насколько человек понимает то, о чем говорит. Понятно, что он следует “своему” любимому паттерну, даже если тот совершенно не подходит для его языка или противоречит структуре приложения. И он сделает все, чтобы соблюсти чистоту этого паттерна, даже если для этого приходится идти на неоправданные жертвы.

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