Як можна змістовно вимірювати ремонтопридатність?


23

Контекст: Я розробник підприємства в магазині, що займається всіма MS.

Хтось може порекомендувати хороший спосіб об’єктивного вимірювання ремонтопридатності фрагмента коду чи програми?

Чому ремонтопридатність : я втомився від «якісних» показників у моїй групі, які обертаються лише кількістю помилок та охопленням кодом. Обидві показники прості у грі, особливо якщо ви не вимірюєте ремонтопридатність. Короткозорість і терміни призводять до величезної кількості технічної заборгованості, яку ніколи не вирішують.

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

Я переглядаю кодові показники VS2010 , але мені цікаво, чи є у когось інші рекомендації.


@Anon - Я згоден, але, принаймні, це дасть мені місце для початку. Зараз нічого немає; його навіть не потрібно грати.
nlawalker

1
Я дійсно не бачу, як ви могли це зробити без огляду коду рівних. Комусь потрібно по-справжньому зрозуміти загальний дизайн системи (і він повинен існувати), щоб подивитися на одиницю коду та перейти ... хм, це могло б бути покращене вдосконаленим дизайном, або це видання коду або хороший пане, коли ваші інструменти застаріли. ... У подібній примітці ви можете дотримуватися загальних рекомендацій, таких як "ей, хлопці, не дуже гарна ідея вводити індекси жорсткого коду на перегляд сітки, використовувати шаблони елементів і замість них вибирати стовпці за назвою". Коли справа зводиться до цього, дияволи просто повинні бути хорошими та привабливими. Да Вінчі не може навчити дивовижності.
P.Brian.Mackey

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

3
"Все, що можна перерахувати, не обов'язково підраховувати; все, що підраховує, не обов'язково можна перерахувати". -Ейнштейн
Джейсон Бейкер

@nlawalker Окрім проблем, які вже виникли відповіді, ваше запитання завантажено сумнівним припущенням про те, що якби таке вимірювання існувало, люди могли щось із цим зробити. Низька рентабельність є результатом різних факторів, зовнішніх для самого програмного забезпечення: наскільки складною чи чітко визначеною є проблема, яку намагається вирішити програма, досвід роботи персоналу, плинність, час до вимог ринку, зміни обсягу ... ви просто не можете поставити суму в цьому очікуванні проблеми - справа доброї волі.
Артур Гавлічек

Відповіді:


7

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

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

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


7

Що ж, міра, яку я використовую, або як я думаю, я використовую:

Для кожної незалежної, однолінійної, однорядкової функціональної вимоги, прийняти або залишити її, проаналізуйте базу коду перед її реалізацією. Потім реалізуйте це, включаючи пошук та виправлення будь-яких помилок, введених у процесі. Потім запустіть diffміж базою коду до і після. У diffзаповіті з'явиться список усіх вставок, видалень та модифікацій, які впровадили зміни. (Як і вставлення 10 послідовних рядків коду - це одна зміна.) Скільки змін було? Чим менше це число, як правило, тим більш ретельним є код.

Я називаю це надмірністю вихідного коду, тому що це як надмірність коду, що виправляє помилки. Інформація містилася в 1 шматок, але була кодована як N шматки, які всі повинні бути зроблені разом, щоб бути послідовними.

Я думаю, що це ідея, що стоїть за DRY, але вона трохи більш загальна. Причина, що добре, що цей показник є низьким, це те, що для впровадження типової вимоги потрібно N змін, а як помилковий програміст, спочатку ви отримуєте лише N-1 або N-2 з них правильно, ви ставите 1 або 2 помилки. Крім помилок програмування O (N), ці помилки мають бути виявлені, розміщені та виправлені. Тому малий N - це добре.

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

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

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


Хіба це не дуже припущення - що всі функціональні вимоги мають приблизно однаковий розмір? І чи не буде ця метрика відлякує розмежування відповідальності? Мені потрібно реалізувати горизонтальну функцію; Таким чином, самий "підтримуваний" код - це майже повне перезапис програми, яка повністю міститься в одному монолітному методі.
Aaronaught

@Aaronaught: Я не знаю, наскільки це велично, але в нашій групі ми розробляємо списки вимог / особливостей, деякі взаємозалежні, деякі ні. Кожен має відносно короткий опис. Якщо знадобиться велике перезапис, я впевнений, що я це бачив / робив, але мені це каже, що, мабуть, був кращий спосіб впорядкувати код. Це мій канонічний приклад. Я не кажу, що це легко навчитися, але колись навчившись, це економить велику кількість вимірюваних зусиль, отримуючи зміни, швидко введені без помилок.
Майк Данлаве

5

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

Для подачі фрагмента коду придумайте ідею ідеального дизайну.

Тоді за будь-якого відхилення реального коду від цього ідеального зменшіть значення 100 на деяке число. Від того, що саме залежить від наслідків обраного не досконалого підходу.

