Kodėl PHP nėra programavimo kalba?

Nesupraskite šio įrašo antraštės tiesiogiai, taip mes juokaujam darbe programuotojų tarpe, kai susiduriam su eiliniu PHP trūkumu...

Nors iš tikrųjų, PHP nėra pilnavertė programavimo kalba, ji yra scenarijų kūrimo kalba, o jei tiksliau – web scenarijų kūrimo kalba. Nepaisant didelių PHP trūkumų, ji yra labai populiari ir dėl didelio populiarumo naudojama daugelyje vietų, dažnai kur reikia ir kur nereikia.

Kur tinka naudoti PHP scenarijų kalbą?

Jei planuojate paleisti nedidelės apimties interneto svetainę, pavyzdžiui savo asmeninę svetainę ar įmonės pristatomąją svetainę, tuomet PHP puikiai tam reikalui tiks.

Kada geriau nenaudoti PHP?

PHP iš esmės sukurta interneto svetainių kūrimui, todėl niekam kitam, išskyrus interneto svetainių kūrimui, ji nėra tinkama. Žinoma, PHP galimybės leidžia kurti tiek programas veikiančias tekstiniame režime, tiek grafinėje aplinkoje. Bet mano nuomone, karvė nėra tinkama jodinėjimui, nors jos galimybės tai leidžia... Tas pats ir su PHP.

Tai gi, PHP tinka naudoti interneto svetainėms kurti, bet tik nedidelės apimties interneto svetainėms! Tikrai nerekomenduočiau naudoti PHP didelių įmonės intraneto sistemų kūrimui, dideliems interneto portalams ar kitoms sudėtingesnėms sistemoms.

Sakote geram šokėjui ir ••• trukdo?

Tas tiesa, geras programuotojas ir asemblerio instrukcijomis gali programuoti, bet kam taip kankintis, jei yra kur kas pažangesnių programavimo technologijų.

PHP programuoju jau beveik visą dešimtmetį, tačiau esu susipažinęs ir su kitomis programavimo kalbomis, pradedant tuo pačiu asembleriu, C/C++, baigiant Bash, Awk ir t.t. Kadangi esu susipažinęs su daugeliu programavimo kalbų, tai galiu jas lyginti.

Kai sakau, kad PHP nėra programavimo kalba, daugelis prašo įvardinti konkrečius trūkumus. Būtent tokių klausimų pastūmėtas ir nusprendžiau surašyti visus pastebėtu PHP trūkumus vienoje vietoje. Jei taip pat, kaip ir aš, nuolat susiduriate su PHP trūkumais, tai laukiu papildymo komentaruose.

Tai kodėl gi PHP nėra programavimo kalba?

Arba kitaip sakant, kokie trūkumai apsunkina programavimo darbus su PHP?

weak typing

PHP leidžia priskirti bet ką, bet kam ir bet kaip. Iš pirmo žvilgsnio atrodo, kad tai yra labai lankstu, bet kai reikia ieškoti skriptuose paliktų klaidų, tai pradedi galvoti kas per žmonės sugalvojo tokią nesamonę...

Štai keli pavyzdžiai:

  1. $a = (
  2. false == '' &&
  3. false == '0' &&
  4. '' != '0' &&
  5.  
  6. 0 > -1 &&
  7. 0 == false &&
  8. false < -1
  9. );

Spėkit, kam bus lygus kintamasis $a? Jis bus lygus True, jei netikit, išbandykite patys. Kiekvienas atidesnis programuotojas turėtų pastebėti, kad PHP palyginimo operacijos dažnai prasilenkia su logika. Praktikoje tokie dalykai labai apsunkina klaidų paiešką...

Klaidų apdorojimas

PHP kalboje egzistuoja tokie klaidų tipai:

  • crash o taip, pasitaiko, kad PHP tiesiog segfaultina esu su tuo susidūręs ne karta, ypač dirbant su PDO.
  • fatal error sintaksės ar panašios klaidos kurių negalima apdoroti, programos vykdymas tiesiog nutraukiamas, be jokios galimybės tai kontroliuoti
  • notice, warning dalinai kontroliuojamos klaidos aprašius klaidų apdorojimo funkciją.
  • exception pilnai kontroliuojamos klaidos

Tokios painiavos tikriausiai nesate matę? PHP neturi normalaus klaidų apdorojimo mechanizmo. Visokie parse error, notice warning ir panašiai susiklostė istoriškai, vėliau atsirado exception palaikymas, bet visi seni dalykai, taip pat liko.

Štai elementariausias pavyzdys, kuriame išlenda klaidų apdorojimo trūkumai:

  1. $fp = @fopen('/etc/passwd', 'a');
  2. if ($fp) {
  3. fwrite($fp, "boo\n");
  4. fclose($fp);
  5. }
  6. else {
  7. trigger_error('Error', E_USER_WARNING);
  8. // or... throw new Exception('Error');
  9. }

Šiame pavyzdyje bandoma tvarkingai atidaryti failą ir apdoroti atvejį, kai to failo atidaryti negalima. Deja PHP atveju, jei failo negalima atidaryti, paprasčiausiai išspjauna warning tipo klaidą ir vienintelis būdas tokią klaidą pagauti – pasirašyti klaidų apdorojimo funkciją su set_error_handler. Vienintelis būdas išvengti šioje vietoje nepageidaujamų klaidų pranešimų – @ (eta) simbolis, kuris iš vis panaikina bet kokius klaidų pranešimus (išskyrus fatal tipo), bet nepaisant to, klaidos vis tiek keliauja į klaidų apdorojimo funkciją, jei tokia aprašyta.

Trumpai tariant, visiška painiava. Vienintelis mano akimis žiūrint, teisingas sprendimas – į klaidas apdorojančią funkciją įrašytas exception iškvietimas.

Klaidų pranešimai

Kadangi interneto svetainėje išvedami klaidų pranešimai yra potenciali saugumo spraga, tai dažniausiai tie pranešimai būna išjungti ir... ir toliau kiekvienas daro kaip išmano, kad tas klaidas sugaudytų. Standartiškai PHP turi galimybę visus klaidų pranešimus nukreipti į failą, tačiau tame faile nurodyta tik vieta kur įvyko klaida ir nieko daugiau, kai išsamus traceback'as padėtų kur kas labiau. Žinoma yra išsigelbėjimas pavadinimu xdebug, tačiau production serveriuose jo tikrai niekas nenaudoja, o ir nederėtų.

