Koji programski jezik učiti

Pitanje iz naslova jedno je od najčešće postavljenih pitanja svršenih diplomaca ili ljudi koji ulaze u svet programiranja. Pitanje nije trivijalno iz jednostavog razloga što dobro odabrana tehnologija znači veće mogućnosti za pronalaženje posla, bolje plaćen posao, … u najkraćem - svetliju budućnost.

Sve do juče na pitanje iz naslova bez mnogo razmišljanja odgovarao bih - PHP. Jednostavno, PHP poslova uvek ima, PHP se relativno brzo nauči, tako da za relativno kratko vreme možete doći do posla. Čak i za one bez ikakvog iskustva, otvorenost Web platforme omogućava početnicima da naprave sopstveni sajt, sajt komšijine prodavnice, prijatelja … whatever … i tako za kratko vreme steknu kakve takve reference i iskustvo - stvar koju tako mnogo tražimo mi koji tragamo za kvalitetnim developerima.

Elem, pre nekoliko dana kolega iz FBM-a zamolio me je da otvorim novu poziciju za iPhone developere, nakon čega sam nažalost jako brzo saznao da se broj iPhone Developera u Srbiji može nabrojati “na prste” jedne ruke.

Međutim situacija u svetu a naročito u USA je dramatično drugačija. Broj downloada iPhone aplikacija na Apple Application Store-u bliži se cifri sa 9 nula, a trenutno na listi najprodavanijih knjiga na Amazonu u kategoriji Računari i Internet možete naći samo nekoliko programerskih knjiga, od kojih su apsolutno sve vezane za iPhone. Ista priča je i kada odete i na kategoriju Programming gde su tri od prvih pet naslova knjige o razvoju iPhone aplikacija!

iPhone Development Books
iPhone Application Develpment Books

Nažalost cene Apple računara i nedostatak zvanične iPhone podrške u Srbiji i dalje je veliki problem u ovoj priči. No, za one za koje taj problem nije nepremostiv, današnji odgovor na pitanje iz naslova definitivno bi bio Objective C. Nisam siguran da ću čak i ja odoleti iskušenju …

Browser Detection Update

Danas sam sticajem okolnosti bio u prilici da nakon duzeg vremena updatujem svoju klasu za detekciju browsera. Radi se o klasi koja omogucava detektovanje tacne verzije Browsera/OS-a na osnovu user agenta browsera.

Npr: Mozilla Firefox 3.0.4 / Mac OS X

Može biti od koristi u slučaju da želite da korisnike određenih browsera redirektujete na posebne strane, kod pravljenja sopstvene statistike korišćenosti browsera itd.

Update sadrži dodatu podršku za Google Chrome, iPhone i Windows Vista OS.

Kompletan kod sa primerima možete downloadovati ovde

Izlaz scripta na ekranu i fajlu

Zbog prirode svog posla gotovo svakodnevno se bakćem sa raznoraznim php cli scriptovima. Često su u pitanju programi koji rade jako dugo (satima, neki čak i danima), ponekad praveći veliku količinu outputa, te zbog toga praktikujem da iste startujem unutar screen sesije, kako bih uvek mogao da se ponovo ulogujem u sesiju i bacim pogled kako stoje stvari.

Veoma je dobro logovati kompletan output skripta u fajl, za slučaj da je nešto pošlo naopako, ali nekako sam uvek voleo da onako “live” vidim na ekranu šta se dešava, umesto da mi ceo izlaz stoji u nekom tamo log fajlu. No, zahvaljući unix tee komandi i ovom postu, danas sam naučio da mogu imati obadva.

./script.php | tee out.log

Ovo će kreirati fajl out.log i usmeriti kompletan output scripta u njega, ali će isti biti prikazan i na ekranu (STDOUT). U slučaju da želite samo da dodate (append) output u postojeći log, nema problema:

./script.php | tee -a out.log

MySQL Jokeri

