Временная связанность происходит между последовательными вызовами метода, когда они должны оставаться в определенном порядке. Это неизбежно в императивном программировании, но мы можем уменьшить его негативное влияние, только превратив эти статические процедуры в функции.
Взгляните на этот пример.
Вот этот код:
Вот этот код:
class Foo { public List<String> names() { List<String> list = new LinkedList(); Foo.append(list, "Jeff"); Foo.append(list, "Walter"); return list; } private static void append( List<String> list, String item) { list.add(item.toLowerCase()); } }
Что ты об этом думаешь? Полагаю, что понятно, что делает name () - создание списка имен. Чтобы избежать дублирования, существует дополнительная процедура append (), которая преобразует элемент в нижний регистр и добавляет его в список.
Это плохой дизайн.
Это процедурный дизайн, и существует временная связь между строками в именах методов ().
Позвольте мне сначала показать вам лучший (хотя и не лучший!) Дизайн, а затем я попытаюсь объяснить его преимущества:
Это плохой дизайн.
Это процедурный дизайн, и существует временная связь между строками в именах методов ().
Позвольте мне сначала показать вам лучший (хотя и не лучший!) Дизайн, а затем я попытаюсь объяснить его преимущества:
class Foo { public List<String> names() { return Foo.with( Foo.with( new LinkedList(), "Jeff" ), "Walter" ); } private static List<String> with( List<String> list, String item) { list.add(item.toLowerCase()); return list; } }
Идеальная конструкция для метода with () создаст новый экземпляр List, заполнит его через addAll (список), затем добавит (item) к нему и, наконец, вернется. Это было бы непреложно, но медленно.
Итак, что случилось с этим:
Итак, что случилось с этим:
List<String> list = new LinkedList(); Foo.append(list, "Jeff"); Foo.append(list, "Walter"); return list;
Он выглядит совершенно чистым, не так ли? Создайте экземпляр списка, добавьте к нему два элемента и верните его. Да, сейчас чисто. Потому что мы помним, что делает append (). Через несколько месяцев мы вернемся к этому коду, и он будет выглядеть следующим образом:
List<String> list = new LinkedList(); // 10 more lines here Foo.append(list, "Jeff"); Foo.append(list, "Walter"); // 10 more lines here return list;
Теперь понятно, что append () добавляет в список «Jeff»? Что произойдет, если я удалю эту строку? Это повлияет на результат, возвращаемый в последней строке? Я не знаю. Мне нужно проверить тело метода append (), чтобы убедиться в этом.
Кроме того, как насчет возвращения списка первым и вызова append ()? Вот что может сделать «рефакторинг» для нашего кода:
Кроме того, как насчет возвращения списка первым и вызова append ()? Вот что может сделать «рефакторинг» для нашего кода:
List<String> list = new LinkedList(); if (/* something */) { return list; } // 10 more lines here Foo.append(list, "Walter"); Foo.append(list, "Jeff"); // 10 more lines here return list;
Прежде всего, мы возвращаем список слишком рано, когда он не готов. Но кто-нибудь сказал мне, что эти два вызова append () должны произойти до возврата списка? Во-вторых, мы изменили порядок вызовов append (). Опять кто-то сказал мне, что важно называть их в этом конкретном порядке?
Никто. Нигде. Это называется временной связью.
Наши линии связаны между собой. Они должны оставаться в этом определенном порядке, но знания о нем скрыты. Легко уничтожить заказ, и наш компилятор не сможет нас поймать.
Напротив, в этом проекте нет никакого «порядка»:
Никто. Нигде. Это называется временной связью.
Наши линии связаны между собой. Они должны оставаться в этом определенном порядке, но знания о нем скрыты. Легко уничтожить заказ, и наш компилятор не сможет нас поймать.
Напротив, в этом проекте нет никакого «порядка»:
return Foo.with( Foo.with( new LinkedList(), "Jeff" ), "Walter" );
Он просто возвращает список, который строится с помощью нескольких вызовов метода with (). Это одна строка вместо четырех.
Как обсуждалось ранее, идеальный метод в ООП должен иметь только один оператор, и этот оператор возвращается.
То же самое относится и к валидации. Например, этот код плохой:
Как обсуждалось ранее, идеальный метод в ООП должен иметь только один оператор, и этот оператор возвращается.
То же самое относится и к валидации. Например, этот код плохой:
list.add("Jeff"); Foo.checkIfListStillHasSpace(list); list.add("Walter");
Хотя это намного лучше:
list.add("Jeff"); Foo.withEnoughSpace(list).add("Walter");
видите разницу?
И, конечно, идеальным подходом было бы использование композитных декораторов вместо этих уродливых статических методов. Но если по какой-то причине это невозможно, просто не делайте эти статические методы похожими на процедуры. Убедитесь, что они всегда возвращают результаты, которые становятся аргументами для дальнейших вызовов.
И, конечно, идеальным подходом было бы использование композитных декораторов вместо этих уродливых статических методов. Но если по какой-то причине это невозможно, просто не делайте эти статические методы похожими на процедуры. Убедитесь, что они всегда возвращают результаты, которые становятся аргументами для дальнейших вызовов.
Комментариев нет:
Отправить комментарий