Didesnė blogybė yra ta, kad dažniausiai, pagal nutylėjimą apie klaidas pranešama tyliai, tai reiškia, kad daugelis mažiau patyrusių programuotojų iš vis nesirūpina klaidų pranešimais, ko pasekoje susilaukia daug problemų.

Namespace

Kuriant didelės apimties sistemas, anksčiau ar vėliau susidursite su vardų erdvės problema, priešingu atveju teks naudoti tokius funkcijų pavadinimus: ManoPaketas_ManoModulis_ManoStrukturosElementas_ManoFunkcija, be galimybės kažką keisti.

PHP daugelį metų neturėjo vardų erdvių, tik visiškai nesenai, nuo 5.3 versijos atsirado vardų erdvių galimybė, bet pati realizacija taip pat neguodžia...

References

Prieš PHP 5.0, referencas buvo kuriamas tik tada, kai nurodomas & simbolis, po PHP 5.0 prasidėjo linksmybės, nes visi objektai automatiškai perduodami kaip referencai, o visi ne objektai, kaip kopijos. Tačiau techniškai, pati perdavimo procedūra, naudojant referencus iš tikrųjų kuria kopijas, užima daugiau atminties ir apsunkina skriptą. Sunku suprasti, bet liūdna tiesa yra ta, kad geriau nenaudoti PHP referencų, nors teoriškai referencų perduodant kintamuosius yra efektyvesnis. Plačiau apie tai galite pasiskaityti čia:

http://schlueters.de/blog/archives/125-Do-not-use-PHP-references.html

Objektai ir referencai

Nuo PHP 5.0, visi objektai, automatiškai perduodami kaip referencai, o tai reiškia, kad atmintyje objekto kintamieji susiejami ryšiais. PHP turi tokią ydą, kad jei objektas atmintyje yra susietas su kitu objektu, tuomet tas objektas pasidaro nesunaikinamas ir nuolat sėdi atmintyje. Tai puikiausiai iliustruoja žemiau pateiktas pavyzdys:

  1. class MyParent {
  2.  
  3. public $child;
  4.  
  5. public function __construct() {
  6. $this->child = new MyChild($this);
  7. }
  8.  
  9. }
  10.  
  11. class MyChild {
  12.  
  13. public $parent;
  14.  
  15. public function __construct($parent) {
  16. $this->parent = $parent;
  17. }
  18.  
  19. }
  20.  
  21. foreach (range(0, 10) as $i) {
  22. $a = new MyParent;
  23. }

Gausime tokį rezultatą:

  1. 335508
  2. 336160
  3. 336696
  4. 337232
  5. 337768
  6. 338320
  7. 338856
  8. 339392
  9. 339928
  10. 340464
  11. 341000

Kaip matote, atminties naudojimas vis auga, nors cikle objektas turėtų būti sunaikintas, o jo naudota atmintis atlaisvinta. Bet deja taip nėra. Išvada – programuojant PHP, geriau nenaudoti objektų.

Round funkcijos klaida ar funkcionalumas?

Spėkit, kam bus lygus kintamasis $a?

  1. $a = (string) round(-0.1);

Neatspėjote, $a bus lygus "-0" :)

Jei manote, kad šioje vietoje PHP yra teisus ir kaltos kreivos rankos, štai dar vienas pavyzdys:

  1. $a = round(-0.1) === 0;

Kintamasis $a bus lygus false...

Išvados

Programuojant PHP geriau nenaudoti objektų, geriau nenaudoti referencų, geriau išvis nenaudoti PHP :)

Kol kas pateikiau tik kelis pavyzdžius, bet jų yra kur kas daugiau. Kai tik turėsi laiko, papildysiu įrašą pateikdamas daugiau pavyzdžių.

Nuorodos

Komentarai

Anonymous portretas

Na atsiprašau, php

Na atsiprašau, php privalumus, tokius kaip lengvas/automatinis pavertimas iš vieno tipo į kitą bandant pateikti kaip trūkumus...
weak typing pavyzdys visiškai teisingas ir niekur neprasilenkia su logika (bent jau kurioje vietoje galėtų prasilenkti - tikrai namatau, gal parodytumėte man kodėl jis turėtų būti false? tik nepradėkite taikyti kitų programavimo kalbų kintamųjų interpretavimo logikos) apie kintamųjų perdavimus kaip reference nesigilinau (vienintelė silpna vieta), o su round funkcija tikrai nustebinai. Bet dėl tokių dalykų sakyti, kad php nėra programavimo klaida yra aiškiai per daug.

PHP puikiai atitinka unix filosofiją - daryti vieną dalyką ir daryti jį gerai. t.y. apdoroti ir pateikti web puslapius. Kai php pradedama taikyti GUI programoms kurti tai (IMHO) toks pats iškrypimas kaip su asembleriu kurti web puslapius arba su kokiu nors perl daryti windows RPG žaidimus. Ji ne tam buvo kurta ir natūralu, kad ne pats geriausias įrankis.

Atsiprašau, bet tikrai šis įrašas tikrai traukia į tą pasakymą kur blogam šokėjui nesigauna šokti :)

P.S. Kad būtų visiškai aišku ką palaikai, galėjai parašyti kokią kalbą siūlai naudoti kaip pats sakai "dideliems projektams"?

Anonymous portretas

>PHP puikiai atitinka unix

>PHP puikiai atitinka unix filosofiją - daryti vieną dalyką ir daryti jį gerai. t.y. apdoroti ir pateikti web puslapius.

PHP atitinka Unix filosofiją? Nu atsiprašau.. Jei PHP developeriai (ne useriai) bent kiek stengtųsi tą filosofiją pritaikyti, PHP turėtų normalius modulius, o ne šimtus funkcijų vienoj vardų erdvėj. Ir aš nesivelsiu į diskusiją, ar PHP tikrai gerai atlieka web puslapių pateikimą.

sirex portretas

Dėl weak typing tai

Dėl weak typing tai nesileisiu į diskusija, nes tai jau išdiskutuota daugybę kartų, o jei
false == '0' != '' == false
arba
false == 0 > -1 > false
tau neprasilenkia su logika, tai matyt esi mažai patyręs programavime.

Dideliems projektams rašyti tinka Java, Python.

Anonymous portretas

"Tikrai nerekomenduočiau

