Parametrii de configurare nginx

26 februarie - No Responses

După vreo 4-5 instalări de nginx pe diverse platforme, am început să folosesc următorii parametrii pentru ./configure:


./configure --conf-path=/etc/nginx/main.conf /
 --with-http_ssl_module --pid-path=/var/run/nginx.pid /
 --error-log-path=/var/log/ngix/error.log /
 --http-log-path=/var/log/nginx/access.log /
 --sbin-path=/usr/local/sbin/nginx --user=app --group=app /
 --http-client-body-temp-path=/var/tmp/nginx/client_body_temp /
 --http-proxy-temp-path=/var/tmp/nginx/proxy_temp /
 --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi_temp

Fişierul executabil ajunge în /usr/local/sbin/, cum ar trebui, log-urile într-un folder dedicat în /var/log/, fişierele temporare în /var/tmp/. Are modulul de HTTPS instalat (dar e complet opţional, update-ul de fişier binar se poate face fără downtime).

Fişierul de configurare este în /etc/nginx/main.conf, ceea ce poate părea un pic ciudat, dar ideea e ca acel fişier să conţină configuraţia globală, nu cea per virtual host. Acelea ar merge într-un folder numit vhosts, de exemplu.

Ruby 1.9 la Google Tech Talks

24 februarie - No Responses

Ştiu, deja devin un fel de stalker pentru Matz. Dar Google Tech Talk + Ruby n-are cum să fie de rău. L.E.: Bonus la 40′11″.

… şi dacă cei de la Google se hotărăsc să scoată embeddul şi pentru filmuleţul acesta, mergi la http://www.youtube.com/watch?v=oEkJvvGEtB4

1 MB de Silverlight

23 februarie - 4 Responses

Am vrut să-mi instalez Silverlight pentru Mac OS X şi am remarcat că ceva interesant la pagina de download:

1 MB vs 4.7 MB

(calitatea proastă a imaginii se datorează faptului că sunt pe Mobile Internet)

Subversion remote cu Mercurial local

23 februarie - No Responses

În ultimele zile am încercat să-mi schimb felul în care fac commit-uri în Subversion. Ştiu că e bine ca acestea să fie cât mai “atomice”, dar invariabil ajungeam să modific un set suficient de mare de fişiere doar ca să nu urc pe server un cod care nu funcţionează. O soluţie rapidă ar fi să folosesc un repository local unde să fac check-in-uri mai frecvente.

Aşa că am folosit instrucţiunile dintr-un articol mai vechi şi am încercat să adaptez modul meu de lucru la workflow-ul cu un sistem distribuit gen Mercurial. Rapid am remarcat că nu mă interesează ca istoricul din repository-ul local să corespundă cu cel din repository-ul remote, însă e foarte important pentru mine ca operaţiile de commit să fie cât mai simplu de efectuat.

Şi pentru că nu-mi place să ţin doar pentru mine (şi pentru că blogul începe să devină un dumping ground din ce în ce mai util), iată micul meu setup, pas cu pas:

Mai întâi se face checkout via Subversion şi se editează proprietăţile repository-ului astfel încât să ignore fişierele specifice Mercurial:


$ svn co http://example.com/svn/proiect proiect
$ cd proiect
$ svn propedit svn:ignore .

iar în fişierul apărut se adaugă .hg şi .hgignore, fiecare pe o linie nouă.

Apoi se setează Mercurial ca să versioneze fişierele curente şi să ignore folderele specifice Subversion:


$ hg init
$ vim .hgignore

unde vim poate fi înlocuit cu editorul preferat. În fişierul .hgignore se adaugă următoarele două linii pentru a se ignora foldere .svn:


syntax: glob
.svn

Pe Windows, dacă se foloseşte hack-ul cu underscore pentru a se putea utiliza Subversion cu proiecte ASP.NET, a doua linie poate fi _svn.

Apoi se adaugă fişiere în Mercurial şi se face commit în ambele sisteme de versionare:


