RFC – upravit matoucí syntaxi public property služby v services.neon

m.brecher
Generous Backer | 863
+
+2
-

Ahoj,

pokud chcete použít v konfiguračním souboru .neon public property služby, použijete tuto syntax:

@myService::$publicProperty()

Syntaxi jsem ověřil testováním, protože v dokumentaci v sekci „Konfigurace služeb“ – https://doc.nette.org/…ion/services#… uvedena není.

Logicky správná syntaxe by ale neměla obsahovat závorky, aby bylo jasné, že nechceme volat metodu:

@myService::$publicProperty

Tato syntax není podporována:

Nette\DI\ServiceCreationException
Service 'myService': Expected function, method or property name, '$$cookiePath' given.

Pro doplnění dokumentace jsem podal PR, a po krátké veřejné diskuzi bych podal Issue (na opravu DI si netroufám) na doplnění alternativní správné syntaxe do DI bez závorek.

Jaký je názor komunity ? Která alternativa je nejlepší:

  • přidat novou syntax @myService::$publicProperty a starou syntax se závorkami deprecovat + časem vyhodit ?
  • přidat novou syntax a nechat obě syntaxe trvale jako validní ?
  • nechat to být jak je ?
Kamil Valenta
Člen | 815
+
+3
-

m.brecher napsal(a):

pokud chcete použít v konfiguračním souboru .neon public property služby

Můj názor je, že tohle nikdo chtít nemá a tím vlastně padá diskuze jak toho docílit :)

Jaký je důvod, aby config cpal cokoliv neznámého do public property? Jaký je důvod, aby config nezavolal setter?

Marek Bartoš
Nette Blogger | 1260
+
+2
-

Jaký je důvod, aby config nezavolal setter?

Property budou čím dál častější. https://wiki.php.net/…operty-hooks

Kamil Valenta
Člen | 815
+
+1
-

Marek Bartoš napsal(a):

Property budou čím dál častější. https://wiki.php.net/…operty-hooks

Předpokládám, že to je jen osobní odhad. Který se (možná) naplní.

Z mého pohledu je to paranoidní potřeba vyhnout se setteru, aby se novým, atypickým jazykovým konstruktem napsalo něco jako setter. Vyzdvihovaná ergonomičnost se mi zdá subjektivní, resp. já ji v tom nespatřuji.

Jak bys v neonu řešil potřebu

@myService::foo(1)::bar(2)

?

m.brecher
Generous Backer | 863
+
0
-

@KamilValenta

Jaký je důvod, aby config cpal cokoliv neznámého do public property?

Nemám na mysli zápis do public property služby, ale „použití public property služby“ pro zápis její hodnoty někam jinam – do konstruktoru jiné služby, nebo jako hodnotu do jiné konfigurační položky. Takže upřesňuji návrh:

Tento matoucí zápis:

session:
	cookiePath: @configProvider::$cookiePath()  #  ?? public method cookiePath() ??

nahradit srozumitelným:

session:
	cookiePath: @configProvider::$cookiePath   #  clear - public property $cookiePath

Pro předání hodnoty do public property služby je v konfiguraci sekce setup:

https://doc.nette.org/…ion/services#…

Ukázka použití public property v sekci setup:

services:
    foo:
        create: \Foo
        setup:
            - $value = 123	# tato syntaxe je správně !!

Syntaxe pro public property v sekci setup je správně – bez závorek. O to víc důvod udělat v tom pořádek a syntaxi public properties sjednotit !!

Můj názor je, že tohle nikdo chtít nemá a tím vlastně padá diskuze jak toho docílit :)

Snad jsem to doplňujícím výkladem dostatečně vysvětlil, že se jedná o běžně používaný postup

Kamil Valenta
Člen | 815
+
+1
-

Ono je celkem jedno, zda se bavíme o setterech (pravda, že jsem to tak prvně pochopil), nebo getterech, je to „stejné“. Skoro.

