Чи траплялося вам коли-небудь дивитися старі чорно-білі фільми про війну? Втомлений солдат обережно вибирається з заростей чагарнику. Попереду нього вільний простір, і солдат задається питанням: чи є попереду міни або можна безбоязно йти далі? Ніщо не говорить про те, що попереду мінне поле, - немає ні знаків, ні колючого дроту, ні воронок. Солдат намагається багнетом грунт перед собою і здригається в очікуванні вибуху. Але нічого не відбувається. Якийсь час він продовжує обережно просуватися але полю, промацуючи грунт. Зрештою, переконавшись, що прохід безпечний, він розпрямляється і починає гордо марширувати вперед ... назустріч смерті.
Перші пошуки хв, проведені солдатом, були безрезультатні, але йому просто пощастило. Він прийшов до помилкового висновку, що закінчилося катастрофою.
Програмісти також працюють на замінованій території. Існують сотні пасток, які підстерігають нас щодня. Пам'ятаючи про історію з солдатом з фільму, нам варто побоюватися неправдивих висновків. Необхідно уникати програмування в розрахунку на збіг обставин, покладаючись на удачу і випадкові успіхи, і зробити вибір на користь навмисного програмування.
Як програмувати в розрахунку на збіг обставин
Припустимо, Фреду дано завдання написати програму. Фред становить якусь програму, пробує її запустити, і вона начебто працює. Фред пише ще один фрагмент, пробує його запустити, і знову все працює. У такій обстановці проходить ще кілька тижнів, але раптово програма припиняє працювати, і, витративши кілька годин на усунення дефекту, Фред все ще не знає, в чому причина. Фред може витратити багато часу, копаючись з цим фрагментом, без перспективи на відновлення роботи програми. І що б він не робив, здається, що програма ніколи не буде працювати правильно.
Фред не знає, чому програма дає збої, тому що не знає, чому вона працювала спочатку. Вона лише здавалася діючу пенсійну систему умовах обмеженого «тестування», яке проводив Фред, але це було лише збігом обставин. Перебуваючи в полоні хибної впевненості, Фред впав у забуття. Більшості інтелектуалів знаком цей образ Фреда, але ми знаємо його краще. Адже ми не покладаємося на збіг обставин, чи не так?
Втім, іноді покладаємося. Часом легко сплутати щасливий випадок з цілеспрямованим плануванням. Розглянемо кілька прикладів.
Випадкова реалізація - це те, що відбувається просто тому, що програма написана саме так, як вона написана. Ви перестаєте покладатися на недокументовану помилку або граничні умови.
Схоже, що Фред робить відчайдушні спроби вивести щось на екран. Але ці підпрограми не призначені для того, щоб до них зверталися таким способом; хоча вони здаються працюють, насправді це лише збіг обставин.
Щоб не отримати нових ударів, коли компонент все-таки намальований, Фред не намагається повернутися назад і усунути підроблені запити. "Зараз вона працює, залишимо все як є ...".
Такі міркування можуть ввести вас в оману. Навіщо ризикувати, псувати те, що працює? Так можна думати з кількох причин:
• Програма дійсно може не працювати, вона може лише здаватися працює.
• Гранична умова, на яке ви покладаєтеся, може бути лише окремим випадком. У різних обставинах (наприклад, при іншому екранному дозволі) програма може вести себе по-різному.
• Недокументовані поведінка може змінитися з випуском нової версії бібліотеки.
• Додаткові і необов'язкові виклики уповільнюють роботу програми.
• Додаткові виклики також збільшують ризик привнесення нових дефектів, пов'язаних з цим викликами.
При написанні програми, що викликається іншими розробниками, корисними можуть виявитися базові принципи чіткої модулярізаціі і приховування реалізації за нескладними, чітко документовані інтерфейсами. Чітко визначений контракт (див. "Проектування за контрактом") може усунути непорозуміння.
Для викликаються вами підпрограм покладайтеся лише на документоване поведінку. Якщо з якоїсь причини ви не можете зробити цього, то чітко документуйте ваше припущення.
Ви також можете зустрітися зі "випадковим контекстом". Припустимо, ви пишете сервісний модуль. Оскільки в даний час ви пишете програму для графічного середовища, чи повинен модуль покладатися на існуючий графічний інтерфейс? Покладаєтеся ви на англомовних користувачів? На грамотних користувачів? Покладаєтеся ви ще на якийсь контекст, наявність якого не гарантується?
Збіги можуть вводити в оману на всіх рівнях - від генерації вимог до тестування. Тестування особливо загрожує наявністю неправдивих причинних зв'язків і випадковим збігом результатів. Легко припустити, що А викликає У, але, як сказано в розділі «Налагодження" не припускайте це, а доводьте.
На всіх рівнях люди працюють, тримаючи багато припущень в голові, але вони рідко документуються і часто викликають суперечності між розробниками. Припущення, які базуються на відомих фактах, здатні отруїти будь-які проекти.
Підказка 44: Не пишіть програми в розрахунку на збіг обставин