Archive for the ‘tech’ Category.

Perl tips – ep 6

Lizibilitatea

Puteti spune ca lizibilitatea este specifica tuturor limbajelor si ca nu-si are rostul intr-o serie de tips & tricks despre Perl. Eu zic ca isi are rostul, mai ales datorita faptului ca Perl este bland cu persoanele care il folosesc si le permite acestora sa-si manifeste creativitatea in moduri cu totul si cu totul noi.

Lizibilitatea, mai ales in limbaje in care se poate aluneca usor pe o panta “criptica” este deosebit de importanta. Adoptarea unui stil lizibil aduce beneficii mari mai ales in cazul aplicatiilor medii si mari. Principiile dupa care ar trebui sa se ghideze cineva care scrie o aplicatie trebuie sa includa cel putin:

  1. Folosirea de nume adecvate si relevante, pentru variabile, functii, metode, clase, etc.
  2. Indentarea codului conform standardelor;
  3. Gruparea in functii cu scop precis si specific;
  4. Reutilizarea codului;
  5. Folosirea tuturor avantajelor limbajului.
Toate aspectele de mai sus au relevanta doar aplicate corect si la locul potrivit ! Nu trebuie ca scopul unei aplicatii sa fie modul in care aceasta este scrisa !

Seria ‘asa nu’:

my ($v1,$v2);

print "Enter v1: ";
$v1=<>;
$v2 = $v1*1.12*1.24;
print "V2 este: $v2\n";

Seria ‘asa da’:

#!/usr/bin/perl

use common::sense;

my ($adaos, $tva);

sub init {
  #adaosul este de 10% iar TVA de 24%
  $adaos = 1.10;
  $tva = 1.24;
}

sub calculeaza_pret_vanzare {
  my $pret_achizitie = shift;

  return $pret_achizite * $adaos * $tva;
}

sub main {
  my $pret_achizitie;

  init();

  print 'Introduceti pretul de achizitie:',$/;
  $pret_achizitie = <STDIN>;

  print 'Pretul de vanzare este: ', calculeaza_pret_vanzare($pret_achizitie), $/;
}

main();

IMHO, al doilea cod sursa este foarte usor de inteles. Este cat se poate de clar din sursa ca vorbim de o aplicatie care calculeaza un cost, este clar care sunt variabilele, la ce folosesc unde se initializeaza si care e durata lor de viata. Din punct de vedere al utilizatorului, stie ce introduce, stie ce obtine. De asemenea, pornind de la un astfel de cod, este foarte usor de crescut o aplicatie. Trebuie doar sa urmati aceleasi principii.

PS: Sursele prezentate nu sunt exemplu absolut ci doar cu titlu de exemplu didactic.

Lucrul cu adrese IP

Sa stiti ca n-am renuntat la seria de tips pentru Perl, sunt inca articole in lucru. Pana atunci, sa va povestesc ce-am mai descoperit azi. Am nevoie sa scriu o aplicatie mica (care se va face maaare), care sa lucreze cu adrese IP. In principiu aplicatia trebuie sa ia de pe un router clasele de adrese IP exportate de routerul ala catre diversi neighbours, sa le bage intr-o baza de date si sa le zica cand se schimba ceva pe acolo. Ofc, din baza aia de date clasele de adrese IP se vor exporta prin diverse metode (webservices mostly) catre diverse aplicatii. Pare simplu nu ? O aplicatie triviala, care nu necesita cine stie ce chestii complicate. Asta in teorie, pentru ca in practica la jumatatea aplicatiei iti dai seama ca adresele alea IP nu sunt doar IPv4 ci si IPv6 :) Si asta schimba cu totul aplicatia. Pentru ca:

  • daca baza de date utilizata este MySQL, surpriza: MySQL are suport pentru IPv6 doar in MySQL 6.0, care nu e pe nici o distributie.
  • o adresa IPv4 impreuna cu netmask-ul asociat, pot fi stocate lejer in 2 campuri de 32 de bits fiecare. Super optimizare de stocare, indecsi rapizi, etc.
  • o adresa IPv6 poti sa o stochezi momentan doar ca sir de caractere. Si netmask-ul la fel. Nu mai avem nici optimizare la stocare, nici indecsi rapizi, nici macar etc (asta tot pe MySQL)
  • multe din modulele din CPAN (in special cele ce au bucati [sau sunt complet] in C) nu au suport pentru IPv6.
  • regexp-urile folosite pentru IPv4 nu mai merg. Trebuie altele.

