Чи може функція бути занадто короткою?


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, який би диктував, чи потрібно викидати виняток / тощо. у випадку, якщо зворотний виклик не є функцією.
робота

38
Так, лише в одному випадку: функція myFunction () {}
Spooks

5
def yes(): return 'yes'
дієтабудда

3
@Spooks - тут я розщеплюю волоски, але порожні функції діють принаймні для класів адаптерів, наприклад, MouseMotionAdapter в download.oracle.com/javase/6/docs/api/java/awt/event/… . Звичайно, це лише спосіб подолати мовні обмеження.
Aleksi Yrttiaho

3
@dietbuddha: Вимоги просто змінилися - тепер він повинен підтримувати дві мови для демонстрації наступного тижня. Хлопець, який написав "def yes ()", відчував себе дуже радий перед тим, як змінити його на "def yes (: (IsFrench ()? 'Oui": "Так") "
Ендрю Пастух

Відповіді:


167

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

1) Читання вашого коду збільшується в десять разів.

2) Настільки легко зрозуміти процес вашого коду через читабельність.

3) СУХО - не повторюйтеся - ви дуже добре дотримуєтесь цього!

4) Тестова. Крихітні функції перевірити в мільйон разів легше, ніж ті 200 лінійних методів, які ми бачимо занадто часто.

О, і не хвилюйтеся з приводу функціональних стрибків з точки зору продуктивності. Оптимізація побудови та компілятора "Release" дуже непогано про це піклуються про нас, а продуктивність становить 99% часу десь ще в дизайні систем.

Це ледачий? - Дуже навпаки!

Це погана практика? - Абсолютно ні. Краще потягнути цей спосіб виготовлення, ніж кульки дьогтю чи «Божі об’єкти», які так поширені.

Слідкуйте за хорошою роботою мого колеги-ремісника;)


40
Ви не відповідаєте на запитання, ви просто проповідуєте правило, більш екстремальне застосування якого тут поставлено під сумнів.

4
Не дуже часто мені здається, що обмеження лише на 1 підсумковість засмучує. Але, на цю відповідь, +1, схоже, не робить це справедливим.
Беван

4
+5 ... ой можна робити лише +1, о добре! І щоб підтримати MeshMan, я пропоную наступну книгу Роберта К. Мартіна Чистого коду . Ця книга дійсно змінює те, як я зараз програмую.
Ерік-Карл

10
Дуже симпатична відповідь, але я не погоджуюсь з більшою частиною: 1) Надзвичайно малі функції призводять до загального коду в цілому через всю сантехніку, необхідну для кожної функції. Це може зменшити читабельність, особливо для дійсно великого проекту. Також залежно від мови. 2) Цілком залежить від пункту 1, а тому не має нічого спільного з питанням. 3) Що? runCallback повторює "зворотний виклик" чотири рази, і три рази посилається на одну і ту ж змінну для запуску однієї функції. 4) Методи ліній 200+, звичайно, не перевіряються, але шлях до цього рядка довгий.
l0b0

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 () у цьому прикладі, якщо тільки я не мав намір його замінити чи використати цей код в іншому місці.


7
Відокремлення методу однієї лінії у другому випадку може бути корисним для збереження рівня абстракції методів виклику. Наведений приклад є на огорожі, якщо використовується ця міркування: чи точна ширина пікселя та висота занадто багато деталей для показу діалогового вікна?
Aleksi Yrttiaho

2
Метод "isNotValue ()" невірно названий, і його слід змінити, щоб вказати фактичне запитання домену.

4
@Aleksi: Я не згоден; деталі вже приховані в методі showDialog () у цьому прикладі; не потрібно подвійно рефакторировать його. Приклад призначений для показу ізольованого випадку використання; якщо потрібен шаблон з різними конфігураціями діалогів у різних випадках, було б доцільно повернутися назад та рефактор після встановлення шаблону.
RMorrisey

1
@Thorbjorn: Я можу побачити випадок, коли ви відповідаєте на питання ділового домену, чия логіка може бути не очевидною. Я просто вказую, що є окремі випадки, коли це надмірно.
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), але якщо це так, ця ж ідея буде стояти, оскільки функція фактично є перекладом з англійської до цієї мови - тому ім'я не те саме, що визначення.
Rei Miyasaka

1
Я говорю про функції ідентичності речей зі стандартної бібліотеки Haskell - я не думаю, що ви можете отримати більше "тавтологічного", ніж це :)
hugomg

1
@missingno Ба, це обман: D
Rei Miyasaka

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; }

Або іншими словами, справа не в довжині методу, а в коді самодокументування.


5
Мій шановний колега вказує, що ви також могли писати if x == PIXEL_ON. Використання константи може бути настільки ж описовим, як і використання методу, і трохи коротше.
Том Андерсон

7

