Jak vysvětlit, že settery nejsou špatně? Nebo jsou? rubrika: Návrh

2 vosykapavel
položil/-a 8.4. 16:54

Narazil jsem před rokem na dobrý tým. Šéf shání dobré zakázky a protože je programátor, záleží mu i na kvalitě kódu. Děláme code review, máme coding standards. Učíme se, zlepšujeme se. Někdy si to jen myslíme.

Jedním pravidlem totiž je "Setters - do not use them". Přijde mi to docela dogmatické.

Jedna náhrada, je že místo setterů se má použít argument v konstruktoru.
To je jasné pro povinné atributy.
Settery jsou mnohdy používány zbytečně (ale přece né vždy?), protože je prostě generuje IDE/make a private atributy už pak nejsou úplně tak private. Myslím, že na to poukazuje většina článků, které jsou "proti setterům".

Šéf zmiňuje ještě jeden důvod proč je nepoužívat. "Znějí příliš obecně, málo výstižně". Typicky uvádí, že místo setStatus(1/0) se má použít activate()/deactivate(). V tom má samozřejmě také pravdu. Jenže status s nějakým konečným počtem stavů není typický příklad.

Typičtější je asi Article a jeho title, content, date, author a dejme tomu třeba nepovinný mainImage a mainVideo (nebo mi pomožte s jiným příkladem).

Takové případy prostě přicházejí. Samozřejmě si s tím umíme poradit :-). Ale myslím, že si tím zanášíme do kódu bordel, což je škoda, když je to celé ve snaze mít kód čistý.
Dějí se pak většinou tyto dvě věci.

1) převlečené settery
Settery se přejmenují na updatery. Prostě místo set() dáme update(). To nám v review projde. :-)

Jenže to stejně není moc výstižné. Snad možná pro ty povinné atributy, ty už nastavené byly a tak je aktualizuju. Ale ty nepovinné? Prostě to tam teď chci "nastavit" a nejlepší slovo mi přijde "set". Někdy se objeví něco jako "přidat" addMainImage() nebo "přiřadit" assignMainVideo(). Jenže prostě se to stává takové neprůhledné. Člověk si začne říkat co to asi dělá, jestli se jich dá nastavit (add je typicky u ArrayListu).

A co když ho chci odebrat? Jasné by bylo setMainImage(null), to by neprošlo, takže tu máme assignMainVideo(null), což je divné removeMainVideo() zas naznačuje ten ArrayList. A dělat kvůli tomu resetMainImage(), když předtím nebylo možné použít set...

Prostě mám pocit, že se s tím názvoslovím dostáváme, kam nechceme. Nebo aspoň já ne.

2) setujeme, ehm updatujeme hromadně z přepravky
Přepravka, která má public :-) atributy (občas si všimnu, že je to s nějakými anotovanými asserty Symfony\Component\Validator\Constraints as Assert ... ale tady mám mezeru ve vzdělání, nevím jak to funguje, moc tomu nevěřím) se předá v jedné metodě updateFromDeatils(entityDetails), která bez setterů a často bez nějakých kontrol, které by do nich měli patřit (aspoň kdyby byly private).

No takže pokud chápu význam nějakého zapouzdření, kterého se dosahuje pomocí private atributů a kontrolovaného přístupu k nim přes metody, tady se prostě o tu výhodu připravujeme.

Aspoň z mého pohledu. Nejsem žádný profík na OOP, ale tohle mi prostě smrdí.

Jsem sám? Jsou snad settery špatně? Máte nápad, co k tomu dodat? Dík

