Что такое "свободная связь"? Приведите примеры

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

Будет ли кто-нибудь показывать код "до" и "после" (или псевдокод), который иллюстрирует это понятие?

Ответ 1

Рассмотрим простую корзину, которая использует класс CartContents для отслеживания элементов в корзине покупок и класса Order для обработки покупки. Приказ должен определить общую стоимость содержимого в корзине, он может сделать это так:

Плотно связанный пример:

public class CartEntry
{
    public float Price;
    public int Quantity;
}

public class CartContents
{
    public CartEntry[] items;
}

public class Order
{
    private CartContents cart;
    private float salesTax;

    public Order(CartContents cart, float salesTax)
    {
        this.cart = cart;
        this.salesTax = salesTax;
    }

    public float OrderTotal()
    {
        float cartTotal = 0;
        for (int i = 0; i < cart.items.Length; i++)
        {
            cartTotal += cart.items[i].Price * cart.items[i].Quantity;
        }
        cartTotal += cartTotal*salesTax;
        return cartTotal;
    }
}

Обратите внимание, что метод OrderTotal (и, следовательно, класс Order) зависит от деталей реализации классов CartContents и CartEntry. Если бы мы попытались изменить эту логику, чтобы позволить скидки, нам, вероятно, придется изменить все 3 класса. Кроме того, если мы перейдем к использованию коллекции List, чтобы отслеживать элементы, которые мы должны были бы изменить и в классе Order.

Теперь немного лучше сделать то же самое:

Меньше сопряженный Пример:

public class CartEntry
{
    public float Price;
    public int Quantity;

    public float GetLineItemTotal()
    {
        return Price * Quantity;
    }
}

public class CartContents
{
    public CartEntry[] items;

    public float GetCartItemsTotal()
    {
        float cartTotal = 0;
        foreach (CartEntry item in items)
        {
            cartTotal += item.GetLineItemTotal();
        }
        return cartTotal;
    }
}

public class Order
{
    private CartContents cart;
    private float salesTax;

    public Order(CartContents cart, float salesTax)
    {
        this.cart = cart;
        this.salesTax = salesTax;
    }

    public float OrderTotal()
    {
        return cart.GetCartItemsTotal() * (1.0f + salesTax);
    }
}

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

Ответ 2

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

То же самое, 1:1, идет на разработку программного обеспечения.

Ответ 3

Я буду использовать Java в качестве примера. Скажем, у нас есть класс, который выглядит так:

public class ABC
{
   public void doDiskAccess() {...}
}

Когда я вызываю класс, мне нужно сделать что-то вроде этого:

ABC abc = new ABC();

abc. doDiskAccess();

До сих пор так хорошо. Теперь позвольте сказать, что у меня есть другой класс, который выглядит так:

public class XYZ
{
   public void doNetworkAccess() {...}
}

Он выглядит точно так же, как ABC, но пусть он работает по сети, а не на диске. Итак, теперь напишите такую ​​программу:

if(config.isNetwork()) new XYZ().doNetworkAccess();
else new ABC().doDiskAccess();

Это работает, но это немного громоздко. Я мог бы упростить это с помощью такого интерфейса:

public interface Runnable
{
    public void run();
}

public class ABC implements Runnable
{
   public void run() {...}
}

public class XYZ implements Runnable
{
   public void run() {...}
}

Теперь мой код может выглядеть так:

Runnable obj = config.isNetwork() ? new XYZ() : new ABC();

obj.run();

Посмотрите, насколько понятнее и понятнее? Мы только что поняли первый базовый принцип свободной связи: абстракция. Ключ отсюда состоит в том, чтобы гарантировать, что ABC и XYZ не зависят от каких-либо методов или переменных классов, которые их называют. Это позволяет ABC и XYZ быть полностью независимыми API. Или, другими словами, они "развязаны" или "слабо связаны" с родительскими классами.

Но что, если нам нужна связь между ними? Ну, тогда мы можем использовать дополнительные абстракции, такие как Event Model, чтобы гарантировать, что родительский код никогда не должен соединяться с созданными вами API.

Ответ 4

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

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

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

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

Реализация этого оставлена ​​как упражнение для читателя:).

Ответ 5

Плотно связанный код зависит от конкретной реализации. Если мне нужен список строк в моем коде, и я объявляю его так (на Java)

