От известно време наблюдавам тази тенденция в интернет – по форуми, блогове и статии, да се проповядват (и то доста религиозно) нови технологии, използващи езика JavaScript, като в частност имам предвид node.js или дори целия MEAN. Всъщност нямам нищо против тези технологии, но са някои от техните евангелисти, които ме дразнят.

Защо?

Хубаво е да има нови технологии, но толкова често забелязвам тази пропаганда, че тези JavaScript технологии (отново MEAN) решават всички програмистки проблеми. А колко от вас всъщност осъзнават, че проблемите в развитието на един проект/продукт са директно свързани с предмониторни проблеми? Доста смели изявления чух в последно време, и особено когато се стигне до сравнение на node.js vs php (а по-нахалните дори намесват java).

Искам да кажа, че технологията не е отговорна

Когато нямаш понятие (за желание да не говорим) от дизайн патърни, рефакторинг и тестване как по-точно ще ти помогне лъскавият node.js(и в този момент се разхвърлят хиляди статистики за това колко е бърз node.js с hello world)?

Спомням си когато за пръв път чух термина NoSQL, беше в едно изречение със “заместител на релационните бази данни”. Примитивите не осъзнават, че релационните бази данни се разработват от 20-30 години и са се доказали на академично ниво. Много харесвам документ-ориентираните бази данни като MongoDB, но също така е важно да се отбележи, че подобни DB-та имат много тесен терен за изява, когато става въпрос за сериозен софтуерен продукт. Направих това отклонение, защото MongoDB е част от компилацията MEAN.

Нека мине време, пък ще видим

Познавам доста node.js маниаци, но не познавам нито един, който може да се похвали, че работи върху node.js проект, който е на повече от 2 години. Когато работиш върху проект с по-дълъг жизнен цикъл (две години всъщност не е особено дълго време за един софтуерен продукт) забелязваш в отражението на разработката истинските проблемни области. И в колкото проекта съм участвал, технологията (езикът) никога не е бил главният виновник. Винаги изпъкват липсата на познания по качествен код, design patterns и прочие.

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

Било хубаво клиента, сървъра и базата данни да използват един език

(Майко, майко…)

Това го чух на една лекция за MEAN:

  • MongoDB работи с колекции под формата на JSON
  • node.js е сървър-сайд JavaScript
  • В клиента (браузъра) пък винаги имаме JavaScript

иии… аз ли нещо изпускам романтиката? Интересна изглежда тази вълшебна моногамия, но… за колко неща по-точно ще използваш MongoDB ефективно. Човек дори не може да направи добре функциониращо (и бързо) странициране с MongoDB (ако на някой му е интересно за какво точно говоря, може да прочете тук).

И доста класически design pattern-и не могат да се имплементират коректно в JavaScript поради липсата на някои неща, като например интерфейси… Ама и аз какъв съм старомоден! Че за какво са ни интерфейси?! Бухай здраво в прототипа, другия след теб – да му мисли!

Малка доза консерватизъм

Като цяло не искам да звуча като някаква интернет леля-фашист, която анатемосва копнежа на младите да експериментират с нови технологии. Харесвам новите технологии и насърчавам всеки, който не е пробвал node.js или angular.js – да го направи! Но не се заблуждавайте, че се това е средство, които ще ви оттърве от code smells.

За да избягате от ада на вмирисания код трябва да анализирате собствените си лоши навици. Прочетете книги на Чичо Боб, Martin Fowler, Kent Beck и др.

Бъдете критични към собствения си стил непрекъснато!

Незнам дали мога да обявя себе си за хейтър, но определено след всеки изминал ден ставам все по-критичен що се стигне до обектно-ориентирана архитектура и качество на код. Често ми се налага да реагирам остро в дискусиите си с нисши форми на разум, като най-често оставям клетите и изгубени в заблуда души сами да се опарят от собственото си невежество, като тихичко накрая им шушна “Нали ти казах?”. В течение на времето започнах да забелязвам едни и същи тъпи грешки, които всички задружно допускат, че даже не им прави впечатление. Реших да събера есенсията от тези грешки като представя 5-те най-големи и непростими грехове на PHP програмистите.

1. Логика в контролерите

Контролерите не са мястото, където трябва да пишете логиката си. Контролера работи с модели, които съдържат логика.

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