Si tot asa. Pana la urma, tot am gasit ceva bun: Net::Subnet stie sa lucreze si cu IPv4 si cu IPv6 ;)

Perl tips – ep 5

use common::sense;

Nope. Nu e o gluma. Initial m-am uitat patrat cand am vazut in lista de dependente a unui modul Perl (despre care sper sa am ocazia sa povestesc odata). Dar dupa ce m-am uitat in pagina de manual, mi-a placut foarte mult ideea. Iar numele impreuna cu use sunt excelente :)

Pe scurt, common::sense “trage” dupa sine mai multe setari implicite, de bun simt. Citez din pagina de manual:

   # supposed to be the same, with much lower memory usage, as:
    #
    # use utf8;
    # use strict qw(vars subs);
    # use feature qw(say state switch);
    # no warnings;
    # use warnings qw(FATAL closed threads internal debugging pack
    #                 portable prototype inplace io pipe unpack malloc
    #                 deprecated glob digit printf layer
    #                 reserved taint closure semicolon);
    # no warnings qw(exec newline unopened);

Eu zic ca este super fain.

Perl tips – ep 4

Documentarea

Fiecare are motivele lui pentru fuga de documentarea codului sau mai rau, a aplicatiei in sine. Nu cred ca am intalnit inca pe cineva care sa spuna ca ii place sa scrie documentatie in cod. Cu toate acestea, documentarea codului este importanta mai ales pentru cei cu memoria scurta (adica eu). Codul trebuie mentinut, indiferent cat ne place sa sustinem contrariul. Un cod trebuie adus la zi, curatat sau modificat in functie de necesitati.

Eu am crescut cu interfata CLI in fata iar paginile de manual din Linux (man pages) mi-au fost cel mai bun prieten, mai ales ca atunci accesul la Internet era destul de lent (Iasi – Bucuresti, 256Kbps). Prin urmare primul lucru de care m-am bucurat atunci cand a trebuit sa documentez o aplicatie Perl a fost ca documentarea unei surse in Perl inseamna ca acea documentatie poate fi folosita in stilul man pages.

Aici sunt descrise foarte bine si pe larg directivele pe care le puteti utiliza pentru a documenta cat mai facil, util si clar un cod sursa. Pentru ca nu tot timpul este nevoie de documentare completa a codului si pentru ca sunt momente cand este nevoie doar de cateva fraze, o macheta de documentare de bun simt a unei aplicatii ar putea arata asa:

__END__

=head1 NAME

YARFA - Yet Another Rabbit Feeding Application

=head1 VERSION

0.1

=head1 DESCRIPTION

My app is B<the> feeding rabbits B<application>

=head1 SYNOPSIS

Just start the application in the background and it will
detect and feed all your rabbits automatically.

=head1 SUBROUTINES/METHODS

=head2 new()

Class constructor.

=head2 start()

Starts the feeding process

=head1 DEPENDENCIES

L<Rabbits>, L<Food>

=head1 CONFIGURATION AND ENVIRONMENT

You must point your rabbit location on Google Maps

=head1 INCOMPATIBILITIES

Only the blue eye rabbits can be fed by this application due to their
sensibility in daylight.

=head1 BUGS AND LIMITATIONS

If the application is started during the night, the rabbits will be fed
only on the second day.

=head1 SEE ALSO

L<Dogs>.

=head1 AUTHOR

John DOE C<< <john@doe.name> >>.

=head1 LICENSE AND COPYRIGHT

Copyright (c) 2011, John Doe C<< <john@doe.name> >>.
All rights reserved.

This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See L<perlartistic>.

Macheta de mai sus se poate adauga pur si simplu la sfarsitul unui program in Perl si se poate vizualiza folosind: “perldoc sursa.pl”. Si mai fain este ca documentatia respectiva se poate exporta si in alte formate utilizand pod2{man,text,latex,html}. Sa stiti ca tag-urile puse de mine in exemplu nu sunt batute in cuie. Puteti trece orice atata vreme cat sunt relevante. Eu le-am pus pe cele de mai sus pentru ca eu consider ca sunt minimumul care ar trebui sa existe intr-un program OpenSource.

Hint ! Pod, chiar daca a fost gandit ca un markup language pentru Perl, poate fi folosit pentru a scrie orice informatie ;)

Perl tips – ep 3

Gruparea codului

Desi nu este dependenta de limbaj, gruparea codului in functii, este un aspect important care nu trebuie niciodata ignorat. In Perl cu atat mai mult cu cat limbajul permite folosirea sa intr-un mod creativ :)

