Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Рефакторинг

Рефакторинг. Виміри у конструюванні.

Лекція 3.

1. Рефакторинг.

2. Виміри у конструюванні.

 

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

Код являється одним із найбільш чітко детермінованих активів проекту (поступово такими стають і моделі, які будуються на основі структур метаданих, і тісно пов’язані з кодом – наприклад, UML). Також код є носієм тієї функціональності, яка вимагається. Відповідно, застосування вимірів у відношенні до коду стає тим самим інструментом, який впливає і на сам код. Застосування вимірів, зокрема, метрик, дозволяє визначити необхідність проведення рефакторингу коду, як методам його реструктуризації, що мають на меті без зміни змісту (тобто функціональності та функціональної цілісності) забезпечити рішення задач мінімізації складності, готовності до змін (гнучкості), прозорості документування та інших актуальних аспектів конструювання. Термін «рефакторинг» виник із слова «факторинг», яке у контексті структурного програмування означає максимально можливу декомпозицію програми на складові.

Для виконання рефакторингу існують певні попереджувальні знаки, які Мартін Фаулер ще називає «запахами» (smells):

1. Код повторюється, що говорить про неповну факторизацію системи на етапі проектування;

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

3. Цикл занадто великий або глибоко вкладений в інші цикли. Часто знизити складність циклу та краще факторизувати код допоможе перетворення тіла циклу в метод;

4. Клас має погану зв’язність, тобто має багато аспектів відповідальності, які ніяк не пов’язані між собою. Тоді краще розбити клас на декілька класів так, щоб кожний із них отримав зв’язний набір аспектів;

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

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

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

8. Метод використовує більше елементів іншого класу, ніж своїх власних. Метод потрібно перемістити в інший клас і викликати із старого;

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

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

11. Об’єкт-посередник нічого не робить, просто перенаправляє виклики методів до інших класів. Подумайте, чи можна такий метод усунути;

12. Один клас надто багато знає про інший. Намагайтесь зробити інкапсуляцію більш строгою;

13. Метод має невдале ім’я;

14. Складний код пояснюється за допомогою коментарів. Як зауважують Б. Керніган та Б. Плагер: не документуйте поганий код– перепишіть його;

15. У коді присутні глобальні змінні. Перегляньте код на можливість їх усунення;

16. У програмі міститься код, який може ще знадобитися. Думка експертів однозначна: не пишіть гіпотетично потрібний код, а підвищену увагу приділіть ясності та зрозумілості коду, що потрібен прямо зараз.

Значення слова «рефакторинг» досить розмите: так називають виправлення дефектів, реалізацію нової функціональності, модифікацію проекту – по суті, будь-яку зміну коду. Проте самі по собі, без ефективної стратегії зміни коду переваг не мають.

Рефакторинг на рівні даних:

· Якщо Ви використовуєте числовий або рядковий літерал, наприклад, 3.14, замініть його іменованою константою, такою як PI.

· Якщо ім’я змінної неінформативне, присвойте їй краще ім’я.

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

· Заміна виразу на виклик методу зазвичай слугує усуненню з коду виразів, які повторюються.

· Якщо змінна використовується більш, ніж з однією ціллю (часто такими є i, j, temp, x), створіть під кожну ціль свою змінну та оберіть для неї більш визначене ім’я.

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

· Якщо елементарний тип даних необхідно розширити додатковими формами поведінки (наприклад, більш строгим контролем типу) або додатковими даними, перетворіть його у клас і реалізуйте потрібну поведінку. Це відноситься й до простих числових типів на зразок Money чи Temperature, і до перечислень, таких як Color, Shape чи Country.

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

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

Рефакторинг на рівні окремих операторів:

· Спрощуйте логічні вирази, вводячи грамотно названі проміжні змінні.

· Якщо вираз досить складний, винесіть його в грамотно названу булеву функцію.

· Якщо в кінці блоків else та if є однаковий фрагмент коду, винесіть його за межі оператора if-then-else.

· Використовуйте замість управляючої змінної виходу із циклу break або return.

Рефакторинг на рівні окремих методів:

· Іноді фрагмент методу краще представити окремим методом.

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

· Якщо метод дуже об’ємний, спробуйте перетворити його у клас і розбити на кілька методів.

· Заміна складного алгоритму на простий.

· Якщо метод потребує додаткової інформації, передавайте її у вигляді додаткового параметра, і навпаки, якщо метод параметра не потребує – видаліть його.

· Розділення операцій запиту даних від операцій по їх зміні.

· Об’єднання схожих методів шляхом їх параметризації.

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

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

Рефакторинг реалізації класів:

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

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

Рефакторинг інтерфейсів класів:

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

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

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

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

· Якщо дані-члени відкриті, краще зробити їх закритими та реалізовувати доступ до них за допомогою методів.

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

· Якщо степінь спеціалізації підкласу невисока, об’єднайте його із суперкласом.

Невірному застосуванню рефакторингу можуть запобігати:

· Збереження первісного коду.

· Виконання окремих видів рефакторингу по одному за раз.

· Складання списку дій, що Ви збираєтесь виконувати та списку видів рефакторингу, що будете виконувати пізніше.

· Часте створення контрольних точок.

· Задання компілятору найбільш строгого рівня діагностики.

· Створення регресивних та інших додаткових тестів.

· Зміна підходу в залежності від ризикованості рефакторингу (деякі види рефакторингу пов’язані з більш високим рівнем ризику, ніж інші).

Рефакторинг – зміна працездатного коду, яка не впливає на поведінку програми. Тому не потрібно його застосовувати для приведення програми до працездатного стану. Також іноді код краще переписати з нуля, ніж покращувати невеликими змінами.

Приклади рефакторингу:

До: x = y % 32;
Після: x = y & 31;

До: x = y * 8;
Після: x = y << 3;

До: x = y / w + z / w;
Після: x = (y + z) / w;

До: if(a==b && c==d && e==f) {...}
Після: if(((a-b)|(c-d)|(e-f))==0) {...}

До: if((x & 1) || (x & 4)) {...}
Після: if(x & 5) {...}

До: if(x >= 0 && x < 8 && y >= 0 && y < 8) {...}
Після: if(((unsigned)(x|y))<8) {...}

До: if((x==1) || (x==2) || (x==4) || (x==8) ||...)
Після: if(x&(x-1)==0 &&x!=0)

До: if((x==2) || (x==3) || (x==5) || (x==7) || (x==11) || (x==13) || (x==17) || (x==19)) {...}
Після: if((1<<x) & ((1<<2)|(1<<3)|(1<<5)|(1<<7)|(1<<11)|(1<<13)|(1<<17)|(1<<19))) {...}

До: #define abs(x) (((x)>0)?(x):-(x))
Після: static i32 abs(i32 x)
{
i32 y = x >> 31;
return (x ^ y) - y;
}


До: int a[3][3][3]; int b[3][3][3];
for(i=0;i<3;i++)
for(j=0;j<3;j++)
for(k=0;k<3;k++)
b[i][j][k] = a[i][j][k];
Після: struct 3DArrayType
{
int elem[3][3][3];
};
3DArrayType a,b;
b = a;


До: for(i=0;i<3;i++)
for(j=0;j<3;j++)
for(k=0;k<3;k++)
a[i][j][k] = 0;
Після: memset(a, 0, sizeof(a));

 

<== предыдущая лекция | следующая лекция ==>
 | Розмірно-орієнтовані метрики
Поделиться с друзьями:


Дата добавления: 2014-01-07; Просмотров: 852; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.025 сек.