Обичайното извинение на грешниците е:

“Ами аз нямам време да се занимавам с някакви си там модели, клиента чака!”

А когато ти се наложи глупако, да използваш същата логика в друг контролер, какви ще ги вършиш? Ще копираш код ли?

Като съвет, който бих дал на всеки прегрешил е да разпределя логиката си в модели, с които също трябва да се внимава (един модел трябва да върши само една задача или област от много сходни задачи). За най-добрите практики в разпределянето на логиката всеки заинтересован може да прочете Patterns Of Enterprise Application Architecture.

2. Използване на Unix Timestamp в MySQL

В MySQL съществуват два много удобни формата за запазване на date/time стойности. Единият е TIMESTAMP, а другият е DATETIME. За съжеление множеството от програмисти никога не са ползвали тези времеви типове, а записват времеви стойности в INT поле като Unix Timestamp.

Защо Unix Timestamp е лош избор в MySQL?

Защото е грозен. Ето, казах го! Unix Timestamp е грозен формат (да, да… знам колко е гъвкъв, фундаментален, знам, че може да го преобразуваш в какъвто формат искаш, бла-бла-бла). Не е четим от човешки същества, и в MySQL съществуват легални алтернативи. Също така в комбинация с PHP функциите date() и mktime() нещата могат лесно да излезят извън контрол с големи грешки заради несъответствия в настройките на времевите зони на PHP и MySQL.

Както споменах по-горе, в MySQL съществуват два времеви типа TIMESTAMP и DATETIME. И двата формата запазват дата и време, но TIMESTAMP е зависим от времевата зона. Тук можете за да прочетете за разликите между двата типа.

Моят съвет е винаги да използвате DATETIME/TIMESTAMP когато трябва да съхранявате дата и час. Тези формати разрешават употребата на MySQL времевите функции, които са мощни и удобни. Не забравяйте да индексирате (и то правилно) ако правите селекция по времево поле.

3. Коментиране на код

“Този код може би ще ни потрябва в по-късен етап, нека да го закоментираме” – из разсъжденията на един грешник

Хора, използвайте системи за контрол на версиите (git, hg, svn). Няма нищо по-грозно от това да видиш закоментиран код, оставен за поколенията.

4. Неправилно наследяване

Често се натъквам на много нелогично наследяване. За пример имаме система и програмиста е решил, че всеки негов клас ще наследява някакъв абстрактен и много велик клас. Нека наречем този клас AbstractPieceOfShitModel. Често в този клас ненадейно е попаднала логика за работа с база данни и какви ли не други несъответстващи си методи.

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

Вината не е изцяло на обикновените програмисти. Вина имат водещите PHP фреймуъркове (с изключение на Zend разбира се, Praise Hail To Our Saviour Zend Framework) като CodeIgniter, CakePHP, Yii и всичките, които налагат идеята, че има някакъв вид универсален скелет на модел, който могат всички класове да ползват чрез наследяване. Няма универсален скелет на модел (ако сте запознати с философията на Test-Driven Development, ще разберете защо). Това освен да ви върже ръцете и ограничи креативността няма как да помогне.

5. Работа с Windows

Ако си PHP програмист – трябва да работиш с Linux (всъщност това важи за всички освен за .net-аджиите. Те просто нямат избор).

Линукс като работна среда дава много предимства на PHP програмистите. Ето само малка част от тях:

  • Лесна конфигурация на PHP, Apache(или който и да е друг сървър), MySQL и т.н.
  • Обвивката на Линукс (shell) предоставя възможност за писане на мощни скриптове, които да помогнат в процеса на разработка
  • Лесна инсталация на LAMP (Linux-Apache-MySQL-PHP/Perl/Python) и лесно обновяване. В Windows почти всеки играе с XAMPP или подобен пакет
  • Много разширения и библиотеки за PHP се срещат като пакети в Ubuntu/Debian. Това значително ускорява процеса на разработка.

Заключение

Разбира се нещата, които ме дразнят са далеч повече, но това са главните 5, за които всеки трябва да си даде сметка.