Bad code:

   #!/usr/bin/perl

   use strict;
   use warnings;

   print "Hello world";

Good code:

   #!/usr/bin/perl

   use strict;
   use warnings;

   sub main {
      print "Hello world";
   }

   main();

Gruparea codului in functii ajuta la:

  • claritate: este mult mai usor pentru oricine, inclusiv pentru autor, sa parcurga un fisier sursa in care codul este grupat logic si rational in blocuri. Claritatea este unul din aspectele cheie intr-un cod sursa !
  • refactorizare: in cazul in care la un moment dat este nevoie de schimbat modul in care functioneaza o anumita functie insa nu si modul in care este apelata (parametri, rezultat intors), un cod grupat in functii este mai usor de refactorizat, oferind o privire de ansamblu mai larga;
  • documentare: un cod grupat in functii mici, este usor de documentat nefiind necesara explicarea tuturor pasilor/instructiunilor ci doar a blocului respectiv;
  • intretinere si depanare: in cazul gasirii de bug-uri, un cod modular va fi mai usor de intretinut si de depanat, functiile mici permitand o depanare rapida.
  • scalabilitate: atunci cand o aplicatie creste destul de repede si se impune “spargerea” sursei initiale in mai multe bucati, un cod sursa modular va facilita reorganizarea rapida a functionalitatilor comune intr-o noua forma (librarii, clase, etc).

Stiu ca subiectul este foarte larg si este mult de povestit, dar dupa cum spuneam si la inceput, ideea este sa povestesc tips & tricks care sa ajute, nu sa fac curs de Ingineria Programarii sau mai stiu eu ce altceva.

PS: Din experienta pot sa va spun ca oricand o aplicatie “de test” se poate transforma intr-un proiect la care sa lucrezi 2-3 ani (eu am patit-o de 2 ori ;)

Perl tips – ep 2

use strict‘.

Are 2 aspecte:

1. Perl permite unui program crearea automata a variabilelor, in orice loc din program, fara a fi nevoie ca acestea sa fie declarate inainte. Aceasta facilitate foarte comoda pentru programator, este in acelasi timp o incredibila sursa de bug-uri intr-o aplicatie. Atunci cand folositi ‘use strict’ Perl va genera erori de fiecare data cand o variabila este folosita fara a fi declarata inainte.

Bad code:

       $i = int rand(100);

        print $i;

Good code:

       my $i;

        $i = int rand(100);
        print $i;

2. Pentru ca Perl ofera mai multe moduri in care se poate realiza ceva, deseori incearca sa determine din context ce anume a vrut programatorul sa faca. Cateodata reuseste, alteori nu.

Exemplu:

      $a = test_value;
       print "Value: ", $a, "\n";
       sub test_value { return "test passed"; }

In exemplul de mai sus, Perl va initializa variabila $a cu sirul de caractere test_value, nu cu rezultatul intors de functia test_value(), pentru ca:

  • test_value nu este marcat corespunzator ca fiind apel de metoda, folosind ()
  • la momentul interpretarii primei linii, Perl inca nu “stie” ca exista o metoda numita test_value();

Varianta corecta:

       use strict;
       sub test_value; #Se declara functia ce va fi definita mai tarziu
        my $a = test_value();
        print "Value: ", $a, "\n";
        sub test_value { return "test_passed"; }

Inspiratie: de aici.

Perl tips – ep 1

Incepand de astazi, o sa pun, in functie de timp, un serial de tips & tricks pentru PERL in care am de gand sa povestesc lucruri utile, scurte si la obiect. Tutorialul este pentru persoane care au avut deja contact cu PERL si l-au folosit macar pentru a scrie cateva scripturi. Azi, partea 1:

Bad:

 #!/usr/bin/perl

  print "Hello world";

Good:

 #!/usr/bin/perl

  use warnings;
  print "Hello world";

Implicit, interpretorul de PERL pleaca de la premisa ca programatorul stie ce scrie/face si prin urmare ii ofera destul de multe libertati. ‘use warnings’ activeaza o serie de verificari ce au ca scop reducerea bug-urilor generate de folosirea incorecta a limbajului.

Exemplu:

 use warnings;

  $filename = "./logfile.txt";
  open (LOG, $fn);
  print LOG "Test\n";
  close LOGFILE;