"Tikrai nerekomenduočiau naudoti PHP didelių įmonės intraneto sistemų kūrimui, dideliems interneto portalams ar kitoms sudėtingesnėms sistemoms."

Papasakok Facebook'o developer'iams ;-)

sirex portretas

Ar girdėjai, kad Facebook

Ar girdėjai, kad Facebook perrašė PHP interpretatorių ir padarė PHP to C transliatorių. Kitaip tariant, už blogą pradžią, dabar skaudžiai moka.

http://www.sdtimes.com/blog/post/2010/01/30/Facebook-rewrites-PHP-runtim...

Anonymous portretas

Sirex, parašyk apie PHP

Sirex, parašyk apie PHP funkcijų vardų sudarymo taisykles. Su žemais brūkšniais, žodžiai neatskirti, o gal abu variantai iškart ;)

Anonymous portretas

Prieš diskutuojant, reikėtų

Prieš diskutuojant, reikėtų susitarti dėl terminų „programavimas“, „programavimo kalba“ ir pan. Asmeniškai man beveik visos veiklos su kompiuterių yra programavimas: excel ataskaitos, DOS batch ar AutoHotkey (www.autohotkey.com) skriptukų pasirašymas - viskas, per ką galiu išreikšti kokį nors algoritmą, kad kompiuteris jį vykdytų, vadinu programavimu. Todėl ir PHP yra programavimo kalba. Dėl kalbų tinkamumo tam tikroms situacijoms/sritims jau galima būtų diskutuoti.

Anonymous portretas

Hmm..

Hmm.. http://www.alexa.com/topsites kiek čia daug blog'ų ir visi jie su PHP ir dar lankomi... Facebook tikrai neblogas "blog'as" ir auditorija lyg ir surenka. O gal autoriui, tai yra labai mažas saitukas? Gal peržiūrime sarašą ir pažiūrime kokių dar "mažų" saitukų yra prikepta, kurie "netyčia" papuola į Top100?

Ką rūkei, kai rašei šitą straipsnį?

Dalį tiesios pateikei rašydamas apie NameSpace'us ir reference'us (memory leak'us).

Ponas, jei PHP jums buvo atlaikdus ir leido belekaip programuoti, tai nereiškia, kad ir visi programuotojai lygiai taip pat kreivai programuoja.

Aš suprantu, jei būtų kalbama apie, tai, kad tokios apimties saituose kaip Facebook yra naudojamos kelios programavimo kalbos arba PHP kodo kompiliavimas į C kodą (HipHop PHP), tai bent jau galėtų skambėti kaip minusai...

Neišsiplėsiu per daug. Jūsų įrašas vertas mano išsamios kritikos (parašysiu savo blog'e, kur galėsiu skleisti savo tiesas).

Anonymous portretas

manau kad mantas siulydamas

manau kad mantas siulydamas nekurti dideliu svetainiu turejo ne php greiti o jo funkcionaluma

sirex portretas

Dėl Facebook, galite

Dėl Facebook, galite pažiūrėti viešai paleistus Facebook projektus:

http://github.com/facebook

Ir pastebėsite, kad daugelis jų parašyti su Python arba C kalbomis ir kai kurie skirti sušvelninti nuo pradžių padarytą klaidingą pasirinkimą – PHP.

Anonymous portretas

O kur iš jų pusės nuskambėjo

O kur iš jų pusės nuskambėjo teiginys, kad jie padarė blogą pasirinkimą?

Jei būtų pasirinkę Java, tai facebook'as dar ir dabar būtų dev stadijoje.

Anonymous portretas

Iš dalies pritariu Sirex'ui.

Iš dalies pritariu Sirex'ui. Kuriant PHP'ą reikėjo griežtesnės tvarkos, nes dabar kiekvienam libe vis kitos taisyklės, kiti pavadinimų įpročiai ir t.t. Kad kartais pavykdavo gauti T_PAAMAYIM_NEKUDOTAYIM ir panašius errorus, tik parodo bardaką php vystyme.

Kad PHP yra neišbaigta kalba, parodo kokie milžiniški skirtumai tarp skirtingų jų versijų ir kaip sunku pereit nuo vienos prie kitos. Kitos kalbos tokius namespace'us turi nuo pat 'gimimo'.

Gerai yra tai, kad šiuo metu niekas nebeprogramuoja PHP. Visi programuoja kokiais nors Frameworkais (ačiū ZF), tad šioje srityje reikalai gerokai pasitaisė.

P.S. Jau įpratau visur rašyt $a === $b, lyginant reikšmes :-)

Anonymous portretas

PHP bendruomėnė jau

PHP bendruomėnė jau diskutuoja dėl bendros tvarkos nebuvo lib'uose.
Tai tik evoliucijos reikalas :)

Dėl versijų skirtumų, tai gal gali pateikti daugiau pavyzdžių, nes aš žinau tik 5.2.x => 5.3. Bet ir tai, ten labiau buvo pašalintas backwards compatibility PHP5 (reference'ai!).

P.S. dėl framework'ų - tai būtų negražu nepaminėti "Symfony" :)

Anonymous portretas

4 => 5 :-) O dėl bendros

4 => 5 :-)

O dėl bendros tvarkos diskutuoja jau senokai. Kas bus kai priims sprendimą (tikiuosi, kad priims)? Vėl migruosim :-) Aišku aliasus paliks, bet..

Anonymous portretas

Migravimas tai nuolatinis ir

Migravimas tai nuolatinis ir nesustabdomas proceas :)

Anonymous portretas

Ai bet nieko, mes pratę :-)

Ai bet nieko, mes pratę :-)

Anonymous portretas

Tiek šitas "tools'ai parašyti

Tiek šitas "tools'ai parašyti su C ir Python", tiek "facebook perrašė PHP runtime'ą" nereiškia, kad facebookas neprogramuoja PHP. Programuoja, ir dar kaip! Kas iš to, kad HipHop'as paverčia PHP kodą į C? Čia tas pats, kas sakyt kad "C/C++ saks, nes va, visi kompiliatoriai paverčia C/C++ kodą į assemblerį - assembler4evah'!!!". HipHop'as buvo parašytas dėl to, kad PHP performancas buvo tikrai žemas. O jeigu sekt tavo mintį "dėl to kad padarė klaidingą pasirinkimą - PHP", tai pats pagalvok - jeigu jie dabar perrašė PHP runtime'ą - tai jeigu jiem PHP būtų pain in the ass ar jie nebūtų perrašę ant kitos platformos visko? Ten dirba žmonės iš top5 univerų ir su galybe patirties, nemanau kad jiem būtų sunkiau perrašyt. Ypač kai patį HipHop padarė vienas žmogus.