Pitanje za milion dolara u nekom popularnom kvizu. Imate samo 15 sekundi za odgovor. Srecni ste jer ste izvukli pitanje iz vase omiljene oblasti :)

Kako obrisati sve korisnike ciji nick pocinje sa donjom crtom (’_').

I vas odgovor je naravno:

delete from users where username like '_%';

Vec mastate o raskalasnom zivotu daleko od kompjutera, mozda i neka jahtica pride (i sve sto ide u to lol). Glas voditelja vraca vas u surovu realnost. “Zao mi je, ovo nije tacan odgovor”. U neverici gledate vas query i milione koji su otisli u nepovrat.

Verovali ili ne, slicnu nevericu iskusio sam na svojoj kozi pre nekoliko veceri, tacnije 8. aprila. U tabeli sa nekoliko miliona generisanih domena uocen je bug (mala greska u regularnom izrazu) i nekako su generisani i domeni koji pocinju sa znakom “_”. Underscore (donja crta) naravno nije dozvoljen kod domena, bug je ispravljen ali treba obrisati i te nevalidne domene iz baze. Nista lakse, jedan brzi query i sve ce ubrzo biti pocisceno. Otvaram mysql klijent i bez mnogo razmisljanja kucam:

mysql> delete from result_domains where domain like '_%';
Query OK, 9035782 rows affected (9 min 57.35 sec)

WTF!?? Query je obrisao sve domene iz tabele. Ali kaaakooo???

I onda se setim. Donja crta - ‘_’ je poput ‘%’, takodje joker karakter koji za razliku od ‘%’ (koji menja ‘nula ili vise’ karaktera), ‘_’ menja tacno jedan karakter. Ne secam se kada sam ga poslednji put koristio (ako sam ga uopste koristio), ali znam da mi je on dosao glave.

Cimam admina na ICQ … treba mi backup, server taj i taj, tabela ta i ta, poslednji koji imamo … ASAP! Posle 30-tak sekundi admin se javlja “ok, poslednji koji imamo je od 8 marta. Gde da ti stavim?”. FUCK!!!

FUCK!!! FUCK!!! FUCK!!! FUUUUCK!!!

Ustajem od kompjutera i besno setam kroz sobu. Na postoji nacin da objasnim klijentu da sam jednim jedinim kverijem sjebao sate i sate mukotrpnog rada, podatke vredne verovatno hiljade dolara. Da imam utoku verovatno bih pao u iskusenje da pucam sebi u glavu. Mozda pre toga da sredim i admina? Kako god, sta je tu je, ne preostaje nista drugo nego da napisem email i objasnim svom klijentu sta se desilo.

Sedam ponovo za comp, ali umesto da otvorim thunderbird, cimam ponovo admina.

- Ja: “Jebote … kako se desilo da je poslednji backup star mesec dana???”
- Admin: “Kako to mislis? Ovo je backup od sinoc!?”
- Ja: “Rekao si 8 mart???”
- Admin: “Ups. Sorry, 8. April. Sad gledam, kreiran je pre samo par sati. Moze?”

I tako, my ass has been saved. Ali moglo je i biti drugacije. Mnogo drugacije.

Pouka price:

1) Budite ekstremno oprezni kada kucate nesto unutar mysql klijenta (ili phpmyadmina) koji barata sa live podacima
2) Ako morate da brisete/update-ujete nesto, uvek uradite prvo count nad istim podacima i istom where klauzom kako bi ste se uverili da je to bas ono sto ste zeleli.

Npr:

mysql> select count(*) from result_domains where domain like '_%';
+----------+
| count(*) |
+----------+
|  9035782 |
+----------+
1 row in set (5.27 sec)

(ups nesto ne valja, ovo ce obrisati sve domene koje imamo)

mysql> select count(*) from result_domains where domain like '\_%';
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (4.18 sec)

Aha, sada je sve ok :)

3) Uvek pravite redovan backup. Ako to za vas rade admini postarajte se da rade svoj posao kako treba. Cak i tada nije losa ideja da s vremena na vreme napravite sopstveni backup.

