Перекрёстные ссылки между классами
От: igor-booch Россия  
Дата: 23.07.11 09:47
Оценка:
Слышал, что перекрёстные ссылки между классами это признак плохого кода. Почему?
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания
http://rsdn.ru/Info/rules.xml
Re: Перекрёстные ссылки между классами
От: Spiceman  
Дата: 23.07.11 09:59
Оценка:
Здравствуйте, igor-booch, Вы писали:

IB>Слышал, что перекрёстные ссылки между классами это признак плохого кода.


Кто тебе это сказал?
Re: Перекрёстные ссылки между классами
От: AlexNek  
Дата: 23.07.11 10:03
Оценка: 2 (2)
Здравствуйте, igor-booch, Вы писали:

IB>Слышал, что перекрёстные ссылки между классами это признак плохого кода. Почему?

Хм, вроде вопрос по типу, отчего не следует подносить руки близко к огню.
Вообще то "хорошие" объекты должны быть достаточно изолированы и бывают варианты, когда объекты должны знать друг о друге.

Но, имея два объекта с бепорядочными сслыками друг на друга можно считать это одним обектом, а если это не два а больше, то код превращается в там называемое спагетти, которое работает чисто по волшебству.
Одним изолированным объектом всегда проще управлять и его контролировать.
Cообщение написано в ... << RSDN@Home 1.2.0 alpha 5-AN-R5 rev. 7279>>
Re[2]: Перекрёстные ссылки между классами
От: igor-booch Россия  
Дата: 23.07.11 10:03
Оценка:
мой руководитель
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания
http://rsdn.ru/Info/rules.xml
Re: Перекрёстные ссылки между классами
От: Sinix  
Дата: 23.07.11 10:10
Оценка: +1
Здравствуйте, igor-booch, Вы писали:

IB>Слышал, что перекрёстные ссылки между классами это признак плохого кода. Почему?


It depends, как всегда. Если объекты логически связаны друг с другом и обе ссылки контролирует только один из классов — никаких особых проблем я не вижу. В обратном случае — да, могут вылезти неочевидные косяки из-за зависимости между двумя в теории несвязанными объектами.
Re[3]: Перекрёстные ссылки между классами
От: skeptic  
Дата: 23.07.11 10:11
Оценка: 2 (1)
Здравствуйте, igor-booch, Вы писали:

IB>мой руководитель


И правильно делает ваш руководитель — связи между сущностями надо резать нещадно бритвой Оккама и выносить их в отдельную сущность.
Начинать отсюда
Re: Перекрёстные ссылки между классами
От: Rustavelli  
Дата: 23.07.11 11:57
Оценка:
Здравствуйте, igor-booch, Вы писали:

IB>Слышал, что перекрёстные ссылки между классами это признак плохого кода. Почему?


Это может быть как плохо, так и нормально...как обычно.
Но в этом случае получается сильная связанность классов. Одну из связей (или обе) можно попробовать заменить на интерфейс.
Re[2]: Перекрёстные ссылки между классами
От: Sinix  
Дата: 23.07.11 12:45
Оценка: 1 (1)
Здравствуйте, Rustavelli, Вы писали:

R>Но в этом случае получается сильная связанность классов. Одну из связей (или обе) можно попробовать заменить на интерфейс.


Я бы не назвал такой подход правильным. Интерфейсы в первую очередь служат для описания ролей ("ведёт себя как", эдакий типизированный duck-typing). Классы — для описания сущностей ("является чем-то"). Когда мы прячем информацию о сильной связанности в интерфейс, мы намекаем, что сильная связность нужна только для некоторых сценариев использования. Здесь налицо нарушение SRP и в таких случаях лучше вообще отказаться от двусторонней зависимости.
Re[4]: Перекрёстные ссылки между классами
От: Carc Россия AmlPages.com — http://www.amlpages.com/home.php
Дата: 23.07.11 13:08
Оценка:
Здравствуйте, skeptic, Вы писали:

S>Здравствуйте, igor-booch, Вы писали:


IB>>мой руководитель


S>И правильно делает ваш руководитель — связи между сущностями надо резать нещадно бритвой Оккама и выносить их в отдельную сущность.

S>Начинать отсюда
Угу, только вспоминаем исходную цитату...

Не следует привлекать новые сущности без самой крайней на то необходимости

