Оборонне програмування: це параноїя чи інтелектуальне кодування?

Чому захисне програмування - найкращий спосіб надійного кодування

Оборонне програмування - єдине реальне програмування.

Іміджеві кредити: Pixabay.com

Оборонне програмування - це коли програміст передбачує проблеми та пише код для їх вирішення.

Це як побачити автокатастрофу в майбутньому… .. і залишатися спокійним, тому що ви застрахували це.

Втім, вся захисна програма програмує від помилок, яких ви не очікуєте. Оборонний програміст слідкує за неприємностями, щоб уникнути цього, перш ніж він може спричинити реальні проблеми. Ідея - не писати код, який ніколи не виходить з ладу. Це утопічна мрія. Ідея зробити код невдалим у випадку будь-якого несподіваного питання. Збій красиво може означати будь-яке з наступного.

· Невдача достроково: ваш код повинен забезпечити, щоб усі важливі операції були припинені заздалегідь, особливо якщо вони обчислювально дорогі або можуть незворотно вплинути на дані.

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

· Явна помилка: коли щось порушено, воно повинно повернути дуже чітке повідомлення про помилку та опис, що може дати команді підтримки вирішити помилку.

Гаразд. Ви можете тут сперечатися.

В даний час проблем немає. Мій код працює прекрасно. Чому я повинен вкладати час і зусилля на проблему, що очікується на майбутнє? Зрештою, нас неодноразово вчили користуватися "Вам це не потрібно" (YAGNI). А ви професійний програміст, а не хобіст, здатний продовжувати додавати до коду за бажанням.

Ключовим тут є прагматизм.

Ендрю Хант у своїй книзі «Прагматичний програміст» описує оборонне програмування як «Прагматичну параною».

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

Здорове параноїдальне програмування - це правильний вид програмування. Але параноїю можна зайняти занадто далеко. Ключ - досягнення правильного балансу.

Ось кілька способів зробити оборонне програмування.

Запитайте себе: якщо це не вдається?

Кожен рядок коду робить щось, тому 1-й пункт захисту запитує себе, якщо код не вдається, то що.

Наприклад, розглянемо наступний невідповідний код.

СЛУЧАЙ SY-INDEX. // Невідповідний; відсутні пункти КОЛИ ДРУГІ
КОЛИ ОДИН.
ЗАПИСЬ "Один".
КОЛИ 2.
НАПИСИСЬ "Дві".
ЕНЦЕЗАЦІЯ.

Тут ми можемо задати наступні питання.

Що станеться, якщо sy-індекс не дорівнює 1.

Що станеться, якщо sy-індекс не 2.

Щоб вирішити цю проблему, ми додаємо інше твердження OTHERS.

СЛУЧАЙ SY-INDEX.
КОЛИ ОДИН.
ЗАПИСЬ "Один".
КОЛИ 2.
НАПИСИСЬ "Дві".
КОЛИ ДРУГІ. // Сумісний
ЗАПИСЬ "Неочікуваний результат"
ЕНЦЕЗАЦІЯ.

Простий. Чи не так?

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

Краса цієї техніки оборонного програмування полягає в тому, що вона майже не витрачає часу на додавання вичерпної перевірки типу до вашого коду. Ви не “перекодували”. Ви просто "закріплюєте" свій код.

Ретельно перевіряйте граничні умови.

Найперша перевірка полягає у встановленні, якщо вам потрібна гранична умова, адже адже петлі дорогі.

Граничні (або крайові) умови - це те, де відбувається вся дія. Цикл від 0 до 100 і значення циклу від 1 до 98 майже однакові (забороняючи умови в коді, звичайно). Але цикл 0 - це те, де код надходить у цикл, і умови ініціалізації налаштовані (і, можливо, встановлені неправильно). Аналогічно, остання петля - це місце, де все залишається, і все, що цикл робив для значень, припиняється.

Цикл із щонайбільше однією ітерацією еквівалентний використанню оператора IF для умовного виконання одного фрагмента коду. Жоден розробник не повинен сподіватися знайти таке використання твердження циклу. Якщо початковий задум автора насправді був умовно виконати один фрагмент коду, слід використовувати IF-заяву на місці.

Розглянемо наступний невідповідний та сумісний код. У цьому випадку нам взагалі не потрібна петля. Простий ЯК зробить.

            Приклад невідповідного коду
