В «Докторе Кто» персонаж Камелион был роботом, который мог принимать любую форму. Физическая опора, которую они использовали, якобы была очень хлопотной и понималась только ее создателем, который не был рядом, чтобы помочь исправить это.
Так что к функции Chamelion …
Рассмотрим этот код:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
public List<Document> getAllDocuments(Request request, int userId, String field) { Query q = createQueryFrom(request); switch (field) { case "title" : q.addCriteria(Criteria.where( "title" ).is(request.getTitle()); break ; case "name" : q.addCriteria(Criteria.where( "name" ).is(request.getName()); break ; default : throw new IllegalArgumentException( "Bad field: " + field); } return q; } |
Там справедливо происходит немного выше. Давайте просто поймем это. Приходит какой-то запрос, и мы можем сделать из него базовый запрос. Затем на основе поля, предоставленного вызывающей стороной, мы добавляем критерий к запросу, используя это поле и вытягивая операнд из запроса.
Кроме того, мы должны выдать ошибку, если вызывающая сторона предоставляет поле, которое мы не знаем, как запросить.
Что не так с этой функцией?
Я скажу тебе, что не так …
Это не функция. Это две функции. Смотрите также оба вида музыки .
Код вызова может выглядеть так:
1
2
3
4
5
|
// one call site getAllDocuments(request, id, "title" ); // another getAllDocumetns(request, id, "name" ); |
Мы используем выбор строки, чтобы контролировать половину потока одной функции.
Хуже того … нам нужно исключение, чтобы бросить, когда какой-то вызывающий изобрел строку, о которой мы никогда не слышали
Давайте просто сделаем рефакторинг на секунду:
01
02
03
04
05
06
07
08
09
10
11
|
public List<Document> getAllDocumentsByTitle(Request request, int userId) { Query q = createQueryFrom(request); q.addCriteria(Criteria.where( "title" ).is(request.getTitle()); return q; } public List<Document> getAllDocumentsByName(Request request, int userId) { Query q = createQueryFrom(request); q.addCriteria(Criteria.where( "name" ).is(request.getName()); return q; } |
Разделив это на две функции, он самодокументируется, его легче отслеживать и ему не нужно обрабатывать мошеннические строки. Это, вероятно, немного быстрее, но это не очень важный драйвер.
Но как насчет дублирования?
Я подозреваю, что один драйвер для функций хамелеона — ошибочная попытка уменьшить дублирование кода. Обратите внимание, что в приведенном выше примере есть примеры повторного использования кода в двух функциях — createQueryFrom, но в каждой есть независимая логика. Это не дублированный код.
Пример, из которого я извлек это, мог изначально иметь более одной строки кода, где мы теперь видим createQueryFrom, из-за чего, возможно, возникло чувство страха перед дублированием, которое, в свою очередь, создало монстра. Рефакторинг неустанно, чтобы уменьшить правильное дублирование, и такого рода вещи не произойдут.
Смотрите оригинальную статью здесь: функция хамелеона Мнения, высказанные участниками Java Code Geeks, являются их собственными. |