Может ли функция быть слишком короткой?

125

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

function conditionMet(){
   return x == condition;
}

ИЛИ ЖЕ

function runCallback(callback){
   if($.isFunction(callback))
     callback();
}

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

Марк Браун
источник
3
Нет, не слишком коротко. В C # я бы сделал 'условие выполнено' как свойство, которое элегантно, и рассмотрел бы использование Assert.AreEqual<int>(expected, actual, message, arg1, arg2, arg3, ...);. Второй хорошо как есть. Я бы потенциально включил необязательный флаг bool, который будет указывать, следует ли генерировать исключение / etc. в случае, если обратный вызов не является функцией.
Работа
38
Да, только в одном случае: function myFunction () {}
Spooks
5
def yes(): return 'yes'
dietbuddha
3
@Spooks - здесь я расщепляю волосы, но пустые функции действительны, по крайней мере, для классов адаптера, например MouseMotionAdapter в download.oracle.com/javase/6/docs/api/java/awt/event/… . Конечно, это только способ обойти языковые ограничения.
Алекси Ирттиахо
3
@dietbuddha: требования только что изменились - теперь он должен поддерживать два языка для демонстрации на следующей неделе. Парень, который написал «def yes ()», очень обрадовался, прежде чем сменить его на «def yes (: (IsFrench ()? 'Oui': 'Yes')"
Эндрю Шепард,

Ответы:

167

Хе-хе, о мистер Браун, если бы я только мог убедить всех разработчиков, с которыми я встречался, держать их функции такими маленькими, поверьте мне, мир программного обеспечения был бы лучше!

1) Читаемость вашего кода увеличивается в десять раз.

2) Так легко понять процесс вашего кода из-за читабельности.

3) СУХОЙ - Не повторяйся - Ты очень хорошо согласуешься с этим!

4) Тестируемый. Крошечные функции в миллион раз легче тестировать, чем те 200-строчные методы, которые мы видим слишком часто.

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

Это ленивый? - Совсем наоборот!

Это плохая практика? - Точно нет. Лучше использовать этот способ создания методов, чем смоляные шарики или «Объекты Бога», которые слишком распространены.

Продолжайте в том же духе, мой товарищ по ремеслу;)

Мартин Блор
источник
40
Вы не отвечаете на вопрос, вы просто проповедуете правило, более экстремальные приложения которого ставятся здесь под сомнение.
4
Это не очень часто, что я нахожу ограничение только 1 upvote расстраивающим. Но, для этого ответа +1, похоже, не делает это справедливо.
Беван
4
+5 ... ну можно только +1, ну ладно! И чтобы поддержать MeshMan, я предлагаю следующую книгу Роберта С. Мартина « Чистый код» . Эта книга действительно меняет то, как я сейчас программирую.
Эрик-Карл
10
Очень приятный ответ, но я не согласен с большинством из них: 1) Чрезвычайно маленькие функции приводят к большему количеству кода в целом из-за всей сложности, необходимой для каждой функции. Это может снизить читабельность, особенно для действительно большого проекта. Также зависит от языка. 2) полностью зависит от пункта 1 и, следовательно, не имеет ничего общего с вопросом. 3) что? runCallback повторяет «обратный вызов» четыре раза и три раза ссылается на одну и ту же переменную для запуска одной функции. 4) Методы 200+ строк, конечно, не поддаются тестированию, но от этого до длинной строки еще далеко.
10
10
-1: самое страшное здесь - это количество голосов, поданных за этот ответ.
Лука
64

Я бы сказал, что рефакторированный метод слишком короткий, если либо:

  • Он дублирует примитивную операцию только для того, чтобы сделать его методом:

Пример:

boolean isNotValue() {
   return !isValue();
}

или же...

  • Код используется только один раз, и его намерение легко понять с первого взгляда.

Пример:

void showDialog() {
    Dialog singleUseDialog = new ModalDialog();
    configureDialog(singleUseDialog);
    singleUseDialog.show();
}

void configureDialog(Dialog singleUseDialog) {
    singleUseDialog.setDimensions(400, 300);
}

Это может быть допустимым шаблоном, но я бы просто включил метод configureDialog () в этом примере, если только я не намеревался переопределить его или повторно использовать этот код в другом месте.