P.S. Problem sa pocetka price (matchovanje stringa koji pocinje sa ‘_’) resava se jednostavnim escapovanjem specijalnog karaktera. Dakle:

select foo from footable where somefield like '\_%';

ili ako ste ljubitelj regularnih izraza:

select foo from footable where somefield regexp '^_';

Curl HTTP Client 1.2

Upravo uploadovao novu verziju sa nekim sitnim izmenama. Ispravljeno je nekoliko sitnih bugova na koje su se korisnici žalili, a od novih mogućnosti dodata je mogućnost pozivanja send_post_data metoda direktno sa post stringom, zatim podrška za gzipped contents itd.

Verziju 1.2 možete skinuti ovde.

PHP 4 end of life announcement

Preuzeto sa php.net

[12-Jul-2007]

Today it is exactly three years ago since PHP 5 has been released. In those three years it has seen many improvements over PHP 4. PHP 5 is fast, stable & production-ready and as PHP 6 is on the way, PHP 4 will be discontinued.

The PHP development team hereby announces that support for PHP 4 will continue until the end of this year only. After 2007-12-31 there will be no more releases of PHP 4.4. We will continue to make critical security fixes available on a case-by-case basis until 2008-08-08. Please use the rest of this year to make your application suitable to run on PHP 5.

For documentation on migration for PHP 4 to PHP 5, we would like to point you to our migration guide. There is additional information available in the PHP 5.0 to PHP 5.1 and PHP 5.1 to PHP 5.2 migration guides as well.

Šta reći nego - Konačno! Nadam se da će ovo najzad pogurati ljude ka migraciji ka petici. A PHP6 samo što nije :)

MySQL 5.x - Konačno unapređen klijent

Listajući svoje omiljene WebDev feed-ove, za oko mi je zapao jedan post na sjajnom MySQL Perfomance Blogu:

…if you press CTRL-C MySQL Command Line Client will not exit but will terminate query being executed.

Drugim rečima, u dosadašnjim verzijama MySQL klijenta, kada bi ste ukucali neki query i pritiskom na CTRL-C pokušali da prekinete njegovo izvršavanje, CTRL-C bi zapravo ubio MySQL klijent, ali query nastavlja da se izvršava u pozadini! Rešenje u takvim slučajevima je traženje id-a tog query-a na listi procesa upitom “show full processlist”, a zatim njegovo “ubijanje” upitom “kill 12345″ gde je 12345 u ovom slučaju id procesa koji želimo da ubijemo. Dakle, recimo nešto ovako:

mysql> select * from odm_result_keywords where keyword like '%foo%joe%';
^CAborted
bash-2.05b$ mysql -A --enable-local-infile -udinke -ppass mydb
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1512 to server version: 4.1.18-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show full processlist;
+------+-------+----------------------------+-------------------+---------+------+--------------+--------------------------------------------------------------------+
| Id   | User  | Host                       | db                | Command | Time | State        | Info                                                               |
+------+-------+----------------------------+-------------------+---------+------+--------------+--------------------------------------------------------------------+
| 1486 | dinke | localhost                  | mydb | Query   |    3 | Sending data | select * from odm_result_keywords where keyword like '%foo%joe.cl' |
+------+-------+----------------------------+-------------------+---------+------+--------------+--------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> kill 1486;
mysql>

Zahvaljujući izmenama u MySQL klijentu, sada je dovoljno da stisnete CTRL-C, i query će biti odmah prekinut:

mysql> select domain from odm_result_keywords_de where whois_status is null and domain like '%.%.%';
Query aborted by Ctrl+C
ERROR 1317 (70100): Query execution was interrupted
mysql>

Više informacija o ovoj, kao i drugim izmenama u pomenutoj verziji (5.0.25) možete naći ovde.

MySQL - Backup velikih MyISAM tabela