ArrayList<String> myList = new ArrayList<String>();

то я зависим от реализации ArrayList.

Если я хочу изменить это на слабосвязанный код, я делаю ссылку ссылкой (или другим абстрактным).

List<String> myList = new ArrayList<String>();

Это не позволяет мне вызвать какой-либо метод на myList, специфичный для реализации ArrayList. Я ограничен только теми методами, которые определены в интерфейсе List. Если позже я решит, что мне действительно нужен LinkedList, мне нужно только изменить код в одном месте, где я создал новый List, а не в 100 местах, где я делал вызовы методов ArrayList.

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

Ответ 6

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

Ответ 7

Степень разницы между ответами здесь показывает, почему было бы сложно понять это, но просто так, как я могу описать это:

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

С нединамическими языками, такими как С# или Java и т.д., мы реализуем это через интерфейсы. Итак, скажем, у нас есть следующий интерфейс:

public ICatcher
{
   public void Catch();
}

А теперь скажем, что у нас есть следующие классы:

public CatcherA : ICatcher
{
   public void Catch()
   {
      console.writeline("You Caught it");
   }

}
public CatcherB : ICatcher
{
   public void Catch()
   {
      console.writeline("Your brother Caught it");
   }

}

Теперь как CatcherA, так и CatcherB реализуют метод Catch, поэтому служба, которая требует Catcher, может использовать любой из них, и на самом деле не наплевать, какой она есть. Таким образом, тесно связанная служба может напрямую инициировать захват.

public CatchService
{
   private CatcherA catcher = new CatcherA();

   public void CatchService()
   {
      catcher.Catch();
   }

}

Итак, CatchService может выполнить именно то, что он намеревался сделать, но использует CatcherA и всегда будет пользователем CatcherA. Его жестко закодированы, поэтому он остается там, пока кто-то не придет и не реорганизует его.

Теперь давайте возьмем еще один вариант, называемый инъекцией зависимостей:

public CatchService
{
   private ICatcher catcher;

   public void CatchService(ICatcher catcher)
   {
      this.catcher = catcher;
      catcher.Catch();
   }
}

Таким образом, calss, который запускает CatchService, может сделать следующее:

CatchService catchService = new CatchService(new CatcherA());

или

CatchService catchService = new CatchService(new CatcherB());

Это означает, что служба Catch не тесно связана ни с CatcherA, ни с CatcherB.

Существует несколько других стратегий для таких слабых сервисов связи, как использование инфраструктуры IoC и т.д.

Ответ 8

Определение

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

Высокое сцепление

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

Свободная связь

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

Ответ 9

Это довольно общая концепция, поэтому примеры кода не будут давать всю картину.

Один парень здесь, на работе, сказал мне: "Узоры похожи на фракталы, вы можете видеть их, когда приближаетесь очень близко, и когда вы приближаетесь к уровню архитектуры".

Чтение краткой страницы википедии может дать вам ощущение этой общности:

http://en.wikipedia.org/wiki/Loose_coupling

Что касается конкретного примера кода...

Здесь одна свободная связь, с которой я недавно работал, из материала Microsoft.Practices.CompositeUI.

    [ServiceDependency]
    public ICustomizableGridService CustomizableGridService
    {
        protected get { return _customizableGridService; }
        set { _customizableGridService = value; }
    }

Этот код объявляет, что этот класс имеет зависимость от CustomizableGridService. Вместо того, чтобы просто ссылаться на точную реализацию службы, она просто заявляет, что для этого требуется НЕПОЛНАЯ реализация этой службы. Затем во время выполнения система разрешает эту зависимость.

Если это неясно, вы можете прочитать более подробное объяснение здесь:

http://en.wikipedia.org/wiki/Dependency_injection

Представьте, что ABCCustomizableGridService - это imlpementation, которую я собираюсь подключить здесь.

Если я захочу, я смогу выдернуть это и заменить его на XYZCustomizableGridService или StubCustomizableGridService без каких-либо изменений для класса с этой зависимостью.

Если бы я напрямую ссылался на ABCCustomizableGridService, тогда мне нужно было бы внести изменения в эту/эти ссылки /s, чтобы поменять местами другую реализацию службы.