RMorrisey
источник
7
Разделение однострочного метода во втором случае может быть полезным для обеспечения согласованности уровня абстракции вызывающих методов. Приведенный пример приведен на заборе, если использовать эти рассуждения: точная ширина и высота пикселя - слишком много деталей для отображения диалога?
Алекси Ирттиахо
2
Метод isNotValue () имеет неправильное имя и должен быть реорганизован, чтобы назвать реальный вопрос домена.
4
@Aleksi: я не согласен; детали уже скрыты в методе showDialog () в этом примере; нет необходимости в двойном рефакторинге. Пример предназначен для демонстрации отдельного варианта использования; если шаблон требуется с разными конфигурациями диалогов в разных случаях, имеет смысл вернуться и выполнить рефакторинг после того, как шаблон будет создан.
RMorrisey
1
@Torbjorn: я мог бы увидеть это, когда вы отвечаете на вопрос бизнес-сферы, чья логика может быть неочевидной. Я просто указываю на то, что в некоторых случаях это излишне.
RMorrisey
3
Может быть, это придирки, но я бы сказал, что в ваших примерах проблема не в том, что функция слишком короткая, а в том, что они не добавляют описательную ценность.
Кеппла
59

Может ли функция быть слишком короткой? В общем нет.

На самом деле единственный способ обеспечить, чтобы:

  1. Вы нашли все классы в вашем дизайне
  2. Ваши функции делают только одно.

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

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

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

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

В Эпизоде ​​III «Чистого кода» об этом есть еще много всего на cleancoders.com

Дядя Боб.
источник
5
Дядя Боб! Рад видеть вас на борту здесь. Как и следовало ожидать, фантастический совет. Я никогда раньше не слышал термин «Извлекай, пока не уронишь», и наверняка использую этот термин в офисе в понедельник;).
Мартин Блор
1
Хотели бы вы уточнить вашу точку № 1? Объясняя, что на примере было бы здорово.
Даниэль Каплан
53

Вау, большинство из этих ответов не очень полезны.

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

Рассмотрим вашу функцию conditionMetи эту другую функцию addOne(простите за мой ржавый JavaScript):

function conditionMet() { return x == condition; }

function addOne(x) { return x + 1; }

conditionMetправильное концептуальное определение; addOneэто тавтология . conditionMetэто хорошо, потому что вы не знаете, что conditionMetвлечет за собой просто говоря «условие выполнено», но вы можете понять, почему addOneэто глупо, если вы прочитаете это на английском:

"For the condition to be met is for x to equal condition" <-- explanatory! meaningful! useful!

"To add one to x is to take x and add one." <-- wtf!

Ради любви ко всему, что еще может быть святым, пожалуйста, не пишите тавтологических функций!

(И по той же причине не пишите комментарии для каждой строки кода !)

Рей Миясака
источник
Некоторые из более сложных языковых конструкций могут быть незнакомыми или трудными для чтения, что делает этот прием полезным.
3
Согласитесь, что именно должно быть превращено в функцию, во многом будет зависеть от языка, на котором она написана. Такая функция, как addOne, будет полезна, если вы работаете на языке, подобном VHDL, где вы на самом деле определяете значение добавления одного на бинарный или числовой уровень теории. Я хотел бы думать, что ни один язык не является настолько загадочным, что его трудно читать даже опытным программистам (возможно, brainf # ck), но если это так, то та же самая идея останется в силе, поскольку эта функция фактически является переводом с английского. на этот язык - так что имя не совпадает с определением.
Рей Миясака
1
Я говорю о функции идентичности вещей из стандартной библиотеки Haskell - я не думаю, что вы можете получить более "тавтологическую", чем эта :)
hugomg
1
@missingno Бах, это обманывает: D
Рей Миясака
5
Если вы называете функции по назначению, а не по содержанию, они сразу перестают быть глупыми. Так что ваши примеры могут быть, например, быть function nametoolong() { return name.size > 15; }или function successorIndex(x) { return x + 1; } Так что проблема с вашими функциями на самом деле просто в том, что их имя неверно.
Ханс-Петер Стёрр
14

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

Так, например, если ваш код будет выглядеть так:

if x == 1 { ... } // is pixel on?

вместо этого сделайте так:

if pixelOn() { ... }

с участием

function pixelOn() { return x == 1; }

Или, другими словами, речь идет не о длине метода, а о самодокументированном коде.