Когато за пръв път се сблъсках със Zend Framework бях заслепен от високото ниво на абстракция, изчистения код и богатата библиотека. Тогава бях на 18 години, а познанията ми по ООП бяха ограничени до разработване на семпли сайтове, използващи 2-3 класа + Smarty. На теория знаех всичко за ООП, но концептуално нямах идея как да се възползвам от силата на тази технология, просто бях чувал, че да използваш класове и обекти е готино. Zend Framework изигра главна роля в професионалното ми развитие, и успя да пречупи мирогледа ми, превръщайки тогаващата представа за програмирането в нещо много по-различно. Zend Framework ме научи да мисля обектно.

Илюзията на всеки програмист, който знае ООП на теория(но не познава design pattern-и например), е че той няма нужда от приети в общността похвати, той е велик и няма защо да се учи от някой. Това срещам във почти всеки PHP програмист в днешно време. Преди да се сблъскам със ZF, аз също бях един твърдоглав начинаещ.

Нека опиша един проект, който не използва фреймуърк: разполага с един клас, който често се казва Main или Core, а в него се съдържат методи от връзка с база данни до извличане на информация за продукти, та чак до потребителска регистрация. Това е корабът Майка. Често се случва корабът Майка да достигне над 10 000 реда код, което е голяма гордост за автора. Някои програмисти си мерят… редовете код, но в сорс кода количество != качество.

Преминаването от този стар стил към обектно-ориентирано мислене е много труден (това че ползваш два-три класа не значи, че проекта ти е обектно-ориентиран, а по-скоро обектно-дезориентиран).

Когато преди година разбрах, че се готви нова версия на любимата ми платформата, бях повече от сигурен, че ще има куп нови неща за учене и имах чувството, че Zend ще промени света на PHP за втори път.

Какво не беше наред със Zend Framework 1?

Въпреки, че храня доста сантиментални чувства към ZF, не мога да пренебрегна факта, че има много неща, които не ми харесват.

Тромава модулна система

Модулната система в Zend Framework беше добавена по-късно. В по-ранните версии на ZF не беше обърнато внимание на модулите и затова възможността за модули в ZF 1 e по-скоро нагодена. Липсват много важни възможности като модулна конфигурация и конфигуриран лоудър за класове. Всички тези неща бяха не чак толкова трудно поправими, но създадоха нерви.

Прекалено много Сингълтон

Един от най-често срещаните шаблони в платформата е Singleton. Но защо Сингълтон е лош? Той е толкова лесен за импелентация и използване. Истината е, че времето на сингълтоните мина и ние трябва плавно да забравим за тях.

Защо Сингълтон е лош?

Да вземем например Zend_Controller_Front – гръбнака на MVC имплементацията в Zend. Този клас предоставя единствен обект в цялото приложение чрез метода getInstance(). Извиква се лесно от всички крайща на кода. Благодарение на това ние можем да получим информация за текущата http заявка както и много други ценни параметри, които той съхранява. Но какво правим, ако искаме да сменим Zend_Controller_Front с наша собствена имплементация на класа? Това е напълно невъзможно, защото останалите класове в библиотеката Zend_Controller използват този сингълтон и няма чист начин да променим това. Те винаги ще ползват този клас. Не можем да редактираме останалите класове в пакета, защото трябва да правим това всеки път когато излезе нова версия на Zend Framework 1.*.

Освен сингълтоните, лоши са всички други класове, предоставящи статични методи с важна имплементация, като например Zend_Controller_Action_HelperBroker -  той също се извиква статично от много места и не можем да го сменим с наш клас.

Някои ограничения на Zend_Db

Един от най-любимите ми компоненти в Zend e Zend_Db.

Zend_Db е добре измислен абстрактен слой, чиято цел е да облече SQL заявките в обектно-ориентирани дрехи. В структурата на компонента са използвани шаблони от Patterns of Enterprise Application Architecture като Table Data Gateway и Row Data Gateway. Използването на Zend_Db е истинско удоволствие. За един проект със средна сложност, Zend_Db може да осигури функционалност без да има нужда да се пише нито една SQL заявка.

Какво не е наред със Zend_Db?

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

Класът Zend_Db_Adapter осигурява 4-те стандартни CRUD метода insert(), update(), delete() и select(), с чиято помощ може лесно да боравите със съответните SQL команди, но това което ограничава функциалността на този клас е, че не можете лесно да обогатите функциалността на някой от тези методи.

