Zrušení properties v Nette\Object
- v6ak
- Člen | 206
Já mnohdy také radši použiju getter/setter, ale také nepovažuji existenci této vlastnosti jako významný problém. Nechci-li, nepoužiju ji. Navíc si troufám říct, že přístup k non-public vlastnostem a metodám jiných instancí využívám zřídkakdy. V Javě hlavně u metody equals(Object), kterou mi ale stejně většinou generuje Lombok, v PHP si na takové použití nepamatuji.
- Honza Marek
- Člen | 1664
22 napsal(a):
Da se uvést příklad, jak taková těžko odhalitelná chyba na základě properties vznikne? Sám jsem se s tím ještě nesetkal, tak abych byl v obraze, abych se s tím nesetkal ani v budoucnu :-)
<?php
class Test extends \Nette\Object
{
private $name;
public function getName()
{
if (empty($this->name))
{
$this->name = necoNajdi();
}
return $this->name;
}
public function test()
{
// není na první pohled zřejmé, jestli chci private proměnnou nebo getName()
echo isset($this->name) ? "funguje" : "nefunguje";
}
}
?>
- jasir
- Člen | 746
<?php
class TestClass extends \Nette\Object {
private $prom = 1;
function getProm() {
return $this->prom * 100;
}
function test(TestClass $obj) {
return $obj->prom; //tady se nevolá getter
}
}
$a = new TestClass;
$b = new TestClass;
echo $a->test($b); //vypíše 1, nikoli 100
?>
- Šaman
- Člen | 2659
Properties se snažím nepoužívat. A to ze dvou (vlastně tří
čtyř) důvodů:
- IDE mi nenašeptává vlastnosti, ale gettery a settery ano
- volání $myClass->property se chová jinak v myClass a jinak venku. Uvnitř třídy stejně musím používat gettery a settery, tak proč to venku psát jinak?
- ve třídách, které nedědí od NObject se to používat nedá. A pak
mám bordel v tom kdy mohu a kdy ne. Třeba tohle
$exception->message
vyhodí fatálku. (A propo, zdá se mi to, nebo už NObject není taťka všech Nette objektů, ale jen některých?)
Jo a 4. Properties nepodporují fluent rozhraní.
Takže je používám jen v šablonách a jinde je považuji spíš za zdroj problémů.
(Spíš se mi nelíbí, že se toto prezentuje jako cool vlastnost frameworku a přitom to je jenom pozlátko. Pilíře Nette jsou naštěstí jinde. A bohužel, taky jsem toto pozlátko ve svém prvním projektu cpal kam jsem mohl.. ono to k tomu svádí. Holt každý si musí najít svou cestičku k čistým kódům sám. Nechci tím říct, že jsou properties špatné, ale že mému stylu psaní nevyhovují. Supr na nich je, že je v php kódu nemusím používat a v šablonách se hodí.)
- v6ak
- Člen | 206
Pravda, někdy jsou y properties nevhodné. Například extrahuji z třídy rozhraní. Kód, který používal tu třídu, bude nyní používat to rozhraní. Ale u rozhraní nemám vynucenu podporu properties. Toto považuji za největší problém properties. Ano, je možné do kontraktu napsat požadavek na dědění z Nette\Object, popř na implementaci __get a __set takovou, aby třídě Nette\Object odpovídala. Ale kdo mi to pohlídá?
- jasir
- Člen | 746
@v6ak:
Je to jen příklad s nesmyslnými názvy. Podstatné je, že dostanu objekt, vyvolám na něm property a přesto se getter nevyvolá. Při použití protected, složitějších třídách a více úrovni dědění už se může stát, že si ani neuvědomím, že objekt ($this), může být v hierchii dědičnosti spolu s jiným objektem jiné třídy (mají nějakého společného předka) a má tedy přístup k jeho protected proměnným.
Editoval jasir (4. 10. 2010 13:54)
- jasir
- Člen | 746
David Grudl napsal(a):
Nette\Forms je poslední místo, kde se nacházejí protected attributy, ale i ty časem zmizí. Nicméně existuje řešení, které NObject od počátku své existence cíleně nabízí a tím je psát properties s velkým prvním písmenem.
Aha, tak tohle jsem opravdu nevěděl a rozhodně jsem to v žádné doku
nikdy nečetl…
No tak to je ale pěkné… A opravdu, pokud upravím svůj předchozí
příklad takto:
<?php
class TestClass extends \Nette\Object {
private $Prom = 1; //aha, velké písmenko a getter se volá
function getProm() {
return $this->Prom * 100;
}
function test(TestClass $obj) {
return $obj->prom;
}
}
$a = new TestClass;
$b = new TestClass;
echo $a->test($b); //už vypíše 100
?>
Tak teď ještě jak s touto informací naložit…
- pekelnik
- Člen | 462
…NObject od počátku své existence cíleně nabízí a tím je psát properties s velkým prvním písmenem.
Také o tom slyším poprvé. Člověka napadne jako první tohle: $_<property> a jako druhé asi $data[‚<property>‘]. Což je jeden větší hnus než druhej…
To velké písmeno je ovšem geniální… samozřejmě v rámci jistých přednastavených parametrů… :D
Vyhovím tvé žádosti a podporu properties z frameworku skutečně odstraním. Jen to nebude hned. Udělám to s přechodem na verzi PHP, která je nativně zavede. Takže zkuste tlačit tímto směrem.
+1 Přesně tak!
Editoval pekelnik (4. 10. 2010 15:27)
- v6ak
- Člen | 206
jasir: To je celkem zajímavý argument. Koncepčně je to problém chápání protected v php, ale použitelnost to samozřejmě ovlivňuje.
Já preferuji obvykle spíše méně dědění a více kompozice, ale to neznamená, že Tebou uvedený problém nastat nemůže. (Já navíc properties používám spíše vzácně a rozhodně ne uvnitř třídy, ale to už sem nepatří.)
- Majkl578
- Moderator | 1364
grey napsal(a):
$_<property> je krásné, velké písmeno je hnus :)
$_<property> se tváří jako přežitek z dob PHP4 (a jím je).
Velké písmenko se mi nelíbí, je to sahání do coding standardu
s vedlejším WTF efektem pro člověka, který kód nezná. Ale budiž vám to
přáno.
Kdysi jsem je s oblibou používal, ale poslední dobou čím dál častěji
používám přímo gettery, takže mi je to ve výsledku jedno. Ale určitě
bych to neodstraňoval.
- David Grudl
- Nette Core | 8218
Obcházení coding standardu? Vždyť právě coding standard může stanovit, že property se budou používat jen s velkým písmenem.
- westrem
- Člen | 398
1. jasirova ukazka
Ano toto je spravny priklad kedy nastava problem
Edit: Povodne som si neuvedomil preco 2. jasirova ukazka funguje a ziadal som o odkazanie na manual PHP preco to fici, potom som si to vsak lepsie precital a zistil co je vo veci.
Šaman napsal:
Konecne niekto podlozil objektivne dovody preco nepouziva properties!
Je pravda, ze v urcitych pripadoch je treba na properties davat pozor a vediet s cim clovek naraba, ale to je tak aj pri inych sucastiach FW a obecne – je dobre vediet co sa deje pod kapotou a nespoliehat sa na to, ze sa to nejak upatla samo.
Myslim si, ze najvecsia sila properties je v sablonach pripadne nejakych jednoduchych code snipetoch, kde skracuju a sprehladnuju zapis – imho ich primarny ucel.
Editoval westrem (4. 10. 2010 18:47)
- 22
- Člen | 1478
Děkuji za širokou odezvu na můj dotaz.
Já bych to shrnul v kostce asi tak, že propertis je „vyšší Nette
dívčí“ a je to Nette feature, ke které by člověk měl dojít až
v momentě, kdy ví přesně co dělá. Je jasný, že properties jsou asi
problém pro týmovou práci, kdy pak člověk, který převezme kód, kde se
properties využívají, má velký problém odladit chybu, kdy musí měnit
chování aplikace, a ještě horší to je v případěk, když se dostanete
k Nette projektu, který není dokončený a původní programátor byl ztracen
v „překladači“, pak tohle může být problém a připravit horké chvilky
před „Haškovou brankou“.
Tedy z mého pohledu rozhodně nechat, jen zdůraznit úskalí plného využívaní této Nette feature. Tímto taky žádám o zvýšení příspěvků pro titulu „Nette guru“ z 200 na 500 a to si ještě nejsem jistý, jestli to není málo :-)
- v6ak
- Člen | 206
Napadá mě, že u .NETu musí řešit vlastně stejný problém, jako napsal jasir ve své první ukázce . Co jsem tak viděl C# zdrojáky, tak prefixují vlastnosti podtržítkem. (Nejsem ze světa .NET a neznám jejich coding standards přesně.) To by ale řešilo i jasirovu stížnost na nevhodné chování při dědění . Podobný problém může být i v JavaFX, tam se ale obávám, že moc řešen není.
jtousek: Souhlas.
- nAS
- Člen | 277
Mě už to nedá a přihodím také do mlýna. Každý rozumný jazyk properties podporuje a tedy argument, že to někdo nemusí znát mi přijde zcela mimo. To byste si mohli stěžovat, že někdo nemusí znát továrničky, Latte filtr, MVC, atd. a tak to všechno z frameworku vyhodíme.
Properties v Nette jsou navrženy velmi pěkně a problém
s vyhodnocování viditelnosti proměnných na úrovni tříd místo na úrovni
objektů je sice nepříjemný, ale to stačí dát nějaký varovný boxík do
dokumentace a nemusíme kvůli tomu rušit či nepoužívat užitečnou featuru.
Kolikrát potřebujete v objektu pracovat s jinou instancí stejné třídy?
Občas se to stát může, ale moc obvyklé to není. A s potomkem už
pracovat mohu bez problému, když bude atribut private
.
Celá tahle diskuze mi připadá, že kvůli prkotině chcete zavrhnout moc pěknou vlastnost Nette.
- Honza Marek
- Člen | 1664
v6ak napsal(a):
Napadá mě, že u .NETu musí řešit vlastně stejný problém, jako napsal jasir ve své první ukázce . Co jsem tak viděl C# zdrojáky, tak prefixují vlastnosti podtržítkem. (Nejsem ze světa .NET a neznám jejich coding standards přesně.)
To jsi viděl nějaký divný C# zdrojáky. Mám za to, že normálně píšou proměnné s malým písmenem na začátku a property s velkým.
- Majkl578
- Moderator | 1364
grey napsal(a):
jak doplatila?
Jak píše Roman B.:
The reasoning is simple: The prefix „_“ is usually either used for easier distinction of instance variables from other, i.e. local variables, instead of always using „this.“ (often seen in C#), or it is used to signal that a member is not meant to be accessed from outside of the class when the language does not have visibility modifiers (PHP4).
Since you always have to use „$this->“ in PHP5+ when accessing instance members and there are visibility modifiers, the „_“ is largely superfluous and just makes the verbose OO code even more verbose.
Editoval Majkl578 (5. 10. 2010 12:54)
- v6ak
- Člen | 206
Možná byly divný, ale podtržítko na začítku jsem tam viděl. Property s velkým počátečním mě nenapadla, ale vlastně to taky mají. (Opravdu nejsem C# programátor, napsal jsem v tom jen pár řádků a to hlavně kvůli porovnání asistence MonoDevelopu u Boo a C#.) Na druhou stranu, přijde mi to v PHP jako poněkud nekonvenční.
- jtousek
- Člen | 951
Majkl578 napsal(a):
Podtržítková varianta ala Doctrine už doplatila na svoji historičnost a mizí.
Vzhledem k tomu, že je to v Doctrine 2 použité si troufám tvrdit, že to až tak nemizí.
Když se to propojí s Nette properties tak argument že
$this->_name
namísto $this->name
je zbytečné
když jsou všechny proměnné stejně private neberu, protože podtržítko by
zůstalo POUZE v gettrech, settrech a v deklaraci samotné proměnné. Všude
jinde už by se použilo $this->name
a automaticky se volaly
gettry a settry.
- pekelnik
- Člen | 462
@v6ak: s tou konvencí malých počátečních písmen máš naprostou pravdu :)
use Nette;
class Foo extends Nette\Object
{
// Property
private $Bar;
// Getter
public function getBar()
{
return $this->Bar;
}
// Usage inside the class
public function getHelloBar()
{
return 'Hello :) ' . $this->bar; // Hle! malé písmeno :)
}
}
// Usage outside the class
$foo = new Foo();
echo $foo->bar; // Hle! Malé písmeno :)
Editoval pekelnik (5. 10. 2010 13:44)
- David Grudl
- Nette Core | 8218
Asi by stačilo dodržovat zásadu o nepoužívání properties uvnitř knihovního kódu, tj. pokud píšete komponentu, nepoužíváte v jejím kódu vlastní properties, zatímco pokud komponentu používáte v aplikaci, využíváte properties dle libosti.
- David Grudl
- Nette Core | 8218
Mám na mysli dobrovolné zásady pro psaní kódu (které používá třeba Nette samotné), nikoliv vynutitelnost. Ta by představovala řádově větší magii. Pravidla pro používání properties musí zůstat jednoduchá.