Що доведено як хороша максимальна тривалість функції? [зачинено]


44

Чи впливає довжина функції на продуктивність програміста? Якщо так, то яка хороша максимальна кількість рядків, щоб уникнути втрати продуктивності?

Оскільки це дуже впевнена тема, будь ласка, підкріпіть заяву деякими даними.


6
Довжина не повинна вимірюватися в LOC, а в кількості часу, необхідного для того, щоб зрозуміти, що саме вона робить. І ця довжина повинна бути не більше хвилини. Якщо я не можу це зрозуміти за кілька секунд, це, мабуть, робиться занадто багато ... через хвилину, це безумовно.
CaffGeek


13
Максимальна довжина повинна бути 17.
ThomasX

1
Подумайте S у твердому.
Кріс Краузе

1
@CaffGeek Або, можливо, функція просто робить щось нетривіальне. Я бачив функції, які потребували б днів, щоб повністю зрозуміти. Навіть функції, де я розумію всі задіяні концепції, можуть легко зайняти півгодини, щоб детально опрацювати деталі. Хоча приємно мати тривіальні функції, багато проблем просто по суті важкі.
CodesInChaos

Відповіді:


46

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

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

Частина проблеми полягає в тому, що програмістів сьогодні не вчать модулювати речі.

Стандарти кодування, які максимально витрачають вертикальний простір, також є частиною проблеми. (Мені ще доводиться зустрічатися з менеджером програмного забезпечення, який прочитав " Психологію комп'ютерного програмування " Джеральда Вайнберга . Вайнберг зазначає, що багаторазові дослідження показали, що розуміння програміста по суті обмежується тим, що програміст може побачити в будь-який момент. Якщо програміст повинен прокручувати або перегортати сторінку, їх розуміння значно падає: вони повинні пам’ятати і абстрагуватися.)

Я все ще переконаний, що багато добре задокументованих приріст продуктивності програміста від FORTH були пов'язані із системою "блокування" FORTH для вихідного коду: модулі були жорстко обмежені абсолютним максимумом 16 рядків з 64 символів. Ви можете розраховувати нескінченно, але ні за яких обставин ви не могли писати розпорядження 17 рядків.


3
Вся філософія FORTH була покликана сприяти цьому ... Ви мали на меті створити власний словниковий запас, невблаганно розбиваючи свою програму на більш дрібні та менші шматочки, що закінчується меншою кількістю сценарію та більше словника. Самі обмеження довжини цього не роблять - ви побачите рутину, розбиту на довільні шматки просто для задоволення певного стандарту кодування. Я думаю, що ви абсолютно праві, підозрюючи, що програмістів просто "не вчать модулювати речі"; це мало бути однією з найбільших перемог ООП, але з різних причин це часто знецінюється як мета для себе.
Shog9

1
@Містер. CRT: обмеження довжини в блоково-орієнтованих реалізаціях FORTH модуляції FORCED. Інтерактивна природа більшості FORTH допомагає шляхом заохочення невеликих модулів та швидкого тестування цих модулів. D85, файловий FORTH, не здійснював модуляції, і я бачив хлопців, які грають з D85, що назавжди пишуть безліч модулів, які свідомість потоку програміста. Звідси моє переконання. (Для чого це варто, Ліз Скоріше не погоджується зі мною. Вона вважає, що головним чином інтерактивність
сприяє

2
+1, щоб представити мені чудову книгу "Психологія комп’ютерного програмування" :)
Самуїл

30

Що насправді потрібного розміру?

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

  • В ідеалі менше 25 рядків.
  • Прийнятно , менше 35 рядків.

Якщо це більше, то це те, що мені потрібно повернутися пізніше і переробити.

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

(Нещодавно моя команда запустила програму на нашій кодовій базі: ми знайшли клас із 197 методами та ще один із 3 методами, але один із них був 600 рядків. Симпатична гра: що гірше за 2 зла?)


Тепер для більш дзен-відповіді ... Взагалі вважається хорошою практикою (TM) цитувати одного або двох великих людей, тож ось:

Все повинно бути зроблено максимально просто, але не простіше. - А. Ейнштейн

Досконалість, нарешті, досягається не тоді, коли більше нічого не можна додати, а коли вже немає чого відняти. - А. де Сент - Екзюпері


Додаток до стилів коментарів

Як додаток до цього, ваші функції повинні мати чіткі назви, що пояснюють їх наміри. Щодо коментарів, я зазвичай не коментую функцію:

  • коментарі кажуть "чому?" ,
  • код говорить "як?" .

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

Детальніше, будь ласка, прочитайте мою відповідь на Стиль та рекомендації коду коментування


@haylem Я думаю, що це версія програміста Freddy vs. Jason :-)
Gaurav

Я згоден, однак я б додав, що це має бути розмір однієї сторінки на екрані. якщо у вас на одній екранній сторінці 72 рядки, функція не повинна перевищувати 72 рядки.
Відображати ім’я

