Качествен програмен код Светлин Наков Национална академия по разработка на софтуер www.devbg.org.

Презентация:



Advertisements
Похожие презентации
Средства на Visual Studio Team System за управление на проекти, версии на системата, извеждане на отчети, изграждане на изпълними версии на системата.
Advertisements

Практически съвети за оптимално използване на сървърните ресурси Любомир Русанов.
Как да напишем некомерсиална книга с екип от 30 автора? Светлин Наков Консултантска агенция по информационни технологии
Съдържание Кои сме ние и защо сме тук? Какво е nZoom? Какви са ползите от nZoom? Допълнителна информация.
Microsoft Visual Studio Team System (VSTS). Основни моменти: ВЪВЕДЕНИЕ ПРЕДИМСТВА НА VISUAL STUDIO TEAM SYSTEM МЕТОДОЛОГИИ РЕАЛИЗАЦИЯ НА МЕТОДОЛОГИИТЕ.
Одитиране на уеб сайтове Правилният път към превръщането на посетителите в клиенти.
ОСНОВИ НА ИНФОРМАТИКАТА АЛГОРИТМИ. 1. Науката информатика Предмет на науката информатика е информацията и основните информационни дейности Компютърна.
ПРЕДСТАВЯНЕ НА АЛГОРИТМИ. Прилагат се три основни начина за описание на алгоритмите: Словесно Блок – схеми Алгоритмични (програмни) езици.
Услуги и ресурси на интернет от ново поколение СА "Д.А.Ценов" - гр. Свищов.
Основи на PKI - Public Key Infrastructure Росица Младенова Фак
Myths, Folk Tales, Fables, and Fairy Tales A PowerPoint Presentation By Kim Denney, Lake Murray Elementary, Lexington School District One.
Как се измерва успеха на една имейл кампания ? Добре дошли Twitter hashtag: #eiwebinar Invest Невяна Коева Маркетинг специалист Invest.com.
Въведение в ISO 27001Page 1 Въведение в международния стандарт ISO/IEC 27001:2005.
Създаване на циркулярни документи. 1. Структура на циркулярен документ А) Циркулярни документи: Компютърни текстови документи, които представляват образци,
По Безопасност и Защита Изготвил: Атанасис Авгеринудис Ф. 7210, гр. 30 П Р Е З Е Н Т А Ц И Я.
С ЪДЪРЖАНИЕ : Какво е Linux? Ядро Обвивка X Среда Свободен софтуер Ubuntu Debian Отворен код Дистрибуции.
7 стъпки за отскок на Вашата имейл кампания Добре дошли Invest Невяна Коева Маркетинг специалист Invest.com.
Внедряване на логери за разход на вода год.
Използване на макроси. Макрос Макросът представлява запомнена серия от команди Макросът представлява запомнена серия от команди Изпълняват се в приложенията.
Транксрипт:

Качествен програмен код Светлин Наков Национална академия по разработка на софтуер

Лекторът Светлин Наков Директор на Национална академия по разработка на софтуер (НАРС)Директор на Национална академия по разработка на софтуер (НАРС) Безплатни курсове за програмисти – Java и.NETБезплатни курсове за програмисти – Java и.NET Обучение по стипендия + осигурена работаОбучение по стипендия + осигурена работа Председател на Българска асоциация на разработчиците на софтуер (БАРС)Председател на Българска асоциация на разработчиците на софтуер (БАРС) Преподавател по съвременни софтуерни технологии в СУ "Св. Климент Охридски"Преподавател по съвременни софтуерни технологии в СУ "Св. Климент Охридски" Консултант по разработка на софтуерКонсултант по разработка на софтуер Носител на наградата "Джон Атанасов" на президента на България за 2004Носител на наградата "Джон Атанасов" на президента на България за 2004

Съдържание Дефиниция за качествен кодДефиниция за качествен код Софтуерен дизайнСофтуерен дизайн Висококачествени подпрограмиВисококачествени подпрограми Защитно програмиранеЗащитно програмиране Правилно използване на променливитеПравилно използване на променливите Имената на променливитеИмената на променливите Преработка на съществуващ кодПреработка на съществуващ код Самодокументиращ се кодСамодокументиращ се код

Какво е качествен програмен код? Качествен програмен код

Какво е качествен код? Качеството на софтуера има 2 аспекта:Качеството на софтуера има 2 аспекта: Външно качество – видимото за потребителяВъншно качество – видимото за потребителя Коректност на софтуераКоректност на софтуера Удобство и леснота за работаУдобство и леснота за работа Производителност (скорост на работа)Производителност (скорост на работа) Вътрешно качество – вътрешната организация на архитектурата и програмния кодВътрешно качество – вътрешната организация на архитектурата и програмния код РазбираемостРазбираемост Леснота за промяна и добавяне на функционалност (поддръжка)Леснота за промяна и добавяне на функционалност (поддръжка) Простота на реализациятаПростота на реализацията

Какво е качествен код? Характеристики за качество на кода:Характеристики за качество на кода: КоректностКоректност Четимост и разбираемостЧетимост и разбираемост Висока свързаност на отговорностите (strong cohesion) на всички нива (модули, класове, методи)Висока свързаност на отговорностите (strong cohesion) на всички нива (модули, класове, методи) Функционална независимост (loose coupling) на всички нива (модули, класове, методи)Функционална независимост (loose coupling) на всички нива (модули, класове, методи) Добро, консистентно форматиранеДобро, консистентно форматиране Подходящо и консистентно именуване на класовете, методите, променливите и останалите елементиПодходящо и консистентно именуване на класовете, методите, променливите и останалите елементи Добра документация, вградена в кодаДобра документация, вградена в кода