$ hg add
$ hg commit -m "Initializarea proiectului"
$ svn commit -m "Ignoring Mercurial specific files."

Din acest moment, workflow-ul e foarte simplu: se utilizează comenzi Mercurial mai puţin în momentul în care se doreşte un commit în serverul central de Subversion. Avantajul major e că acum poţi folosi commit hooks pe Mercurial (care sunt ceva mai simplu de setat decât în svn) şi poţi rula propriul setup local, eventual cu un build de continuous integration.

Frumuseţea unui cod

22 februarie - 9 Responses

De câteva ori am fost întrebat, de prieteni sau de membri ai familiei mele, care este motivul pentru care am ales să încep o carieră ca programator. Răspunsul meu a fost de fiecare dată atât de simplu încât probabil că n-a mulţumit pe nimeni: pentru că altceva nu ştiu să fac.

Povestea ar începe undeva prin ‘93 când am făcut două module de programare în BASIC pe nişte maşini HC ‘85 în clădirea de lângă cinematograful Patria, actualul Cărtureşti. Atunci ai mei mi-au cumpărat un sistem întreg HC ‘91 cu unitate de floppy şi monitor monocrom. Pe care l-am folosit aproape exclusiv pentru jocuri şi a sfârşit prin a fi vândut pe 50 de dolari, bani cu care mi-am luat o geacă Diesel din Prisma.

Tastatură de HC 91

Nu acela a fost genul de expunere care m-a adus spre programare, deoarece ţin minte că nu gândeam foarte mult paşii unui program şi multe instrucţiuni erau empirice (ţin minte că îi explicam tatălui meu că nu va merge pentru că pur şi simplu nu merge — şi el nu era de acord cu argumentele mele “ştiinţifice”).

Primul pas spre IT l-am făcut în vara dinaintea clasei a IX-a. Intrasem la o clasă de matematică-informatică şi auzisem că se face Pascal aşa că mi-am luat o carte scrisă de un autor român (parcă “Învăţaţi limbajul Pascal în 12 lecţii” de Bogdan Pătruţ) şi m-am apucat să citesc despre Pascal şi să înţeleg cum se fac programele, fără să am un calculator la dispoziţie. În timpul liceului am avut un mic avantaj faţă de restul colegilor, deşi am făcut C, avantaj care s-a conservat pentru că parcă înţelegeam mai uşor cum să faci un program. “Furasem” de la profesoara de informatică nişte mici trick-uri, gen cum să folosesc debugger-ul din Borland C++ 3.1, IDE-ul pe care-l foloseam în liceu, despre breakpoint-uri şi watch-uri.

Încă din liceu simţeam, măcar intuitiv, că aveam o abordare diferită când venea vorba de scris codul. De fiecare dată când codul era scris în fugă aveam o senzaţie de disconfort. Iar un cod scris bine mă făcea tot timpul un pic mai fericit.

DHH şi slide-ul cu So be happy

Am lecturat recent eseul lui Yukihiro “Matz” Matsumoto din Beautiful Code intitulat Treating Code As an Essay. Următorul paragraf m-a făcut să-mi aduc aminte de vara lui 2006:

What makes a computer program readable? In other words, what is beautiful code? Although different people have different standards about what a beautiful program might be, judging the attributes of computer code is not simply a matter of aesthetics. Instead, computer programs are judged according to how well they execute their intended tasks. In other words, “beautiful code” is not an abstract virtue that exists independent of its programmers’ efforts. Rather, beautiful code is really meant to help the programmer be happy and productive. This is the metric I use to evaluate the beauty of a program.

Acum aproape doi ani făceam o schimbare majoră în viaţă şi renunţam la Automatică & Calculatoare şi porneam pe un drum nou, unde Ruby era limbajul de programare şi Ruby on Rails era platforma aleasă. Iar la momentul respectiv eram Microsoft Student Partner, aveam contacte foarte bune cu o serie de persoane din cadrul Microsoft România şi experienţă pe .NET Framework.