Komentáře

  • PositiveDeveloper : A to ani settery nepoužíváte u entit Doctrine, kde krásně settery generuje make v symfony? 11.4. 4:35
  • Taco : @PositiveDeveloper: To jako používat nějaký zlozvyk, protože na to máme nástroj? 11.4. 16:30
  • PositiveDeveloper : @Taco: To já nepíšu, ale zajímalo mě jestli to dělají u těch entit nebo ne, protože nejsem si jistý jestli to zlozvyk je. Stejně musíš někde nastavit ty vlastnosti entity popořadě a setter se někdy hodí, že se tam dává třeba výchozí hodnota, úprava hodnoty a tak. 17.4. 14:42
  • Taco : @PositiveDeveloper: Dělal jsem na jednom kódu, kde původní autor z formuláře vracel naplněnou entitu/objekt. Plnil ji pomocí setterů. Ne proto, že by to nešlo líp, ale protože to všude viděl tak dělaný, tak to tak udělal taky. *** Já bych teda ty vlastnosti entity nastavil v konstruktoru, to nejde? *** Doctrine si plní entitu reflexí. Žádné settery na to nepotřebuje. 18.4. 18:15
  • mazane : Jak nejlépe v PHP nastavit objekt při vytvoření? Napadá mě předat mu data jako parametry konstruktoru, ale u entit může být těch hodnot poměrně dost. Pak se nabízí asociativní pole, kde to můžu mít i pojmenované, ale zase přijdu o nativní typovou kontrolu a v IDE napovídání zdarma. Takže u Doctrine entit mi ty settery přijdou obhajitelné. Možná mít něco jako třídu se settery, která bude jen parametrem konstruktoru/factory entity, ale nejsem si jist, že by to bylo pro budoucí čtenáře kódu intuitivní. To už možná radši nějakou metodu isValid, která by se volala na entitě ve chvíli, kdy bych ji považoval za nastavenou. Doctrine s použitím setterů počítá, takže v Doctrine se to taky nepokouším lámat a píšu to tak, jak jsem to všude (v oficiální dokumentaci) viděl, ačkoliv by to šlo i jinak (rozuměj lépe v jednom z mnoha dalších úhlů pohledu). Obecně jsem také proti objektům s 20 členskýma proměnnýma vystavenýma ven, ale vyhýbat se setterům u entit v doctrine, tam už IMHO začíná neužitečný dogmatismus. 20.4. 9:20
  • Taco : @mazane: Jak jsem psal, Doctrine si nastavuje objekt přes reflexi. *** V čem je mnoho setterů lepších než mnoho parametrů v konstruktoru? 20.4. 22:17
  • mazane : @Taco: Lepší je to v tom, že $o->setActive(true); $o->setFinished(false); $o->setPrice(1000); je čitelnější než new C(true,false,1000);. Dá se to řešit pomocí coding standards, kde vynutím komentář u každého parametru, ale protože program funguje i když jsou komentáře "rozbité", tak je nemám rád a považuji je vždy až za poslední možnost. A další věc je práce s načtenou entitou. Načtu z DB. Setterem změním jeden údaj. A pak zase uložím. Entita je pořád ve validním stavu. Hrát si s entitami na neměnné objekty by samozřejmě taky šlo, ale nepřijde mi to moc praktické u entit pro tabulky s třiceti sloupci. 22.4. 10:37
  • v6ak : Což je i otázka jazyka. Když jazyk podporuje named parameters (např. Scala nebo Python), problém to není. 22.4. 10:33
  • mazane : v6ak: Přesně tak. Za běžných okolností se mi taky líbí neměnné objekty plněné přes konstruktor. Ale PHP má před sebou ještě spousty cesty, než se dostane tam, kde byl např. C# před deseti lety. 22.4. 10:40
  • Taco : @mazane: Zde pozor. V prvním případě je to sice čitelnější, ale zato je to rozbitné. A vzhledem k tomu, že ti to u komentářů vadí, tak jsi krapet nekonzistentní :-) *** Druhá možnost není spor. Entitu už máš načtenou, a je tedy validní, a setterem jen měníš stav z jednoho stavu do druhého. *** Tomu "Hrát si s entitami na neměnné objekty by samozřejmě taky šlo, ale nepřijde mi to moc praktické u entit pro tabulky s třiceti sloupci." nerozumím. 22.4. 13:45
  • mazane : @Taco: Hodnotit mou konzistentnost hraničí s argumentačním faulem, takže si taky trochu zafauluji, když už nehledáme pravdu, ale vítězství. :-) Přijde mi, že dogmatickým vyžadováním "objekt musí být v každém okamžiku ve validním stavu" se připravuješ o návrhové vzory, které mohou být v určitých situacích (a hlavně jazycích) výhodné. ... Ale asi nemá smysl se tu špičkovat. Pro mě je prioritní čitelnost samotného kódu s použitím co nejméně komentářů, pak nativní typová kontrola a pak až teprve abych měl zajištěnu 100% jistotu, že objekt je v každém okamžiku validní. Zvlášť u entit, které se jako nové plní většinou za účelem vložení do databáze, kdy tu nevalidnost většinou rychle zjistím po prvním testu. Ty máš ty priority seřazené zase jinak. Pokud tedy spor zjednodušíme na to, kdo má priority poskládané lépe, tak toho se nechci účastnit a vzdávám se. 22.4. 15:07
  • Taco : @mazane: Tak zle snad nemusí být. Já si nemyslím, že "musí v každém okamžiku", ale dívej se na to spíše z pohledu: pokud mi validitu ověří databáze - což je IMHO naprosto korektní scénář, tak proč se s nějakýma setterama obtěžovat? Prostě vytvořím slovník {name: John, surname: Dee} a vyřešeno. Ano, vadí mi, když se za účelem čitelnosti dotyčný vzdává kontroly nad kódem (jedním dechem souhlasím, že to často nemusí být tak horke). Ale mnohem víc mi vadí taková schíza, že na jednu stranu se vytváří mraky kódu, který ale nic nedělá - což je právě ten setter. Pokud nevaliduje objekt (jehož je prvkem), tak k čemu je dobrej (opět, čitelnost nemusím řešit setterem, ale mohu na to mít public property, nebo ještě lépe generickej slovník)? 22.4. 16:15
  • mazane : @Taco: S tím zbytečným kódem souhlasím a např v C# je ve většině případů úplně v pořádku mít polovinu věcí jako veřejnou členskou proměnou a druhou polovinu jako vlastnost (tedy něco, co vyvolá kód při nastavování nebo čtení). A z venku se s tím pracuje stejně a nemusím řešit, co je co. Ale PHP nic takového nemá (magic methods nepočítám, protože je to nástroj z pekla, který před svým týmem "tajím") a pak i zbytečné settery a gettery mohou mít svůj význam kvůli sjednocení, abych nemusel přemýšlet, jestli zrovna tohle mám nastavovat přes setter nebo jenom přiřadit hodnotu. Navíc když se pak v budoucnu rozhodnu, že by si něco setter zasloužilo, tak je z toho refactoring půlky aplikace, což je v PHP docela pohroma. 23.4. 12:34
  • v6ak : Ano, to, že mohu změnit implementaci a nemusím měnit kód, který s tím pracuje, je právě princip (a přínos) zapouzdření… 23.4. 13:21
  • Taco : Bavíme se o usecase, kde validaci děla někdo druhej. Takže žádné zapouzdření, žádné settery, žádný refactoring půlky aplikace. Prostě buď jedno, nebo druhé. Já nechci aby si zbytek týmu myslel, ze tato přepravka je bezpečná. Kdyz má přepravka logiku dodavatele dat, tak z něj chytřejší objekt úpravou pár setterů neuděláš. Stejně budeš muset předělat všechna volání. *** V PHP bych zvolil prosté pole. V C# se mi to tak stručně nedaří. 23.4. 13:55
  • mazane : Tým si po první chybě zvykne. Zvlášť když tam uvidí metodu isValid(). :-D Ale vážně: Doctrine počítá s validacemi na entitě. V jednotkových testech se DB vůbec nepřipojuje (od toho jsou jednotkové). Ale mám zkušenost, že v 99% je problém akorát v nedodržení povinnosti něco vyplnit. Jinak těch validací napříč celým objektem je minimum (alespoň na projektech, na kterých dělám). A setterů, jako je setName($firstName, $surname), se vzdávat nemusím. Každopádně já bych prosté pole určitě nezvolil. Přišel bych tím o typovou kontrolu a kontrolu, že jsem neudělal překlep v názvu. A protože toto jsou kontroly, které probíhají už v IDE při psaní kódu a ten kód i pomáhají napovídat, tak by se mi toho vážně vzdávat nechtělo jen proto, abych měl buď jedno nebo druhé. Nepřijde mi zas tak špatně mít všechny kontroly na DB a některé z nich i duplicitně v PHP. Asociativní pole (a jeho kopie) v PHP jsem ochoten použít ve scope tak do dvaceti řádek. Pak se začínám dostávat do paniky. Hlavně při refactoringu. Než prosté pole napříč aplikací, tak to už snad radši ten konstruktor s dvaceti parametry. Sice se to blbě čte, ale aspoň se to dobře píše. A do toho tu máme ještě to, že snad do PHP 7.4 nešlo anotovat datový typ členské proměnné. To byl taky další pádný argument pro setter, i kdyby v něm nebylo nic jiného, než jen přiřazení a otypovaný parametr. Na závěr ještě malé rýpnutí: Stručnost nemusí být to samé, co čitelnost. Někdy to jde dokonce proti sobě. 24.4. 12:53
  • PositiveDeveloper : @Taco: Doctrine si nastavuje entitu možná reflexí, když hydratuje data z DB, ale pokud pracuješ s entitou, tak reflexí se hodnoty nenastavují. V tom setteru potřebuješ třeba někdy nastavit kontrolu jestli se nastavují povolené hodnoty. 24.4. 15:23
  • Kit : @mazane: Poznáš na typech, zda do paramertu dáváš skutečně $firstName a nedal tam omylem $surname? V asociativním poli bys to poznal. Také to poznáš, pokud FirstName a Surname budeš mít jako třídy. 24.4. 17:57
  • Taco : @mazane: Nějak se v té tvé argumentaci ztrácím. Tak chceš aby ty entity byly validní (aby _se_ validovali), nebo nechceš? *** Doctrine si to nastavuje reflexí. Lze použít konstruktor i nepoužít settery, tedy nic nebrání tomu, aby se vytvářeli hezké entity. Tím bych prosím argumentaci ohledně Doctrine považoval za uzavřenou. 25.4. 15:09
  • Taco : @PositiveDeveloper: A? Já snad někde psal, že se nemají používat settery? Já jsem psal, že se nemají používat settery za účelem plnění objektu. Na jeho změnu - například vytažený záznam, změna, a uložení to je cajk. Viz moje odpověď. Na prvotní vytvoření objektu/entity vždycky jenom konstruktor (nebo statická továrna). 25.4. 15:08
  • Kit : @Taco: Kvůli změně záznamu ho nemusíš ani vytahovat. Můžeš objektu oznámit událost nebo injektovat closure s operací, která se má provést uvnitř objektu. Plnění objektu výhradně přes konstruktor (i prostřednictvím továrny či builderu) je OK a také to prosazuji. 25.4. 16:45
  • Taco : @Kit: Samozřejmě, tak to jde taky. Ale teď se bavíme o zapouzdření. Návrhovej vzor command se zapouzdřením nesouvisí. 25.4. 19:25
  • mazane : @Taco: Já se ve své argumentaci taky ztrácím. :-) Můj hlavní problém asi je, že chci mít objekt stále validní. Vlastně ho chci i plnit konstruktorem, akorát to nechci dělat v PHP. Protože jak psal Kit, tak i to setName($firstName, $surname) je V PHP pěkně hloupé. Takže si "můžu" pomoct tím polem, ale na to nepotřebuji PHP 7.4. To jsem zase v té šílenosti bez typových anotací, bez napovídání a bezpečného refactoringu a zbývá mi pak jedině dělat z toho znouzecnost a tvrdit, že mě to nutí k lepšímu návrhu, atd. atd., ale na to už jsem nějak moc starej a vyhořelej. 28.4. 11:44
  • Taco : @mazane: :-) Respekt. 28.4. 16:52
