Подтвердить что ты не робот

Как организовать пакеты (и запретить циклы зависимостей)?

Я выполнял некоторые показатели на моем Java-проекте и, видимо, существует множество циклов зависимости между пакетами. Я действительно не знал, как организовать материал в пакеты, поэтому я просто сделал то, что имело для меня смысл, что, по-видимому, неверно.

Мой проект - нейронная сеть. Нейронные сети имеют нейроны, которые связаны друг с другом с помощью Connections. Они должны зависеть друг от друга. Тем не менее, существуют и другие типы нейронов, поэтому я подумал, что было бы неплохо поставить их на свой пакет "нейронов". Очевидно, что соединение не является нейроном, поэтому оно не должно быть в пакете, но поскольку они относятся друг к другу, теперь у меня есть круговая зависимость.

Это просто пример, но у меня больше таких ситуаций. Как вы справляетесь с такими ситуациями?

Кроме того, я читал, что классы в пакете выше в иерархии пакетов не должны ссылаться на классы в более глубоких пакетах. Это означало бы, что класс NeuralNetwork в пакете "nn" не может ссылаться на Neuron в пакете "nn.neurons". Вы, ребята, следуете этому принципу? И что, если я переведу NeuralNetwork в "nn.networks" или что-то еще? В этом случае это будет относиться к пакету для сиблинга, а не к ребенку. Это лучшая практика?

4b9b3361

Ответ 1

Функция antcontrib VerifyDesign поможет вам сделать то, что вы хотите:

Например, если есть три пакеты в одном исходном дереве

* biz.xsoftware.presentation
* biz.xsoftware.business
* biz.xsoftware.dataaccess

и, естественно, презентация должна зависят от бизнес-пакета и бизнес должен зависеть от доступа к данным. Если вы определяете свой дизайн таким образом и он нарушен, сборка не удастся когда задача verifydesign antназывается. Например, если я создал класс в biz.xsoftware.presentation и этот класс зависел от класса в biz.xsoftware.dataaccess, сборка потерпит неудачу. Это обеспечивает конструкцию фактически следует тому, что документировано ( в некоторой степени, по крайней мере). Это особенно приятно с автоматическими сборками

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

В зависимости от того, как вы хотите что-то делать, вы можете обнаружить, что пакет "utils" имеет смысл.

В конкретном случае, который вы цитируете... Я мог бы сделать что-то вроде этого:

  • пакет nn содержит Nueron и Connection
  • пакет nn.neurons содержит подклассы Nueron

Neuron и Connection - это концепции высокого уровня, используемые в NeuralNetowrk, поэтому их совместное использование имеет смысл. Классы Neuron и Connection могут ссылаться друг на друга, в то время как классу Connection не нужно знать о подклассах Neuron.

Ответ 2

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

Вы должны организовать свои классы, разместив классы, которые вы будете повторно использовать вместе в одном пакете. Итак, если у вас есть, например, AbstractNeuron и AbstractConnection, вы разместите их в одном пакете. Если теперь у вас есть реализации HumanNeuron и HumanConnection, вы разместите их в одном пакете (например, например, *.net.human). Или у вас может быть только один тип соединения, например BaseConnection и множество разных нейронов. Принцип остается неизменным. Вы размещаете BaseConnection вместе с BaseNeuron. HumanNeuron в своем пакете вместе с HumanSignal и т.д. VirtualNeuron вместе с VirtualSignal и т.д. Вы говорите: "Очевидно, что соединение не является нейроном, поэтому оно не должно быть в пакете". Это не так очевидно и не верно.

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

КЛАССЫ В ПАКЕТЕ ВОЗВРАЩАЮТСЯ ВМЕСТЕ. ЕСЛИ ВЫ ВОЗВРАЩАЙТЕ ОДИН ИЗ КЛАССОВ В ПАКЕТЕ, ВЫ ИСПОЛЬЗУЕТЕ ИХ ALL.

Ответ 3

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

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

Код клиента ---- > Интерфейсы < --- Реализация

В этом шаблоне вы скрываете модуль "Реализация" от кода клиента, что означает, что код в модуле "Код клиента" даже не видит код реализации.

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

Ответ 4

О каком размере кода мы говорим? Если у вас всего 10-20 классов, вам, вероятно, не нужно (и не нужно) чрезмерно организовывать код в пакеты только ради него.

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

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

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

Ответ 5

Как вы справляетесь с такими ситуациями?

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