Facebook'as irgi nėra durnas, ten žmonės žino su kuo greičiausiai ir efektyviausią rezultatą pasiekt, todėl tu ir matai ten daug projektų parašytų su kitom kalbom. Turbūt jeigu pasigilintum nors kiek, kas ten per tools'ai ir kam jie yra, o ne pamatęs sąrašą klyktum savo nuomonę. Tai biškį apšviesiu:

  • Cassandra - large scale fast distributed p2p data storage. Tu rašytum didelės apimties ir greito pasiekiamumo duomenų kaupimo softą su PHP? Tu, leisk spėti, ne. Aš irgi ne. Facebook'as irgi nerašė.
  • Hadoop - large scale data storage. Tu rašytum softą apdorot milžiniškiem duomenų kiekiam su PHP? Aš ne. Tu ne. Facebook'as - ne.
  • Scribe - logging server. Ar rašytum loggingo servisą su PHP, kai pirmyn/atgal vaikšto milžiniški duomenų kiekiai? Čia būtų savižudybė.

Žinai kas visus šituos tris didžiulius dalykus, kurie tau atrodo neturi nieko bendro su PHP, jungia? Jungia ketvirtas tools'as - Thrift. Thrift leidžia apjungti skirtingomis kalbomis parašytas programas per tam tikrus interfeisus. Smagumėlis.

Kas čia dar... Ar žinojai, kad Facebook Platform - turbūt daugiausiai naudojamas Facebook įrankis, susidedantis iš API ir FBML komponentų - parašytas su PHP. Pats FBML parašytas kaip extension'as PHP kalbai.

Kas čia dar... PHPEmbed - leidžia embeddinti php kodą į C/C++ programas.

Kas čia dar... PHPSh(ell) - nuostabus įrankis greitiems bandymams su PHP. Gali dabar čia man plūstis, kad parašytas su Python. Tavo Python parašytas su C. Tai ką?

Reziumuojant - yra tam tikros problemos ir yra tam tikri būdai jas spręsti. Labai džiaugiuosi, kad PHP nelaikai programavimo kalba ir tikiuosi jos nenaudosi, ryšium su tuo, kad man galbūt ateity nereikės knistis po kažkieno valdomo kvailų prielaidų parašytą kodą.

Nevertheless, sėkmės su kitomis kalbomis.

sirex portretas

Facebook pasirinko PHP,

Facebook pasirinko PHP, Google renkasi Python. Kuris iš jų teisesnis?

Įtariu ir pačio Facebook viduje vyksta kovos dėl PHP VS. kažkas. Kadangi pats Facebook buvo pradėtas rašyti ant PHP, tai matyt ir programuotojai įdarbinami tie, kurie turi patirties su PHP, o ne su kažkokia kita programavimo kalba.

Bet kuriuo atveju, rašau apie tai, kokių trukumų turi PHP su kuriais pats esu susidūręs ir sugaišau daug laiko ieškodamas klaidų netikėčiausiose vietose arba perrašinėdamas vietas, kurios prastai veikia su PHP.

Gal būt padėsiu kitiems PHP programuotojams išvengti tokių vietų rašant savo skriptus.

Anonymous portretas

Religinės kovos :D Dar galime

Religinės kovos :D Dar galime įtraukti Yahoo. Nes jei gerai pamenu, tai jie pasisamdė vieną iš PHP įkūrėjų.

Arba, kai nebeturim argumentų galima slėptis už "galbūt". Nemanau, kad facebook'e vyksta kažkokios tai kovos. Yra priimami racionalus sprendimai. Kaip Julius ir minėjo - kai kam PHP nesukurtas, todėl yra naudojami kitokie įraniai parašyti kitomis kalbomis.

Jei norėjai padėti kitiems išvengti tokių problemų, tai nereikėjo pasirinkti tokio skambaus topic'o.

P.S. vis grįštam prie posakio "blogam šokėjui..."

vytux portretas

PHP visuomet buvo ir yra

PHP visuomet buvo ir yra tiesiog paprasčiausias template'ų variklis. Naudoti jį kamnors kitam tiesiog kvaila... nors kaip template'ų variklis jis labai nevykęs, užtat žmonės surado kur jį pritaikyti kitur... pats daug kartų nusideginau taip padaręs, ir tos klaidos tikrai nebekartosiu. Visiškai pritariu tam, ką išdėstei. Daiktus reikia naudoti pagal jų paskirtį :)

Anonymous portretas

Tai kodėl PHP nėra

Tai kodėl PHP nėra programavimo kalba? Bash turbūt geresnė? :)
Žinoma, kad PHP nėra tobula, bet tas aišku ir tiek pievų neprirašant.

vytux portretas

Ehh... PHP nėra ir niekados

Ehh... PHP nėra ir niekados nebuvo programavimo kalba, PHP yra skriptai. Tą patį gali pamatyti nuėjęs į php.net: "PHP: Hypertext Preprocessor is a widely used, general-purpose SCRIPTING LANGUAGE". Ir čia ne susitarimo klausimas, yra apibrėžimai, kas yra programavimo kalba, o kas yra skriptas.

Anonymous portretas

Programavimo kalba yra viskas

Programavimo kalba yra viskas kas turi sąlygos sakinius ir ciklus. O jau toliau galima skirstyti į kompiliuojamas/interpretuojamas kalbas.

Anonymous portretas

Šiek tiek papilstysiu savo

Šiek tiek papilstysiu savo nekompetetingos nuomonės :) Visų pirma dėl objektų atminties sunaikinimo, kai juose yra nuorodos į kitus objektus ar patys objektai.. Tai liečia kone visas programavimo kalbas, tame tarpe ir C/C++. Nežinau, kokia situacija su Python, bet spėju, kad irgi ta pati. Tai tokiu atveju gelbsti tik tiesios rankos :) Ir taip pat dėl to pačio facebook. Jis buvo pradėtas kurti paprastų studentų kaip privatus socialinis tinklas, tai vargu ar jie mastė apie savo projekto optimizavimą iš pradžių :) Tai tiek, ačiū už straipsnį, tikrai nesiginčysiu dėl straipsnio pavadinimo tinkamumo, nes pats pritariu, kad PHP programuotojas - ne programuotojas, no offense :)