Я думаю, що це саме те, що ти хочеш зробити. Зараз ця функція може бути лише однією або двома лініями, але з часом вона може зростати. Крім того, що більше функціональних дзвінків дозволяє читати виклики функцій та розуміти, що відбувається всередині. Це робить ваш код дуже сухим (не повторюйте себе), що набагато більш рентабельно.


4
Отже, що поганого в тому, щоб його розбити пізніше, коли ви зможете довести, що вам потрібно, а не зараз, коли це просто мертвий вага?
dimimcha

Функції не зростають самостійно. ІМХО приклади паршиві. conditionMetце занадто загальне ім'я, і ​​воно не бере аргументів, тому воно перевіряє деякий стан? (x == xCondition) в більшості мов і ситуацій так само виразний, як "xConditition".
користувач невідомий

Так, і саме тому ви хочете мати 75% + накладні витрати у своєму коді? Сінг-лайнер, записаний у 3 рядки, насправді становить 300%.
Coder

5

Я погоджуюся з усіма іншими публікаціями, які я бачив. Це гарний стиль.

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

Код слід писати для ясності та простоти. Я намагаюся обмежити метод однією з двох ролей: прийняття рішень; або виконання роботи. Це може генерувати методи однієї лінії. Чим краще я роблю це, тим краще я знаходжу свій код.

Цей код, як правило, має високу когезію та малу зв'язок, що є хорошою практикою кодування.

EDIT: Примітка до назв методів. Використовуйте назву методу, яка вказує, що метод не робить, як це робить. Я вважаю, що verb_noun (_modifier) ​​є хорошою схемою іменування. Це дасть імена, як Find_Customer_ByName, а не Select_Customer_Using_NameIdx. Другий випадок схильний стати неправильним, коли метод модифікований. У першому випадку ви можете замінити всю реалізацію бази даних клієнтів.


+1 для згадування вбудовування, imo головного врахування у виконанні та коротких функціях.
Гарет Клаборн

4

Рефакторинг одного рядка коду у функції здається надмірним. Можуть бути виняткові випадки, такі як ver loooooong / завершує рядки або виграші, але я б цього не робив, якщо не знаю, що функція зростатиме в майбутньому.

і ваш перший приклад натякає на використання глобалів (які можуть або не можуть говорити про інші проблеми в коді), я б перефактурував його далі і ставлю ці дві змінні як параметри:

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...*/);
}

1
Перший його приклад не натякає на глобали. Якщо що, це згуртований метод у високо згуртованому класі, де більшість змінних є на об'єкті.
Martin Blore

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

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


Я б не зараховував це у рядках коду, але у виразах. "(x == умова)" є атомним, тому я ставлю його лише до методу / функції, якщо він використовується декілька разів І може бути змінений, як, function isAdult () = { age >= 18; }але, безумовно, ні isAtLeast18.
користувач невідомий

2

Я б сказав, що вони занадто короткі, але це моя суб'єктивна думка.

Оскільки:

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

Функції, які є довгими, погані, але функції, які коротші 3 рядків і виконують лише 1 річ, однаково погані IMHO.

Тому я б сказав, що записуйте лише невелику функцію, якщо це:

  • 3+ рядків коду
  • Чи є речі, які можуть пропустити молодші дияволи (не знаю)
  • Здійснює додаткову перевірку
  • Використовується, або буде використовуватися принаймні 3 рази
  • Спрощує часто використовуваний інтерфейс
  • Не стане мертвою вагою під час наступного рефакторингу
  • Має якесь особливе значення, наприклад, спеціалізація шаблонів чи щось таке
  • Здійснює якусь роботу із ізоляції - const посилання, впливає на параметри, що змінюються, здійснює пошук приватних членів

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


1

Мені не подобається приклад ні. 1, через i-те родове ім'я.

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

Не існує коду, як немає коду!

Будьте прості і не надмірно ускладнюйте речі.

Це не лінуватися, це робить свою роботу!


0

Так, нормально функціонувати з коротким кодом. У випадку таких методів, як "геттери", "сеттери", "приналежності" дуже часто, як згадували попередні відповіді.

Іноді ці короткі функції "аксесуарів" є віртуальними, тому що при їх перекритті в підкласах у функцій буде більше коду.

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

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

   // more code, maybe, maybe not

  return Result;
}

0

Занадто короткий ніколи не є проблемою. Деякі причини коротких функцій:

Багаторазовість

Наприклад, якщо у вас є функція, як метод встановлення, ви можете стверджувати її, щоб переконатися, що параметри є дійсними. Ця перевірка повинна проводитися скрізь, де встановлена ​​змінна.

Технічне обслуговування

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

Уніфікованість

Ви використовуєте, наприклад, шаблон фасаду, і єдине, що функція робить, це саме передача функції іншому без зміни аргументів.


0