setup: je ještě trochu košatější, protože ten může volat i metody jiných objektů, ale chápu, proč byl použit a co jsi tím chtěl demonstrovat.

Samozřejmě dává smysl @myService::$publicProperty, tak jako fungují konstanty @myService::CONST.

Důvod, proč to dosud nikomu moc nevadilo, odhaduji právě v tom, že lidi mají v configu spíše @myService::getProperty()

m.brecher
Generous Backer | 863
+
0
-

@KamilValenta

Z mého pohledu je to paranoidní potřeba vyhnout se setteru, aby se novým, atypickým jazykovým konstruktem napsalo něco jako setter. Vyzdvihovaná ergonomičnost se mi zdá subjektivní, resp. já ji v tom nespatřuji.

RFC jsem si se zájmem prostudoval a není to žádná křečovitá snaha doplnit do PHP něco jenom proto, že to má většina zavedených hlavních programovacích jazyků. Hlavním smyslem property hooks není dublovat settery, tam, kde jsou settery oprávněné se budou dál používat.

Property hooks mají primárně vyřešit problém průběžného doplnění validace do public properties bez změny public API. Přidání validace se provede náhradou public property za private property + setter/getter. To je ale změna public API čili problém. Proto je v PHP zavedenou praxí dopředu předpokládat, že by se toto u každé veřejné public property mohlo stát a jednoduše je nepoužívat a místo nich použít private property + dvojici prázdných setter/getter které se možná využijou, možná ne. Tedy boilerplate kód.

Přidat do public property validaci beze změny public API lze pomocí __set()/__get() což je komplikované a má řadu známých nevýhod.

Property hooks tak de facto nepřináší nějakou zásadní novou feature – můžeš dál používat setter/getter místo property hooks. Přínos property hooks je ve výrazném zjednodušení kódu. Když se člověk podívá okolo sebe, tak všechny významné jazyky (včetně PHP) směřují ke zjednodušení syntaxe – i Java, která je tradičně verbose (ukecaná).

Editoval m.brecher (4. 11. 1:26)

Kamil Valenta
Člen | 815
+
0
-

m.brecher napsal(a):

Přínos property hooks je ve výrazném zjednodušení kódu.

Settery/gettery jsou běžným konstruktem jazyka, jsou to metody s běžnou syntaxí, potomek je může přepsat, využít v sobě parent.

Property hooks přináší zcela ojedinělý konstrukt, který nikde jinde v jazyku nenajdeme. Jak se bude chovat v dědičnosti zatím patrně není známo (?), jak využít třeba v getu parent get není známo (nebo jsem na to nikdy nikde nenarazil). Fluent interface s nimi patrně neuděláš vůbec.

Nevím tedy, čím je definováno „výrazné zjednodušení“, já bych to nazval spíše „zjednodušení v některých případech, které vůbec nemusely nastat“.

__set a __get se také moc nechytily, ačkoliv jsou případy, kdy mohou být skvělé. Hooky mohou dopadnout úplně stejně. Zda by ale měly být argumentem pro používání public properties je subjektivní. Za mě prostě (zatím) ne.

V neonu (ať držíme myšlenku vlákna) pak @myService::getProperty() a příp. @myService::$publicProperty.

Marek Bartoš
Nette Blogger | 1260
+
0
-

Jak se bude chovat v dědičnosti zatím patrně není známo (?)

Property hooks už jsou dávno mergnuté a stable release PHP 8.4 bude za 17 dní (tj. 21.11.), můžeš si to otestovat. A jak se to chová je sepsané v RFC k nim, nadpis Inheritance.

Předpokládám, že to je jen osobní odhad. Který se (možná) naplní.

Já tím kupříkladu nahradím všechny gettery pro private properties, protože hooks umožňují private set/public get a zjednoduší se tak kód. Společně s tím ale nahradím i ojedinělé settery pro private properties i s jejich validací, což je případ který se řeší tady.

