Top Banner
Якісний код Аудиторія: розробники Олександр Павлишак, 2010 [email protected]
58

Чистий код

Jul 02, 2015

Download

Technology

Igor Bronovskyy

Якісний код забезпечує швидкість розробки програмних продуктів.
Олександр Павлишак
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Чистий код

Якісний код

Аудиторія: розробники

Олександр Павлишак, 2010

[email protected]

Page 2: Чистий код

Чому «якісний код»?

Maintainability

>50%

Зміни

Багфікси

Підтримка

Ітеративні методи розробки

Page 3: Чистий код

Maintainability == $

Maintainability == Якісний код

Якісний код == $$

Page 4: Чистий код

Стандартні питання до розробника

Що робить система, коли відбувається Х?

Як конкретно працює функціональність Y?

Звідки дістаються опції Z?

Скільки часу займе реалізувати Х?

Page 5: Чистий код

Де відповіді?

В специфікації

Якщо у вас вона є ;)

В коді

Код є завжди

Only the Code Tells the Truth

Page 6: Чистий код

В реальному житті

Неякісний код сповільнює розробку

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

Парадокс!

Page 7: Чистий код

Якісний код

Як писати якісний код?

Не пишіть поганий код

Page 8: Чистий код

Імена

Page 9: Чистий код

Осмислені іменa

public void Copy(char[] a1, char[] a2){ for (int i = 0; i < a1.Length; i++) { a2[i] = a1[i]; }}

Page 10: Чистий код

Осмислені іменa

public void Copy(char[] source, char[] destination){ for (int i = 0; i < source.Length; i++) { destination[i] = source[i]; }}

Page 11: Чистий код

Ім’я відображає наміри і суть

d, tot, res, srv, c, cc, c1, c2 – BAD!

createdDate, totalCount, result, storageService, characters – GOOD!

Довге змістовне ім’я краще короткого незрозумілого

Змістовне ім’я краще чисельної константи

Page 12: Чистий код

Константи...

if (!resource.Exists){ result = 404;}else if (resource.WasMoved){ result = 301;}else if (user == null){ result = 401;}...

Page 13: Чистий код

Константи

...

if (!resource.Exists){ result = HttpStatusCode.NotFound;}else if (resource.WasMoved){ result = HttpStatusCode.MovedPermanently;}else if (user == null){ result = HttpStatusCode.Unauthorized;}...

Page 14: Чистий код

Коротке ім’я – коротка видимість

int[] elements = …for (int i = 0; i < elements.Count(); i++){ elements[i] = elements[i] * 2;}

Page 15: Чистий код

Послідовні імена

Get, Fetch, Retrieve, Obtain, Acquire

Feed feed = FeedService.ObtainSyndicationFeed();if (feed.IsValid){ Storage feedStorage = GetFileStorage(path); List<Post> posts = feed.RetrievePosts(); feedStorage.Save(posts);}

Виберіть одне і послідовно дотримуйтесь його

Page 16: Чистий код

Надлишковість

nameString, customersArray

sName, iCount, arrCustomers

string nameString = "Kenny";string[] girlsArray = FindAllAttractiveGirls();

FileStream ouputFile = File.Open("c:\\autoexec.bat");Url urlToBashOrg = new Url("http://bash.org.ru");

Page 17: Чистий код

Імена з предметної області

List<Person> list =

country.GetAllUnemployedPeople();if (list.Count > 1000 * 1000){ presidentFacebookPage.CurrentStatus =

"Still working...";}

Page 18: Чистий код

Імена з предметної області

List<Person> unemployedPeople =

country.GetAllUnemployedPeople();if (unemployedPeople.Count > 1000 * 1000){ presidentFacebookPage.CurrentStatus =

"Still working...";}

Page 19: Чистий код

Імена з предметної області

if (pageIdsByUserId.Get(user.Id) .ContainsKey(page.Id) ) {...}

Map<int, Map<int, int>> pageIdsByUserId;

if (user.HasAccessTo(page)) {...}

Page 20: Чистий код

Типові імена

Імена зміннихcustomer, currentPosition, isCompleted, result

Імена класів – іменникиCustomer, UrlParser, Page, SortAlgorithm

Імена методів – дієсловаGetCustomers(), CreateDirectory(), OpenSocket(), Save(), Close()

Page 21: Чистий код

Ваш код будуть читати

Page 22: Чистий код

Функції

Page 23: Чистий код

Розмір має значення

Максимальний: 20 рядків

Оптимальний: <= 5 рядків

Рівень відступів: <= 2

Page 24: Чистий код

Коротка функція

if (user.IsAuthenticated)

{

SendProcessingCompletedEmail();

}

else

{

RedirectUserToLoginForm(user);

}

Сприяє документуванню коду

Page 25: Чистий код

Good codeBeautiful

Easy to read

Easy to understand

Clean

Clear

TestedCohesive

Compact

Efficient

Obvious

Organic

Page 26: Чистий код

Рівень абстракції

Функція виконує лише одну операцію

Всередині функції – один рівень абстракції

Page 27: Чистий код

Рівень абстракції

public void SynchronizeNewTasks(){ string database = "DBGLOBAL"; if (user.HasAttribute("LOCAL")) { database = service.GetDatabaseBaseName() +

"_LOCAL"; } if (user.Tasks.ContainsNewTasks()) { SaveNewTasks(database, user.Tasks.GetNewTasks()); }}

Page 28: Чистий код

Рівень абстракції

