Относно конвенциите

Хвърлете един поглед на това. Кратка статийка, която навлиза в детайли за стандартите за писане на код. Това е тема, над която съм размишлявал доста време и имам някои фашистки разбирания. Връзката ми дава страхотен повод да споделя някои впечатления.

Във всеки един проект в който работя се опитвам с драконови мерки да налагам железни стандарти за спазваната конвенция. Причината е, че съм много чувствителен към неконсистенции в кода. Винаги подреждам всичко по един и същи начин (празни редове, скоби, пренасяне на аргументи при дълъг ред и т.н.), използвам една и съща част от стандартната библиотека и следвам една схема за наименуване на нещата. Всякакви отклонения ми се набиват на очи и очаквам да има някаква причина за тях. Например, като видя някъде ArrayList заключавам, че кода прави здраво индексации и линейното обхождане ще е неефективно. Като видя някъде while вместо for за Iterable, очаквам да има някакъв по-сложен алгоритъм от едно „за всеки“. А когато видя for вместо .each в Ruby очаквам индексната променлива да се използва някъде по-надолу. Съответно, всеки път когато конвенцията е нарушена без причина това само ми отвлича вниманието и ми губи времето.

Вариациите в езика, бил той компютърен или естествен, са начин за изразяване. „Студено ми е.“ и „Умирам от студ!“ носят една и съща информация (очевидно температурата е кофти), но звучат различно – първото е в тона на хладно твърдение (pun not intended), докато второто изразява по-силна емоция. Езиците за програмиране имат същите нюанси, макар и не толкова изявени. Както не слагате слагате акценти и емоция в речта си когато ви скимне, така и не бива хаотично да ползвате изразните вариации в езика. Щом можете да правите нещата по повече от един начин, правете ги по повече начини консистентно. Разликите в стила и подхода са носител на информация, не пособ за себеизразяване – for(;;) казва, че обхождате някаква колекция, докато while – че се опитвате да достигнете някакво условие. Те не са начин да илюстрирате естетическите вкусове на потиснатия артист в себе си.

Това важи с още по-голяма сила когато работите в екип. Ако сте от онези хора, които вярват, че „различията в стила трябва да се толерират, понеже така бързо може да видите кой е писал кода“ заслужавате да ви застрелят (малко след като ви обяснят какво е version control). В идеалния случай не трябва да има никакъв начин да разберете кой какво е писал само четейки кода. Стиловите нюанси (различно форматиране, различна схема на наименуване, различен подход за стандартни неща или не дай си боже екзотични перверзии) само създават шум и затормозяват прочита. Бъдете добри дружки и правете нещата консистентно – в дългосрочния план всички ще се чувствате много по-добре.

Като цяло, стила носи информация. А най-лошото, което може да направите с информацията, е да я лишите от смисъл.

5 thoughts on “Относно конвенциите

  1. Според мен използването на определени езикове конструкции (for vs. while, ArrayList vs. LinkedList), е твърде ниско ниво за да подлежи на конвенция – програмиста трябва да използва целия арсенал на езика си за да се изрази четливо и еднозначно.

    От досегашната ми работа мога да направя няколко извода за конвенциите.

  2. @Свилен: Сега, аз пък точно за това адвокатствам – че ArrayList/LinkedList, for/while са вариация на едно израно средство – позволяват ти да кажеш едно нещо по няколко начина. И е особено критично да се ползват консистентно в кода. А нещо което е консистентно като нищо може да подлежи на конвенция, била тя и полу-формален фолклор в екипа, а не драконов закон.

    Ще ти дам по-конкретен пример.

    for (int i = 0; i < numbers.length; i++) {
      System.out.println(numbers[i]);
    }
    

    Проста програма. Чете се като „за всяко число в numbers, изведи го на екрана“. Виж какво става, ако го напишеш с

    while
    :

    int i = 0;
    while (i < numbers.length) {
        System.out.println(numbers[i]);
        i++;
    }
    

    Действието е идентично. Дори ще генерира същия байт-код. Но се чете така „докато i е по-малко от дължината на numbers, извеждай i-тото число в numbers и увеличи i след това“. Което е много по-далеч от идеята на кода (intention).

    Когато човек използва for/while неподходящо, само дава грешни сигнали. Не изразява кода четливо и еднозначно, в твои думи. Когато избира между ArrayList и LinkedList ползвайки

    rand()
    , вместо да прецени кое е по-подходящо създава объркване.

    Това важи още повече за някои неща които са по средата. Класическата конвенция в ruby е да се ползва

    begin/end
    за блоково на повече от един ред и
    { }
    за блокове на един ред. Алтернативната идея е да се ползва
    begin/end
    когато важното са странични ефекти, докато
    { ... }
    като се изчислява резултат. Която идея да изберете, трябва да сте консистентни в рамките на екипа – иначе твоя код ще ме обърква, докато моя код ще те дразни, защото ползвам
    { ... }
    за големи блокове.

  3. Признавам –

    ArrayList/LinkedList
    не добър пример – все пак това са различни фундаментални типове данни с характерните си свойства; прилагането им трябва да бъде съобразено.

    От друга страна, според мен влагането на нюанси в

    for/while
    и описвайки ги в конвенция, е малко пресилено. Преполагам никой от нас не използва while за да извърти един масив – просто защото е свикнал да гледа, че това се прави с
    for
    – в учебниците, в кода на колегите, в чужд софтуер. Съгласен съм, че
    for each
    конструкциите са още по експресивни. Колкото повече „стандартни конструкции“ един програмист използва, толкова по-лесен е кода за четене – но пак искам да уточня: ако програмиста смята, че дадена конструкция отговаря по-добре на намерението му – нека я ползва; не трябва конвенцията да го спира. Добър пример е дебата около goto – в език като C, където програмните изключенията (exceptions) са недостъпен лукс. Например функцията с goto, което прехвърлят изпълнението в края при невалиден входни параметри е доста по-четима от няколко вложени
    if
    -a. Ето тук конвенция „goto e враг номер едно на Тутраканската селищна система“ би спънал четливия код.

    Мойте 5 ст’инки.

  4. Codito ergo sum » Думи от занаята

Вашият коментар

Вашият имейл адрес няма да бъде публикуван.