Citind eseul lui Matz mi-am adus aminte de Adrian Spinei la Wurbe #2 care spunea că “n-o să mă convingeți cu Ruby”. Şi mi-am adus aminte de ce am plecat de la C# şi .NET: pentru că îmi este mult mai uşor să scriu cod frumos în Ruby. Şi pentru că un cod frumos mă face mai fericit şi mai productiv.

Şi acelaşi lucru îl fac în general în viaţă: încerc să aduc cât mai aproape de mine oameni şi lucruri care mă fac fericit şi mai bun. Şi în ultima vreme simt că am reuşit.

Bubble cu reţelele sociale

22 februarie - No Responses

Conform unui studiu realizat de Nielsen Online, marile reţele sociale încep să piardă din useri (momentan doar din UK):

Five per cent fewer people in the UK visited the site in January compared to the previous month. A total of 400,000 seem to have become bored with the social network and didn’t bother to return.

referitor la Facebook. “Rivalii” nu o duc mai bine:

Similar drops in interest have hit Facebook’s competitors. Bebo has seen an eight per cent drop in UK users since October. MySpace, meanwhile, has seen 14 per cent of UK users desert it in the last three months.

Surpriză-surpriză. Parcă e destul de probabil ca bubble-ul epocii Web 2.0 să fie centrat pe reţelele sociale.

Via The Register.

ZOMG!

21 februarie - One Response

Hold on, thingz are tweakin

Don’t panic. We have it covered. Însă tema anterioară făcea textul mult prea greu de urmărit. Chiar şi pentru mine, care ştiam ce am scris.

Aşa că mergem pe ceva mai serif-like.

Hopefully tema Sandbox e suficient de inteligent făcută ca să o pot modifica şi eu, altfel va trebui să mă gândesc la ce folosesc Accelerator-ul primit de la Joyent pentru aplicaţii FaceBook.

Teste funcţionale şi parole

21 februarie - 4 Responses

Unul dintre motivele pentru care Ruby on Rails e atât de apreciată ca platformă pentru dezvoltare web e că face o serie de lucruri (sau “best practices”) automat. De exemplu, generează automat fişierele necesare testării, împreună cu un minim necesar de cod.

Chestia un picuţ ciudată e că terminologia folosită de Rails referitor la teste e un pic diferită de cea consacrată. Cel mai elocvent exemplu sunt testele funcţionale, care de fapt sunt folosite pentru a testa componentele Controller-Viewer, pe când testele de unitate sunt orientate strict pe Model. Termenul consacrat de “test funcţional” se referă la testarea funcţiilor specificate şi are caracter de black-box testing, adică testele sunt efectuate fără să se cunoască modul în care aplicaţia funcţionează.

În Extreme Programming conceptul a fost redenumit în “acceptance test”:

Acceptance tests are black box system tests. Each acceptance test represents some expected result from the system. Customers are responsible for verifying the correctness of the acceptance tests and reviewing test scores to decide which failed tests are of highest priority. Acceptance tests are also used as regression tests prior to a production release.

În Rails testarea funcţională se bazează pe o serie de fişiere Ruby generate automat în test/functional pentru fiecare controller în parte. În fişierul respectiv se scriu testele propriu-zise, care sunt de fapt metode Ruby care se bazează pe o serie de metode ajutătoare, gen post sau get, şi nişte assert-uri specifice testării funcţionale, gen assert_response sau assert_redirected_to.

Deşi am început să scriu teste “funcţionale” (în accepţiunea Rails a termenului) abia acum două săptămâni (ştiu, the shame…), am observat că un test “funcţional” bun are următoarele caracteristici:

  • se scrie un singur test per codepath
  • se ţine cont de diverse ipostaze ale unui user (guest, cont normal, administrator, etc.)
  • se verifică toate variabilele care ajung în View
  • se verifică variabilele de sesiune