Какво е качествен софтуерен дизайн? Качествен програмен код

Софтуерен дизайн Качеството на софтуера силно зависи от качеството на дизайнаКачеството на софтуера силно зависи от качеството на дизайна Дизайнът е трудно-дефинируем процесДизайнът е трудно-дефинируем процес Итеративен, недетерминистиченИтеративен, недетерминистичен Няма точна рецепта как да се правиНяма точна рецепта как да се прави Основна цел на дизайна:Основна цел на дизайна: Да се управлява сложността на софтуераДа се управлява сложността на софтуера Основен похват при дизайна:Основен похват при дизайна: Функционална декомпозиция на проблемите на всички ниваФункционална декомпозиция на проблемите на всички нива

Какво е софтуерен дизайн Софтуерният дизайн е:Софтуерният дизайн е: Принципна организация на софтуерната системаПринципна организация на софтуерната система Дизайнът се състои от:Дизайнът се състои от: Архитектурен планАрхитектурен план Описва основните компоненти и подсистеми на системата и взаимодействието между тяхОписва основните компоненти и подсистеми на системата и взаимодействието между тях Детайлен дизайнДетайлен дизайн Описва вътрешната организация на отделните компоненти и подсистемиОписва вътрешната организация на отделните компоненти и подсистеми Описва класовете и методите в класоветеОписва класовете и методите в класовете

Характеристики на дизайна Минимална сложност, леснота за разбиранеМинимална сложност, леснота за разбиране Леснота за поддръжка (промяна и разширяване)Леснота за поддръжка (промяна и разширяване) Функционална независимост между подсистемите, компонентите и класовете (loose coupling)Функционална независимост между подсистемите, компонентите и класовете (loose coupling) Преизползваемост (reusability)Преизползваемост (reusability) Високa входна зависимост (fan-in)Високa входна зависимост (fan-in) Някои utility класове се използват много честоНякои utility класове се използват много често Ниска изходна зависимост (fan-out)Ниска изходна зависимост (fan-out) Един клас да не ползва прекалено много други класовеЕдин клас да не ползва прекалено много други класове Минималност – да няма излишни частиМинималност – да няма излишни части

Процесът на дизайн Функционална декомпозиция:Функционална декомпозиция: Разделяме системата на подсистемиРазделяме системата на подсистеми Разделяме подсистемите на класове и ги подреждаме в пакети (пространства от имена)Разделяме подсистемите на класове и ги подреждаме в пакети (пространства от имена) Разделяме класовете в подпрограми (методи)Разделяме класовете в подпрограми (методи) Проектираме подпрограмите (чрез псевдокод)Проектираме подпрограмите (чрез псевдокод) Не е необходимо да се прави паралелно във всички посокиНе е необходимо да се прави паралелно във всички посоки Започва се от най-важната функционалност за клиентаЗапочва се от най-важната функционалност за клиента

Фази на дизайна Разделяне на подсистемите на класовеРазделяне на подсистемите на класове Идентификация на обектите и процесите от реалния святИдентификация на обектите и процесите от реалния свят Съпоставяне на класове за тези обектиСъпоставяне на класове за тези обекти Идентификация на връзките между обектитеИдентификация на връзките между обектите Проектиране на класова йерархияПроектиране на класова йерархия Използване на шаблони (design patterns)Използване на шаблони (design patterns) Скриване на възможно най-много имплементационни детайлиСкриване на възможно най-много имплементационни детайли

Фази на дизайна Разделяне на класовете на методиРазделяне на класовете на методи Идентификация на действията, които всеки обект може да извършва (методи)Идентификация на действията, които всеки обект може да извършва (методи) Идентификация на съществените характеристики на обектите (атрибути)Идентификация на съществените характеристики на обектите (атрибути) Скриване на възможно най-много имплементационни детайли (private методи)Скриване на възможно най-много имплементационни детайли (private методи) Максимална функционална независимост (loose coupling)Максимална функционална независимост (loose coupling) Висока свързаност на отговорностите (strong cohesion)Висока свързаност на отговорностите (strong cohesion)

Фази на дизайна Проектиране на вътрешността на методитеПроектиране на вътрешността на методите Най-често е отговорност на програмистите, а не на архитектитеНай-често е отговорност на програмистите, а не на архитектите Подбор на подходящи алгоритмиПодбор на подходящи алгоритми Описание на алгоритмите чрез псевдокодОписание на алгоритмите чрез псевдокод

Силата на диаграмите Извикване на уеб услуга Изпълнение на SQL заявка Резултат от SQL заявка XML DataSet Променени данни във вид на XML DataSet Заявки за нанасяне на промените Клиент Web-услуга База данни

Какво са качествените подпрограми (методи)? Качествен програмен код

Защо да използваме методи? Намаляваме сложносттаНамаляваме сложността Разбиваме сложните проблеми на по-простиРазбиваме сложните проблеми на по-прости Добавяме междинни нива на абстракцияДобавяме междинни нива на абстракция Скриваме детайли за имплементациятаСкриваме детайли за имплементацията Намаляваме риска от неуспехНамаляваме риска от неуспех Избягваме повторението на еднакъв кодИзбягваме повторението на еднакъв код Скриваме сложни последователности от действияСкриваме сложни последователности от действия Скриваме работата с указателиСкриваме работата с указатели Опростяваме сложни булеви проверкиОпростяваме сложни булеви проверки

