Чистий код

445 views
437 views

Published on

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

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
445
On SlideShare
0
From Embeds
0
Number of Embeds
85
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • <номер>
  • Чистий код

    1. 1. Якісний код Аудиторія: розробники Олександр Павлишак, 2010 pavlyshak@gmail.com
    2. 2. Чому «якісний код»? Maintainability >50% Зміни Багфікси Підтримка Ітеративні методи розробки
    3. 3. Maintainability == $ Maintainability == Якісний код Якісний код == $$
    4. 4. Стандартні питання до розробника Що робить система, коли відбувається Х? Як конкретно працює функціональність Y? Звідки дістаються опції Z? Скільки часу займе реалізувати Х?
    5. 5. Де відповіді? В специфікації Якщо у вас вона є ;) В коді Код є завжди Only the Code Tells the Truth
    6. 6. В реальному житті Неякісний код сповільнює розробку Щоб дотриматись графіка, розробники швидко пишуть неякісний код Парадокс!
    7. 7. Якісний код Як писати якісний код? Не пишіть поганий код
    8. 8. Імена
    9. 9. Осмислені іменa public void Copy(char[] a1, char[] a2) { for (int i = 0; i < a1.Length; i++) { a2[i] = a1[i]; } }
    10. 10. Осмислені іменa public void Copy(char[] source, char[] destination) { for (int i = 0; i < source.Length; i++) { destination[i] = source[i]; } }
    11. 11. Ім’я відображає наміри і суть d, tot, res, srv, c, cc, c1, c2 – BAD! createdDate, totalCount, result, storageService, characters – GOOD! Довге змістовне ім’я краще короткого незрозумілого Змістовне ім’я краще чисельної константи
    12. 12. Константи ... if (!resource.Exists) { result = 404; } else if (resource.WasMoved) { result = 301; } else if (user == null) { result = 401; } ...
    13. 13. Константи ... if (!resource.Exists) { result = HttpStatusCode.NotFound; } else if (resource.WasMoved) { result = HttpStatusCode.MovedPermanently; } else if (user == null) { result = HttpStatusCode.Unauthorized; } ...
    14. 14. Коротке ім’я – коротка видимість int[] elements = … for (int i = 0; i < elements.Count(); i++) { elements[i] = elements[i] * 2; }
    15. 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); } Виберіть одне і послідовно дотримуйтесь його
    16. 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");
    17. 17. Імена з предметної області List<Person> list = country.GetAllUnemployedPeople(); if (list.Count > 1000 * 1000) { presidentFacebookPage.CurrentStatus = "Still working..."; }
    18. 18. Імена з предметної області List<Person> unemployedPeople = country.GetAllUnemployedPeople(); if (unemployedPeople.Count > 1000 * 1000) { presidentFacebookPage.CurrentStatus = "Still working..."; }
    19. 19. Імена з предметної області if (pageIdsByUserId.Get(user.Id) .ContainsKey(page.Id) ) {...} Map<int, Map<int, int>> pageIdsByUserId; if (user.HasAccessTo(page)) {...}
    20. 20. Типові імена Імена змінних customer, currentPosition, isCompleted, result Імена класів – іменники Customer, UrlParser, Page, SortAlgorithm Імена методів – дієслова GetCustomers(), CreateDirectory(), OpenSocket(), Save(), Close()
    21. 21. Ваш код будуть читати
    22. 22. Функції
    23. 23. Розмір має значення Максимальний: 20 рядків Оптимальний: <= 5 рядків Рівень відступів: <= 2
    24. 24. Коротка функція if (user.IsAuthenticated) { SendProcessingCompletedEmail(); } else { RedirectUserToLoginForm(user); } Сприяє документуванню коду
    25. 25. Good code Beautiful Easy to read Easy to understand Clean Clear Tested Cohesive Compact Efficient Obvious Organic
    26. 26. Рівень абстракції Функція виконує лише одну операцію Всередині функції – один рівень абстракції
    27. 27. Рівень абстракції public void SynchronizeNewTasks() { string database = "DBGLOBAL"; if (user.HasAttribute("LOCAL")) { database = service.GetDatabaseBaseName() + "_LOCAL"; } if (user.Tasks.ContainsNewTasks()) { SaveNewTasks(database, user.Tasks.GetNewTasks()); } }
    28. 28. Рівень абстракції public void SynchronizeNewTasks() { if (user.Tasks.ContainsNewTasks()) { string database = GetDatabaseForUser( user); SaveNewTasks(database, user.Tasks.GetNewTasks()); } }
    29. 29. Аргументи функцій Без аргументів, Save() – найкращі :) Один аргумент, Send(address) – теж нічого Два, Copy(source, destination) – ОК Три – вже не дуже Більше – значно погіршують читабельність :(
    30. 30. Булеві аргументи char[] source = ... char[] destination = ... Copy(source, destination, true); :(
    31. 31. Булеві аргументи List<Task> tasks = ...; Storage storage = ...; SaveNewTasks(tasks, storage, true, false, false, true, true); :(
    32. 32. Вихідні аргументи byte[] fileContent = ... byte[] compressedContent; Compress(fileContent, out compressedContent);
    33. 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; }
    34. 34. Shared state Мінімізуйте спільні дані
    35. 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(...); } ...
    36. 36. Обробляйте помилки ... // Catching exceptions is for communists ... Wrong! http://stackoverflow.com
    37. 37. Граничні умови Враховуйте граничні умови Тестуйте граничні умови public void Sort(int[] array) { ... }
    38. 38. Не дублюйте код
    39. 39. Непотрібний код Функції, які не ніде не використовуються – видаляйте їх! Код, який ніколи не викликається – видаляйте його! Історія – в системі контролю версій
    40. 40. Здоровий глузд Код не повинен викликати здивування Поведінка має бути очевидна «Ви працюєте з чистим кодом, якщо кожна функція робить приблизно те, що ви очікуєте»
    41. 41. Ваш код будуть читати
    42. 42. Коментарі
    43. 43. ... /////////////////////////////////////// this is a well commented line ... http://stackoverflow.com
    44. 44. Про коментарі Надавайте перевагу коду Коментуйте те, що не можна виразити в коді Проблема коментарів – супровід Неточні коментарі – гірше відсутності коментарів Коментарі не компенсують поганого коду
    45. 45. vs. if (server.IsRedirectNeeded())… // check if we should redirect to another URL if (server.HasResponse &&      server.HttpResponseCode == 301)… vs. bool isRedirectNeeded = server.HasResponse &&      server.HttpResponseCode == 301; if (isRedirectNeeded)…
    46. 46. Як коментувати Коментуйте публічний API Коментуйте внутрішній API тільки якщо він складний Не використовуйте коментар там, де можна використати функцію або змінну Видаляйте закоментований код
    47. 47. Класи
    48. 48. Single responsibility Класи повинні бути компактні Компактність визначається кількістю відповідальностей (responsibilities) Клас повинен мати одну відповідальність (single responsibility) Клас повинен мати одну причину для зміни Багато компактних класів
    49. 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 }
    50. 50. Ваш код будуть читати
    51. 51. Ще кілька думок
    52. 52. Робота Робота розробника не закінчується після того, коли програма запрацювала Після цього потрібно покращити структуру і чистоту коду
    53. 53. Правило Дотримуйтесь «правила бойскаута» кожен раз коли ви працюєте з кодом, залишайте його трохи чистішим, ніж він був до цього
    54. 54. Це просто Переважно неважко покращити код Лише трохи переіменувать, введення нових функцій, трохи реструктуризації Це не rocket science Навіть якщо це не просто, ... ... це все одно цікаво Чому б цим не зайнятись?
    55. 55. Тести Чистка коду тісно пов’язана з тестами Тести – впевненість
    56. 56. Код – це ще не все Управління Маркетинг Команда Комунікації Бачення Замовник
    57. 57. Професіоналізм Будьте професіоналом Професіонали не пишуть неякісний код Якщо професіонал написав неякісний код, він його почистить
    58. 58. Література Code Complete, Steve McConnell Clean Code, Robert C. Martin Code Craft, Pete Goodliffe

    ×