Да вземем например insert(). С този метод се създава заявка INSERT INTO .. VALUES .., но ако искам да добавя ключовата дума IGNORE (която ще репресира грешки предизвикани от дублаж на редове с уникални ключове) ще ударя на камък, защото такава настройка в Zend_Db не съществува. В случея лошото е, не че няма INSERT IGNORE заявки, а че не мога лесно да променя Zend_Db, така че да добавя тази функционалност.

Същата ситуация е и с INSERT .. ON DUPLICATE KEY UPDATE.

Ново начало за Zend Framework

Една от главните цели на първата версия на ZF беше да стандартизира употребата на PHP като се лансират новите възможности на 5-та версия. Минаха години от първия релийз на фреймуърка и PHP също се промени. Много от възможностите, планувани за дългоочакваната версия 6 бяха пуснати предварително във феноменалната 5.3.

Наистина езикът се изкачи на още по-високо ниво, приличайки на големия брат Java. Запознахме се с namespace-ове, callback функции, и още други интересни възможности се появиха в следващата версия – PHP 5.4.

С напредването на времето в общността се усети нуждата от примерна и стабилна имплементация на всички тези възможности и следваща мажорна версия на ZF беше неизбежна. Дълго се дискутираха идеи относно бъдещето на новия фреймуърк, но като че ли цялата енергия беше концентрирана около Dependency Injection.

Темата не засяга обучение върху основите на Zend Framework 2, а по-скоро пропаганда. Затова няма да видите конкретни примери за употреба и т.н.

Dependency Injection

Да, Zend Framework 2 трябваше да бъде Dependency Injection базиран. Но защо? Какво ще ни даде това така далечно и неясно понятие?

Всъщност приобщаването на DI в PHP общността беше една сериозна крачка напред.

Повече за DI тук

Гъвкавата архитектура

Най-важната екстра, която дава новата архитектура на ZF 2, е че с използването на Dependency Injection можем да сменим всеки клас в библиотеката с наша собствена имплементация. Лансирано е използването на интерфейси, а за сингълтони не става и дума.

Мощна конфигурация

Подмяната на класове става посредством специални настройки в така наречената DI конфигурация. Няма да давам конкретни примери, защото целта на статията е да обобщя на кратко възможностите на Zend Framework 2.

Имплементация на Service Locator

  Само за разбирачи

Комбинацията между Dependency Injection и Service Locator е като да правиш любов с много красива и нежна жена. Ако приемем, че Dependency Injection е силна, но груба страст, то Service Locator добавя нежност и красота.

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

Service Locator-ите решават този проблем като предоставят инстанциите само когато има нужда от тях. Въпреки, че това е напълно различен патърн, той може да бъде използван много хармонично заедно с DI (което е широка практика). Резултатът е инжектиране не на конкретни инстанции, а на самия Service Locator, чрез който се осъществява достъп до нужните услуги/инстанции.

Въпреки, че DI е в сърцето на Zend Framework 2, разработчиците си нямат взимане-даване директно с DI конфигурацията на контейнера. Самият DI слой е скрит под библиотека, наречена Zend\ServiceManager, която всъщност представлява мощна имплентация на Service Locator. Тя разполага със собствена конфигурация, която от своя страна говори със Zend\Di.

Новата модулна система

ДА! Това е нещо, от което наистина имахме нужда! Но какво точно ни дава тази нова модулна система?

Преносимост

Преносимостта е нещо, към което всеки програмист се стреми. Целта на новата модулна система е да концентрира разпределянето на логиката в модули, така че да се улесни пренасянето и адаптирането на тази логика в други приложения.

За разлика от Zend Framework 1, не е задължително модулите в ZF 2 да са MVC. Може да напишете модул, който предоставя библиотека, осигуряваща логика за други модули. Например може да имаме модул PayPal, в който да се съдържат класове за разплащане с PayPal, но не и съответни контролери, view скриптове и модели.

Като най-ярък практически пример за мощността на новата модулна система е създадената общност за разпространение на модули – http://modules.zendframework.com. На тази страница всеки може да публикува модули и всеки може да използва такива. Това ще направи разработването на проекти със ZF 2 още по-бързо и лесно.

Лесна конфигурация

В Zend Framework 1 бяхме свикнали да пишем платформената конфигурация в .ini файлове. Това осигуряваше добра четимост, но в някои случеи беше трън в очите за хората, които търсеха висока производителност. Освен това липсваше зареждане на модулна конфигурация по подразбиране.