Ответ 10

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

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

Некоторые примеры:

  • Приложение зависит от библиотеки. В условиях жесткой связи приложение разбивается на более новые версии lib. Google для "DLL Hell".

  • Клиентское приложение считывает данные с сервера. При жесткой связи изменения на сервере требуют исправлений на стороне клиента.

  • В объектно-ориентированной иерархии взаимодействуют два класса. В условиях жесткой связи изменения одного класса требуют обновления другого класса для соответствия.

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

Ответ 11

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

Ответ 12

Рассмотрим приложение Windows с формами FormA и FormB. FormA является основной формой и отображает FormB. Представьте, что FormB должен передать данные обратно своему родителю.

Если вы сделали это:

class FormA 
{
    FormB fb = new FormB( this );

    ...
    fb.Show();
}

class FormB 
{
    FormA parent;

    public FormB( FormA parent )
    {
        this.parent = parent;
    }     
}

Форма B плотно связана с FormA. FormB не может иметь другого родителя, кроме типа FormA.

Если, с другой стороны, у вас было FormB опубликовать событие и подписаться FormA на это событие, тогда FormB может передавать данные обратно через это событие любому абоненту, имеющему это событие. В этом случае FormB даже не знает, что он говорит о своем родителе; через свободную связь событие позволяет ему просто разговаривать с подписчиками. Любой тип теперь может быть родителем для FormA.

rp

Ответ 13

Два компонента связаны друг с другом, когда они зависят от конкретной реализации друг друга.

Предположим, что у меня этот код где-то в методе в моем классе:

this.some_object = new SomeObject();

Теперь мой класс зависит от SomeObject, и они сильно связаны. С другой стороны, скажем, у меня есть метод InjectSomeObject:

void InjectSomeObject(ISomeObject so) { // note we require an interface, not concrete implementation
  this.some_object = so;
}

Тогда первый пример может просто использовать вложенный SomeObject. Это полезно при тестировании. При нормальной работе вы можете использовать тяжелые классы, использующие базы данных, сетевые классы и т.д., а для тестов - легкую, макетную реализацию. С жестко связанным кодом вы не можете этого сделать.

Вы можете сделать некоторые части этой работы проще, используя контейнеры для инъекций зависимостей. Вы можете больше узнать о DI в Википедии: http://en.wikipedia.org/wiki/Dependency_injection.

Иногда это слишком сложно сделать. В какой-то момент вам нужно сделать что-то конкретным, или ваша программа будет менее читаемой и понятной. Поэтому используйте эту технику в основном на границе компонентов и знайте, что вы делаете. Убедитесь, что вы используете свободную муфту. Если нет, вы, вероятно, не нуждаетесь в этом в этом месте. DI может сделать вашу программу более сложной. Убедитесь, что вы сделали хороший компромисс. Другими словами, поддерживайте хороший баланс. Как всегда при проектировании систем. Удачи!

Ответ 14

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

Термин "Loose Coupling" впервые вошел в вычисления как термин, используемый в качестве прилагательного в отношении архитектуры ЦП в конфигурации с несколькими процессорами. Его аналоговый термин - "плотная связь". Loose Coupling - это когда CPU не имеют общего количества ресурсов и Tight Coupling, когда они делают.

Термин "система" может вводить в заблуждение, поэтому, пожалуйста, тщательно проанализируйте ситуацию.

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

Условия Tightly Coupled и Loosely Coupled были введены до того, как были изобретены многопоточные и многоядерные процессоры, поэтому этим терминам могут понадобиться некоторые спутники, чтобы полностью озвучить ситуацию сегодня. И, действительно, сегодня у вас вполне может быть система, которая объединяет оба типа в одной общей системе. Что касается существующих программных систем, то есть две общие архитектуры, одна из каждой разновидности, которые достаточно распространены, они должны быть familiar.

Во-первых, поскольку речь шла о некоторых примерах систем Loosely Coupled:

  • VaxClusters
  • Кластеры Linux

Напротив, некоторые примеры Tightly Coupled:

  • Semetrical-Multi-Processing (SMP) Операционные системы - например. Fedora 9
  • Многопоточные процессоры
  • Многоядерные процессоры