public void SynchronizeNewTasks(){ if (user.Tasks.ContainsNewTasks()) {

string database = GetDatabaseForUser( user); SaveNewTasks(database,

user.Tasks.GetNewTasks()); }}

Page 29: Чистий код

Аргументи функцій

Без аргументів, Save() – найкращі :)

Один аргумент, Send(address) – теж нічого

Два, Copy(source, destination) – ОК

Три – вже не дуже

Більше – значно погіршують читабельність :(

Page 30: Чистий код

Булеві аргументи

char[] source = ...char[] destination = ...Copy(source, destination, true);

:(

Page 31: Чистий код

Булеві аргументи

List<Task> tasks = ...;Storage storage = ...;SaveNewTasks(tasks, storage, true, false, false, true, true);

:(

Page 32: Чистий код

Вихідні аргументи

byte[] fileContent = ...byte[] compressedContent;Compress(fileContent, out compressedContent);

Page 33: Чистий код

Побічні ефекти

public bool IsPasswordValid(string userName, string password){ User user = Database.FindUserByName(userName); string encryptedPassword = Encryptor.Encrypt(password); bool result = user.EncryptedPassword == encryptedPassword; if (result) { Session.Initialize(); } return result;}

Page 34: Чистий код

Shared state

Мінімізуйте спільні дані

Page 35: Чистий код

Exceptions замість кодів помилок

if (FindUserByName(userName, out user) == STATUS_OK)

{ if (Encrypt(password, out encryptedPassword) == STATUS_OK)

{ bool result = user.EncryptedPassword == encryptedPassword; if (result)

{ if (Session.Initialize() == STATUS_OK) return true; else LogError(...); } ...

Page 36: Чистий код

Обробляйте помилки

...

// Catching exceptions is for communists

...Wrong!

http://stackoverflow.com

Page 37: Чистий код

Граничні умови

Враховуйте граничні умови

Тестуйте граничні умови

public void Sort(int[] array){ ...}

Page 38: Чистий код

Не дублюйте код

Page 39: Чистий код

Непотрібний код

Функції, які не ніде не використовуються – видаляйте їх!

Код, який ніколи не викликається – видаляйте його!

Історія – в системі контролю версій

Page 40: Чистий код

Здоровий глузд

Код не повинен викликати здивування

Поведінка має бути очевидна

«Ви працюєте з чистим кодом, якщо кожна функція робить приблизно те, що ви очікуєте»

Page 41: Чистий код

Ваш код будуть читати

Page 42: Чистий код

Коментарі

Page 43: Чистий код

...

/////////////////////////////////////// this is a well commented line

...

http://stackoverflow.com

Page 44: Чистий код

Про коментарі

Надавайте перевагу коду

Коментуйте те, що не можна виразити в коді

Проблема коментарів – супровід

Неточні коментарі – гірше відсутності коментарів

Коментарі не компенсують поганого коду

Page 45: Чистий код

vs.

if (server.IsRedirectNeeded())…

// check if we should redirect to another URLif (server.HasResponse &&     server.HttpResponseCode == 301)…

vs.

bool isRedirectNeeded = server.HasResponse &&     server.HttpResponseCode == 301;if (isRedirectNeeded)…

Page 46: Чистий код

Як коментувати

Коментуйте публічний API

Коментуйте внутрішній API тільки якщо він складний

Не використовуйте коментар там, де можна використати функцію або змінну

Видаляйте закоментований код

Page 47: Чистий код

Класи

Page 48: Чистий код

Single responsibility

Класи повинні бути компактні

Компактність визначається кількістю відповідальностей (responsibilities)

Клас повинен мати одну відповідальність (single responsibility)

Клас повинен мати одну причину для зміни

Багато компактних класів

Page 49: Чистий код

if-statementsЧим більше if-statements, тим більше потенційних помилок

public int GetHours() { if (_numberOfManuals <= SMALL) { if (_serviceType == "writing") return 30 * _numberOfManuals; if (_serviceType == "analysis") return 10; } else if (_numberOfManuals <= MEDIUM) { if (_serviceType == "writing") return (SMALL * 30) + (20 * _numberOfManuals - SMALL);

if (_serviceType == "analysis") return 20; } else //i.e. LARGE { if (_serviceType == "writing") return (SMALL * 30) + (20 * (MEDIUM - SMALL)) + (10 * _numberOfManuals - MEDIUM); if (_serviceType == "analysis") return 30; } return 0; //Just a default fallback for this contrived example }

Page 50: Чистий код

Ваш код будуть читати

Page 51: Чистий код

Ще кілька думок

Page 52: Чистий код

Робота

Робота розробника не закінчується після того, коли програма запрацювала

Після цього потрібно покращити структуру і чистоту коду

Page 53: Чистий код

Правило

Дотримуйтесь «правила бойскаута»

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

Page 54: Чистий код

Це просто

Переважно неважко покращити код

Лише трохи переіменувать, введення нових функцій, трохи реструктуризації

Це не rocket science

Навіть якщо це не просто, ...

... це все одно цікаво

Чому б цим не зайнятись?

Page 55: Чистий код

Тести

Чистка коду тісно пов’язана з тестами

Тести – впевненість

Page 56: Чистий код

Код – це ще не все

Управління

Маркетинг

Команда

Комунікації

Бачення

Замовник

Page 57: Чистий код

Професіоналізм

Будьте професіоналом

Професіонали не пишуть неякісний код

Якщо професіонал написав неякісний код, він його почистить

Page 58: Чистий код

Література

Code Complete, Steve McConnell

Clean Code, Robert C. Martin

Code Craft, Pete Goodliffe