Приклад:

Частина коду читає та імпортує певний формат даних і може відображати повідомлення про помилку, якщо щось не так.

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


4

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

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

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

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


2

Я вважаю, що показники коду Visual Studio є досить пристойними для забезпечення швидкої метрики "ремонтопридатності". Захоплено 5 основних показників:

  • Цикломатична складність
  • Глибина спадкування
  • Клас Кулінг
  • Рядки коду (за методом, за класом, за проектом, залежно від рівня збору)

Індекс ремонтопридатності - це те, що мені зручно. Це складений індекс на основі:

  1. Загальний розмір (рядки коду)
  2. № класів або файлів
  3. # методів
  4. Цикломатична складність вище 20 (або 10 - налаштовується, 10 - це мої переваги)
  5. Дублювання

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

Додаткову інформацію про розрахунки див. У білій книзі .


1

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

Цикломатична складність - це міра кількості шляхів у коді. Кожен шлях повинен бути протестований (але, мабуть, ні). Щось складність вище приблизно 20 повинна бути розбита на більш дрібні модулі. Модуль з кікоматичною складністю 20 (можна було б повторити це з 20 послідовними if then elseблоками) матиме верхню межу 2 ^ 20 шляхів для тестування.

Зчеплення класів - це міра того, наскільки щільно пов'язані класи. Приклад деякого поганого коду, з яким я працював у свого попереднього роботодавця, включає компонент "рівень даних" з приблизно 30 елементами в конструкторі. Людина, яка здебільшого "відповідальна" за цей компонент, продовжувала додавати параметри бізнесу та шару інтерфейсу в конструктор / відкриті дзвінки, поки це не була дійсно велика куля грязі. Якщо пам'ять слугує мені правильно, було близько 15 різних нових / відкритих дзвінків (деякі більше не використовуються), всі з дещо різними наборами параметрів. Ми запровадили огляд коду з єдиною метою, щоб не дати йому робити подібні речі - і щоб не виглядати так, як ми його виділяли, ми переглянули код кожного в команді, тому ми витратили близько пів дня на 4-6 люди щодня, тому що ми цього не робили


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

1

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

Порівняно очевидно виміряти, наскільки легко було адаптувати фрагмент коду до мінливих вимог. Це неможливо заздалегідь виміряти, як він буде реагувати на зміни вимог. Це означатиме, що ви повинні передбачити зміни вимог. І якщо ви можете це зробити, ви повинні отримати нобелівську ціну;)

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


1

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

А як щодо технічної заборгованості, яку "наздоганяють події"?

Я пишу бездарний код і кидаю його у виробництво.

Ви зауважуєте - правильно - що це неможливо.

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

"Технічний борг" усувається законодавчими змінами, які роблять його все застарілим.

Показник "ремонтопридатності" перейшов від "поганого" до "нерелевантного" через зовнішні міркування.

Як це можна виміряти?


"Через сто років ми всі будемо мертві, і нічого з цього не буде мати значення. Вигляд ставить речі в перспективу, чи не так?" Якщо є щось нерелевантне, саме ця відповідь не є відповіддю на питання.
Мартін Маат

0

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


0

Анкета

А як зробити анонімну анкету для розробників, яку слід заповнювати раз на місяць чи так? Питання йдуть приблизно так:

  • Скільки часу за останній місяць ви витратили на проект X (приблизно) [0% ... 100%]
  • Як би ви оцінили стан бази коду з точки зору ремонтопридатності [дійсно погано, погано, нейтрально, добре, добре, дійсно добре].
  • Наскільки складно ви б оцінили базу коду порівняно зі складністю проекту [занадто складний, справедливий, занадто спрощений].
  • Як часто ви відчували себе там, де перешкоджали вирішенню завдань через надмірну складність бази коду? [зовсім не раз, часто, постійно].

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


0

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

Модифікація без розуміння.

Чи може виправник помилок увійти в код і виправити проблему, не потребуючи розуміння, як працює вся система.

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

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

maintainabilty1 = K1 . (Code Coverage)/(Coupling of Code) * (Complexity of API)

Модифікація з розумінням.

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

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

Тож, можливо, ми могли б придумати якусь міру цього:

maintainability2 = K2 . (Size of doc)/(Time to write doc)

0

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

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

Це означає, що всі логічно схожі повторювані шаблони повинні бути вилучені у відповідну абстракцію: Подібні кодові блоки? Витягніть його для функціонування. Змінні, які, здається, зустрічаються разом? Витягніть їх у структуру / клас. Класи, члени яких відрізняються лише за типом? Вам потрібен загальний. Ви, здається, перераховуєте те саме в багатьох місцях? Обчисліть на початку та збережіть значення у змінній. Це призведе до скорочення коду. Це принцип DRY в основному.

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

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

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


0

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

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

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

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