Свързаност на отговорностите Свързаност на отговорностите (strong cohesion) е ключово изискване за методитеСвързаност на отговорностите (strong cohesion) е ключово изискване за методите Генерален принцип: Един метод трябва да прави само едно нещо и да го прави добреГенерален принцип: Един метод трябва да прави само едно нещо и да го прави добре Операциите в един метод трябва да са взаимосвързани – насочени към обща задачаОперациите в един метод трябва да са взаимосвързани – насочени към обща задача Идеалният случай:Идеалният случай: Функционална кохезияФункционална кохезия Методът извършва единична ясно дефинирана операцияМетодът извършва единична ясно дефинирана операция Пример: функция Sqrt()Пример: функция Sqrt()

Допустими видове кохезия Последователна кохезияПоследователна кохезия Редица от стъпки за решаване на единна задачаРедица от стъпки за решаване на единна задача Пример: Send ()Пример: Send () 1.свързваме се към сървъра за поща 2.изпращаме съобщението 3.затваряме връзката Комуникационна кохезияКомуникационна кохезия Свързаност на действията по общи данниСвързаност на действията по общи данни Пример: DisplayReport()Пример: DisplayReport() 1.извличаме данните 2.форматираме ги 3.отпечатваме ги

Допустими видове кохезия Времева кохезияВремева кохезия Действия, които се извършват по едно и също времеДействия, които се извършват по едно и също време Пример: LoadSettings()Пример: LoadSettings() 1.зареждаме настройките за шрифтовете 2.зареждаме настройките за цветовете 3.зареждаме настройките за принтера 4.зареждаме настройките за базата данни 5.зареждаме настройките за Интернет достъпа

Недопустими видове кохезия Логическа кохезияЛогическа кохезия Изпълнява се различно действие според някой входен параметър (код на операция)Изпълнява се различно действие според някой входен параметър (код на операция) Лош пример: ReadAll(int op_code) – прочита артикул, цена, адрес или ЕГН според подадения кодЛош пример: ReadAll(int op_code) – прочита артикул, цена, адрес или ЕГН според подадения код Изключение: Обработчици на събития (event handlers)Изключение: Обработчици на събития (event handlers) Случайна кохезия (липса на свързаност)Случайна кохезия (липса на свързаност) Няколко несвързани едно с друго действияНяколко несвързани едно с друго действия Изключително лоша практика!Изключително лоша практика!

Имената на методите Името трябва да описва всичко, което методът извършваИмето трябва да описва всичко, което методът извършва Ако няма подходящо име, имаме лоша кохезия!Ако няма подходящо име, имаме лоша кохезия! Избягвайте безлични и общи думичкиИзбягвайте безлични и общи думички Лош пример: HandleStuff(), ProcessData()Лош пример: HandleStuff(), ProcessData() Не използвайте цифри в иметоНе използвайте цифри в името Лош пример: ReadProfile1(), ReadProfile2()Лош пример: ReadProfile1(), ReadProfile2() Дължината на името трябва да е толкова дълга, колкото е необходимо (9-15 символа)Дължината на името трябва да е толкова дълга, колкото е необходимо (9-15 символа) Ако името е прекалено дълго, имаме лоша кохезияАко името е прекалено дълго, имаме лоша кохезия Използвайте английски езикИзползвайте английски език

Имената на методите Имената на функциите трябва да описват връщаната стойностИмената на функциите трябва да описват връщаната стойност Пример: GetNumberOfProcessors()Пример: GetNumberOfProcessors() Имената на процедурите се съставят по схемата + Имената на процедурите се съставят по схемата + Пример: PrintReport(), LoadSettings()Пример: PrintReport(), LoadSettings() Използвайте консистентно противоположноститеИзползвайте консистентно противоположностите Пример: OpenFile() и CloseFile()Пример: OpenFile() и CloseFile() Лош пример: OpenFile() и _descriptor_close()Лош пример: OpenFile() и _descriptor_close() Използвайте конвенция за честите операцииИзползвайте конвенция за честите операции Пример: GetName(), GetAge(), SetName(), SetAge()Пример: GetName(), GetAge(), SetName(), SetAge() Спазвайте конвенцията навсякъдеСпазвайте конвенцията навсякъде

Колко да са дълги методите? Предпочитайте кратки методи (до един екран)Предпочитайте кратки методи (до един екран) Методите трябва да имат силна кохезияМетодите трябва да имат силна кохезия Това е много по-важно от дължината им!Това е много по-важно от дължината им! Методите трябва да са дълги "колкото трябва"Методите трябва да са дълги "колкото трябва" Не разделяйте на части даден метод само защото е много дълъгНе разделяйте на части даден метод само защото е много дълъг

Параметрите на методите Подреждайте параметрите в последователност (,, )Подреждайте параметрите в последователност (,, ) Подреждайте консистентно параметрите при методи с подобни параметриПодреждайте консистентно параметрите при методи с подобни параметри Използвайте всички параметриИзползвайте всички параметри Ако връщате статус или код за грешка, сложете този параметър последенАко връщате статус или код за грешка, сложете този параметър последен Не използвайте параметрите като работни променливи (не модифицирайте параметрите)Не използвайте параметрите като работни променливи (не модифицирайте параметрите) Документирайте неочевидните допусканияДокументирайте неочевидните допускания Например мерната единица при подаване на числаНапример мерната единица при подаване на числа