В ZF 2 за конфигурация по подразбиране се използва асоциативен масив.

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

Заключение

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

С голямо удоволствие ще наблюдавам израстването и развитието на фреймуърка, но съветвам ZF разработчиците да не прибързат със Zend Framework 2.

Zend Framework не е най-добрият фреймуърк, той просто е в класация “Топ 1″.

В света на PHP има два типа програмисти. Първите са любознателни, търсещи познания и възможно най-елегантни и чисти решения на проблеми в разработките, целящи да превърнат кода си в една хармонична картина, която поражда възхищение, а не безконечни душевни терзания. Вторият тип са мързеливите, вечно бързащи паразити, за които програмирането е близко до някакъв вид миньорска дейност. В сорс кода обаче количество != качество. Прези годините съм разбрал, че в тази област няма положение в което си казваш “Аз съм готов! Няма какво повече да уча!”. Непрекъснато излизат нови методики и подходи, които имат за цел да направят живота на програмиста по-лесен.

В последно време все повече и повече се говори за Dependency Injection(DI) в PHP общността – и има защо. По моя лична преценка, разработката на Zend Framework 2 и Symfony 2 популяризира значително Dependency Injection(в PHP) и хвърли светлина върху важността и големите предимства на този design pattern. Въпреки всичките статии в блоговете, PHP програмистите все още се плашат от тази подход. Ще се опитам да обясня как аз разбирам и използвам DI.

Какво точно е Dependency Injection?

Dependency Injection е design pattern. Много хора не правят разлика между Dependency Injection и Dependency Injection Container. За сега ще се опитам да обясня DI, като за DI Container-и ще си поговорим по-надолу.

Както много други шаблони, така и DI може да се обясни най-лесно с пример. Нека имаме два класа – Keyboard и PersonalComputer.


<?php
class Keyboard
{

}


class PersonalComputer
{

protected $keyboard = null;

public function __construct(Keyboard $keyboard)
{
$this->keyboard = $keyboard;
}

public function getKeyboard()
{
return $this->keyboard;
}

}

<?php
$keyboard = new Keyboard;
$pc = new PersonalComputer($keyboard);

Както се вижда от примера, първо инстанцираме класа Keyboard, след което създаваме обект от тип PersonalComputer. При инстанцирането на PersonalComputer, подаваме като аргумент на конструктора инстанцията на Keyboard. От своя страна конструктора на PersonalComputer капсулира получения обект в protected $keyboard.

Забележете, че в конструктора на PersonalComputer уточняваме какъв тип обект точно ни трябва – инстанция на Keyboard. По този начин сме сигурни, че класа PersonalComputer ще бъде успешно инстанциран тогава и само тогава, когато подадения аргумент $keyboard е обект от тип Keyboard.

Разгледания горе пример представя така наречения constructor injection (инжектиране чрез конструктора). В този случей се казва, че PersonalComputer консумира (consumes) Keyboard.

DI контейнери

Dependency Injection контейнерите са библиотеки, които автоматично инжектират зависими инстанции.

Phemto е DI контейнер за PHP. Ето как ще приложим Phemto с горния пример:

<?php
$injector = new Phemto;
$pc = $injector->create('PersonalComputer');

Контейнерът анализира класа PersonalComputer(използвайки Reflection) и автоматично инжектира нова инстанция на Keyboard.

DI конфигурация

Автоматичното създаване на инстанции е най-фундаменталната възможност на DI контейнерите. В много случеи разработчиците имат нужда да контролират тези инстанции. Универсалното решение е използване на конфигурация във външен файл.

Едни от най-главните опции, които влизат в конфигурацията на повечето DI контейнери са следните:

  • Дефиниране на параметри, които да се подадът на конструктура на даден клас при инстанциране
  • Определяне на опцията shared за клас – ако е true това означава, че даден клас ще се инстанцира само веднъж и всяка едно негово създаване чрез контейнера ще връща една и съща инстанция.
  • Настройка (обикновенно наречена call) за автоматично извикване на setter методи след инстанциране на клас (setter injection е подход подобен на горе споменатият constructor injection, но вместо конструктор се използват setter методи)
  • Дефиниране на конфигурации на инстанции, които се създават в контекста на даден клас (йерархично конфигуриране на инстанции)