Ako ste ikada morali da backup-ujete ili prebacujete podatke iz jedne ili više MySQL tabela, znate da se za to koristi mysqldump utility, pomoću kojeg jednostavno podatke iz MySQL-a “dumpujete” u neki mojetabele.sql fajl, koji zatim možete sačuvati kao backup, prebaciti i importovati na neki drugi MySQL server, itd. Ovu proceduru koristio sam milion puta do sada, i ona se generalno svodi na izvršavanje sledećih komandi u linuxu:

export:

mysqldump -udinke -pmojpass -hhostname.prvog.servera ime_baze tabela1 tabela 2 tabelan > dump_fajl.sql

import:

mysql -udinke -pmojpass -hhostname.drugog.servera ime_baze < dump_fajl.sql

Tu i tamo pojavi se problem kada prebacujete dump sa novije verzije MySQL-a na stariju, i tada je poželjno specifirati i odgovarajući compability flag prilikom izvršavanja mysqldump komande (–compatible=name gde name može biti mysql323, mysql40, postgresql, oracle itd.).

Elem, pre nekoliko dana zbog prebacivanja MySQL servera sa jedne lokacije na drugu, morao sam da odradim dump solidno velikih MySQL tabela (10-tak tabela gde je svaka imala preko 2 miliona slogova). Nakon užasavajuće duge procedure dumpa, gzipovanja i scpovanja na drugi server, konačno sam startovao import. Međutim, nakon 3 sata (tri sata) umesto standardne “no news is a good news” poruke, kada sam bacio pogled na status dočekala me je sledeća poruka …:

[dinke@um-917 ~/public_html]$ mysql -udinke -p325ewfwt23rasf
keyword_discovery < es_miner_data.sql
ERROR 1582 (23000) at line 163833: Duplicate entry '1167548' for key
'PRIMARY'

WTF? Prebacivao sam podatke sa starije verzije na noviju, što znali da import mora proći glatko! Ovo bi trebalo da znači da je MySQL negde nešto pobrljavio sa indexima, i umesto da čekam još 2 sata da se odradi check & repair, odlučujem se da napravim ponovo dump fajl, ovaj put sa ignore opcijom, kako bi svi inserti u dump fajlu bili “insert ignore” tako da u slučaju ovakve greške ne bi došlo do pucanja. Ne preterano pametno, ali podaci nisu extremno osetljivi i mogu da dozvolim luksuz da izgubim desetak slogova, ali ne i desetak sati za import!

Naravno, novi dump, zip, scp … to je traajalooo … toliko dugo da sam posle par sati nakon startovanja importa krenuo da mozgam sa administratorom (kuki) oko alternativnih rešenja. A rešenje je bilo jednostavno ali efikasno. Prekopirali smo sve MySQL data fajlove sa jednog servera na drugi (*.MYI, *.MYD i *.frm fajlove), a zatim odradili myisamchk kako bi sredili pomenute tabele, jer nismo smeli da spuštamo server prilikom backup-a što generalno može da prouzrokuje dosta problema (tipa oštećene tabele) ako se na ovaj način backupuju fajlovi.

Sve u svemu, ova operacija prošla je jako brzo (najduže je trajalo kopiranje fajlova sa jednog hosta na drugi), i za manje od pola sata cela procedura bila je završena.

Zaključak do koga smo došli je da je kod velikih tabela zbog dužine trajanja operacije dumpovanje praktično neprihvatljivo kao backup rešenje, i da se samim tim kao jedino rešenje nameće kopiranje MySQL data fajlova. Kod MyISAM tabela to nije nikakav problem, jer su one “platform safe”, tj. binarni fajl kreiran na jednoj platformi (recimo *.MYI fajl na linuxu) radiće bez ikakvih problema na drugoj platformi (recimo isti *.MYI fajl na Windowsu).

Client size resizovanje slika