sirex portretas

Ačiū už gerą komentarą. Dėl

Ačiū už gerą komentarą. Dėl referencų tarp objektų ir garbage collectoriaus darbo reikės išbandyti ir su kitomis kalbomis, pažiūrėsiu koks rezultatas. Gali būti, kad šioje vietoje ir klystu...

Nors kita vertus, tokios situacijos, kai parent objektas surišamas su child objektu, tai labai dažnos praktikoje tai klausimas ar aukšto lygio kalbose atmintį reikia atlaisvinti pačiam.

sirex portretas

Atlikau tą patį bandymą su

Atlikau tą patį bandymą su Python. Štai kodas:

  1. def mem():
  2. with open('/proc/self/status') as f:
  3. for line in f:
  4. if line.startswith('VmRSS:'):
  5. return line.strip()
  6.  
  7. class Parent:
  8. def __init__(self):
  9. self.child = Child(self)
  10.  
  11. class Child:
  12. def __init__(self, parent):
  13. self.parent = parent
  14.  
  15.  
  16. for i in range(10):
  17. print(mem())
  18. a = Parent()

Rezultatas:

  1. VmRSS: 2840 kB
  2. VmRSS: 2844 kB
  3. VmRSS: 2844 kB
  4. VmRSS: 2844 kB
  5. VmRSS: 2844 kB
  6. VmRSS: 2844 kB
  7. VmRSS: 2844 kB
  8. VmRSS: 2844 kB
  9. VmRSS: 2844 kB
  10. VmRSS: 2844 kB

Tai reiškia, kad dėl PHP garbage collektoriaus klaidingo elgesio neklydau.

sirex portretas

Perrašiau lygiai tą patį su

Perrašiau lygiai tą patį su PHP.

Kodas:

  1. function mem() {
  2. foreach (file('/proc/self/status') as $line) {
  3. if (strpos($line, 'VmRSS:') === 0) {
  4. return $line;
  5. }
  6. }
  7. }
  8.  
  9. class MyParent {
  10.  
  11. public $child;
  12.  
  13. public function __construct() {
  14. $this->child = new MyChild($this);
  15. }
  16.  
  17. }
  18.  
  19. class MyChild {
  20.  
  21. public $parent;
  22.  
  23. public function __construct($parent) {
  24. $this->parent = $parent;
  25. }
  26.  
  27. }
  28.  
  29. foreach (range(0, 10) as $i) {
  30. echo mem();
  31. $a = new MyParent;
  32. }

Rezultatas:

  1. VmRSS: 5044 kB
  2. VmRSS: 5120 kB
  3. VmRSS: 5120 kB
  4. VmRSS: 5124 kB
  5. VmRSS: 5124 kB
  6. VmRSS: 5128 kB
  7. VmRSS: 5128 kB
  8. VmRSS: 5128 kB
  9. VmRSS: 5128 kB
  10. VmRSS: 5128 kB
  11. VmRSS: 5128 kB

Taip pat matosi, kad atminties naudojimas vis didėja...

Kad patikslinti rezultatus, abu skriptus prasukau 1000 kartų ir palyginau atminties sunaudojimą prieš ciklą ir po ciklo.

Štai rezultatai:

  1. » php test.php
  2. VmRSS: 5032 kB
  3. VmRSS: 5832 kB
  4.  
  5. » python test.py
  6. VmRSS: 2840 kB
  7. VmRSS: 2848 kB

PHP sunaudojo beveik 1MB atminties, o Python 8KB.

Anonymous portretas

Bet kaskartą cikle atminties

Bet kaskartą cikle atminties nepadaugėdavo. Taigi ne viskas taip tragiška su tais objektais.

sirex portretas

Su PHP, prasukus 10 kartu:

Su PHP, prasukus 10 kartu: 5128 kB - 5044 kB = 84 kB
tą patį prasukus 1000 kartų: 5832 kB - 5032 kB = 800 kB

Tai reiškia, kad atminties sunaudojimas nuolat didėja (kiekvienu prasukimu pridedant papildomus 8 kB), nors taip neturėtų būti.

Python atveju, prasukus 1000 kartų, atminties naudojimas nepadidėjo nei vienu baitu (išskyrus pirmą kartą, kai sukuriamas naujas objektas).

sirex portretas

Žmonės, jei perskaitot TIK

Žmonės, jei perskaitot TIK įrašo pavadinimą, tai geriau susilaikykit nuo komentarų ir perskaitykit viską.

Ar bent vienas aprašytas PHP bugas yra neteisingas? Ar dėl to, kad Facebook naudoja PHP, bet vienas iš tų aprašytų bugų išnyksta ir PHP dėl to tampa geresnė skriptų rašymo kalba?

Jei jūsų programavimo patirtis apsiriboja tik PHP išmanymų, tai siūlau taip pat susilaikyti nuo komentarų... :)

Anonymous portretas

Man baisiai įdomu kuo tamstos

Man baisiai įdomu kuo tamstos patirtis tokia plati, kad leidžia taip skambiai rašyti? Straipsnį visą perskaičiau ir net du kartus.

Pabūsiu Mitų griovėjas:

weak typing - yra didelis pliusas. Tam kad iš '0' padaryt 0 kitoj kalboj man atrodo tu suvargtum daugiau kodo, negu php, kuris šiuo atveju 0wn'ina.

Nemokėjimas naudotis kalbos feachersais. Mitas sugriautas

Jeigu tamstos rankos kreivos ir nežinot kur ir kaip naudo == bei === operatorius, arba kaip patikrint kokio tipo kintamasis yra, tai PHP yra programavimo kalba, bet deja ne jums.

klaidų apdorojimas - kadangi PHP yra interpretuojama kalba, tai visi klaidų tipai yra gaunami tik executinant kodą. Nesupratau kur tamsta painiavą matot? Ar kitomis kalbomis parašytos programos nesi-crash'ina? Ar kompiliuojant C/C++/C#/Java kodą negaunat compiler error'ų arba linker error'ų (C/C++/C# atveju)? Ar kitų kalbų kompiliatoriai nemeta warningų ir noticų? Ar C++/C#/Java neturi exceptionų? Tai aš taip ir nesupratau - parašei, sirex'ai, kad PHP turi tokius klaidų tipus. Nu ir kas? Kitos kalbos irgi turi. Paaiškink kas čia blogai?