В следващата част ще си поговорим по-сериозно за DI конфигурации. Също така ще погледнем някои други теми, които са свързани с DI (като шаблона Service Locator например).

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

От самото си излизане, Google Chrome предизвика истинска истерия и доста (според мен) фалшиви, и ненужни овации (тук искам да вметна, че въпреки критичното ми отношение към Chrome, аз го слагам в графата “Добри браузъри”, като оставям горкият и измъчен Internet Explorer да се радва съмичък на страхотния си compatibility mode (от който наистина ме е страх!) в секцията “Изтръпнали браузъри”).

Различия между браузърите има и това е нормално. Обикновено един опитен front-end coder (като мен) знае често срещаните проблеми и  бързо се справя в аварийни ситуации. Наскоро обаче се сблъсках с проблем, който успя да подложи на тест не само моето собствено търпение, но и търпението на някои колеги, които също бяха въвлечени в това малко приключение.

Google Chrome + Flash + jQuery UI Draggable = възможни проблеми

Често се налага някъде в сайтовете да добавяме бутони за копиране на текст в буфера на компютъра (copy). Тази опция е забранена от браузърите (не може да се направи само с JavaScript) и един възможен начин да се постигне тази функционалност е използването на малък flash клип. Сигурно сте чували за проекта ZeroClipboard – това е JavaScript/Flash библиотека, която улеснява създаването на бутони за копиране на текст.

В един от последните проекти, с които се занимавах, трябваше да добавя копиране на текст в буфера на няколко места. Едно от тях беше в един draggable контейнер, който работи с jQuery UI Draggable. Същият такъв бутон имаше и на няколко други места, но те не бяха в draggable контейнери. Работя с Mozilla Firefox и там нямаше проблеми.

Еми… Нека тестваме под Chrome

В края на деня реших все пак да тествам под Google Chrome (като бях предубеден, че сериозни проблеми няма да имам, особенно такива, свързани с JavaScript). И изненада – бутонът за копиране на текст не работи под Chrome.

Демо, не работи под Google Chrome

Мина време в търсене на грешката, като бе необходима и намесата на опитен Flash разработчик, с който тествахме няколко часа. В края на крайщата открихме, че под Google Chrome, flash клипът губи фокус. Но защо? След търсене в интернет се натъкнах на тази тема. При наличието на много контейнери, елементи и т.н. (демото горе е много изчистена версия, съдържаща само точния сценарии на проблема) е трудно да разбереш, коя от всичките маймуни те замеря с банани. Оказа се, че възможността за влачене на родителския контейнер “разсейва” Chrome от flash клипа и затова mouseDown събитието не се отчита.

Как поправихме проблема

Както е написано в посочената тема по-горе, добавихме изключение при влаченето – да не работи на контейнера, държащ flash клипа.

$('.draggable').draggable({ cancel: '.with-flash' });

Демо, което работи под Google Chrome

Заключение

Въпреки силно изразената ми антипатия към Google Chrome, бих казал, че този бъг е доста логичен и не е толкова странен. Нормално е при drag да се губи фокус от flash клипове (Вероятно Google Chrome е с по-голямо самочувствие от Flash).

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

Днес реших да създам една малка библиотека(само един клас), която да ми помага при изпълнение на SQL заявки.

Не винаги мога да използвам Zend_Db, а и няма голям смисъл от цялата тази мощ, ако става дума за малък проект.

Представям ви Elegance Database Wrapper(или Elegance_Db). Класът наподобява Zend_Db_Adapter_Pdo_*, но е изключително малък и компактен. Използва PDO дравърите и осигурява удобно и лесно API.

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

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

Кой съм аз, че да съдя другите?

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

Но в тази статия мисля да използвам най-любимото си средство за забавление – иронията.

Чалга няма само в музиката

“Здрастииии!”

“Как сиии?”

Всички знаят тези лафове, но аз все още се чудя, защо толкова много хора ги намират за смешни?

Стандартните извинения

Повечето чалгари крият истинската си същност зад няколко много стандартни и повърхностни извинения. От мои лични наблюдения съм извадил най-често срещаните от тях:

“Аз слушам всичко”