Editoval Marek Bartoš (4. 11. 11:27)

Kamil Valenta
Člen | 815
+
0
-

Marek Bartoš napsal(a):

Jak se bude chovat v dědičnosti zatím patrně není známo (?)

Property hooks už jsou dávno mergnuté a stable release PHP 8.4 bude za 17 dní (tj. 21.11.), můžeš si to otestovat. A jak se to chová je sepsané v RFC k nim, nadpis Inheritance.

Sepsané to sice je, ale zatím se to tak úplně nechová:
get – https://3v4l.org/v9lRD/rfc#…
set – https://3v4l.org/6TKOR/rfc#…

Když chceš v potomkovi přepsat set nebo get (nebo oboje), musíš redeklarovat property, čímž můžeš ztratit nebo změnit její výchozí hodnotu. Pokud ji chceš zachovat (třeba z vendorového balíčku), nemáš jak. To je v RFC popsáno prostě jako fakt a vymalováno.

Nejsem apriori proti hookům, jen se mi zatím nezdají jako nástroj hromadné migrace na public properties.

m.brecher
Generous Backer | 863
+
0
-

Ahoj,

Změna RFC

díky @KamilValenta a @MarekBartoš za podnětné příspěvky do diskuze. Při opakovaném testování jsem s překvapením zjistil, že syntaxe pro public property je implementovaná správně, ale před 3 lety nebyla a proto jsem tehdy v kódu použil tu která tehdy fungovala $myService::$property() ).

Včera mě zmátly tyto věci:

a) @mesour neon plugin napovídá property syntakticky špatně: @myservice::$property
b) v dokumentaci Nette v odstavci ‘Výrazové prostředky’ https://doc.nette.org/…ion/services#… je uvedena syntaxe pro konstanty, ale aktuálně platná syntaxe property tam chybí
c) syntaxe konstanty a property se liší prvním písmenem – uppercase = konstanta, lowercase = property, což je OK, ale když jsem testoval, tak jsem omylem použil pro property uppercase a nahlásilo mě to, že konstanta neexistuje

Takže není potřeba nic nového v konfiguraci implementovat, stačí doplnit chybějící informace do dokumentace + opravit nesprávnou nápovědu v neon pluginu.

PR do dokumentace: https://github.com/…cs/pull/1065

Editoval m.brecher (4. 11. 23:08)

Kamil Valenta
Člen | 815
+
0
-

m.brecher napsal(a):

c) syntaxe konstanty a property se liší prvním písmenem – uppercase = konstanta, lowercase = property, což je OK

Vzhledem k tomu, že Nette opustilo uppercase pro konstanty, je takové odlišení podivné. Čekal bych, že rozhodující bude dolar.

@myservice::$property
@myservice::constant
m.brecher
Generous Backer | 863
+
0
-

@KamilValenta

Vzhledem k tomu, že Nette opustilo uppercase pro konstanty

Nette nahrazuje konstanty ve tvaru DEFAULT_VALUE konstantami ve tvaru DefaultValue, kde první písmeno je uppercase takže konfigurace je v souladu s doporučenou praxí pro názvy konstant. Dolar je vyhrazen pro static property. Použití property/konstant v konfiguraci neon je ale ještě složitější než jsem včera psal, protože jsou zde ještě statické property tříd/objektů a objevil jsem v konfiguraci jiné chyby a chyby v pluginu pro neon.

Udělám tedy důkladné testy a pak podám issue pro opravu chyb v konfiguraci i neon pluginu.

Editoval m.brecher (7. 11. 2:18)

m.brecher
Generous Backer | 863
+
0
-

Tak odvolávám co jsem odvolal – po důkladných testech jsem objevil několik jiných chyb v syntaxi public property, public konstanty a public static property v konfiguraci. Je to poměrně komplexní, proto jsem na to založil nové vlákno zde: https://forum.nette.org/…-aktualizace