Параметрите на методите Ограничете броя на параметрите до около 7Ограничете броя на параметрите до около 7 Човешкото съзнание не може да следи повече от 7 неща едновременно (знаехте ли това?)Човешкото съзнание не може да следи повече от 7 неща едновременно (знаехте ли това?) Разграничавайте входните от изходните параметри (ако езикът не го поддържа)Разграничавайте входните от изходните параметри (ако езикът не го поддържа) Кога да подаваме обект и кога няколко негови полета?Кога да подаваме обект и кога няколко негови полета? Съобразете се логически методът над какво работи – над обекти или над съвкупност от стойностиСъобразете се логически методът над какво работи – над обекти или над съвкупност от стойности Подавайте параметрите в коректния им редПодавайте параметрите в коректния им ред Използвайте именувано извикване, ако се поддържаИзползвайте именувано извикване, ако се поддържа

Функция или процедура Функция или процедура?Функция или процедура? Използвайте функция когато основната задача на метода е да изчисли и върне някаква стойностИзползвайте функция когато основната задача на метода е да изчисли и върне някаква стойност Уверете се, че всеки път на изпълнение връща стойностУверете се, че всеки път на изпълнение връща стойност Не връщайте указател към локални данниНе връщайте указател към локални данни Запазете в променлива стойността преди да я върнете:Запазете в променлива стойността преди да я върнете: return days * hoursPerDay * ratePerHour; int salary = days * hoursPerDay * ratePerHour; return salary;

Какво е защитно програмиране? Качествен програмен код

Защитно програмиране Защитно програмиране (defensive programming)Защитно програмиране (defensive programming) Насочено към защита на кода от некоректни данниНасочено към защита на кода от некоректни данни Пази кода от грешки, които никой не очакваПази кода от грешки, които никой не очаква Имплементира се чрез проверка на коректността на всички входни данниИмплементира се чрез проверка на коректността на всички входни данни данните, идващи от външни източнициданните, идващи от външни източници входните параметри на методитевходните параметри на методите Имплементира се чрез assertions, изключения и други средства за управление на грешкиИмплементира се чрез assertions, изключения и други средства за управление на грешки

Проверки (assertions) Проверките (assertions) следят за различни очаквания за състоянието на програматаПроверките (assertions) следят за различни очаквания за състоянието на програмата Улавят неочаквани входни параметри или вътрешни състоянияУлавят неочаквани входни параметри или вътрешни състояния Силно улесняват откриването на грешки в кодаСилно улесняват откриването на грешки в кода Представляват изрази от вида:Представляват изрази от вида: assert(условие, съобщение_за_грешка) Ако условието е нарушено, програмата завършва аварийно и се отпечатва грешкатаАко условието е нарушено, програмата завършва аварийно и се отпечатва грешката При release компилация се премахват от кодаПри release компилация се премахват от кода Много са полезни при големи и сложни проектиМного са полезни при големи и сложни проекти

Проверки (assertions) Проверките на практика "документират" скритите допускания, които кодът очакваПроверките на практика "документират" скритите допускания, които кодът очаква Някои езици поддържат assertions, в другите можем да си ги реализираме самиНякои езици поддържат assertions, в другите можем да си ги реализираме сами Типични грешки, улавяни с assertions:Типични грешки, улавяни с assertions: Стойност NULL на входен параметърСтойност NULL на входен параметър Стойност извън допустимия диапазон за входен параметърСтойност извън допустимия диапазон за входен параметър Невалидно състояние на файл, поток или друг манипулатор на ресурсНевалидно състояние на файл, поток или друг манипулатор на ресурс Излизане извън размера на масив или колекцияИзлизане извън размера на масив или колекция

Assertions – препоръки Използвайте изключения или друг механизъм за контрол на очакваните грешкиИзползвайте изключения или друг механизъм за контрол на очакваните грешки Използвайте assertions само за грешки, които никога не трябва да се случватИзползвайте assertions само за грешки, които никога не трябва да се случват Не слагайте изпълним код в assertionНе слагайте изпълним код в assertion Лош пример: assert(ConnectToDatabase(), "Can not establish database connection!")Лош пример: assert(ConnectToDatabase(), "Can not establish database connection!") Използвайте assertions за да документирате входни и изходни условия в методитеИзползвайте assertions за да документирате входни и изходни условия в методите Добавете код за управление на грешката след assertion (за по-голяма надеждност)Добавете код за управление на грешката след assertion (за по-голяма надеждност)

Изключения (exceptions) Изключенията (exceptions) предоставят мощен механизъм за централизирано управление на грешки и непредвидени ситуацииИзключенията (exceptions) предоставят мощен механизъм за централизирано управление на грешки и непредвидени ситуации Позволяват проблемните ситуации да се обработват на много ниваПозволяват проблемните ситуации да се обработват на много нива Улесняват писането и поддръжката на надежден програмен кодУлесняват писането и поддръжката на надежден програмен код Изключенията могат да бъдат класове – да се наследяват и да образуват йерархииИзключенията могат да бъдат класове – да се наследяват и да образуват йерархии Могат да се използват на мястото на assertionsМогат да се използват на мястото на assertions