Bitch please! Като слушаш всичко, кажи едно парче на Майлс Дейвис. Естествено защитната реакция е “Този сигурно не е много известен”, което е доста грубо, що се отнася за човек, променил джаза няколко пъти по време на музикалната си кариера. От тук аз си правя изводи, че цитираният индивид няма понятие от джаз, което е доста жалко, като се има предвид влиянието на това течение върху съвременната популярна и ъндърграунд сцена.

“Аз слушам каквото ми пуснат”

Тогава си пусни Sepultura – Primitive Future (силен дизинфектант).

 

Главната тема

Аз съм разработчик и се занимавам с изкуство, наречено уеб вече 8 години. През цялата си практика никога не съм спирал да се уча от по-добрите и винаги съм се доверявал на утвърдени имена в областа, в която градя своите познания. Програмирането е свързано със сложен мисловен процес и изграждането на гъвкаво въображение, което непрекъснато се развива. В програмирането няма ситуация, в която ти си достигнал предела на знанията и няма какво повече да научиш. Винаги има по-добри от теб и винаги трябва да си любопитен.

Програмисти, които слушат чалга

Ето че стигнахме и до сърцевината на темата днес.

Бях много учуден, като открих толкова много хора, които слушат чалга докато пишат код. Кое е толкова странно според мен ли? Ще се опитам да опиша как аз виждам тази комбинация.

Да си представим един програмист, който трябва да напише голяма и комплексна система. За разтоварване е доста приятно да слушаш музика, но нека в нашият пример музиката е чалга. За сега няма нищо странно. Но нека видим какво се пее в дадената чалга песен:

“Кой ще погали котето любовно?”

Програмиране… Интелектуален труд… Котето любовно???? (WTF?!)

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

Особенно добре се вписват и много други текстове, в които лирическият герой описва своята дълбока емоционалност:

“Дали езика си искаш да гълтам, или си мислиш, че може и друго”

Естествено това създава страхотна хармония и се вписва в процеса на разработка на програми.

“Твоите погледи нямат цена, знаеш ли къде ми бъркаш така?”

Къде?

 

Заключение

Като за обобщение искам да кажа, че много се дразня на простотията. Чалгата не подхожда на хора, които се имат за интелигентни. Може да си много умен, но нали знаеш… слушаш чалга ;)

При последния ъпгрейд на Ubuntu (към версия 12.04) ми се затриха някои GNOME 3 настройки. Едно от най-дразнещите неща е тъмния фон на tooltip-овете.

С помощта на тази статия можете бързо и лесно да промените цветовете, не само за тултиповете – http://askubuntu.com/questions/70599/how-to-change-tooltip-background-color-in-unity

Днес трябваше да оптимизирам един мой проект на Zend Framework. На домашния си компютър не бях работил с профайлъра на Zend Studio, така че се заех да го конфигурирам.

Мина известно време в неуспешни тестове, като ми се връщаше една и съща грешка – “A timeout occurred when the debug server attempted to connect to the following client hosts/IPs: -127.0.0.1

Взех да се ровя в интернет, но в крайна сметка реших да подходя по-класически и да оставя Zend Studio – активирах си xdebug и му включих профилинга. Но когато отворих генерирания профил с KCacheGrind бях изненадан, че execution flow-а на приложението ми мистериозно прекъсва до една доста начална позиция.

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

 

В крайна сметка се оказа, че преди време съм си инсталирал XCache (доста добро opcode cache разширение за PHP), което влиза в конфликт с дебъгерите (което е доста логично). Общо взето който и да е opcode cacher би попречил на дебъгването. Веднага следкато изключих XCache всичко беше наред.

Ще разгледаме конфигурирането на Zend Framework върху Linux и Windows.

Конфигурацията на Zend Framework в общи линии е добавяне на пътят до библиотеката на Zend Framework в PHP директивата include_path и конфигуриране на ZF Command Line Tool.

1. Линукс

Като широко разпространена дистрибуция, примерите са направени на Ubuntu (10.10), но би трябвало да работят подобно и на всички други дистрибуции.

Първата стъпка е да се сдобиете със Zend Framework. Това може да стане по няколко начина – да го инсталирате като пакет от терминала, да го изтеглите от официалния сайт на ZF – http://framework.zend.com/download/latest* или да използвате SVN хранилището на фреймуърка.

