1. Работата на програмист

Много често начинаещите програмисти мислят за работата на програмиста напълно различно от начина, по който опитните програмисти мислят за нея.

Начинаещите често казват нещо като "Програмата работи, Howво друго ви трябва?" Един опитен програмист знае, че "работи правилно" е само едно от изискванията за една програма и дори не е най-важното !

Четливост на codeа

Най-важното е програмният code да е разбираем за другите програмисти . Това е по-важно от правилно работеща програма. Много повече.

Ако имате програма, която не работи правилно, можете да я поправите. Но ако имате програма, чийто code е неразбираем, не можете да направите нищо с нея.

Просто вземете произволна компorрана програма, като бележник, и променете цвета на фона й на червен. Имате работеща програма, но нямате разбираем изходен code: невъзможно е да правите промени в такава програма.

Пример за учебник е, когато разработчиците на Microsoft премахнаха играта Pinball от Windows, защото не можаха да я пренесат към 64-битова архитектура. И дори имаха неговия изходен code. Те просто не можеха да разберат How работи codeът .

Отчитане на всеки случай на употреба

Второто най-важно изискване за една програма е да отчита всеки сценарий. Често пъти нещата са малко по-сложни, отколкото изглеждат.

Как един начинаещ програмист вижда изпращането на SMS съобщения:

Коректно работеща програма

Как го вижда професионален програмист:

Коректно работеща програма

Сценарият „работи правилно“ обикновено е само един от много възможни. Ето защо много начинаещи се оплакват от валидатора на задачи на CodeGym: само един сценарий от 10 работи и начинаещият програмист смята, че това е достатъчно.


2. Ненормални ситуации

Ненормални ситуации

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

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

За всяка необичайна ситуация програмистът (авторът на програмата) трябва а) да я предвиди , б) да реши How точно програмата да се справи с нея и в) да напише решение, което е възможно най-близко до желаното.

Ето защо програмите имаха много просто поведение за доста дълго време: ако възникне грешка в програмата, програмата се прекратява. И това беше доста добър подход.

Да приемем, че искате да запишете document на диск, по време на процеса на запис установявате, че няма достатъчно място на диска. Кое поведение бихте искали най-много:

  • Програмата се прекратява
  • Програмата продължава да работи, но не записва file.

Един начинаещ програмист може да мисли, че вторият вариант е по-добър, защото програмата все още работи. Но в действителност това не е така.

Представете си, че сте написали document в Word в продължение на 3 часа, но след две minutesи от процеса на писане е станало ясно, че програмата няма да може да запише documentа на диск. По-добре ли е да загубите две minutesи работа or три часа?

Ако програмата не може да направи това, което трябва, по-добре е да я оставите да затвори, отколкото да продължавате да се преструвате, че всичко е наред. Най-доброто нещо, което една програма може да направи, когато срещне повреда, която не може да поправи сама, е незабавно да докладва за проблема на потребителя.


3. История на изключенията

Програмите не са единствените, които се сблъскват с необичайни ситуации. Те също се срещат вътре в програмите - в методите. Например:

  • Метод иска да запише файл на диска, но няма място.
  • Метод иска да извика функция на променлива, но променливата е равна на нула.
  • Деление на 0 се случва в метод.

В този случай извикващият метод би могъл евентуално да коригира ситуацията (да изпълни алтернативен сценарий), ако знае Howъв проблем е възникнал в извикания метод.

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

Някога програмистите се замислиха над този въпрос и стигнаха до следното решение: всички методи/функции трябва да връщат code за грешка, който показва резултата от тяхното изпълнение. Ако дадена функция работи перфектно, тя връща 0 . Ако не, той връща code за грешка (не нула).

С този подход към грешките след почти всяко извикване на функция програмистите трябваше да добавят проверка, за да видят дали функцията е завършила с грешка. Кодът нарасна по размер и започна да изглежда така:

Код без обработка на грешки Код с обработка на грешки
File file = new File("ca:\\note.txt");
file.writeLine("Text");
file.close();
File file = new File("ca:\\note.txt");
int status = file.writeLine("Text");
if (status == 1)
{
   ...
}
else if (status == 2)
{
   ...
}
status = file.close();
if (status == 3)
{
   ...
}

Нещо повече, доста често функция, която открива, че е възникнала грешка, не знае Howво да прави с нея: повикващият трябва да върне грешката, а повикващият на повикващия я връща на повикващия и т.н.

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

Друг недостатък на този подход е, че ако функциите върнат code за грешка, те вече не могат да върнат резултатите от собствената си работа. Резултатът от изчисленията трябваше да бъде предаден чрез референтни параметри. Това направи codeа още по-тромав и допълнително увеличи броя на грешките.