вторник, ноември 18, 2008

10 advanced съвета за по-добро PHP програмиране


Под това време днес в едно дизайнерско списание, което от време на време гледам (`щото който не може само гледа) излиза статия озаглавена 10 Advanced PHP Tips To Improve Your Programming или в свободен превод 10 съвета за напреднали php програмисти подобрят кода си. Не съм някакъв гуру, но имам няколко коменара по темата.
Ето ги и съветите:

1. Използвайте SQL injection cheat sheet
Често казано не успях да разбера какво точно имат в предвид под cheat sheet, но аз отдавна не филтрирам нищо ръчно. Примерно в CodeIgniter, Active Record класа върши филтрирането за sql injection и в security helper-a си има функция за филтриране срещу xss.

2. Знайте разликата между операторите за сравняване.
Тук съм много съгласен. Признавам си, че едва преди месец-два научих разликата между "==" и "===", просто преди това не бях обръщал никакво внимание.
Не че има много общо, но пък аз често в бързина правя грешката да слагам едно "=" вместо две. За незапознатите с php - едно "=" присвоява стойност, а "==" сравнява променливи. Наскоро също ми дадоха един интересен съвет да избегна това, който обаче работи само ако сравнявате променлива с число(примерно), тоест когато не сравнявате 2 променливи.
Тоест, ако сгрешат, повечето хора пишат следния код:

if($a=1){ blah();}

което вместо да сравни променливата с 1, просто й присвоява стойност 1 и винаги връща TRUE, от където пък може да станат много проблеми. Ако обаче вместо това напишем:
if(1=$a){ blah();}

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

3. Избегнете else
Тук дават един интересен пример. Този код:
if( някакво условие) {
$a=5;
} else {
$a=10;
}

може да се преработи така:
$a=10;
if( някакво условие ){

$a=5;
}

Като според тях втория пример е по-добър. Аз лично не виждам съществена причина това да е така, дори мисля, че втория код е малко по-объркващ, въпреки че е по-елегантен. Unix гурутата винаги са учели, че не трябва да се стремим да пишем хитър код, а възможно най-тъп, в смисъл възможно най-лесно разбираем от следващия, който ще седне да работи по този проект след теб. Това е съществено за един open source проект, защото ако кода е омазан от някой "юноша бледен", който се е скъсал да пише странни недокументирани workaround-и, ще е доста трудно някой да допише нещо и от там вече всичко умира :)

4. Избегнете скобите
Знаете, че можете да напишете
if( някакво условие) {
something();
} else {
something_else();

}

така:
if(някакво условие) something();
else something_else();

Твърдо, ама твърдо съм против това. Пестиш 2 скоби, 1-2 реда и губиш няколко минути на човека след теб за да разбере какво правиш! В случая, който съм показал е лесно да се види какво става, но представте си, че имате няколко вложени if-else конструкции, тогава вече наистина става голямо мазало, защото не се вижда кое къде започва, къде свършва и т.н. Скобите не са за php парсера, те са за вас.
Моля ви, не го правете това, не пишете без скоби!

5. Използвайте str_replace() вместо ereg_replace() and preg_replace()
Това специално не го знаех, но според тях str_replce е 61% по-бързо от ereg_replace и preg_replace. Не че и без това съм се засилил да праскам regular expressions, където трябва и не трябва. Проста причина, повече време ми отнема да измисля regex-а вместо да си прасна str_replace. Това може да не е така за всички, но поне при мен е така. Мисля, че ще е хубаво да се има в предвид.
Този съвет го одобрявам :)

6.Използвайте троични оператори
Не! Моля ви, това също не го правете. Всеки път когато видя троичен оператор отделям 5 качествени минути в красноречиви поздрави към майката на предишния програмист.
Вече обясних защо, за мен това ненужно усложнява кода. Нека си се придържаме към тъпата двуична логика.

7. Използвайте memcached
Признавам, че тук нямам опит, но щом те така казват, да предположим, че тоя съвет е валиден. Евентуално за това, други хора могат да кажат по-компетентно мнение.

8. Използвайте framework
Както вече споменах аз си харесвам CodeIgniter и си използвам него. Имам един колега от университета, с който често спорим на тази тема. Той твърди, че не трябва да се ползват никакви готови framework-ове, че дори и template системи, смята че бавят излишно. Аз пък смятам, че няма нужда да си блъскаш главата да пишеш едни и същи неща по 1000 пъти и то при положение, че някой вече ги е написал вместо теб. Ако пък нямате отделен дизайнер наистина не виждам голям смисъл да се ползва template система. Всеки си избира сам, но аз препоръчвам наистина да ползвате framework.

9. Използвайте правилно suppression оператора
Нямам идея как се превежда suppression оператор на български, става въпрос за символа @ използван като оператор. Иначе каква е идеята?
if (isset($albus)){
$albert = $albus;
}else{
$albert = NULL;

}

е еквивалентно на:
$albert = @$albus;

Проблема е, че ако го напишете по-втория начин се изпълнява 2 пъти по-бавно, защото @ се използва неправилно. Правилното използване е чрез референция:
$albert =& $albus;

Според мене това е само за фанатици на тема скорост, въпреки че е интересно :)

10. Използвайте isset вместо strlen
Това е доста интересно приложение на isset, за което не бях се сещал. Ако искате да определите дължината на даден стринг е нормално да използвате:
echo strlen($str);
Но примерно ако примерно искате да проверите дали някъв низ не е по-къс от определен брой символи:
if (isset($str[9])) {
echo 'низа е равен или по-дълъг от 10 символа';
} else {
echo 'низа е по-къс от 10 символа';
}

По-добре било да се ползва isset защото било 5 пъти по-бързо от strlen. Важно е да се отбележи, че strlen е опимизиран да прави точно това и се справя по-бързо с по-големи низове. Strlen обаче е по-бърз при малки проверки като тази от примера.
Има и една екстра. Ако бяхме написали кода така:
if(strlen($str) > 9) { ...

и променливата $str не съществуваше щеше да ни изплюе грешка и щеше да се наложи да направи преди това допълнителна проверка с isset, което е още едно излишно действие.
Това май е първия интересен съвет, въпреки че трябва да си наистина голям перфекционист за да тръгнеш да гледаш чак такива неща.

Повечето съвети в статията на Smashing Magazine (според мен) са или грешни или излишни и не чак толкова необходими. Какъв е извода ?
Дизайнерите да си гледат дизайна и да не се бутат, където не им е работа :D
(както и обратното).

13 коментара:

Павел Пенев каза...

Не разбирам от PHP но предложение 2 ме накара да изтръпна, ако някой е толкова тъп че не може да осмисли разликата между = и == по добре да не се занимава с програмиране(опа, това е php, моя грешка :D) И значи за да не се объркваш като пишеш само едно = нарочно слагаш числото преди променливата за да може парсера да мисли вместо тебе, бахти идиотията братче.

А това относно скобите, python не използва скоби а интервали, и това определено помага на четимоста, python философията е че скобите са за компилатора, а интервалите са за програмистите, и че програмистът е по важен от компилатора. Друг е въпроса че освен python и haskell друг език който да използва интервали не знам :D

gotha каза...

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

Павел Пенев каза...

За да реши проблемите с недоглеждането на дребни неща господ е създал синтактичното оцветяване :D

gotha каза...

Напусни заведението, младежо !

btw, python - компилатор ?!?!
да не би да ползваш и win32 api за python?

silvernasko каза...

Едно потенциално приложение на memcached. Трябва да направиш система като tyxo.bg. Но понеже тя ще поема стотици (може и хиляди) удари в секунда, би било убийство да караш базата да записва всеки Request в лог таблицата на дадения сайт.

Решението - записваш в memcached и когато достигнеш определено количество (да кажем 100) за даден сайт, записваш всички наведнъж - (базата ще направи едно физическо обръщение до диска).

ivanatora каза...

Абсолютно съм съгласен с мнението ти за троичния оператор.

Анонимен каза...

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

$alabala = isset($tralala)
? 'cigumigu'
? 'цигумигу'

Съгласен съм за скобите -- спестяването на два реда пречи не четаевостта на кода: поне при мен е така.

Това ereg_replace() някой ползва ли го още ;) Иначе наистина, за някой по-елементарни операции наистина не си струва да палиш голямата машина -- разбирайте регулярните изрази :)

Ако си опичате акъла, изключително рядко ще ви се налага да ползвате заглушаващия оператор. Да не говорим колко зле влияе на производителността.

Анонимен каза...

Христо, тези съвети са наистина добри, освен за framework-a.

Скобите трябва да се използват където трябва а не на всякъде където е възможно. А знака @ просто не трябва да се използва в 95% от случаите.

Напълно сигурен съм, че между един сайт написан с framework и един написан на просто php, при високо натоварване вторият ще се представи в пъти по-добре :p
Всички опитни php програмисти знаят че обектно ориентираният код с много наследявания (както са написани framework-овете) е няколко пъти по-бавен от процедурният код. Единственото полезно нещо е удобството на програмиста.

Анонимен каза...

Асен Сотиров - погледни http://www.amazon.com/Building-Scalable-Web-Sites-applications/dp/0596102356

там автора изказва противоположно мнение.

Анонимен каза...

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

gotha каза...

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

Анонимен каза...

Ами защото използваш framework, затова ти е по-трудно на чист PHP.
Ти ме вдъхнови и написах в моя блог най-добрите практики които аз използвам в PHP-то :)

PS: Ще се видим на някой изпит ;)

gotha каза...

Радвам се, че съм те вдъхновил :)
Всъщност аз просто коментирам съветите от списанието, те не са мои.

И въпреки всичко, не съм съгласен за framework-овете, компютрите за това са направени, за да смятат вместо тебе. Ако търсиш бързина пиши си web приложенията на C или дори на асемблер ако искаш :P

Ако някой ден с тебе работим по някой проект ще имаме бая проблеми :D