Так что 20 раз сначала стоит подумать, настолько ли ощутима связь, и стоит ли ее выносить в отдельную сущность
Хотя иногда, ну ей богу все же стоит
Aml Pages Home
Re: Перекрёстные ссылки между классами
От: igor-booch Россия  
Дата: 23.07.11 13:48
Оценка:
Я думаю дело вот в чем.
Если в любой связи между класса, какой-то класс выполняет роль поставщика услуг, а другой класс потребляет эти услуги,
то это делает классы простыми для понимания, отладки, сопровождения и т. д.
Это как в в удалённом взаимодействии,
клиент знает о сервисе, а сервис не знает о клиенте,
клиент спрашивает, сервис отвечает,
у клиента сначала работает рот, потом уши,
у сервиса сначала уши, потом рот.

Если нужно двунаправленное взаимодействие, то есть три пути:

1) изменить логику, так чтобы убрать перекрёстную ссылку, то есть сделать связь однонаправленной
2) если хочется вообще разорвать связь между классами, создать посредника, который будет знать об обоих классах.
3) поступить так же как поступают, если надо организовать двунаправленную коммуникацию между сервером и клиентской машиной: на сервере делается сервис и клиент и на клиентской машине делается сервис и клиент.
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания
http://rsdn.ru/Info/rules.xml
Re: Перекрёстные ссылки между классами
От: DezzzFabius  
Дата: 27.07.11 12:09
Оценка:
Здравствуйте, igor-booch, Вы писали:

IB>Слышал, что перекрёстные ссылки между классами это признак плохого кода. Почему?


По той же причине, по которой в проектировании БД считается плохим наличие связей «многие ко многим» — такую архитектуру сложнее поддерживать, понимать и развивать. Перекрёстные ссылки между классами как правило свидетельствуют о том, что в класс запихнули более одной сущности. В реальной жизни объекты могут взаимоопределяться, например: сила трения об окружающую среду зависит от скорости падающего объекта, и наоборот — скорость падающего объекта зависит в том числе и от силы трения. Однако классы не обязательно должны реализовывать абстракцию отдельной «вещи», класс может описывать асбтрактное свойство или вообще только поведение. Чтобы не быть голословным, приведу пример:


Есть главный класс CMachine, делающий нечто сложное и есть класс CDetail, являющийся некоторой герметичной, но неотъемлимой частью класса CMachine:

class CDetail {...};

class CMachine
{
...
CDetail m_Detail;
}



По ходу реализации мы добавляем некоторый перечисляемый тип EState, как неотъемлимую часть CMachine (допустим CMachine — конечный автомат). Ну и следующая очень вероятная потребность — состояние EState потребуется для какого-нибудь метода CDetail. И если мы определим EState внутри CMachine, то теперь в заголовочный файл класса CDetail нужно будет подключать заголовочный файл класса CMachine.

Можно пойти другим путём — выделить состояние машины в отдельный файл. Правда теперь EState повисает в открытом космосе, что за «состояние», чъё «состояние»? Тут два подхода, либо отражать в названии (CCombustionEngine, CCombustionEngineDetail, ECombustionEngineState), либо (мой вариант) для всего конгломерата классов и типов определить namespace, и одноимённый ему filter в проекте. Внутри этого контекста понятно чъё состояние, извне оно будет выглядеть так: CombustionEngine::EState.

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

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


Можно решать проблему двусторонней связи в другом направлении, сделать класс CDetail локальным, но это приемлимо только при простоте обеих классов.
Re[3]: Перекрёстные ссылки между классами
От: Философ Ад http://vk.com/id10256428
Дата: 27.07.11 17:04
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Интерфейсы .... эдакий типизированный duck-typing


Резазануло по ушам мозгам.

Наследование "говорит" о том, что объекты класса являются:
class Дерево {}
class Яблоня :Дерево {}
т.е. яблоня является деревом, кстати, это основной принцип постоения иерархии.

а вот duck-typing исповедует совершенно другую идеалогию: при некоторых условиях персона может быть уткой.
[go]
class Duck:
def quack(self):
print("Quaaaaaack!")
def feathers(self):
print("The duck has white and gray feathers.")

class Person:
def quack(self):
print("The person imitates a duck.")
def feathers(self):
print("The person takes a feather from the ground and shows it.")
def name(self):
print("John Smith")