Изключения – препоръки Използвайте изключения, за да уведомите другите части на кода за проблеми, които не трябва да бъдат игнорираниИзползвайте изключения, за да уведомите другите части на кода за проблеми, които не трябва да бъдат игнорирани Хвърляйте изключение само в ситуации, които наистина са изключителни и трябва да се обработят по някакъв начинХвърляйте изключение само в ситуации, които наистина са изключителни и трябва да се обработят по някакъв начин Ако даден проблем може да се обработи локално, направете го и не хвърляйте изключениеАко даден проблем може да се обработи локално, направете го и не хвърляйте изключение Хвърляйте изключенията на подходящо ниво на абстракцияХвърляйте изключенията на подходящо ниво на абстракция Пример: GetEmplyeeInfo() може да хвърля EmployeeException, но не и FileNotFoundExceptionПример: GetEmplyeeInfo() може да хвърля EmployeeException, но не и FileNotFoundException

Изключения – препоръки Включвайте в съобщението на изключението пълно описание на причината за възникването муВключвайте в съобщението на изключението пълно описание на причината за възникването му Всеки catch блок трябва да прихваща само изключенията, които очаква и знае как да обработва, а не всичкиВсеки catch блок трябва да прихваща само изключенията, които очаква и знае как да обработва, а не всички Catch блоковете трябва да са подредени така, че да започват от изключенията най-ниско в йерархията и да продължават с по-общитеCatch блоковете трябва да са подредени така, че да започват от изключенията най-ниско в йерархията и да продължават с по-общите Избягвайте празни catch блоковеИзбягвайте празни catch блокове Не е правилно да прихващате всички изключения, без да ви интересува типа имНе е правилно да прихващате всички изключения, без да ви интересува типа им

Изключения – препоръки Очаквайте описаните в документацията изключенияОчаквайте описаните в документацията изключения Документирайте изключенията, които вашият код може да предизвикаДокументирайте изключенията, които вашият код може да предизвика Управлявайте всички необработени изключения централизираноУправлявайте всички необработени изключения централизирано Можете да покажете съобщение за проблем на потребителя и да запишете проблема в log файлМожете да покажете съобщение за проблем на потребителя и да запишете проблема в log файл Установете стандарти за изключенията в приложението и дефинирайте класова йерархияУстановете стандарти за изключенията в приложението и дефинирайте класова йерархия Хвърляйте само обекти от тип "изключение" или негови наследници, а не указатели и числаХвърляйте само обекти от тип "изключение" или негови наследници, а не указатели и числа

Колко защитно програмиране да оставим в Release версията Оставете кода, който проверява за важни грешкиОставете кода, който проверява за важни грешки Премахнете кода, който проверява за маловажни грешкиПремахнете кода, който проверява за маловажни грешки Премахнете кода, който предизвиква непосредствени сривовеПремахнете кода, който предизвиква непосредствени сривове Заместете го с код, който прекратява програмата "културно", без загуба на данниЗаместете го с код, който прекратява програмата "културно", без загуба на данни Непременно log-вайте грешките при клиентаНепременно log-вайте грешките при клиента Ако показвате съобщения за проблеми на потребителя, съобразете се с неговите знанияАко показвате съобщения за проблеми на потребителя, съобразете се с неговите знания

Как да използваме променливите? Качествен програмен код

Принципи при инициализиране Проблемите:Проблемите: Неинициализирана променливаНеинициализирана променлива Пример: int value;Пример: int value; Частично инициализирана променливаЧастично инициализирана променлива Пример:Пример: Student student = new Student(); Student.Name = "Бай Мангал"; // Student.Age – не е инициализирано

Инициализирайте променливите в момента на деклариранеИнициализирайте променливите в момента на деклариране Инициализирайте всяка променлива близо до мястото където се използва за пръв пътИнициализирайте всяка променлива близо до мястото където се използва за пръв път Обръщайте специално внимание на променливите за броене и натрупванеОбръщайте специално внимание на променливите за броене и натрупване Инициализирайте член-променливите на един клас в конструктораИнициализирайте член-променливите на един клас в конструктора Принципи при инициализиране

Използвайте настройките на компилатора за автоматично инициализиране на променливитеИзползвайте настройките на компилатора за автоматично инициализиране на променливите Включвайте предупредителните съобщения от компилатораВключвайте предупредителните съобщения от компилатора Проверявайте входните параметри за валидностПроверявайте входните параметри за валидност Проверявайте за невалидни указатели към паметтаПроверявайте за невалидни указатели към паметта Инициализирайте работната памет в началото на програматаИнициализирайте работната памет в началото на програмата Принципи при инициализиране

Обхват, живот, активност Обхват (variable scope) – колко известна е една променливаОбхват (variable scope) – колко известна е една променлива Глобална (статична), член-променлива, локалнаГлобална (статична), член-променлива, локална Диапазон на активност (span) – среден брой линии между обръщенията към даден променливаДиапазон на активност (span) – среден брой линии между обръщенията към даден променлива Живот (lifetime) – обем на кода от първото до последното рефериране в даден методЖивот (lifetime) – обем на кода от първото до последното рефериране в даден метод Проследете къде се използва дадена променлива, нейният диапазон на активност и период на животПроследете къде се използва дадена променлива, нейният диапазон на активност и период на живот Направете обхвата, живота и активността на променливите колкото се може по-малкиНаправете обхвата, живота и активността на променливите колкото се може по-малки

Работа с променливи Инициализирайте променливите извън тялото на цикълаИнициализирайте променливите извън тялото на цикъла Не инициализирайте променлива до момента, в който ще бъде използванаНе инициализирайте променлива до момента, в който ще бъде използвана Групирайте сходните операцииГрупирайте сходните операции Започнете с най-малкия обхват и разширявайте, ако се наложиЗапочнете с най-малкия обхват и разширявайте, ако се наложи Използвайте всяка променлива точно и само за една целИзползвайте всяка променлива точно и само за една цел Избягвайте променливи със скрито значениеИзбягвайте променливи със скрито значение Използвайте всички декларирани променливиИзползвайте всички декларирани променливи