@ Існує питання про те, щоб одна функція містилася на екранній сторінці, щоб не прокручувати, але це, як правило, не є моєю основною проблемою. Мене турбує кількість часу, необхідного на обробку інформації під час читання функції, і це майже миттєво, якщо це чітко написана в 25 рядках. Це стає лише питанням слідування за викликами функцій. 72 для мене занадто великий (плюс що робити, якщо у вас розділені екрани? І це залежатиме від шрифту. Але я згоден на історичну цінність рекомендації)
haylem

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

1
Якщо функція є, наприклад Map(x => x.Property1); Map(x => x.Property2); Map(x => x.Property3);, зрозуміло, що все це однаково. (Зауважте, це лише приклад; ця функція час від часу з’являється)
конфігуратор

12

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

Щоб використати слова дядька Боба, "Витягайте, поки ви просто не зможете витягти більше. Витягайте, поки не кинете".


2
Що ви маєте на увазі під якомога меншими? Не було б якомога менше, щоб у кожної функції було лише два рядки: один для виконання однієї операції, а інший, який викликає функцію, щоб виконати решту?
Кельмікра

Знов дядько Боб. Думай сам. Не слухайте дядьків. Вони вас обманюють.
gnasher729

10

Якою має бути максимальна висота будівлі? Залежить від того, де знаходиться збірка або висота, яку ви хочете.
Ви можете отримати різні відповіді від різних людей, які приїжджають з різних міст.
Деякі функції сценарію та обробники переривань ядра дуже довгі.


Я повністю з вами згоден. Мені подобаються метафори. :) Будинок з трьох поверхів, можливо, побудував дурний архітектор, який не знає, де поставити дійсний безпечний вихід, а інша будівля може мати десять поверхів і бути ідеальним архітектурним дизайном. Ми завжди повинні мати на увазі, що читабельність та ремонтопридатність повинні бути головною причиною рефакторного способу зменшення його розміру, а не самого розміру. Місто не могло побудувати з 90% хмарочоса, крім фільмів з фантастики. :)
Самуїл

10

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


І ваш метод повинен робити лише одне, щоб мати гарне ім'я ... ні "І", "Або" або що-небудь інше, що робить назву методу довжиною 50 символів.
Самуїл

10

Поки йому потрібно робити те, що потрібно робити, але вже не.


як кажуть в c: "Немає проблеми в c, яку ви не могли б вирішити, додавши до цього вказівника ще один вказівник". ви завжди можете додати під нього ще одну функцію, його питання стосується вашого епіфанія "де це закінчується?"
Відображати ім’я

1
Я б насправді перевернув це і сказав: "як можна коротше, але не коротше", але ви отримаєте мій +1 за те, що ви досить близький :)
Бен Х'юз

6

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

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

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


Мені подобаються короткі методи.
Марсі

Мені подобається те, що ви сказали, тому що сказати, що метод не повинен мати більше 10 рядків, на мій погляд, є утопією. Добре, це добре пам’ятати щоразу, коли ви пишете метод, але це не повинно бути математичним правилом, як 1 + 1 = 2. Якщо ви дотримуєтесь таких принципів, як KISS, DRY, YAGNI тощо ... і ваші методи не повний коментар, що пояснює деякі деталі, оскільки їх занадто довго, методи можуть мати 100 рядків коду і можуть бути абсолютно чистими для розуміння та підтримки. Однак це має бути більше винятком, ніж звичкою. Я думаю, що випадок перемикання у заводському методі є хорошим прикладом винятку.
Самуїл

5

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

  1. Досить короткий, щоб на моніторі помістився розумний шрифт.
  2. Якщо вона повинна бути довшою №1, достатньо коротка для друку на аркуші паперу розумним шрифтом.
  3. Якщо вона повинна бути довшою №2, достатньо короткої, щоб надрукувати 2-х на аркуші паперу.

Я рідко пишу функції довше цього. Більшість із них - гігантські заяви C / C ++.


Досить короткий, щоб поміститися на моніторі, це добре, але із зазначенням типу та розміру шрифту. На мою думку, папір не повинна бути правилом, оскільки ми перебуваємо в 2013 році, і хто ще друкує код на папері, хто надрукує лише для того, щоб побачити, чи він відповідає розміру паперу? За допомогою таких інструментів, як Visual Studio, intellisense, більше немає підстав аналізувати код з папером.
Самуїл

5

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

В основному я дотримуватимуся принципової "високої згуртованості, низької зв'язку", і немає обмежень у довжині.


5

Питання має полягати в тому, скільки речей має виконувати функція. І зазвичай буває рідко, що вам потрібно 100 рядків, щоб зробити "одну" річ. Знову ж це залежить від рівня, з якого ви дивитесь коду: чи є хеширование пароля одним? Або хеш-пам'ять і збереження пароля одне?

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

Я бачив процедури, що зберігаються в SQL, що працюють понад 1000 рядків. Чи кількість рядків збережених процедур також менше 50? Я не знаю, але це робить читання коду, пекло. Мало того, що вам потрібно продовжувати прокручування вгору та вниз, вам потрібно дати кілька рядків коду назви, як-от «це робить перевірку1», «це оновлення в базі даних» тощо - робота, яку повинен був виконати програміст.