odkaz
15 Taco
odpověděl/-a 8.4. 20:09
 
upravil/-a 8.4. 20:13

Settery mají svůj význam. Je špatné je používat špatně, stejně jako je
špatné je nepoužívat protože se to řeklo.

Nahrazením setMainVideo() za assignMainVideo() se vůbec, ale vůbec nic
nezměnilo. assignMainVideo() je setter. Jenom zamaskovanej. Taková
úlitba temným bohům :-)

updateFromDeatils(entityDetails) je celkem použitelná věc, protože měním stav objektu atomicky, a mohu uvnitř zajistit všechny patřicné kontroly. (Pokud to nedělám, jsem blbec.)

Základní pravidlo, které propaguji je, že píšu/programuju to co chci ve skutečnosti dělat. Tedy například:

author = context.getAuthor()
author.setAddress(newAddress)
context.update(author)

Nastavuji/měním existujícímu uživateli adresu.

Na rozdíl od:

author = new User
author.setName("John")
author.setSurname("Dee")
// author.setBirth() - zapomněl jsem povinnou položku
author.setAddress(address)
context.insert(author)

V druhém případě, nejen, že jsem zapomněl na povinnou položku, ale ve skutečnosti dělám sadu těchto kroků:

  1. vytvořím úplně prázdného uživatele (což je nevalidní stav)
  2. tomu uživateli nastavím pouze jméno (což je nevalidní stav)
  3. následně tomu uživateli změním pouze příjmení (což je nevalidní stav)
  4. následně tomu uživateli změním pouze adresu (což je stále nevalidní stav)