Почивка! Качествен програмен код

Как да именуваме променливите? Качествен програмен код

Именуване на променливи Избирайте добро име!Избирайте добро име! Името трябва да описва точно и ясно обекта, който променливата представляваИмето трябва да описва точно и ясно обекта, който променливата представлява Добри имена: account, blockSize, customerDiscountДобри имена: account, blockSize, customerDiscount Лоши имена: r18pq, __hip, rcfd, val1, val2Лоши имена: r18pq, __hip, rcfd, val1, val2 Адресирайте проблема, който решава променливата – какво вместо какАдресирайте проблема, който решава променливата – какво вместо как Добри имена: employeeSalary, employeesДобри имена: employeeSalary, employees Лоши имена: myArray, customerFile, customerHashTableЛоши имена: myArray, customerFile, customerHashTable

Именуване на променливи Оптимална дължина на името – 10 до 16 символаОптимална дължина на името – 10 до 16 символа Изборът на име зависи от обхватаИзборът на име зависи от обхвата Променливите с по-голям обхват и по-дълъг живот имат по-дълго и описателно име:Променливите с по-голям обхват и по-дълъг живот имат по-дълго и описателно име: protected Account[] mCustomerAccounts; Променливите с малък обхват и кратък живот могат да са по-кратки:Променливите с малък обхват и кратък живот могат да са по-кратки: for (int i=0; i

Именуване на специфични типове данни Именуване на броячиИменуване на броячи Пример: UsersCount, RolesCount, FilesCountПример: UsersCount, RolesCount, FilesCount Именуване на променливи за състояниеИменуване на променливи за състояние Пример: ThreadState, TransactionStateПример: ThreadState, TransactionState Именуване на временни променливиИменуване на временни променливи Пример: index, value, countПример: index, value, count Лош пример: a, aa, tmpvar1, tmpvar2Лош пример: a, aa, tmpvar1, tmpvar2 При булеви променливи използвайте имена, които дават предпоставка за истина или лъжаПри булеви променливи използвайте имена, които дават предпоставка за истина или лъжа Пример: canRead, available, isOpen, validПример: canRead, available, isOpen, valid

Именуване на специфични типове данни Булевите променливи трябва да носят "истина" в името сиБулевите променливи трябва да носят "истина" в името си Пример: isReady, canRead, hasMoreDataПример: isReady, canRead, hasMoreData Лош пример: notReady, cannotRead, noMoreDataЛош пример: notReady, cannotRead, noMoreData Именуване на изброими типовеИменуване на изброими типове Използвайте вградените изброени типове (когато езикът за програмиране ги поддържа):Използвайте вградените изброени типове (когато езикът за програмиране ги поддържа): Color.Red, Color.Yellow, Color.Blue Или използвайте подходящи префикси:Или използвайте подходящи префикси: colorRed, colorBlue, colorYellow Именуване на константи – с главни буквиИменуване на константи – с главни букви Пример: MAX_FORM_WIDTH, BUFFER_SIZEПример: MAX_FORM_WIDTH, BUFFER_SIZE

Кога е необходима конвенция за именуване Когато екипът е по-голямКогато екипът е по-голям Когато програмата ще се поддържа дълго времеКогато програмата ще се поддържа дълго време Когато програмата ще се проверява от други програмисти във Вашата организацияКогато програмата ще се проверява от други програмисти във Вашата организация Когато програмата е прекалено голяма и е невъзможно да се проследят всички модули наведнъжКогато програмата е прекалено голяма и е невъзможно да се проследят всички модули наведнъж Когато програмата ще спре да се развива за известно времеКогато програмата ще спре да се развива за известно време Когато във вашия проект имате много непозната терминология, обща за целия проектКогато във вашия проект имате много непозната терминология, обща за целия проект

Стандартни префикси Унгарска конвенция – използва се все по-рядкоУнгарска конвенция – използва се все по-рядко Дефинирани типове от потребителяДефинирани типове от потребителя Например: typedef int Color;Например: typedef int Color; Семантични префикси (напр. btnSave )Семантични префикси (напр. btnSave ) Не изпускайте букви за да съкратите иметоНе изпускайте букви за да съкратите името Съкращавайте по един и същ начин из целия кодСъкращавайте по един и същ начин из целия код Създавайте имена, които да можете да произнесете (не като btnDfltSvRzlts )Създавайте имена, които да можете да произнесете (не като btnDfltSvRzlts ) Избягвайте комбинации, които водят до друга дума или различно значение (напр. preFixStore )Избягвайте комбинации, които водят до друга дума или различно значение (напр. preFixStore )

Стандартни префикси Документирайте кратките имена в кодаДокументирайте кратките имена в кода Помнете, че имената са предназначени за хората, които ще четат кода, а не за тези които го пишатПомнете, че имената са предназначени за хората, които ще четат кода, а не за тези които го пишат Избягвайте заблуждаващи имена или съкращенияИзбягвайте заблуждаващи имена или съкращения Избягвайте променливи с подобни имена, но с различно предназначениеИзбягвайте променливи с подобни имена, но с различно предназначение Например: UserStatus и User Current StatusНапример: UserStatus и User Current Status Избягвайте имена, които звучат еднаквоИзбягвайте имена, които звучат еднакво Избягвайте цифри в имената (напр. pi314 )Избягвайте цифри в имената (напр. pi314 ) Избягвайте грешно написани думи в именатаИзбягвайте грешно написани думи в имената

Стандартни префикси Избягвайте думи, които често се грешатИзбягвайте думи, които често се грешат Избягвайте използването на повече от един народен езикИзбягвайте използването на повече от един народен език Избягвайте използването на стандартни типове и ключови думи в имената на променливитеИзбягвайте използването на стандартни типове и ключови думи в имената на променливите Не използвайте имена, които нямат нищо общо с това което променливите съдържатНе използвайте имена, които нямат нищо общо с това което променливите съдържат Избягвайте имена, които съдържат трудни за четене символиИзбягвайте имена, които съдържат трудни за четене символи

Какво е преработка на кода (Refactoring)? Качествен програмен код

Митове и реалност за процеса за разработка на софтуер МитътМитът Когато един проект стриктно спазва правилата на процеса за разработка, единствената последвала промяна в кода е само в периода на поддръжка на софтуера (software maintenance phase)Когато един проект стриктно спазва правилата на процеса за разработка, единствената последвала промяна в кода е само в периода на поддръжка на софтуера (software maintenance phase) Така генерирането на код е праволинейно без да се налага преработкаТака генерирането на код е праволинейно без да се налага преработка

Митове и реалност за процеса за разработка на софтуер РеалносттаРеалността Кодът постоянно се променяКодът постоянно се променя Причината: променя се разбирането за проблемната област в хода развитие на проектаПричината: променя се разбирането за проблемната област в хода развитие на проекта Всяка промяна в изискванията налага промени и в съществуващия кодВсяка промяна в изискванията налага промени и в съществуващия код Дори в най-добре управляваните проектиДори в най-добре управляваните проекти

Преработка на кода (Refactoring) Еволюцията на софтуера наподобява биологичната еволюцияЕволюцията на софтуера наподобява биологичната еволюция Някои промени са с благоприятен ефект, други не саНякои промени са с благоприятен ефект, други не са Еволюцията на софтуера е неизбежнаЕволюцията на софтуера е неизбежна Еволюцията е възможност да се приближим към съвършения продуктЕволюцията е възможност да се приближим към съвършения продукт

Преработка на кода (Refactoring) Основно правило на еволюцията на софтуера:Основно правило на еволюцията на софтуера: Еволюцията трябва да подобрява начина на реализация на даден проект Основният начин за реализиране на това правило:Основният начин за реализиране на това правило: Преработката на кода

Кога даден код се нуждае от преработка ? Повторение на кодПовторение на код При проблеми в дублициран код се налага да се правят модификации на няколко местаПри проблеми в дублициран код се налага да се правят модификации на няколко места Даден метод е прекалено обемистДаден метод е прекалено обемист Даден цикъл е прекалено обемист или съдържа дълбоко ниво на влаганеДаден цикъл е прекалено обемист или съдържа дълбоко ниво на влагане Даден клас изпълнява несвързани отговорности (poor cohesion)Даден клас изпълнява несвързани отговорности (poor cohesion) Даден клас не предоставя добро ниво на абстракцияДаден клас не предоставя добро ниво на абстракция

Кога даден код се нуждае от преработка ? (продължение) Даден метод има дълъг списък с параметриДаден метод има дълъг списък с параметри Една промяна налага паралелна модификация на няколко класаЕдна промяна налага паралелна модификация на няколко класа Свързани една с друга данни се използват винаги заедно, но не са обединени в класСвързани една с друга данни се използват винаги заедно, но не са обединени в клас Даден метод използва повече функционалност от други класове отколкото от собствения сиДаден метод използва повече функционалност от други класове отколкото от собствения си Даден клас е прекалено обвързан с другДаден клас е прекалено обвързан с друг Полета на даден клас са publicПолета на даден клас са public

Преработка на код на ниво данни Заместете вълшебните числа и низове с именувана константа (напр BUF_SIZE )Заместете вълшебните числа и низове с именувана константа (напр BUF_SIZE ) Преименувайте дадена променлива с по-ясно и по-информативно име ( p currentPos )Преименувайте дадена променлива с по-ясно и по-информативно име ( p currentPos ) Преработете даден условен израз в методПреработете даден условен израз в метод Използвайте междинни променливи за резултата от сложни изразиИзползвайте междинни променливи за резултата от сложни изрази Преобразувайте обикновени данни в нов класПреобразувайте обикновени данни в нов клас Групирайте свързаните константи в изброими типове (enumerations)Групирайте свързаните константи в изброими типове (enumerations)

Преработка на кода на ниво метод Преметете фрагмент от кода на даден метод в нов метод (extract method)Преметете фрагмент от кода на даден метод в нов метод (extract method) Премахнете даден метод, ако кодът, който съдържа, е прекалено прост и кратъкПремахнете даден метод, ако кодът, който съдържа, е прекалено прост и кратък Преработете дълъг и сложен метод в няколко по-малки или в изцяло нов класПреработете дълъг и сложен метод в няколко по-малки или в изцяло нов клас Премахнете неизползваните параметриПремахнете неизползваните параметри Ако има нужда от допълнителен параметър за даден метод, добавете гоАко има нужда от допълнителен параметър за даден метод, добавете го

Преработка на кода на ниво клас Променете обекти, подавани по стойност, с обекти, подавани по указател (референция)Променете обекти, подавани по стойност, с обекти, подавани по указател (референция) Изнесете общата функционалност за набор от класове в отделен базов класИзнесете общата функционалност за набор от класове в отделен базов клас Преместете метод от един клас в друг, ако той логически принадлежи на последнияПреместете метод от един клас в друг, ако той логически принадлежи на последния Преобразувайте един клас в два или повечеПреобразувайте един клас в два или повече Премахнете даден клас, ако не се ползваПремахнете даден клас, ако не се ползва

Преработка на кода на ниво система Създайте абстракция на данните, върху които нямате контролСъздайте абстракция на данните, върху които нямате контрол Дефинирайте клас, който ще енкапсулира тези данни и чиито обекти ще бъдат подавани на потребителитеДефинирайте клас, който ще енкапсулира тези данни и чиито обекти ще бъдат подавани на потребителите Ако не е наложително, премахвайте цикличните зависимости между класоветеАко не е наложително, премахвайте цикличните зависимости между класовете Ако не е нужна употребата на изключения, използвайте кодове за грешкиАко не е нужна употребата на изключения, използвайте кодове за грешки Използвайте "factory метод" за създаване на инстанции на даден клас според даден параметърИзползвайте "factory метод" за създаване на инстанции на даден клас според даден параметър

Какво е самодокументиращ се код и как се реализира? Качествен програмен код

Стилът на програмиране и документацията Документация на високо нивоДокументация на високо ниво Архитектурен план на систематаАрхитектурен план на системата Документация на ниско нивоДокументация на ниско ниво Разглежда особености в най-големи детайли, касаещи кода на програматаРазглежда особености в най-големи детайли, касаещи кода на програмата Коментарите в кода не са основният източник на документацияКоментарите в кода не са основният източник на документация Добрият стил на програмиране е най-добрата документация!Добрият стил на програмиране е най-добрата документация! Самодокументиращ се кодСамодокументиращ се код Лесно се разбира основната му целЛесно се разбира основната му цел

Характеристики на самодокументиращия се код Добра структура на програмата – подравняване, организация на кодаДобра структура на програмата – подравняване, организация на кода Използване на ясни и лесни за разбиране конструкцииИзползване на ясни и лесни за разбиране конструкции Употреба на подходящи имена на променливи, методи и класовеУпотреба на подходящи имена на променливи, методи и класове Употреба на именувани константи, вместо магически константи и стринговеУпотреба на именувани константи, вместо магически константи и стрингове Минимизация на сложността на реализациятаМинимизация на сложността на реализацията

Самодокументиращ се код – важни въпроси Дава ли интерфейсът на класа добра абстракция?Дава ли интерфейсът на класа добра абстракция? Подходящо ли е името на класа и показва ли основната му цел?Подходящо ли е името на класа и показва ли основната му цел? Става ли ясно от интерфейса как трябва да се използва класа?Става ли ясно от интерфейса как трябва да се използва класа? Показва ли името на метода основната му цел?Показва ли името на метода основната му цел? Всеки метод реализира ли една добре определена задача?Всеки метод реализира ли една добре определена задача? Имената на променливите съответстват ли на тяхната употреба?Имената на променливите съответстват ли на тяхната употреба?

Самодокументиращ се код – важни въпроси (продължение) Групирани ли са свързаните един с друг оператори?Групирани ли са свързаните един с друг оператори? Само една задача ли изпълняват конструкциите за итерация (циклите)?Само една задача ли изпълняват конструкциите за итерация (циклите)? Има ли дълбоко влагане на условни клаузи?Има ли дълбоко влагане на условни клаузи? Показва ли организацията на кода неговата логическата структура?Показва ли организацията на кода неговата логическата структура? Дизайнът недвусмислен и ясен ли е?Дизайнът недвусмислен и ясен ли е? Скрити ли са детайлите на имплементацията възможно най-много?Скрити ли са детайлите на имплементацията възможно най-много?

Ефективни коментари Коментарите понякога могат да навредят повече отколкото да помогнатКоментарите понякога могат да навредят повече отколкото да помогнат Добрите коментари не повтарят кода и не го обясняват – те изясняват неговата идеяДобрите коментари не повтарят кода и не го обясняват – те изясняват неговата идея Коментарите трябва да обясняват на по-високо ниво какво се опитваме да постигнемКоментарите трябва да обясняват на по-високо ниво какво се опитваме да постигнем Писането на коментари помага да осмислим по-добре това, което искаме да реализирамеПисането на коментари помага да осмислим по-добре това, което искаме да реализираме

Правила на ефективните коментари Използвайте псевдокод, когато е възможноИзползвайте псевдокод, когато е възможно Пишете коментари когато създавате самия код, а не след товаПишете коментари когато създавате самия код, а не след това Продуктивността не е добра причина за да не пишете коментариПродуктивността не е добра причина за да не пишете коментари Документирайте всичко, което не става ясно от вашия кодДокументирайте всичко, което не става ясно от вашия код Поставянето на много коментари е толкова вредно колкото и липсата на такиваПоставянето на много коментари е толкова вредно колкото и липсата на такива Не коментирайте трудно разбираем код – по добре го преработетеНе коментирайте трудно разбираем код – по добре го преработете

Ресурси по темата Code Complete, 2 nd edition, Steve McConnell, Microsoft Press, 2004, ISBN , Code Complete, 2 nd edition, Steve McConnell, Microsoft Press, 2004, ISBN , Курс по "Качествен програмен код" в СУ –Курс по "Качествен програмен код" в СУ –

Качествен програмен код Въпроси?