Коли ви даєте ім'я розділу коду, це по суті є надання йому імені . Це може бути з будь-якої з кількох причин, але вирішальним моментом є те, якщо ви можете дати йому змістовне ім’я, яке додасть вашій програмі. Такі імена, як "addOneToCounter", нічого б не додали, але зробили conditionMet()б.

Якщо вам потрібно правило дізнатися, чи фрагмент занадто короткий або занадто довгий, то подумайте, скільки часу знадобиться для пошуку значущої назви фрагмента. Якщо ви не можете протягом розумного проміжку часу, фрагмент не є відповідним розміром.


0

Ні, але це може бути занадто лаконічно.

Пам'ятайте: Код пишеться один раз, але читається багато разів.

Не пишіть код для компілятора. Напишіть це для майбутніх розробників, яким доведеться підтримувати ваш код.


-1

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

На мою думку, я здебільшого працюю над Front End Technologies. Малі функції в основному використовуються як допоміжні функції, які ви обов'язково будете використовувати їх як багато під час роботи з невеликими фільтрами та використовуючи ту саму логіку для вашої програми. Якщо у вашій програмі є занадто багато загальної логіки, тоді ви будете мати багато дрібних функцій.

Але в додатку, де у вас немає загальної логіки, ви не будете зобов’язані робити невеликі функції, але ви можете розбити свій код на сегменти, де вам стає легко керувати та розуміти.

Загалом, розбийте ваш величезний код на невеликі функції - це дуже хороший підхід. У сучасних рамках та мовах ви зобов'язані це робити, наприклад

data => initScroll(data)

є анонімною функцією в ES 2017 JavaScript і Typescript

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, якщо не було підтримки збільшення або зменшення кутових шаблонів HTML, тоді це було б рішенням для я.

Давайте візьмемо інший приклад

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

Наведений вище приклад є необхідним під час відтворення, коли масиви всередині кутових шаблонів HTML. Тому іноді вам доведеться створювати невеликі функції


-2

Я не погоджуюся з майже відповіді, що дається в цей час.

Нещодавно я знайшов колегу, яка записує всіх учасників класів, як:

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

Це може бути хорошим кодом у спорадичних випадках, але, безумовно, ні, якщо ви визначаєте багато класів, що мають багато і багато властивостей. Я не хочу сказати при цьому, що такі методи, як описані вище, не пишуться. Але, якщо ви закінчите писати більшу частину коду як "обгортку" реальної логіки, щось не так.

Ймовірно, програміст пропускає загальну логіку, побоюючись майбутніх змін та рефакторингу коду.

Визначення інтерфейсу обумовлено реальною потребою; Дійсно, якщо вам потрібно встановити та отримати просте властивість (без особливої ​​логіки, що робить член коротшим), це буде можливо. Але якщо справжню потребу можна було проаналізувати по-іншому, чому б не визначити більш інтуїтивний інтерфейс?

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


6
Є вагома причина додати методи аксесуарів / мутаторів, на які ви натякаєте під "страхом за майбутнє ... рефакторинг". Але ви також маєте рацію, що це не додає значення коду. Ні за рахунок зменшення розміру (локально чи глобально), ні збільшенням читабельності. На мій погляд, це говорить про поганий дизайн мови як у Java, так і в конвенції JavaBeans. Це одна область (з багатьох), де C # успішно вдосконалив мову для вирішення обох проблем з синтаксисом автоматичного властивості . Як програміст Java, я згоден з сирим стилем для основних STRUCT-подібних класів.
Anm

1
Функції Getter / Setter хороші, навіть якщо все, що вони роблять зараз, - це читання або запис змінної. В якості практичного питання ви можете уявити сценарій, коли пізніше ви вирішите надрукувати значення на екрані кожного разу, коли поле змінюється, або перевірити, чи це значення дійсне чи ні. (Можливо, це знаменник дробу, і ви хочете перевірити, щоб переконатися, що він не дорівнює нулю.)
Рей Міясака

2
геттери і сетери жахливі, незважаючи на їх дійсне використання. Якщо потрібно їх використовувати, я вважаю це недоліком мови.
Карсон Майєрс

@Rei: чому зовнішній клас повинен перевіряти значення знаменників? Це повинно бути виконано функцією розділення () класу Fraction, або клас Fraction повинен забезпечити isDivisible () для перевірки нульових знаменників. Необхідні геттери / сетери - це зазвичай кодовий запах, який у вашому класі відрізняється високою сполучністю та / або низькою когезією (тобто погано).
Lie Lie Ryan

@Lie Що? Я ніколи не казав, що для перевірки знаменників слід використовувати зовнішній клас. Я кажу, що зовнішній клас може випадково встановити знаменник 0. Метою проведення перевірок дійсності у сетераторах є заохочення будь-яких помилок у споживчому коді до пошуку раніше. Надання функції isDivisible (), яку можна або не можна викликати, також не працює з цією метою. І як саме потрібні геттери / сетери вказують на наявність високої зв'язку?
Рей Міясака
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.