Což není to co chci dělat. Nemluvě o tom, že uživatel beze jména je nevalidní.

Což je druhé pravidlo - objekt se nesmí dostat do nevalidního stavu.

Ve své podstatě je jedno, jestli toho dosáhneme pomocí konstruktoru (ideální, protože nejsnazší a většinou nám v tom jazyk pomáhá), nebo pomocí setterů.

Dobré je, když jazyk podporuje vícero konstruktorů. Díky tomu mohu pro každý use-case vytvořit konstruktor, kterým nastavím takovou konstelaci objektu, kterou požaduji. S validací a se sémantikou. Vhodně to řeší volitelné props.

Některé jazyky podporují hromadné nastavení props. To je fajn. Můžeš v tom hlídat validaci. Něco podobného jde více či méně hezky udělat asi v každém jazyce.

Zakázat settery a přitom stále vytvářet nevalidní objekty mi přijde takové nepromyšlené.

A do třetice, je vhodné respektovat zvyklosti.
Ty prefixy obvykle něco znamenají. Obvykle pomáhají se zorientovat. Místo getUpdated() mít isUpdated() je přirozeně lepší, protože to zní normálněji. Ale nahradit setUpdated() za assignUpdated() mi přijde samoúčelné a ve výsledku ke škodě. Já konkrétně assignUpdated() používám. Ale nikoliv jako setter. Používám ho v případě, kdy chci nějakému jinému objektu nastavit nějaké vlastnosti. Ostatně to ta angličtina i trochu říká. A každý vývojář, který to po mě bude číst si řekne "co to je, jaký podivný prefix, co to asi znamená". A to je v mém případě cílem.