ДАНІ решта ТИП i.
Зробіть 20 ЧАСІВ.
залишок = sy-індекс MOD 2.
cl_demo_output => write_text ().
ВХІД. "Невідповідний, цикл виконується лише один раз. Ми можемо використовувати IF
ENDDO.
          Приклад коду відповідності
ДАНІ решта ТИП i.
Зробіть 20 ЧАСІВ.
залишок = sy-індекс MOD 2.
cl_demo_output => write_text ().
ENDDO.

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

Використовуйте TDD (тестова розробка)

Основна ідея TDD - "спочатку записати одиничні тести, потім написати код, потім рефактор, а потім повторити".

Блок тестів - це автоматизовані тести, які перевіряють, чи функціонують функції, як очікувалося. Ваш перший тестовий пристрій має бути невдалим, оскільки він написаний ще до того, як у вас є будь-яка база даних коду.

Ви додасте трохи до коду тестового випадку. Ви додаєте трохи до виробничого коду. Два потоки коду одночасно переростають у взаємодоповнюючі компоненти. Випробування відповідають виробничому коду так, як антитіло відповідає антигену.

Проблема тестування коду полягає в тому, що вам потрібно ізолювати цей код. Часто складно перевірити функцію, якщо ця функція викликає інші функції. Щоб написати цей тест, ви повинні розібратися з тим, як від'єднати функцію від усіх інших. Іншими словами, необхідність тестування спочатку змушує задуматися про хороший дизайн.

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

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

На відміну від застарілих методів кодування, TDD дозволяє розробникам повернутися до креслярської дошки і сконцентруватися на розробці легкої, гнучкої архітектури наперед.

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

Завжди пишіть оптимізований код.

Деякі програми (і програмісти) дуже люблять ресурси. Але коли можна, використовуйте мінімум. А щоб використовувати мінімум, ваш код повинен бути максимально оптимізованим.

Зазвичай, один з надійних способів оптимізації - це включення будь-яких оптимізацій, які компілятор забезпечує вбудованим.

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

Окрім стандартних оптимізацій компілятора, можна використовувати кілька інших методів настройки.

Збирайте загальні підокспреси.

Якщо дороге обчислення відбувається в декількох місцях, краще обчислити в одному місці і запам'ятати результат. Не кладіть такі обчислення в цикл, якщо цього не потрібно.

Замініть дорогі операції дешевими.

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

Усуньте петлі.

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

Кеш часто використовуваних значень.

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

Перепишіть мовою нижчого рівня.

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

Пам'ятайте в оптимізації, вибір, мабуть, 90% гри. Варто витратити час, щоб вирішити, що ви робите, і зробити це правильно. Звичайно: саме тут лежить чорна магія!

І нарешті, довіряти нікому.

«Є відомі знання; є речі, які ми знаємо, що ми знаємо », - сказав одного разу на прес-конференції міністр оборони Дональд Рамсфельд під час другої адміністрації Буша. «Ми також знаємо, що є відомі невідомі; тобто, ми знаємо, що є деякі речі, про які ми не знаємо. Але є і невідомі невідомі - ті, які ми не знаємо, ми не знаємо ».

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

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

Дані налаштувань програми також схильні до помилок. Файли INI використовувались як поширений спосіб збереження налаштувань програми. Оскільки вони були текстовим файлом, багато людей звикли редагувати їх вручну за допомогою текстового редактора і, можливо, (ймовірно) викручувати значення. Дані реєстру, файли баз даних - хтось може їх колись змінити, тому платить за перевірку навіть цих речей.

Коротше кажучи, дані, які надходять, повинні бути чистими, якщо ви сподіваєтесь, що ваш код зробить те, що він повинен робити. Якщо ви коли-небудь чули фразу "Сміття в, ​​сміття поза", саме звідси воно і з'явилося.

Як справедливо сказав Едвард Деммінг.

"Ми віримо в Бога. Усі інші повинні надати дані. "
Про автора-:
Раві Раджан - глобальний менеджер ІТ-програм, що базується в Мумбаї, Індія. Він також завзятий блогер, письменник поезії Хайку, ентузіаст археології та маніяк історії. Спілкуйтеся з Раві на LinkedIn, Medium та Twitter.