Я змінив один метод підпису і тепер маю понад 25 000 помилок. Що тепер?


166

Нещодавно я розпочав нову роботу, де працюю над дуже великим додатком (локація 15М). У моїй попередній роботі у нас був аналогічно великий додаток, але (на краще або на гірше) ми використовували OSGi, що означало, що програма розбита на безліч мікросервісів, які можна було самостійно змінювати, компілювати та розгортати. Новий додаток - це лише одна велика база коду, можливо, пара .dlls.

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

На своїй останній роботі я ніколи не стикався з такою проблемою. Що мені робити?


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

137
"понад 25000 помилок", такі числа, показані в VS, часто помиляються. Існує декілька помилок, але, коли збірка часто використовуваного dll зламана, інші збірки також провалюються, що призводить до збільшення астрономічних чисел помилок. Я завжди починаю виправляти з першого повідомлення про помилку, знайденого у виводі збірки, а не у списку помилок.
Бернхард Гіллер

13
Я хотів би бачити підписи до та після того, як ви змінили метод. BTW - 25k помилок насправді не звучить як занадто багато, щоб мати справу. Набридливий так, непростий, так, некерований, ні.
jmoreno

46
Публічний інтерфейс - це договір. Не розривайте таких контрактів - створюйте нові.
Матвій

6
25000 помилок !? Х'юстон, у нас проблема. Однозначно скасуйте зміни та поговоріть зі своїм менеджером, поясніть йому, що вам, можливо, доведеться створити новий інтерфейс взагалі.
Code Whisperer

Відповіді:


349

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

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


79
Це не обов'язково повинен бути новий клас . Залежно від мови та обставин це може бути функція, інтерфейс, ознака тощо
Ян Худек

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

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

13
@theDmi: Я погоджуюсь, що 1 зміна та 25k помилок, швидше за все, означає максимум 2,5 тис. змін, і я би не здивувався, коли виявив, що це близько 250. Багато роботи в будь-якому випадку, але виконано.
jmoreno

33
Ці 25000 помилок можуть бути виправлені однією зміною. Якщо я порушую базовий клас величезної герархії, кожен із похідних класів буде виписувати помилки щодо недійсної бази, кожне використання цих класів буде викривляти помилки щодо класу, що не існує тощо. Уявіть, що це було "getName", і я додав суперечка. Перевизначення класу реалізації "HasAName" зараз не працює (помилка), і все, що успадковується від нього, тепер генерує помилки (всі 1000 класів), а також щоразу, коли я створюю екземпляр будь-якого з них (24x на клас на середній). Виправлення - це один рядок.
Якк

80

Розділіть і завоюйте рефактори

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

Розділити

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

Перемагай

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

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

Приклад

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

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

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

Іноді це не працює

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

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


12
Це. Рефактор, якщо ви можете (безпечно), інакше вам потрібна належна міграція.
sleske

3
І для любові до будь-якого, будь ласка, скористайтеся вбудованими інструментами рефакторингу вашого IDE, а не просто змінюйте підпис (наприклад) методу локально, а потім обмінюйте виправлення наслідків помилок.
KlaymenDK

36

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

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

Удачі.


15
Це перший крок, який я б зробив - "Я молодший, і мій начальник сказав мені зробити щось, і тепер я отримую дійсно велике повідомлення про помилку, але мій начальник не сказав мені про це". Крок 1: "Ей, босе, я це зробив, але я отримую помилки 25 к. Зараз це повинно статися, або ..."
Pimgd

28

Не торкайся. Не робіть нічого.

Замість цього сідайте на стілець і кричіть "Heeeeelp !!!!!" як можна голосніше.

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

І, можливо, начальник сказав вашим старшим колегам зробити ту саму зміну, і вони сказали «ні». Бо вони знали, що станеться. Ось чому вам і дали роботу.


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

@TheGreatDuck: Скажіть, ви ніколи не бачили інтерфейсу, що використовується скрізь, і неправильного скрізь. Я впевнена.
Джошуа

@ Джошуа, це навіть не стосується того, що я щойно сказав. Бували випадки, коли виправляли незначну помилку - це не завжди найрозумніша ідея, це означає переписання 10 000+ рядків коду. На жаль, новий працівник може виявитись досить легковажним, щоб витягнути 10 всеногих поза роботою, переписавши цей код, щоб справити враження на свого начальника і зробити це. Звичайно, це чудово робити, але іноді достатньо. Вам просто потрібно прийняти існування помилки.
Велика качка