Fara ‘use warnings’, codul de mai sus ar fi rulat de interpretorul de PERL care nu ar semnala nici un fel de eroare, insa nu ar functiona deloc. Adaugand ‘use warnings’, PERL ne semnaleaza:

  1. variabila $filename este initializata si nu mai este folosita;
  2. handler-ul LOGFILE este folosit doar o data, la apelul lui close;
  3. variabila $fn este folosita fara a fi initializata;
  4. functia print() incearca sa scrie intr-un fisier ce nu a fost deschis;

Intotdeauna folositi ‘use warnings’ !

Inspiratie de aici.

Despre programare

Nu stiu altii cum sunt insa mie imi place foarte mult ca lucrurile sa fie structurate bine. Sa fie cat se poate de atomice si sa coabiteze pasnic cu alti atomi intr-un echilibru cat mai aproape de perfectiune. In acelasi timp trebuie sa ofere un anumit grad de flexibilitate absolut necesar intr- o comunitate. Dupa parerea mea structura codului trebuie sa respecte unul din principiile de baza ale GNU/Linux: un program trebuie sa permit folosirea sa ca generator de input initial, tranzit sau output final. Cumva, asa am facut intotdeauna. Am spart o problema in bucati mai mici pe care le-am facut astfel incat sa poata fi folosite nu numai in cadrul aplicatiei pentru care au fost concepute cat si in alte aplicatii (ofc, acolo unde este posibil ;) .

Teoria suna ca mai sus. Majoritatea celor ce programeaza (la orice nivel si in orice limbaj) cunosc principiile. Le cunosc adica au cunostinta ca ele exista, insa nu le aplica decat mult prea putin. Insa, atunci cand codul sursa este evaluat si sunt descoperite probleme, cel mai des sunt invocate lipsa timpului sau presiunile din partea superiorilor. Amuzant (si trist in acelasi timp) este ca evitarea principiilor sanatoase in scrierea aplicatiilor, impreuna cu resursele mai mari necesare, duce in cele din urma la costuri mai mari asociate cu mententanta si dezvoltarea ulterioara.

In urma cu cativa ani (vreo 3, daca nu ma inseala memoria), am vazut intr-o prezentare din cadrul proiectului GEANT (un proiect european foarte mare in care sunt implicate cam toate NREN-urile din Europa) un principiu foarte interesant: “principiul pisicii moarte”; care este legat de pasarea responsabilitatii la “ceilalti”. Principiul pisicii moarte spune “nu sunt eu de vina, ceilalti sunt pentru ca …”. Ei bine, acest principiu este una din problemele majore la proiectele mari, mai ales la cele comerciale. Iar in scrierea aplicatiilor este foarte usor de folosit acest principiu pentru ca problemele sunt descoperite foarte tarziu, in cazul in care sunt descoperite, iar investigatiile sunt destul de greu de realizat. Problemele generate sunt foarte multe si variaza de la bug-uri ciudate la probleme de securitate majore iar in unele cazuri duc chiar la bug-uri majore ce nu pot fi corectate si care pot afecta core-ul unei aplicatii.

Din pacate factorii autohtoni ce ar trebui sa fie promotorii principiilor sanatoase de coding evita sa se implice in mod real in promovarea si explicarea importantei acestora si se multumesc doar sa le mentioneze pe alocuri, bifand in agenda yet another … thing.

Statistici BIND (pe zone)

Am mai aflat ceva azi (ma rog, ieri). Daca ai un bind9 pe undeva, in care tii niste zone, si e musai ca pentru fiecare din zonele de acolo sa afli niste statistici de genul: cate query-uri au fost pe domeniul x.ro sau cate transferuri de zona s-au facut, tot ce ai de facut este sa-i spui lui bind: zone-statistics yes; Si gata :) rndc stats si bind va face un dump pe disc  (pe Debian/Ubuntu statisticile vor fi varsate in /var/cache/bind/named.stats; numele se poate schimba din config) cu toate statisticile pe zone. Urmatorul apel al rndc stats va adauga informatiile noi la fisierul deja existent. Normal, activarea acestei optiuni utilizeaza cativa MB suplimentari de memorie, dar ce nu facem noi pentru un scop nobil ?

 

Tema GMail

Eu folosesc statii de lucru cu Linux, MacOSX si Windows, unde Linux este in diverse combinatii si arome :) Pe toate statiile (mai putin pe cele cu MacOSX unde functioneaza impecabil), noua tema implicita de la Google (gmail si reader) se misca infiorator de lent. Interesant e ca pe toate platformele folosesc aceeasi versiune a aceuiasi browser. Oare de ce se intampla asta ?