PHP lygiai tokia pati painiava, kaip kitose sistemose. Mitas sugriautas

klaidų pranešimai - aš jaučiu tu nesi net to error_log'o gyvai matęs. Yra ten viskas - ir failas, ir vieta tiksli, ir visas traceback'as. Reikia mokėt susitvarkyt savo sistemą, o tik paskui skųstis: "OMG OMG OMG PHP šūdas, čia to nėra (nes aš esu per didelis kietas programuotojas, kad pradėčiau čia kažką konfigūruot - give me ze koud!)".

Kreivos rankos - nepriežastis sakyti, kad programavimo kalba - šūdas. Mitas sugriautas

namespace - "implementacija neguodžia..." - yra super argumentas! Šitą užskaitau, ir matydamas, kad tu net nesuvoki kaip ir kam vardų erdvės yra naudojamos pasiūlysiu pasiskaityt www.phpdeveloper.org archyvuose esančius php elito straipsnius, kaip jie diskutavo kaip reikėtų implementint vardų erdves, kad nebūtų tokių problemų, kokios yra kitose kalbose. O jų yra, bet kadangi tu kietas programeris, bet ne ant PHP, tai nematai.

Nepagrįstas argumentais teiginys - ne teiginys ("Anksčiau neturėjo, o dabar implementacija neguodžia..." - ne argumentas). Mitas sugriautas

objektai ir referencai - tą patį rezultatą gausi ir kitoj normalioj OOP kalboj, kai neaprašysi destruktoriaus.

Neišmanymas - ne priežastis sakyti, kad programavimo kalba - šūdas. Mitas sugriautas

round funkcijos klaida ar funkcionalumas? - yra programuotojo klaida. Kas round'ina numberį ir verčia jį į string'ą? Tu dabar paimi kopūstą, pridedi juodų taškiukų ir sakai kad čia yra arbūzas. Čia nėra arbūzas. Skaičius yra skaičius ir jį reikia naudot kaip skaičių. WTF? Aš nesupratau tavo pavyzdžio niekaip kitaip kaip tik blogo kodo pavyzdį.

Kažkoks kreivas kodo gabalas - nėra argumentas. Mitas sugriautas

Taip, kad kai naudosi PHP 3-5 metus, sirex'ai, tada galėsi aiškint, kas toj kalboj yra blogai, o kas yra gerai. Nes dabar tokie patauzyjimai kelis kartus paprogramavus kelis projektus naudojant blogas programavimo praktikas tave bet kurioj kalboj pavers tokių bambekliu, kad ir kaip tau atrodytų kad Python/Java/etc. kalbos geresnės, man atrodo, kad tu ten tas pačias klaidas darysi, kokias čia surašei. Tik tiek, kad tose kalbose tos programuotojo klaidos, gal ne tokios akivaizdžios.

Anonymous portretas

hehe, matosi kad nelabai

hehe, matosi kad nelabai supranti apie ka kalbi ;)

Anonymous portretas

jezau kas tau yra? zhmogus

jezau kas tau yra? zhmogus parashe savo nuomone kilusia ish patirties su php, nebutinai chia per miliona postu putotis, lyg ant taves paties butu uzhvazhiave. atsipalaiduok truputi

Anonymous portretas

Nors šis postas senas

Nors šis postas senas atsakysiu į tavo mitus ir klaidas. Dėl destruktoriaus: PHP 5.3 tikrai turi garbage collection, jei nežinai kas tai yra, tai paaiškinsiu, tai automatinis atminties apvalymas, kai nereikia objekto, kadangi Sirex objektai auga mažesniu, nei naujo objekto dydžiu galiu drąsiai teigti, kad PHP nesugeba apvalyti švariai atminties, net ir destruktorius nepadės. Kažkaip tiek JAVA tiek C# tiek Python tiek Ruby, praktiškai visos šios eros kalbos sugeba tai. (Kurtos nuo 90-ųjų). C++ yra senesnė kalba, todėl ji ir privalomai naudoja destruktorių. Kitavertus C++ bruožas ir yra low level atminties valdymas (pointerių aritmetika ir t.t.), kas retai sutinkama labai aukšto lygio kalbose, ir net jei destruktorius veikia, keista, kad reikia valdyti atmintį skriptinimo kalboje.
Dėl round'inimo esmė, kad ne vertimas į string yra blogas, tačiau paliekamas ženklas, be to round(-0.1) nėra lygu, čia tai wtf, atidumo reikia.
Dėl weak typing: sakai sunaudotum daug kodo, bet kuo kai loginės reikšmės pjauna gryba, nepaisant pastangų( palygink : "false" == true "false" == false ir "false" == 0 , paskutinis bus true, nepaisant, kad pirmas bus true, o antras teiginys false. Kad išvengtum šitos nesąmonės turi leisti explicit cast:
(string) "false" === (int) 0 . Kokia esmė jei privalai naudoti explicit cast, kad būtum užtikrintas, be to vienu atveju "false" lygu true, bet kartais ir false.
Dėl klaidų nenoriu ginčytis, bet kiek naudojau, matau, kad šiokios tokios painiavos yra.

Anonymous portretas

Kaip kokie sektantai čia

Kaip kokie sektantai čia klykiat, kad PHP yra skriptinimo kalba...

O, ne! Tik nesakyk, kad nežinojot prieš pradėdami su ja dirbti. Nežinojot? Labai gaila, patys kalti. Čia maždaug kaip neluptą kiaušinį suvalgyt ir paskui gailėtis. Pats kaltas.

Čia tarp pasiūlymų alternatyvoms matau Java ir Python. Tai guest what - nuliūdinsiu - Python yra skriptų kalba. Netikim? Skaitom Usage dalį. Bet Python kodą galimą kompiliuot! Liūdna - ten bytecodas, kuriam vistiek reikia Python interpretatoriaus. Bet aš mačiau Python'u parašytą exe programą!1101!! Liūdna - tam yra skirti specialūs įrankiai. Dar liūdniau - analogiškus įrankius naudoja PHP pasiekt tam pačiam rezultatui. OMG ir dar - PHP kodą taip pat galima kompiliuoti į bytecodą.

Java? Java iškart kompiliuojasi į bytecodą! Liūdna. Java yra žymiai lėtesnė. Netikit? Eikit pabandykit "didelį projektą" kaip autorius išsireiškė, parašyt su Java. Rašyt bus smagu, programuot smagu. Bet tada ateina "pabandom pažiūrėt ką čia padarėm" fazė ir visi einat kavos darytis "nes Java yra per daug krūta kalba, kad greit užsikrautų".

Taip, kad, sorry gaiz, bet Python yra lygiai tokia pati interpretuojama kalba, kaip ir PHP. Tik ačiū jos autoriui, ji bent jau verčia programerius laikytis tam tikrų kodavimo taisyklių. Java - apskritai yra ne web'ui sukurta, o kitoms užduotims, kurias ji atlieka puikiai.

Taigi autoriui linkiu pereit ant Python arba ant Java arba ant .NET platformos ir ten kurt tinklapius klientams, tada sukūrus tinklapį už N litų - pasiūlyt klientui nusipirkt hosting'ą už N^2 litų.

O tavo klientui jeigu nežinojai neįdomu su kuo tu rašysi tą tinklapį, jam nors ant perfojuostos taškiukus su tušinuku išbadyk, tai nerūpės - rūpės tik developmento ir po to - trumpalaikio arba ilgalaikio supporto ir vystymo kaštai.

Su atsuktuvu niekas vinių nekala, nors gali. Taip, kad galima tauzyt čia šituos niekus, bet smulkus, vidutinis ir kai kurie didesnieji verslai jau yra pamatę piniginę naudą iš projektų, kurie rašomi PHP kalba. Jeigu tamsta nesugebat programuot ir pasiimt tų pinigų? Na ką gi, kaip sakiau, pirmyn - eikit prie kitų kalbų, mokėkit liūto dalį nuo užsakymo sumos hostingam, už tools'us (tik nesakyk, kad programuoji su nupiratautu soft'u, gali kas nors išgirst) ir klientui dar pasiūlyk susimokėt "nūūūū... klientas... nūūū, nes mano įrankiai brangūs...".