1
@Joshua btw, я приєднався лише до цієї спільноти, оскільки це запитання з’явилось у моїй популярній стрічці запитів. Я не маю досвіду такого масштабного дизайну. Я просто погодився з поглядом цієї людини.
Велика качка

22

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


10

Оцініть

Оцініть, чи потрібна ця зміна, чи ви можете додати новий метод та знехтувати інший.

Вперед

Якщо необхідні зміни; тоді необхідний план міграції.

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

Це пункт фіксації: перевірте, чи всі тести проходять, виконувати, натискати.

Міграція

Зайнята робота - це переміщення всіх абонентів старого методу на новий. На щастя, це можна зробити поступово завдяки експедитору.

Тож ідіть вперед; не соромтеся використовувати інструменти для надання допомоги ( sedє найосновнішими, є й інші).

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

Це пункт фіксації (або, можливо, декілька пунктів фіксації): перевірте, чи всі тести проходять, введіть, натисніть.

Видалити

Через деякий час (можливо, за день) просто видаліть старий метод.


4
sedце, мабуть, погана ідея ... Краще те, що насправді "розуміє" мову і не зробить ненавмисних різких змін.
wizzwizz4

1
@ wizzwizz4: На жаль, я знайшов дуже мало інструментів, які насправді добре розуміють мову для C ++; Здається, більшість інструментів задовольняє перейменування, і все. Зрозуміло, перейменування лише точних викликів методу (і не будь-яких перевантажень або неспоріднених, але аналогічно названих викликів методів) вже вражає, але це недостатньо для нічого складнішого. Принаймні, вам знадобляться здатності (1) перемішувати аргументи, (2) застосовувати перетворення до заданого аргументу (дзвінок, .c_str()наприклад) та вводити нові аргументи. sedякось працює, компілятор згодом вирішує свої проблеми.
Матьє М.

1
sed(або ed) може бути достатнім для подібних речей - до тих пір, поки ви належним чином перегляньте відмінності перед тим, як здійснити.
Toby Speight

Це TCRR html, так? :)
Даніель Спрінгер

8

Якщо ваша зміна підпису методу - це лише зміна імені, простим рішенням є використання інструментів для автоматизації змін у 25000 класах, на які посилається на відповідний метод.

Я припускаю, що ви просто відредагували код вручну, що призвело до всіх помилок. Я також припускаю, що ви знайомі з Java (бачите вашу посилання на OSGi), тому, наприклад, у Eclipse (я не знаю, яке середовище програмування ви використовуєте, але в інших середовищах є подібні інструменти рефакторингу), ви можете використовувати "Refactoring -> Rename" оновити всі посилання на метод, який не повинен залишати помилок.

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


2
ОП спеціально сказала, що OSGi працював на їх попередній роботі, тому це не дуже актуально.
CVn

3
@ MichaelKjörling Якщо ОП був програмістом Java на їхній попередній роботі, є більший шанс, ніж вони, і програміст Java в цій роботі.
Багатий

@ MichaelKjörling Я хотів дати конкретну рекомендацію, використовуючи Eclipse для рефакторингу, оскільки OP знайомий з Java. Чи справді ОП використовує Java для поточного проекту, я думаю, є менш важливим, але я повинен уточнити свою відповідь. Дякую.
MikkelRJ

6

Ось мій внесок.

Нещодавно я почав нову роботу, де працюю над дуже великим додатком (15М рядків коду).

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

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

Як зазначав @Greg, ви повинні мати можливість протестувати існуючий код, щоб мати дійсне посилання для порівняння (регресійні тести). Ваше рішення повинно бути здатне генерувати ті самі результати, що й існуючі. На цьому етапі вам не байдуже, чи правильні результати чи ні . Перша мета - рефактор, а не виправлення помилок. Якщо в існуючому рішенні сказано "2 + 2 = 42", ваше рішення також має бути. Якщо це не кидає винятків, і ваш не повинен. Якщо вона повертає нулі, і ваші повинні повернути нулі. І так далі. В іншому випадку ви поставите під загрозу 25-рядовий рядок коду.

Це заради ретро-сумісності.

Чому? Тому що зараз - це ваша унікальна гарантія успішного рефактора.

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

Для вас терміново потрібен спосіб гарантувати ретро-сумісність. Ось тут ваш перший виклик. Ізолюйте компонент для тестування одиниць.

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

Після того, як ви розробили та впровадили новий "контракт", замініть старий. Позбавити його або вийняти.

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

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

Як тільки ваше перше завдання буде виконано. Викрийте ці помилки / функції вашому начальнику.

Нарешті, як @Stephen сказав:

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


5

Перевірте це.

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

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

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