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

Чистий код

Embed Size (px)

DESCRIPTION

Якісний код забезпечує швидкість розробки програмних продуктів. Олександр Павлишак

Citation preview

Якісний код

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

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

[email protected]

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

Maintainability

>50%

Зміни

Багфікси

Підтримка

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

Maintainability == $

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

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

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

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

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

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

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

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

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

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

В коді

Код є завжди

Only the Code Tells the Truth

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

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

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

Парадокс!

Якісний код

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

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

Імена

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

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

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

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

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

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

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

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

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

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

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

Константи

...

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

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

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

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

Get, Fetch, Retrieve, Obtain, Acquire

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

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

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

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");

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

List<Person> list =

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

"Still working...";}

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

List<Person> unemployedPeople =

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

"Still working...";}

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

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

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

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

Типові імена

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

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

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

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

Функції

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

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

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

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

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

if (user.IsAuthenticated)

{

SendProcessingCompletedEmail();

}

else

{

RedirectUserToLoginForm(user);

}

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

Good codeBeautiful

Easy to read

Easy to understand

Clean

Clear

TestedCohesive

Compact

Efficient

Obvious

Organic

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

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

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

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

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

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

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

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

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

user.Tasks.GetNewTasks()); }}

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

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

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

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

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

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

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

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

:(

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

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

:(

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

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

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

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;}

Shared state

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

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(...); } ...

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

...

// Catching exceptions is for communists

...Wrong!

http://stackoverflow.com

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Коментарі

...

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

...

http://stackoverflow.com

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

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

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

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

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

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

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)…

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

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

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

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

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

Класи

Single responsibility

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

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

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

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

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

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 }

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

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

Робота

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

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

Правило

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

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

Це просто

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

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

Це не rocket science

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

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

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

Тести

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

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

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

Управління

Маркетинг

Команда

Комунікації

Бачення

Замовник

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

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

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

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

Література

Code Complete, Steve McConnell

Clean Code, Robert C. Martin

Code Craft, Pete Goodliffe