Se înţelege de la sine că testele trebuie să acopere toate codepath-urile dintr-un control. Pentru asta, eu tind să folosesc un concept pe care l-am întâlnit în Code Complete şi care se numeşte “Structured Basis Testing”. Ideea e simplă:

  • pentru fiecare acţiune (metodă) se porneşte un contor de la 1
  • contorul se incrementează pentru fiecare for, while, if, repeat, and sau or (sau
  • contorul se incrementează pentru fiecare case (în ideea în care există tot timpul şi un caz default, altfel se contorizează şi acel caz)

… şi aşa obţii numărul minim de teste pentru a acoperi toate codepath-urile dintr-o metodă.

În ceea ce priveşte aplicaţiile web, lucrurile sunt un pic mai complicate, pentru că de multe ori se bazează pe nişte date existente în baza de date. Cel mai clar exemplu e al accesări unor resurse care necesită un cont.

În Rails sunt nişte “fixtures”, adică nişte fişiere YAML prezente în test/fixtures care sunt importate direct în baza de date. Numele fişierului YAML e identic cu cel al tabelei (gen users.yml va fi importat în tabela users).

Un fişier YAML cu useri arată cam aşa:

foo:
  id: 1
  username: foo
  password: example
bar:
  id: 2
  username: bar
  password: example

În codul de test se pot obţine datele despre un cont folosind users(:foo) şi obţinem un obiect de tip user şi putem efectua:


post :login, { :username = > users(:foo).username,
	:password => users(:foo).password }

pentru a simula un login.

Problema e că datele din fişier sunt introduse exact în baza de date, aşa că parola va fi introdusă în clar în tabelă. În cazul în care aplicaţia face automat un hash al parolei pentru a nu fi stocată în clar, atunci vor fi probleme de autentificare pentru că se va compara example cu c3499c2729730a7f807efb8676a92dcb6f8a3f8f.

Trick-ul folosit în general (şi aici încep să ajung la ideea articolului) e să foloseşti Erb pentru a face un Hash automat al parolei. Adică fişierul YAML ar trebui să arate aşa:

foo:
  id: 1
  username: foo
  password:
bar:
  id: 2
  username: bar
  password:

Problema e că în acest caz va trebui specificată parola cumva de mână, pentru că users(:foo).password va returna hash-ul pentru că mai întâi se face evaluarea Erb-ului, nu parola în clar şi atunci aplicaţia va face un hash la hash, care în mod cert va fi diferit de ce dorim.

Un mic trick e să se adauge o metodă în test/test_helper.rb în genul:


def login_as(user)
  user = user.to_s if user.is_a? Symbol

  fixture = YAML::load_file(File.join(RAILS_ROOT,
	"test/fixtures/users.yml"))
  fixture[user]['password'] =~ /\('(.*)'\)/

  # Set the email and password from the fixture
  username = fixture[user]['username']
  password = $1    

  # Use the LoginController to perform the login action
  old_controller = @controller

  @controller = LoginController.new

  post :login, {:username => username, :password => password}

  # Revert to the former control
  @controller = old_controller
end

… unde users.yml este fixture-ul care conţine userii (se poate numi altfel în funcţie de aplicaţie, gen clients.yml) şi LoginController este numele controller-ului care oferă facilitatea de login. Requestul POST poate fi diferit de la aplicaţie la aplicaţie.

Pentru că e în test_helper.rb, toate testele funcţionale vor putea beneficia de login_as :foo sau login_as "foo" (în funcţie de preferinţele fiecăruia). În mod automat se va căuta userul respectiv în fixture, se va folosi o expresie regulată pentru a se extrage parola în clar, se va muta pe controller-ul de Login, se va efectua login-ul şi apoi se va preda fluxul de control la controller-ul folosit iniţial.

Nu pot, e important

21 februarie - 3 Responses

Comentariul asta si gata!

Getting C++ Threads Right

20 februarie - 3 Responses

Via MenTaLguY, am găsit un Google Tech Talk referitor la programarea de threaduri în C++.

L.E.: Se pare că cei de la Google au ales să nu permită embedding-ul filmuleţului. Linkul direct e: http://www.youtube.com/watch?v=mrvAqvtWYb4.