Zrušení properties v Nette\Object

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Ped
Člen | 64
+
0
-

phx napsal(a):

Takova drobnost: pravdepodobne pouzivani properties ma vliv na vykon aplikace. Preci jen se musi vykonat vice radku kodu:))

Tohle mi prijde jako mnohem lepsi argument, nez puvodni litanie.

Ale jak pravi klasicke rceni „premature optimization is root of all evil“.

jasir
Člen | 746
+
0
-

Ondřejův bod 3) je problém. Ale jinak jsou properties poměrně příjemná záležitost a pokud člověk zná jejich omezení…

v6ak
Člen | 206
+
0
-

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.

22
Člen | 1478
+
0
-

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 :-)

Honza Marek
Člen | 1664
+
0
-

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";
	}

}

?>
westrem
Člen | 398
+
0
-

// není na první pohled zřejmé, jestli chci private proměnnou nebo getName()

Jak neni jasne?! To je snad krystalovo jasne, ze pristupujes priamo k premennej a nevolas ziadnu metodu nad tym .. unika mi nieco?

jasir
Člen | 746
+
0
-
<?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
?>
v6ak
Člen | 206
+
0
-

To je na jednu stranu dobrý příklad, na druhou stranu to je otázka best practices. Neměla by se vlastnost prom jmenovat spíše centiProm, popř. promCenti?

Šaman
Člen | 2602
+
0
-

Properties se snažím nepoužívat. A to ze dvou (vlastně tří čtyř) důvodů:

  1. IDE mi nenašeptává vlastnosti, ale gettery a settery ano
  2. 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?
  3. 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
+
0
-

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
+
0
-

@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
+
0
-

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
+
0
-

…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)

grey
Člen | 94
+
0
-

$_<property> je krásné, velké písmeno je hnus :)

v6ak
Člen | 206
+
0
-

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
+
0
-

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.

Ondrej
Člen | 110
+
0
-

Nejsem pro rušení properties. I obyčejné plnění šablony v presentru přes $this->template->foo = "" používá magii getTemplate().

David Grudl
Nette Core | 7887
+
0
-

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
+
0
-

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
+
0
-

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 :-)

jtousek
Člen | 951
+
0
-

Myslím, že používání properties by se třeba v dokumentaci a příkladech nemělo objevovat. Respektive v dokumentaci jen u Nette\Object.

v6ak
Člen | 206
+
0
-

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
+
0
-

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.

jtousek
Člen | 951
+
0
-

Pořád tu zůstává podtržítková varianta ala Doctrine. Co je na ní vlastně tak špatného?

Honza Marek
Člen | 1664
+
0
-

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.

jasir
Člen | 746
+
0
-

Aby nedošlo k mýlce, já properties z Nette vyhazovat rozhodně nechci. Jen je potřeba znát jejich omezení.

Majkl578
Moderator | 1364
+
0
-

jtousek napsal(a):

Pořád tu zůstává podtržítková varianta ala Doctrine. Co je na ní vlastně tak špatného?

Podtržítková varianta ala Doctrine už doplatila na svoji historičnost a mizí.

grey
Člen | 94
+
0
-

Majkl578 wrote:

Podtržítková varianta ala Doctrine už doplatila na svoji historičnost a mizí.

jak doplatila?

Majkl578
Moderator | 1364
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

@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 | 7887
+
0
-

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.

v6ak
Člen | 206
+
0
-

Hmm, ale bez backtrace je to těžko vynutitelné. A backtrace znamená další zpomalení.

David Grudl
Nette Core | 7887
+
0
-

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á.

pekelnik
Člen | 462
+
0
-

Tímhle pravidlem jsem se řídil doposavad… a je to trochu matoucí ;)