Julio
источник
5
Мой уважаемый коллега отмечает, что вы тоже можете написать if x == PIXEL_ON. Использование константы может быть таким же описательным, как использование метода, и немного короче.
Том Андерсон
7

Я думаю, что это именно то, что вы хотите сделать. Сейчас эта функция может состоять только из одной или двух строк, но со временем она может расти. Также наличие большего количества вызовов функций позволяет читать вызовы функций и понимать, что происходит внутри них. Это делает ваш код очень СУХИМ (не повторяется), что намного удобнее в обслуживании.

оборота в минуту
источник
4
Так что плохого в том, чтобы разобраться с этим позже, когда вы можете доказать, что вам нужно, а не сейчас, когда это просто мертвый вес?
dsimcha
Функции не растут сами по себе. ИМХО примеры паршивые. conditionMetявляется слишком общим именем и не принимает аргументов, поэтому он проверяет некоторое состояние? (x == xCondition) в большинстве языков и ситуаций столь же выразителен, как и «xConditition».
пользователь неизвестен
Да, и именно поэтому вы хотите, чтобы в вашем коде было 75% + накладных расходов? Одиночный лайнер, написанный в 3 строки, на самом деле составляет 300%.
Кодер
5

Я согласен со всеми другими постами, которые я видел. Это хороший стиль.

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

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

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

РЕДАКТИРОВАТЬ: примечание о названиях методов. Используйте имя метода, которое указывает, что метод делает не так, как он это делает. Я считаю, что verb_noun (_modifier) ​​- это хорошая схема именования. Это дает имена вроде Find_Customer_ByName, а не Select_Customer_Using_NameIdx. Второй случай может стать неправильным при изменении метода. В первом случае вы можете заменить всю реализацию базы данных клиентов.

оборота BillThor
источник
+1 за упоминание встраивания, imo основное внимание в производительности и коротких функциях.
Гарет Клаборн
4

Рефакторинг одной строки кода в функцию кажется чрезмерным. Могут быть исключительные случаи, такие как строки veroooooong / comples или выражения, но я бы не стал этого делать, если бы не знал, что функция будет расти в будущем.

и ваш первый пример намекает на использование глобальных переменных (которые могут или не могут говорить о других проблемах в коде), я бы еще больше изменил его рефакторинг и сделал бы эти две переменные параметрами:

function conditionMet(x, condition){
   return x == condition;
}
....
conditionMet(1,(3-2));
conditionMet("abc","abc");

conditionMetПример может быть полезным , если условие было долгим и повторяющимся , такие как:

function conditionMet(x, someObject){
   return x == ((someObject.valA + someObject.valB - 15.4) / /*...whole bunch of other stuff...*/);
}
FrustratedWithFormsDesigner
источник
1
Его первый пример не намекает на глобалы. Во всяком случае, это сплоченный метод в очень сплоченном классе, где большинство переменных находятся на объекте.
Мартин Блор,
7
Эта conditionMetфункция просто многословный ==оператор. Это вероятно не полезно.
1
Я определенно не использую глобалы. @MeshMan, это именно то, откуда пример ... метод в классе.
Марк Браун
1
@Mark Brown: @MeshMan: Хорошо, я думаю, пример кода был слишком расплывчатым, чтобы знать наверняка ...
FrustratedWithFormsDesigner
Я нюхаю conditionMet (x, relation condition) {здесь, где вы передаете х, '==' и отношение. Тогда вам не нужно повторять код для «<», «>», «<=», «! =» И так далее. С другой стороны - в большинстве языков эти конструкции встроены, поскольку операторы (условие x ==) делают именно это. Функции для атомарных операторов - еще один шаг.
пользователь неизвестен
3

Учти это:

Простая функция обнаружения столкновений:

bool collide(OBJ a, OBJ b)
{
    return(pow(a.x - b.x, 2) + pow(a.y - b.y, 2) <= pow(a.radius + b.radius, 2));
}

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

оборота мунту
источник
Если мы имеем дело с C здесь, мы могли бы просто издеваться #define;)
Коул Джонсон
Возможно, вы даже захотите поменять это на более медленную, но не подверженную переполнению гипотезу, если ваши размеры или расстояния станут очень большими. Это, очевидно, намного проще сделать один раз.
Мэтт Краузе
2

Нет, и это редко проблема. Теперь, если кто-то считает, что ни одна функция не должна быть длиннее одной строки кода (если бы это могло быть так просто), это было бы проблемой и в некотором смысле ленивым, потому что он не думал о том, что уместно.

JeffO
источник
Я не посчитал бы это в строках кода, но в выражениях. «(x == условие)» является атомарным, поэтому я бы поместил его только в метод / функцию, если он используется несколько раз, и его можно изменить, как, function isAdult () = { age >= 18; }но не обязательно isAtLeast18.
пользователь неизвестен
2

Я бы сказал, что они слишком короткие, но это мое субъективное мнение.

Потому что:

  • Нет смысла создавать функцию, если она используется только один или два раза. Прыжки в защиту сосать. Особенно с удивительно быстрым кодом VS и C ++.
  • Обзор класса. Когда у тебя тысячи маленьких функций, это меня бесит. Мне нравится, когда я могу просматривать определения классов и быстро видеть, что они делают, а не как SetXToOne, SetYToVector3, MultiplyNumbers, + 100 сеттеров / геттеров.
  • В большинстве проектов эти помощники теряют вес после одного или двух этапов рефакторинга, а затем вы выполняете «поиск по всем» -> удаление, чтобы избавиться от устаревшего кода, обычно ~ 25% + от него.

Длинные функции - это плохо, но функции, которые короче 3-х строк и выполняют только одну вещь, одинаково плохи ИМХО.

Так что я бы сказал, написать только небольшую функцию, если это:

  • 3+ строки кода
  • Есть вещи, которые младшие разработчики могут пропустить (не знаю)
  • Есть ли дополнительная проверка
  • Используется или будет использоваться как минимум 3x
  • Упрощает часто используемый интерфейс
  • Не станет мертвым грузом при следующем рефакторинге
  • Имеет какое-то особое значение, например, специализация шаблона или что-то
  • Выполняет некоторую работу изоляции - константные ссылки, влияет на изменяемые параметры, выполняет поиск закрытых членов

Бьюсь об заклад, у следующего разработчика (старшего) будут дела поважнее, чем помнить все ваши функции SetXToOne. Так что в любом случае они скоро превратятся в мертвый вес.

кодировщик
источник
1

Мне не нравится пример нет. 1, потому что это общее имя.

conditionMetне кажется общим, так что означает конкретное условие? подобно

isAdult () = { 
  age >= 18 
}

Это было бы хорошо. Это семантическая разница, в то время как

isAtLeast18 () { age >= 18; } 

не будет хорошо для меня.

Может быть, он часто используется и может быть предметом последующих изменений:

getPreferredIcecream () { return List ("banana", "choclate", "vanilla", "walnut") }

тоже хорошо. Используя его несколько раз, вам просто нужно поменять одно место, если вам нужно - возможно, взбитые сливки станут возможными завтра.

isXYZ (Foo foo) { foo.x > 15 && foo.y < foo.x * 2 }

не атомарный, и должен дать вам хорошую возможность для тестирования.

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

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

Последнее слово: некоторые функции выглядят только уместно, потому что они написаны слишком многословно:

function lessThan (a, b) {
  if (a < b) return true else return false; 
}

Если вы видите, что это так же, как

return (a < b); 

у вас не будет проблем с

localLessThan = (a < b); 

вместо

localLessThan = lessThan (a, b); 
неизвестный пользователь
источник
0

Там нет кода, как нет кода!

Сохраняйте это простым и не усложняйте вещи.

Это не лень, это делает вашу работу!

RDL
источник
0

Да, нормально иметь функцию короткого кода. Как упоминалось в предыдущих ответах, очень часто встречаются такие методы, как «геттеры», «сеттеры», «аксессоры».

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

Если вы хотите, чтобы ваша функция была не такой короткой, ну, во многих функциях, будь то глобальные или методы, я обычно использую переменную «result» (стиль Паскаля) вместо прямого возврата, что очень полезно при использовании отладчика.

function int CalculateSomething() {
  int Result = -1;

   // more code, maybe, maybe not

  return Result;
}
umlcat
источник
0

Слишком короткий, никогда не является проблемой. Некоторые причины для коротких функций:

Повторное использование

Например, если у вас есть функция, например, метод set, вы можете утверждать, что параметры верны. Эта проверка должна выполняться везде, где установлена ​​переменная.

Ремонтопригодность

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

единообразие

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

Мишель Кейзерс
источник
0

Когда вы даете разделу кода имя, оно, по сути, дает ему имя . Это может быть по любой из нескольких причин, но критический момент заключается в том, можете ли вы дать ему осмысленное имя, которое добавляет вашу программу. Такие имена, как «addOneToCounter», ничего бы не добавили, но conditionMet()сделали бы.

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

user1249
источник
0

Нет, но это может быть слишком кратко.

Помните: код пишется один раз, но читается много раз.

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

Джим Г.
источник
-1

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

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

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

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

data => initScroll(data)

является анонимной функцией в JavaScript и Typescript ES 2017

getMarketSegments() {
 this.marketService.getAllSegments(this.project.id)
  .subscribe(data => this.segments = data, error => console.log(error.toString()));
}

В приведенном выше коде вы можете увидеть 3 объявления функций и 2 вызова функций. Это простой вызов службы в Angular 4 с Typescript. Вы можете думать об этом как о своих требованиях

([] 0)
([x] 1)
([x y] 2)

Выше приведены 3 анонимные функции на языке Clojure

(def hello (fn [] "Hello world"))

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

Так что да, функции могут быть как меньше, но хорошо это или плохо, если у вас есть такие функции, как:

incrementNumber(numb) { return ++numb; }

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

Давайте возьмем другой пример

insertInArray(array, newKey) {
 if (!array.includes(newKey)) {
   array.push(newKey);
 }
}

Приведенный выше пример является обязательным при воспроизведении массивов внутри Angular HTML Templates. Так что иногда вам придется создавать небольшие функции

оборота Анваар Улхак
источник
-2

Я не согласен с почти ответом, данным в это время.

Недавно я нашел коллегу, который пишет всем ученикам, например, следующее:

 void setProperty(int value){ mValue=value; }
 int getProperty() const { return (mValue); }

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

Вероятно, программист упускает общую логику, опасается будущих изменений и рефакторинга кода.

Определение интерфейса - потому что реальная потребность; действительно, если вам нужно установить и получить простое свойство (без особой логики, которое делает член короче), это будет возможно. Но если реальная потребность может быть проанализирована по-другому, почему бы не определить более интуитивный интерфейс?

Чтобы действительно ответить на вопрос, конечно, нет, и причина очень очевидна: метод / свойство / whatelse должен быть определен для того, что ему нужно. Даже пустая виртуальная функция имеет причину существования.

Лука
источник
6
Есть веская причина добавить методы доступа / мутатора, о которых вы намекаете в разделе «Страх перед будущим ... рефакторинг». Но вы также правы, что это не добавляет ценности коду. Ни путем уменьшения размера (локально или глобально) или повышения читабельности. На мой взгляд, это говорит о плохом проектировании языка как в Java, так и в соглашении JavaBeans. Это одна из многих областей, в которой C # успешно улучшил язык, чтобы решить обе проблемы с помощью автоматического синтаксиса свойств . Как программист на Java, я согласен с вашим необработанным стилем для базовых структуроподобных классов.
Anm
1
Функции получения / установки хороши, даже если все, что они делают сейчас, это чтение или запись переменной. На практике вы можете представить себе сценарий, в котором впоследствии вы решите выводить значение на экран при каждом изменении поля или проверить, является ли это значение действительным или нет. (Может быть, это знаменатель для дроби, и вы хотите проверить, чтобы убедиться, что это не ноль.)
Рей Миясака
2
геттеры и сеттеры ужасны, несмотря на их правильное использование. Если необходимо их использовать, я считаю это провалом языка.
Карсон Майерс
@Rei: почему внешний класс должен проверять значение знаменателей? Это должно быть сделано с помощью функцииdiv () класса Fraction, или класс Fraction должен предоставить isDivisible () для проверки на нулевые знаменатели. Необходимые получатели / установщики, как правило, являются запахом кода, который ваш класс имеет высокую связь и / или низкую когезию (то есть плохо).
Ли Райан
@ Лай Что? Я никогда не говорил, что внешний класс должен использоваться для проверки знаменателей. Я говорю, что внешний класс может установить знаменатель в 0 случайно. Цель проверки достоверности в установщиках состоит в том, чтобы поощрять любые ошибки в потребительском коде, которые будут обнаружены ранее. Предоставление функции isDivisible (), которая может вызываться или не вызываться, также не работает с этой целью. И как именно наличие геттеров / сеттеров указывает на высокую связь?
Рей Миясака