Sėkmės.

Anonymous portretas

Pilnai pritariu mantui - PHP

Pilnai pritariu mantui - PHP viena is prasciausiai sudesignintu kalbu.

Anonymous portretas

Na ir privirė čia košės dėl

Na ir privirė čia košės dėl nieko... Ideologinės kovos. Nieko naujo, nieko blogo.

PHP "kai ko" nerado taip (ar iš viso negali padaryti) kaip "kitos programavimo kalbos". Lygiai tą patį galima būtų pasakyti ir apie kurią nors kitą kalbą.

Ir kas? Ogi nieko. Šnipštas. Pasikartosiu: čia yra ideologinis straipsnis, faktų jis nesistengia pakeisti. Aš programuoju (!) PHP, sprendžiu įv. problemas, optimizuoju, sėkmingai iš to uždirbu pinigus ir galiu atlikti visas užduotis.

Kai žmogus parašo "PHP programuotojas - ne programuotojas", tai tada man kyla klausimas: kodėl? Dėl to, kad aš nenurodau tipų? Ar todėl, kad PHP yra "skriptinimo kalba"? Nors kodas tiek ant Java, tiek ant PHP *iš idėjos* būtų toks pat. Tik PHP reikėtų daugiau tikrinti, o Java - catch`inti.

Ir galiausiai: "A scripting language, <...> is a programming language that allows control of one or more software applications", (c) http://en.wikipedia.org/wiki/Scripting_language

Anonymous portretas

Kad PHP yra skriptinimo

Kad PHP yra skriptinimo kalba, tai php.net tinklapyje viršuje galima rasti:

PHP is a widely-used general-purpose SCRIPTING language that is especially suited for Web development and can be embedded into HTML.

O, kad PHP turi bug'ų, tai sutinku. Didžiausias dalykas kuris sucks, tai yra tai, kad negalima nuhandlinti kai kurių dalykų, pvz:

try {
mysql_connect(...)
} catch {
// vistiek čia nepavykdys, nes klaidos atveju mysql_connect vykdys "print"
}

Taigi, pritariu, šaunuolis Mantai!

Anonymous portretas

Taigi kuo skriptinimo kalba

Taigi kuo skriptinimo kalba blogesnė už programavimo kalbą? Ar aš darau mažesnį darbą, ar mano pasiekiamas rezultatas "nusileidžia" kita kalba atliktam darbui? Ar čia "pimpalo matavimas"?

PS> klaidų išvedimas PHP nėra vykdomas su print(). Tam naudojama trigger_error(), bent jau vidiniuose PHP libuose. Tavo norimą funkcionalumą galima imituoti (taip, imituoti, nes tai nėra kalbos defacto standartas) su custom error handleriu.

Anonymous portretas

cia zmogus turejo omeny kad

cia zmogus turejo omeny kad try nesuveiks o ne print

Anonymous portretas

Tai juk logiška, nes PHP

Tai juk logiška, nes PHP nemėto išimčių out of the box...

vytux portretas

Esmė juk ne tame. Esmė tame,

Esmė juk ne tame. Esmė tame, kad PHP be reikalo turi milijonus būdų pranešti apie klaidą, ir dėl tokios nesamonės tu kaip programuotojas turi daugiau darbo, negu turėtum kurioje nors kitoje kalboje.

Anonymous portretas

Aš nesakiau, kad ji būtinai

Aš nesakiau, kad ji būtinai blogesnė. Teigiu, kad tai yra skriptinimo kalba, nes patys kurėjai ją taip pavadino. Na, o dėl programavimo, tai sutinku: "skriptina" ir programuoja tas pats programuotojas...

Dėl klaidų išvedimo, tai gal ir tavo tiesa, kad nevykdo print. Tiesiog norėjau pasakyti, kad tokie dalykai ant standartinių PHP funkcijų kaip try...catch neveikia. PROGRAMAVIMO KALBOSE Delphi, C++, Python jie daro tai ką reikia: įvykus exceptionui leidžia suhandlinti klaidą...

Na, o dėl custom error handlerio tai tu ESI PRIVERSTAS jį rašyti, arba rašyti @ prieš funkciją. Bet tu negali kaip kitose kalbose normaliai catchint'i klaidą...

Anonymous portretas

o kas maišo pasitikrinti

o kas maišo pasitikrinti permission'us prieš bandant atidaryti failą?

sirex portretas

T/S nori pasakyti, kad prieš

T/S nori pasakyti, kad prieš atidarant failą reikia tikrinti ar įjungtas safe_mode režimas, jei jis įjungtas ar failas patenka į open_basedir ribojamų katalogų sąrašą, jei su safe_mode viskas gerai patikrinti ar failas egzistuoja ir jis nėra katalogas, ar į tą failą galima įrašyti ir tik atlikus visus šiuos patikrinimus saugiai atidaryti failą?

Tikriausiai juokauji?

Normaliose programavimo kalbose failai atidaromi taip:

  1. file = '/tmp/test.txt'
  2.  
  3. try:
  4. f = open(file, 'w')
  5.  
  6. except IOError:
  7. print 'cannot open', file
  8.  
  9. else:
  10. f.write('line\n')
  11. f.close()

Tuo tarpu PHP siūlo:
If the open fails, an error of level E_WARNING is generated. You may use @ to suppress this warning.

Ir viskas, kiekvienas gali pats galvoti kaip apdoroti klaidas, o daugelis tiesiog naudoja @, kad jų iš vis nerodytų.

Anonymous portretas

PHP kalboje egzistuoja tokios

PHP kalboje egzistuoja tokios funkcijos kaip:
bool file_exists ( string $filename )
tai bool is_readable ( string $filename )
Ir nereikia ten jokių try, exception, o vieno vientelio if'o.
O vietoj fopen galima naudoti:
array file ( string $filename [, int $flags = 0 [, resource $context ]] )
tada viskas paprastai pasidaro.

Ta pati C, C++, Python turi daug trūkumų, apie tai diskutuojama, dėl jų plaukai nuo galvos raunami... ar dėl to jos pasidaro nebe programavimo kalbos? Manau, kad ne. O tavo logika mažų mažiausiai keista.

Google ne vien Python naudoja. Google svetainių turi ir su PHP, su tuo pačiu Drupal (nors ir retai). Kaip ir išimtiniais atvejais, kad ir koks orkut.Com/About.aspx. Gmail vidus padarytas su Java, Google paieškos sistema su C. Kodėl Java? Tiesiog jie turi puikių programuotojų kurie puikiai programuoja su Java. Nors Python tikriausiai ima viršų. Ir šiaip, kad Google tą ar aną naudoja tai nereiškia, kad visi tai turi naudoti ir, kad tai geriausias sprendimas. Visada reikia galvoti sveiku protu, o ne laikytis kažkieno kito primesta nuomone, o be to pats Google nesėdi ties tuo, o patys bando ištaisyti programavimo kalbų kuriomis programuoja ydas ir padarė programavimo kalbą Go.

P.S. Pats Google parašė savo Python implementaciją. Tai dabar reikštų, kad Python jau nebe programavimo kalba? Deja, deja jos yra programavimo kalbos.

sirex portretas

Ar skaitei mano aukščiau

Ar skaitei mano aukščiau parašytą komentarą? file_exists, is_readable, is_writable apsunkina programos veikimą, nes vietoj failo atidarymo operacijos, reikia atlikti papildomas failo egzistavimo ir skaitomumo ar įrašymo tikrinimo operacijas.

Tam ir yra exceptionai, kad klaidos būtų apdorojamos tada, kai jos įvyksta, o ne užbėgant prieš akis ir tikrinant ar klaida gali įvykti ar ne. Tuo labiau, klaidos įvyksta ir jas reikia apdoroti tik išimtinais atvejais. O PHP atveju, reikia daryti didžiulius overheadus galimų klaidų tikrinimui, prieš joms įvykstant, nors greičiausiai toks klaidos niekada ir neįvyks.

PHP nuo 5.0 versijos įgyvendino Exception galimybę, tačiau visas senas funkcijas, paliko su senu trigger_error like klaidų apdorojimo mechanizmu.

Be to, nelabai suprantu kodėl visi kabinėjasi prie įrašo pavadinimo, kai jo prasmė išaiškinta pačioje pirmoje pastraipoje. Matyt komentatoriai neturi kompetetingos nuomonės, tai bent prie įrašo pavadinimo prisikabina.. :)

Anonymous portretas

"T/S nori pasakyti, kad prieš

"T/S nori pasakyti, kad prieš atidarant failą reikia tikrinti ar įjungtas safe_mode režimas, jei jis įjungtas ar failas patenka į open_basedir ribojamų katalogų sąrašą, jei su safe_mode viskas gerai patikrinti ar failas egzistuoja ir jis nėra katalogas, ar į tą failą galima įrašyti ir tik atlikus visus šiuos patikrinimus saugiai atidaryti failą?

Tikriausiai juokauji?"

ne, aš nejuokauju - jeigu tu pasirenki šūdiną sprendimą (implementacijos, ne kalbos) - ką gi, užsičiaupk ir dirbk.

sirex portretas

Blogo įraše rašiau, kad su

Blogo įraše rašiau, kad su PHP vienintelis būdas pagauti klaidą, tokiose funkcijose kaip fopen, prieš tai neatliekant tikrinimų – panaudojant error handlerius ir įrašant į juos Exception iškvietimą. PHP atveju, manau tai yra teisingiausias sprendimas. Rezultatas gautųsi toks:

  1. try {
  2. $fp = fopen('/tmp/test.txt', 'w');
  3. fwrite($fp, "line\n");
  4. fclose($fp);
  5. }
  6. catch (MyException $e) {
  7. // Apdorojama klaida, priklausomai nuo $e->getCode();
  8. }

Jei aš klystu, gal galėtum pasidalinti savo implementacijos sprendimu, pateikiant veikiantį kodo pavyzdį?

Anonymous portretas

Sveiki, Norėdami gauti

Sveiki,

Norėdami gauti informaciją apie Sirex.lt autorių ir susidoroti, siųskite SMS žinutę su tekstu SIREX numeriu 1679. Gausite žinutę kur šiuo metu yra Sirex. Žinutės kaina 10 lt.

Skelbti naują komentarą

Šio laukelio turinys bus laikomas privatus ir nerodomas viešai. If you have a Gravatar account, used to display your avatar.
  • Leidžiamos HTML žymės: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Linijos ir paragrafai atskiriami automatiškai
  • Web puslapiu adresai ir el. pašto adresai automatiškai tampa nuorodomis.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. Beside the tag style "<foo>" it is also possible to use "[foo]".

Daugiau informacijos apie teksto formatavimą

CAPTCHA
Šis klausimas skirtas patikrinti ar esi žmogus, taip apsisaugant nuo internetinių reklamos robotų.
Image CAPTCHA
Enter the characters (without spaces) shown in the image.
Surinktas turinys