def in_the_forest(duck):
duck.quack()
duck.feathers()

def game():
donald = Duck()
john = Person()
in_the_forest(donald)
in_the_forest(john)

game()
[/go]

Пример взят вот отсюда: http://en.wikipedia.org/wiki/Duck_typing#Concept_examples
Всё сказанное выше — личное мнение, если не указано обратное.
Re: Перекрёстные ссылки между классами
От: Философ Ад http://vk.com/id10256428
Дата: 27.07.11 17:11
Оценка:
Здравствуйте, igor-booch, Вы писали:

IB>Слышал, что перекрёстные ссылки между классами это признак плохого кода. Почему?


Потому, что это определяет жёсткую связь между классами.
Например, усложняет замену одного класса на другой, это осложняет раздельное тестирование классов.
Если есть такая необходимость, то лучше всего выносить нужные методы в интефейсы.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[4]: Перекрёстные ссылки между классами
От: Sinix  
Дата: 28.07.11 11:03
Оценка:
Здравствуйте, Философ, Вы писали:

S>>Интерфейсы .... эдакий типизированный duck-typing


Ф>а вот duck-typing исповедует совершенно другую идеалогию: при некоторых условиях персона может быть уткой.

Ну да. Всё, что делают интерфейсы — добавляют возможность проверки на соблюдение контракта во время компиляции. Если заменю выделенное выше на "статитчески-проверяемый", будете ещё придираться?
Re[3]: Перекрёстные ссылки между классами
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 03.08.11 23:38
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Я бы не назвал такой подход правильным. Интерфейсы в первую очередь служат для описания ролей


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

S> ("ведёт себя как", эдакий типизированный duck-typing).


duck typing никак с типизированностью не конфликтует. К примеру, при наложении делегата на метод в дотнете имеем вполне себе классический, и при этом строго типизированный duck typing.

S>Классы — для описания сущностей ("является чем-то").


Ну да. Только стоит учесть, что сущностью в модели мы можем сделать что угодно, в том числе и роль.

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


Сдается мне, он просто так специфично описал IoC.
... << RSDN@Home 1.2.0 alpha 5 rev. 1530 on Windows 7 6.1.7601.65536>>
AVK Blog
Re[4]: Перекрёстные ссылки между классами
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 03.08.11 23:38
Оценка:
Здравствуйте, Философ, Вы писали:

Ф>Наследование "говорит" о том, что объекты класса являются:

Ф>class Дерево {}
Ф>class Яблоня :Дерево {}
Ф>т.е. яблоня является деревом, кстати, это основной принцип постоения иерархии.

Ф>а вот duck-typing исповедует совершенно другую идеалогию: при некоторых условиях персона может быть уткой.


Да ту же самую идеологию оно исповедует, разница только в способе конструирования иерархии — со стороны самих сущностей иерархии vs с внешней стороны. Разница примерно такая же, как между виртуальными методами и паттерном визитор.
... << RSDN@Home 1.2.0 alpha 5 rev. 1530 on Windows 7 6.1.7601.65536>>
AVK Blog
Re[5]: Перекрёстные ссылки между классами
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 03.08.11 23:38
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Ну да. Всё, что делают интерфейсы — добавляют возможность проверки на соблюдение контракта во время компиляции.


Интерфейсы дотнета/джавы это классическое наследование, никаким боком оно на утятину не тянет.
... << RSDN@Home 1.2.0 alpha 5 rev. 1530 on Windows 7 6.1.7601.65536>>
AVK Blog
Re[4]: Перекрёстные ссылки между классами
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 04.08.11 14:52
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>duck typing никак с типизированностью не конфликтует. К примеру, при наложении делегата на метод в дотнете имеем вполне себе классический, и при этом строго типизированный duck typing.


А что значит "наложение делегата на метод" ?
Re[5]: Перекрёстные ссылки между классами
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 04.08.11 17:12
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>А что значит "наложение делегата на метод" ?


Создание экземпляра делегата над конкретным методом. В отличие от джавы с ее listeners, в дотнете не нужно при этом точное совпадение типа, достаточно совпадения сигнатуры, да еще и с ко/контрвариантностью.
... << RSDN@Home 1.2.0 alpha 5 rev. 1530 on Windows 7 6.1.7601.65536>>
AVK Blog
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.