В современных вычислениях примеры работы в одной общей системе нередки. Например, возьмите современные Pentium с двумя или четырёхъядерными процессорами под управлением Fedora 9 - это плотно связанные вычислительные системы. Затем объедините несколько из них в слабо связанном кластере Linux, и теперь у вас есть как свободно, так и тесно связанные вычисления! О, это не современное оборудование замечательно!

Ответ 15

Несколько длинных ответов здесь. Однако принцип очень прост. Я представляю вступительное выражение из wikipedia:

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

Каждый конец транзакции делает свои требования явными и делает несколько предположений о другом конце. "

Ответ 16

Я предлагаю очень простой тест кодовой связи:

  • Часть A кода тесно связана с Piece B кода, если существует какая-либо возможная модификация Piece B, которая будет приводить к изменениям в части A, чтобы сохранить правильность.

  • Часть A кода не плотно связана с Piece B кода, если нет возможной модификации Piece B, которая сделала бы изменение на Piece A необходимым.

Это поможет вам проверить, сколько связей между частями вашего кода. для размышлений об этом см. это сообщение в блоге: http://marekdec.wordpress.com/2012/11/14/loose-coupling-tight-coupling-decoupling-what-is-that-all-about/

Ответ 17

Связывание относится к тому, как тесно разные классы связаны друг с другом. Тесно связанные классы содержат большое количество взаимодействий и зависимостей.

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

Legos, игрушки, которые SNAP вместе, будут считаться слабо связанными, потому что вы можете просто соединить кусочки вместе и построить любую систему, в которой хотите. Тем не менее, головоломка имеет кусочки, которые тесно связаны. Вы не можете взять кусок из одной головоломки (системы) и привязать его к другой головоломке, потому что система (головоломка) очень зависит от конкретных частей, которые были созданы специально для этого конкретного "дизайна". Legos построены более общим образом, чтобы их можно было использовать в вашем Lego House или в моем Lego Alien Man.

Ссылка: https://megocode3.wordpress.com/2008/02/14/coupling-and-cohesion/

Ответ 18

Вы можете узнать больше об общей концепции "свободная связь" .

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

Ответ 19

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

--- A.java ---

package interface_package.loose_coupling;

public class A {

void display(InterfaceClass obji)
{
    obji.display();
    System.out.println(obji.getVar());
}
}

--- B.java ---

package interface_package.loose_coupling;

public class B implements InterfaceClass{

private String var="variable Interface";

public String getVar() {
    return var;
}

public void setVar(String var) {
    this.var = var;
}

@Override
public void display() {
    // TODO Auto-generated method stub
    System.out.println("Display Method Called");
}
}

--- InterfaceClass ---

package interface_package.loose_coupling;

public interface InterfaceClass {

void display();
String getVar();
}

--- MainClass ---

package interface_package.loose_coupling;

public class MainClass {

public static void main(String[] args) {
    // TODO Auto-generated method stub

    A obja=new A();
    B objb=new B();
    obja.display(objb);     //Calling display of A class with object of B class 

}
}

Пояснение:

В приведенном выше примере мы имеем два класса A и B

Класс B реализует интерфейс, то есть InterfaceClass.

InterfaceClass определяет класс Contract for B, поскольку InterfaceClass имеет абстрактные методы класса B, к которым может быть доступен любой другой класс, например A.

В классе A мы имеем метод отображения, который может за исключением объекта класса, который реализует интерфейс ClassClass (в нашем случае это класс B). И по этому объекту метод класса A вызывает display() и getVar() класса B

В MainClass мы создали объект класса A и B. И вызов метода отображения A путем передачи объекта класса B i.e. objb. Метод отображения A будет вызываться с объектом класса B.

Теперь поговорим о свободной связи. Предположим, что в будущем вы должны изменить имя класса B на ABC, тогда вам не нужно менять его имя в методе отображения класса B, просто создайте объект нового (класс ABC) и передайте его методу отображения в MailClass. Вам не нужно ничего менять в классе A

ref: http://p3lang.com/2013/06/loose-coupling-example-using-interface/

Ответ 20

Возможно, лучшей метафорой является брак.

Когда вы не состоите в браке, вы слабо связаны.

Вы можете легко оставить своего партнера.

Когда вы "женаты", вы тесно связаны.

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

Ответ 21

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

Надеюсь, что это несколько полезно.