как решить проблему с велосипедом? - PullRequest
0 голосов
/ 28 июля 2010

У меня есть такая ситуация зависимости:

C (->) B -> A -> C

где B-> C означает, что модуль C имеет зависимость от B в своем файле pom.xml.

Ну ... я хочу использовать класс из B в C, поэтому я должен поставить C-> B, НО я получаю ошибку циклирования, как вы можете видеть выше ...

Видите ли вы обходной путь? Я НЕ МОГУ переместить этот класс из B в C, потому что он уже использует некоторые классы из A и снова будет цикл.

Я пытался объявить интерфейс IAlfa в C и реализовать его в B (Alfa) (но когда я хочу использовать его, мне нужно создать экземпляр как:

IAlfa alfa = new Alfa() 

Итак, снова мне нужно импортировать Альфа из B.

Что вы думаете?

Спасибо.

Ответы [ 4 ]

5 голосов
/ 29 июля 2010

Этого не должно быть.То, что я обычно делаю, имеет такую ​​структуру модуля:

root
    - api (interfaces, enums and custom exceptions only)
    - impl (standard implementation of api -> dependency to api)
    - server (runtime dependency to impl, compile time to api only)
    - client (dependency to api only)

Допустим, у нас есть интерфейс Person в модуле api.Теперь в модуле impl у вас будет класс JpaPerson, потому что impl использует JPA.Однако это детали, которые не нужны клиенту и серверу сейчас, поэтому вы не должны (и в моем дизайне не можете) сделать new JpaPerson() в client или server.Вместо этого у вас будет интерфейс (также внутри api) с именем PersonFactory (звучит ужасно, когда вы говорите о людях, возможно, назовите его более удобным для человека), который имеет такие методы:

public interface PersonFactory{

    Person findPersonBySsn(String socialSecurityNumber);
    List<Person> findPersonsByName(String firstName, String lastName);
    List<Person> findPersonByBirthDate(Date birthDate);
    Person createPerson(
        String firstName, String lastName,
        Date birthDate, String socialSecurityNumber
    );

}

Опять же, реализуйте этот интерфейс в модуле impl, но упоминайте его как интерфейс только в других модулях.Затем используйте внедрение зависимостей , чтобы соединить все вместе (Spring, SEAM, EJB3 и т. Д.).

Ситуация, о которой вы упоминаете, является результатом того, что код выполняет то, что находится вне его ответственности (читайте о разделение интересов ).

Большим преимуществом этой конструкции является то, что вы можете выполнить рефакторинг всех модулей (кроме api) по отдельности, без изменения кода в других модулях.Поэтому, если вы хотите перейти с jpa на классический hibernate, вам просто нужно отредактировать impl.Если вы хотите переключить сервер с оси на cxf, просто измените server.Это делает вещи намного проще.И, конечно, вы не получаете циклические зависимости.


РЕДАКТИРОВАТЬ:

простое (более простое) решение для вас будет ввести модуль d, который включен в качестве зависимости ва, б и в.Переместить весь общий код в d.(На самом деле переименуйте этот d в a и a, b, c в b, c, d).

2 голосов
/ 28 июля 2010

Такая ситуация, кажется, является признаком плохой организации класса / библиотеки.

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

Если у вас есть полный контроль над композициями A, B и C, вы можете сделать по крайней мере следующие вещи:

  1. Объедините A, B и C в одну библиотеку и покончите с этим. (Не рекомендуется - хорошая модульность сделает практически невозможным)
  2. Вам нужно было использовать класс B в C, чтобы выполнить работу W. Вместо этого выполните эту работу в библиотеке D.
  3. Переместите желаемый класс B 'и' из класса A, от которого зависит класс B, в C.
1 голос
/ 28 июля 2010

Есть пара вещей, которые нужно сделать.

Сначала начиная с артефакта C и вплоть до A, используйте mvn dependency:analyze, чтобы проверить, какие зависимости действительно используются, а не просто объявлены в вашем pom.xml, этот плагин Maven очень полезен в качестве первого шага для отладки дерева зависимостей , Может быть так, что есть некоторые зависимости, которые только что объявлены, но не используются, и / или используются, но не объявлены и т. Д.

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

Я не знаю, насколько глубока ваша проблема, так как вы не опубликовали ни одной конфигурации и / или отсканированного кода, но вы можете попробовать в C pom.xml что-то вроде:

    <dependency>
        <groupId>org.sample</groupId>
        <artifactId>module-b</artifactId>
            <exclusions>
              <exclusion>
                <groupId>org.sample</groupId>
                <artifactId>module-c</artifactId>
              </exclusion>
           </exclusions>
    </dependency>

Чтобы исключить зависимость C от B, которая транзитивно наследуется от A.

0 голосов
/ 28 июля 2010

В большинстве случаев, когда мне приходится решать такую ​​проблему, я явно объявляю зависимости в файле POM, а затем добавляю условие EXCLUDES к рассматриваемым зависимостям. Таким образом, я уверен, что получу версии, которые хочу. Это больше работы, но это избавляет вас от 12 копий общего журнала в вашем файле WAR. ;)

...