+1 лише для першого абзацу. все інше стосується справи, над якою ви працюєте.
Відображати ім'я

І як допомагає розділити його на 50 функцій? Коли функції повинні зв’язуватися, тож ви закінчите не 500 рядків, а тисячу?
gnasher729

5

З цикломатичної складності (Вікіпедія):

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

  • Я рекомендую вам зберігати це число менше 10 в одному методі. Якщо вона потрапляє до 10, то час переосмислити.

  • Є інструменти, які дозволяють оцінити ваш код і дати цикломатичну кількість складності.

  • Ви повинні прагнути інтегрувати ці інструменти у свій конвеєр.

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

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


Цикломатична складність показана на реальному коді одного з великих публічних сховищ, а не надуманих прикладах, що дуже сильно співвідноситься з необробленою SLOC. Це робить його в основному нікчемним, оскільки підрахувати повернення вагонів набагато простіше. (Так, можна грати в SLOC. Будьте чесними, ось тут: як довго хто-небудь, хто грав у метрику SLOC у вашого роботодавця, дозволив би продовжувати малювати зарплату?)
Джон Р. Стром

4

Як правило, я намагаюся дотримуватися своїх методів / функцій тим, що відповідає екрану монітора 1680x1050. Якщо воно не підходить, використовуйте допоміжні методи / функції, щоб розібрати завдання.

Це допомагає читати як на екрані, так і на папері.


Я роблю те саме, але варто вказати, який тип та розмір шрифту ви використовуєте. Для себе я віддаю перевагу "консолям" розміром 14, як запропонував Скотт Гансельман. hanselman.com/blog/… Вперше важко працювати з таким великим шрифтом, але найкраща практика завжди пам’ятати про те, що ваш метод повинен бути якнайменшим.
Самуїл

4

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

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


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

4

Досить короткий, щоб правильно його оптимізувати

Методи повинні бути такими короткими, щоб робити саме одне. Причина цього проста: так ваш код можна правильно оптимізувати.

У мові JIT-ted, як Java або C #, важливо, щоб ваші методи були простими, щоб компілятор JIT міг швидко створювати код. Більш тривалі, складніші методи вимагають більше часу на JIT. Крім того, компілятори JIT пропонують лише кілька оптимізацій, і від цього виграють лише найпростіші методи. Цей факт навіть був названий у Ефективному C # Білла Вагнера .

Для мови нижчого рівня, наприклад C або C ++, важливим є також використання коротких методів (можливо, десяток або більше рядків), оскільки таким чином ви мінімізуєте потребу в зберіганні локальних змінних в ОЗУ, а не в регістрі. (Aka "Реєстрація розливу". Однак зауважте, що в цьому некерованому випадку відносна вартість кожного виклику функції може бути досить високою.

Навіть у динамічній мові, як у Ruby чи Python, наявність коротких методів також допомагає в оптимізації компілятора. У динамічній мові чим "динамічніша" особливість, тим важче її оптимізувати. Наприклад, довгий метод, який займає X і може повернути Int, Float або String, швидше за все, виконує набагато повільніше, ніж три окремі методи, кожен з яких повертає лише один тип. Це тому, що якщо компілятор точно знає, до якого типу функція повернеться, він може оптимізувати і сайт виклику функції. (Наприклад, не перевіряючи конверсії типів.)


Близько 99,999% додатків там набагато більше, що сповільнює швидкість таких програм, як доступ до бази даних, доступ до файлів або затримка в мережі. Думка про швидкість при розробці методів може бути вагомою причиною для ігор, додатків у режимі реального часу або звітування з тоннами даних, але не в інших випадках. Однак, це хороший момент, але настільки ж маленьким, як я, як програміст, мені рідко доводиться робити такий тип оптимізації у своїх програмах.
Самуїл

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

3

Це дуже залежить від того, що в коді.

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

Я також дивлюсь на 120 рядків у перемикачі переді мною. Жоден випадок не перевищує 3 рядки - охоронець, завдання та перерва. Це розбір текстового файлу, об'єкти - це не можливість. Будь-яку альтернативу було б важче прочитати.


2

Більшість компіляторів не враховують довжину функції. Функція повинна бути функціональною, але бути одночасно простою для розуміння, зміни та використання людьми. Виберіть довжину, яка вам найбільше підходить.


1

Моє загальне правило - функція повинна розміщуватися на екрані. Я знайшов лише три випадки, які, як правило, порушують це:

1) Диспетчерські функції. У старі часи це було звичайним явищем, але більшість із них замінюється спадкоємством об'єктів в наші дні. Хоча об'єкти працюють лише всередині вашої програми, і, таким чином, ви все одно будете бачити випадкові функції диспетчеризації, коли маєте справу з даними, які надходять з інших місць.

2) Функції, які виконують цілу купу кроків для досягнення поставленої мети, і в яких кроки не мають хорошого підрозділу. Ви закінчуєте функцію, яка просто викликає довгий список інших функцій по порядку.

3) Як і номер 2, але там, де окремі кроки настільки малі, що їх просто вводити, а не називати окремо.


1

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

Для методів X встановлено на 30, і це досить жорстко.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.