* На страницата Downloads -> Latest Release ще се покажат няколко възможности за сваляне на фреймуърка. Първата (Zend Framework + Zend Server Community Edition(CE)) е само ако искате да свалите ZF в комплект със Zend Server. Zend Server e пакет съдържащ конфигурирани Apache, PHP, MySQL, Zend Framework, phpMyAdmin, etc. Zend Server е най-удобен ако сте Windows потребител.

Инсталиране като пакет

Този метод на инсталиране е за предпочитане!

Най-лесният начин да се сдобиете със Zend Framework под Ubuntu е да го инсталирате като пакет.

Отворете терминал и въведете

$ sudo apt-get install zend-framework

Тази команда ще инсталира за Вас последната стабилна версия на ZF. Инсталацията ще свали файловете в /usr/share/php/libzend-framework-php

SVN Export

SVN (Subversion) е широко използвана система за контрол на файловите версии(повече за SVN може да прочетете тук).

В бъдеще ще напиша статия специялно за SVN и Version Control системите. Ако не сте наясно, по-добре изтеглете Zend Framework по стандартния начин.

За да инсталирате SVN на Ubuntu въведете следното в терминала:

$ sudo apt-get install subversion

След като SVN се инсталира, създайте папка, в която искате да изтеглите ZF:

$ mkdir zend-framework

$ cd zend-framework

Не забравяйте втората команда! Ако не смените директорията, ZF ще се “стовари” в home/потребител папката ви, а това е нещо, което не бихме искали да се случва.

За да изтеглите файловете, трябва само да напишете следната команда:

$ svn export http://framework.zend.com/svn/framework/standard/trunk/ ./

Изтегляне от сайта

http://framework.zend.com/download/latest

Изтеглете Zend Framework Minimal Package и разархивирайте в папка по избор. За да изтеглите и разархивирате от терминал, може да използвате следните команди:

$ wget http://framework.zend.com/releases/ZendFramework-1.11.2/ZendFramework-1.11.2-minimal.tar.gz ./zend-framework.tar.gz

$ tar xvzf zend-framework.tar.gz

Zend Framework е изтеглен в /home/потребител/zend-framework

Конфигурация

Следкато вече имаме Zend Framework, трябва да направим малко настройки.

Отворете php.ini и намерете следните редове:

;;;;;;;;;;;;;;;;;;;;;;;;;
; Paths and Directories ;
;;;;;;;;;;;;;;;;;;;;;;;;;

; UNIX: “/path1:/path2″
include_path = “.:/usr/share/php”

Тук трябва да направите промяна на include_path, трябва да добавите пътят до папка наречена library, която сте свалили (/home/потребител/zend-framework/library). При добавянето на директория в include_path не бива да забравяте да добавите “:” преди новата директория. Ето пример за това как може да изглежда един include_path:

include_path = “.:/usr/share/php:/home/потребител/zend-framework/library”

Запазете файла и рестартирайте уеб сървъра си. Ако използвате Apache – sudo service apache2 restart или sudo service lighttpd restart за Lighttpd

Остава само да добавим и един  скрипт в /usr/bin по-известен като CLI Tool. В следващата глава ще обясня за какво служи този скрипт.

В директорията /home/потребител/zend-framework трябва да съществува папка на име bin. Въведете тази команда от терминала:

$ sudo ln -s /home/потребител/zend-framework/bin/zf.sh /usr/bin/zf

2. Windows

Най-лесният начин да инсталирате Zend Framework под Windows е със Zend Server CE.

Zend Server е пакет съдържащ в себе си PHP, Apache, MySQL(по избор), Zend Framework(по избор), phpMyAdmin(по избор).

Няма нужда от никакви настройки.

Ръчна инсталация

Ако все пак вече имате инсталиран сървър, и той не е Zend Server, ето как да инсталирате ZF ръчно:

  1. Изтеглете Zend Framework от тук(изтеглете предпоследния пакет – Zend Framework 1.**.** Minimal)
  2. Разархивирайте в папка по избор
  3. Отворете php.ini и намерете следните редове:
    ; Windows: “\path1;\path2″
    ;include_path = “.;c:\php\includes”
  4. Добавете пътят до папката library в include_path (не забравяйте да махнете ; пред ;include_path). Трябва да се получи нещо такова: include_path = “.;c:\php\includes;c:\път\до\zend\framework\library”
  5. Рестартирайте Apache