Radeći na servisu Blogodak, nedavno sam se susreo sa problemom kod slika velikih dimenzija koje neki korisnici uključuju u svojim feedovima. Naime, kako Blogodak “vuče” feed-ove sa raznih domaćih blogova, a sa njima i slike koje se u njima nalaze, dešavalo se da one dimenzija većih od 560px uredno “skrljaju” layout blogotka, obzirom da to e == “Microsoft Internet Explorer”)
{prevazilazi predviđenu veličinu containera, tako da u najboljem slučaju dolazi do pojave horizonatalnog skrol bara. Kako nemamo nikakav uticaj na slike koje se vuku sa servera gde su hostovane, server side varijante(npr. resize korišćenjem GD liba ili Image Magicka) nisu primenjive, jedino rešenje je da se dimenzije slike smanje direktno u browseru - Client Side.

CSS Rešenje
Za browsere koji imaju potpunu podršku za css2, dovoljno je staviti nešto tipa:

.container img{
  max-width:560px;
}

u stil strane, tako da će sve slike koje se nalaze unutar nekog <div idclass=”container”>…</div> elementa biti ograničene na max 560 piksela, tj. biće automatski resizovane na odgovarajuću veličinu. Naravno, ovo ne radi u IE-u (verzije < 7) tako da je potreban hack :)

IE Hack (CSS verzija)

.container img{
  max-width:560px;
  /*hack for IE*/
  width: expression(this.width > 560 ? 560: true);
}

Ovaj css hack je validan samo u IE-u, koristi se neka vrsta “ternarnog operatora”, a sam hack skinut je sa ovog bloga. Rado bih vam rekao da više informacija potražite tamo, ali i sam autor priznaje da na razume mnogo oko toga “kako to radi”, ali jednostavno radi. Za ljubitelje standardnijih rešenja, sledi JS verzija.

IE Hack (JS verzija)

Obzirom da mi se nije svidela ideja da koristim nevalidan css kod koji uz to i ne razumem u potpunosti(na stranu što je pravio i neke nekoegzistentne probleme sa IE-om za koji je i namenjen), odlučio sam se za JavaScript rešenje koje sledi.

function fixImages()
{
  //fix images for ie only
  if(navigator.appName == "Microsoft Internet Explorer")
  {
    for(i=0; i<document.images.length; i++)
    {
      //if image is bigger than 560
      if(document.images[i].width > 560)
      {
        imgRatio = document.images[i].width/document.images[i].height;
        document.images[i].width = 560;
        document.images[i].height = 560 / imgRatio;

        //hack neophodan da bi se uklonio skroler zbog prvobitne velicine slike
        //mainContent je ime div kontejnera koji drzi sadrzaj strane
        divid = document.getElementById('mainContent');
        content = divid.innerHTML;
        divid.innerHTML = '';
        divid.innerHTML = content;
      }
    }
  }
}

Ova funkcija se poziva nakon učitavanja stane(onLoad). U slučaju da je u pitanju IE, proveravaju se dimenzije svih slika na strani(parsuje se niz document.images), i u slučaju da dimenzije prevazilaze 560 piksela, setuju se na manje, uz očuvanje proporcija slike. Naravno, ovaj metod ima manu, jer je neophodno da se sve slike prvo učitaju, pa tek onda dolazi do resizovanja. Kod IE-a i pored resizovanja slike na “prihvatljive” dimenzije, bilo je potrebno nekako mu i staviti do znanja da je došlo do promene dimenzija(samo resizovanje nije dovoljno da nestane horizontalni skroler), tako da je bilo neophodno ručno ili skriptabilno rezisovati i prozor browsera. Srećom posle manjeg “prčkanja” sa alternativama prošlo je i jednostavnije rešenje sa setovanjem kontejnera cele strane na prazan string i vraćanjem na prvobitno stanje korišćenjem innerHTML-a.

Nadam se da će ovo nekome biti od koristi :)

Curl HTTP Client - Update

Upravo sam postavio novu verziju svoje Curl_HTTP_Client klase. Nove mogućnosti uključuju file download/upload, korišćenje proxya itd.

Novu verziju možete skinuti sa PHP Classes kao i sa mog sajta - ovde. Opis svih mogućnosti možete naći ovde.

« Older Entries