Есть ли когда-нибудь оправдание «антишаблону псевдо-typedef»?

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

  •  12-09-2019
  •  | 
  •  

Вопрос

У меня относительно сложный общий тип (скажем, Map<Long,Map<Integer,String>>), который я использую внутри класса.(Внешней видимости нет;это всего лишь деталь реализации.) Я бы хотел скрыть это в typedef, но в Java такой возможности нет.

Вчера я заново открыл для себя следующую идиому и был разочарован, узнав, что она считается антипаттерном .


class MyClass
{
  /* "Pseudo typedef" */
  private static class FooBarMap extends HashMap<Long,Map<Integer,String>> { };

  FooBarMap[] maps;

  public FooBarMap getMapForType(int type)
  {
    // Actual code might be more complicated than this
    return maps[type];
  }

  public String getDescription(int type, long fooId, int barId)
  {
    FooBarMap map = getMapForType(type);
    return map.get(fooId).get(barId);
  }

  /* rest of code */

}

Может ли быть какое-либо оправдание этому, если тип скрыт и не является частью библиотечного API (что, насколько я понимаю, является основным возражением Гетца против его использования)?

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

Решение

Настоящая проблема заключается в том, что эта идиома создает сильную связь между вашими псевдоопределение типа и ваш клиентский код.Однако поскольку вы используете FooBarMap в частном порядке реальных проблем со сцеплением нет (это детали реализации).

Примечание:

Современная Java IDE должна определенно помогать справляться со сложными универсальными типами.

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

ИМХО, проблема антишаблонов Java в том, что они поощряют черно-белое мышление.

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

Я хочу сказать, что вам нужно понимать антипаттерны и сделать мотивированное суждение о том, когда и где их избегать.Просто принимая позицию: «Я буду никогда сделать X, потому что это антишаблон» означает, что иногда вы исключаете приемлемые или даже хорошие решения.

Что касается общедоступных интерфейсов, мне не нравится видеть обобщенные типы, потому что они не имеют смысла.Для меня метод с аргументом HashMap<Long,Map<Integer,String>> очень похож на такие методы C, как foo(int, int, int, void*, int) и так далее.Наличие реального типа делает код намного проще для чтения.Для общедоступного интерфейса было бы лучше создать FooBarMap, который обертывает HashMap<Long,Map<Integer,String>>, а не 'typedef', но для внутреннего использования класса я вообще не вижу недостатков.

Без этого псевдотипа я бы предпочел написать

private Map<Long,Map<Integer,String>>[] maps;

и если я когда-нибудь решу изменить класс реализации с HashMap на TreeMap или Java7GreatEnhancedWonderfulMap :-) ничего не сломается.Но при этом вы застряли в HashMap.Ну, вы можете сделать:

interface FooBarMap extends Map<Long,Map<Integer,String>> { };
class FooBarHashMap extends HashMap<Long,Map<Integer,String>> implements FooBarMap{ };

но это становится все более и более громоздким.

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

Но я не вижу веской причины не использовать его локально, при условии, что это облегчает вам жизнь и делает код более читабельным — и вы знаете, что делаете.Брайан может обобщать и категорически возражать против этого в любой ситуации, но это его мнение Гетца :p

Если вы используете его только в небольшом локализованном блоке кода, проблемы невелики, это правда.

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

Я, вероятно, не стал бы переписывать код, который делал это, но, похоже, это плохая привычка.

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