Komentáře

  • vit.herman : Jen k druhému pravidlu "Objekt se nesmí dostat do nevalidního stavu": V databázově orientovaných aplikacích lze jen obtížně zaručit. Např. nastavíš referenci na neexistující entitu. I kdyby jsi nakrásně referenci databázově kontroloval vždy při přiřazení (magické a tím potenciálně neefektivní), nezaručíš platnost této reference, protože cíl reference může být mezitím smazán. Teoreticky by databáze mohla notifikovat o změnách a objekt na to vnitřně reagovat. Asi je zřejmé, že nedává smysl takto implementovat konzistenci v běžných aplikacích. Objektové modelování mi tedy dává smysl jen pro modelování paměťových struktur daného prog. jazyka a nikoli perzistentních struktur externí databáze. Právě z tohoto důvodu jsem se ze světa tříd a objektů vrátil k datovým strukturám a funkcím pro běžné aplikace. Ale piškvorky bych klidně programoval objektově. 20.4. 14:29
  • v6ak : IMHO je praktičtější si u objektů ujasnit, jakou míru validity požadujeme. E-mailová adresa lze zkontrolovat nezávisle na okolním světě (aspoň teda syntax), u referencí je praktičtější použít presumpci správnosti a nechat to zvalidovat až databázi. 20.4. 14:59
  • vit.herman : @v6ak: Ano, to jsem si přesně ujasnil. A to do té míry, že objekty pro účel zapouzdření databázových struktur už dávnou nepoužívám. 20.4. 15:03
  • Kit : @vit.herman: Objekty a relační databáze moc dohromady nejdou. Je potřeba mít buď mezivrstvu ORM, anebo mít objektově pouze řídicí objekty, přes které data jen protékají ve formě datových struktur. Osobně se přikláním ke druhé variantě, neboť odpadají aplikační cache, které bývají častým zdrojem problémů. Dále při vhodné horizontální dekompozici vypadají řídicí objekty velmi jednoduše a dají se snadno zaměňovat. 20.4. 15:51
  • Taco : @vit.herman: Já jsem na OOP rezignoval také. Každopádně máš samozřejmě pravdu. A já se absolutně nestydím sem nebo tam nasekat hromadu setterů - když je důvodem ekonomie. Člověk musí vědět proč to dělá. Pak někdy dává smysl pravidla porušovat. 20.4. 22:19
  • Mlocik97 : No Settery a Gettery v Jave sú vraj len preto, že aby programátori platený od riadkov kódu, mohli program nafúknuť na 2 násobok riadkov. Aspoň to som počul od viacerých a zároveň si myslím totéž. 20.4. 22:31
  • Kit : @Mlocik97: Kdyby settery byly užitečné, tak by je do Javy přidali podobně, jako byly přidány do C#. Jenže užitečné nejsou, ale vývojáři je stejně chtěli, neboť si mysleli, že tím zapouzdří objekty. 20.4. 22:51
  • vit.herman : @Taco: Souhlas. Aplikoval bych především tvé první pravidlo "píšu/programuju to co chci ve skutečnosti dělat". Ztotožňuji se s ním. A někdy to může zahrnovat i to psaní getterů, setterů. Určitě neplatí prohlášení, že settery jsou vždy špatné. To by bylo veliké zjednodušení. 21.4. 12:54
  • vit.herman : @Mlocik97: Buď jsi to blbě pochopil, protože sis to nezařadil do kontextu nebo Ti chybí představivost nebo jsi poslouchal nesmysly. Není těžké najít ukázat vhodné případu užití pro getter/setter. Pokud budeš chtít dejme tomu po nastavení barvy hracího pole překreslit canvas, už potřebuješ setter, který vedle nastavení barvy pole provede překreslení. Nebo pokud budeš chtít okamžité perzistentní ukládání hodnot datové entity, potřebuješ setter. Atd. Dá se vymyslet nekonečno případů. Když někomu radíš, měl bys vždy brát ohled na hranice platnosti toho, co říkáš. Ale to je tvá velká slabina a ukazuje na tvou nezkušenost. Asi je to ode mne arogantní, ale doporučoval bych méně radit a spíš naslouchat... 21.4. 13:11
  • Taco : @Kit: nechám si vysvětlit, co je na tomto kousku kódu nezapozdřeného: https://gist.github.com/tacoberu/fdb8769de81ec7a5dd042b2bec6444ed 21.4. 22:05
  • Kit : @Taco: Kdokoli zvenčí může změnit jméno, adresu a věk, jak se mu zamane. Nikde žádné ověřování, zda to smí udělat. 22.4. 8:34
  • Taco : @Kit: Ano, to je v pořádku. Otázka zněla zda to je zapouzdřené. Máš tam něco ještě? 22.4. 13:48
  • Kit : @Taco: Z toho, co jsem napsal, vyplývá, že to zapouzdřené není. 22.4. 15:50
  • Taco : @Kit: Děkuji za odpověď. Nebudu tě dál mučit. 22.4. 16:16
  • Andreaw Fean : @Kit: To co popisuješ už není zapouzdření, zapouzdření vyžaduje jen neprozrazovat vnitřní implementaci. Ty už si vymýšlíš vlastní pravidla k těm oficiálním. Příklad ze života: Klíč se taky neptá, zda ho smím použít. Pokud se k němu dostanu, tak ho použít můžu. 22.4. 20:16
  • mr.fatblunt : Se vsim co pise Taco souhlasim a pridal bych jednu asi obecne znamou vec - me na projektech vzdycky nejvic vytrestala mutabilita v multivlaknovem prostredi. Kdyz neco menim za behu (setterem, nebo obecne necim co meni stav) tak je potreba zajistit aby to bylo konzistentni napric vlakny co referenci na mutovany objekt maji na svych zasobnicich. Cim vic je takovych stavu co se daji treba i novackem na projektu kdykoliv za behu zmenit nebo predat mezi vlakny, tim slozitejsi je prijit na to co zpusobilo nejaky uplne nahodny crash systemu v runtime. Dalsi zradou u mutabilnich objektu mohou byt (u pass-by-reference) ruzne RAM-based cache, nikdo nechce menit objekt ktery mezitim jine vlakno dostalo z cache a treba uz jej napul zpracovalo... Proto se snazim mit minimalne datove objekty (jako "User" a podobne) immutable a validace provadet pri vytvareni objektu. Pokud uzivateli chci zmenit adresu, udelam na to specialni metodu v DAO vrstve, pripadne setter vrati novou kopii objektu se zmenenymi udaji (takovy CoW). 24.4. 15:39
  • v6ak : Tak vícevláknové prostředí by mělo mít nějaký memory model, který nejspíš řekne, že bez nějaké operace jako synchtonizace není možné zapisovat data ani číst data potenciálně zapsaná jiným vláknem. Když to udělám, mohou se dít různé podivné věci vymykající se intuitivnímu chápání významu kódu – právě kvůli různým implementačním detailům (zejména optimalizacím), které se spoléhají, že se budu chovat určitým způsobem. A nejde jen o cache, ale i o různé reorganizace instrukcí kompilátorem i procesorem. Když jedno vlákno podle kódu zapíše hned po sobě hodnoty dvou různých proměnných, mohou ty zápisy na mnoha platformách ostatní vlákna vidět v opačném pořadí, nebo vlivem cache taky třeba vůbec. Nicméně podstatné je, že programátor má hlavně dostatečně rozumět tomu memory modelu. Znalost jevů jako přeskládání instrukcí nebo cache je sice fajn bonus, ale typicky to programátor nepotřebuje nutně znát. 24.4. 16:29

Pro zobrazení všech 7 odpovědí se prosím přihlaste:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.