Autor Zpráva
iiic
Profil
Ahoj mám funkci, která už se používá na více místech a dosud vracela bool
Teď ji potřebuji rozšířit aby vracela bool a navíc nějaké řetězce.
A jde mi o to, jestli s tímhle můžu nějak zachovat i zpětnou kompatibilitu, nebo ji mám raději dropnout.
Jaký postup by byl nejlepší:
- zachovat zpětnou kompatibilitu a další výsledky této funkce vracet nějakou jinou funkcí?
- zachovat zpětnou kompatibilitu a přidat funkci parametr kdy bude vracet pole namísto bool?
- vykašlat se na zpětnou kompatibilitu a vracet array?
- rozdělit funkci na více menších, zřetězit je jedna bude vracet pole a druhá bool?
anonymníí
Profil *
iiic:
Funkce by měla mít jasně daný typ návratové hodnoty. Navíc si nedovedu představit, jak by v praxi vypadalo zanevření na zpětnou kompatibilitu - v dalších částech aplikace, kde tu funkci používáš, se stane co? Půl aplikace přestane fungovat jen proto, že si ji sám a dobrovolně rozbiješ?

Takže, pokud má funkce vracet bool, což asi má, ať vrací bool.
Pokud má vracet array, a to i v předchozích užitích, ať vrací array.
Pokud má vracet array, ale v předchozích použitích chceš bool, použij dvě funkce.
Keeehi
Profil
anonymníí:
Funkcí, které vracejí v PHP různé návratové typy je spousta. Za všechny třeba obyčejná strpos která vrací číslo -> int nebo false -> bool. Chceš říct, že jsou špatně navržené?

iiic:
Nedá se ti konkrétně poradit, když jsi nám neřekl, co má tvá funkce dělat.
anonymníí
Profil *
Keeehi:
To je těžké... dle mě by měl ten strpos vracet spíše NULL, ale to je jedno. Kdyby se indexovalo v PHP od jedničky, false by pravděpodobně vracet nemusela a mohla by vraet nulu, tedy int.

Ale, když mám vlastní kód, na několika (ne jednom, dvou, ale x) místech tu fci používám a vždy vracela jen true/false, nedovedu si představit x+1. použití, kde od ní najednou potřebuji array. To smrdí spíše špatný návrhem čehosi, než oprávněnou potřebou.
Keeehi
Profil
anonymníí:
To smrdí spíše špatný návrhem čehosi, než oprávněnou potřebou.
S tím souhlasím. Proto jsem chtěl po iiic, aby napsal co má funkce doopravdy dělat.
Alphard
Profil
anonymníí:
Ale, když mám vlastní kód, na několika (ne jednom, dvou, ale x) místech tu fci používám a vždy vracela jen true/false, nedovedu si představit x+1. použití, kde od ní najednou potřebuji array.
Tak já bych si to i představit uměl. Dosud jsem mohl mít nějakou validační funkcí bool isValid();, která mi vracela true/false a byl jsem spokojený. Nyní ale vyvstane potřeba specifikovat chybovou hlášku vysvětlující, proč je vraceno false. V místech, kde mi dřív stačilo true/false mi stačí pořád, ale v jednom dalším chci i tu hlášku a přitom rozhodně nechci duplikovat algoritmy.
Dan Charousek
Profil
Alphard:
Nyní ale vyvstane potřeba specifikovat chybovou hlášku vysvětlující, proč je vraceno false

Já osobně jsem taktéž zastáncem toho, že by

anonymníí:
Funkce by měla mít jasně daný typ návratové hodnoty.

Na druhou stranu je pravda, že někdy samotný boolean není dostačující. Řešení bych si představoval podobně jak je navržena preg_match() ta taky nevrací shody/false ale true/false a shody vrací přes referenci.

Návrh strpos() mi přijde krkolomný a hezčí mi přijde vracet -1 (int).
anonymníí
Profil *
Alphard:
Ano, jako příklad to je dobré. Tebe považuji za programátora, využil bys to v praxi? Mícháš reálně pro jednu funkci více návratových hodnot? Jen se ptám :-) A doporučil bys míchání typů návratových hodnot začátečníkovi? Ona pak snadno vznikne jedna funkce, která bude dělat všechno. Zavolá se a pak se bude podmínkami zjišťovat, jak to vlastně dopadlo (i to jsem už viděl).
Alphard
Profil
Dan Charousek [#7], anonymníí [#8]:
Popisoval jsem spíš ten use-case, který si vy neumíte představit :-), než příklad pro vracení více hodnot v poli.

V PHP (a obecně v jazycích silně vycházejích z C) není vracení více hodnot příliš obvyklé a ani pro to dané jazyky neposkytují pohodlnou podporu. Já jsem v tomto pod vlivem Pythonu, kde je to řekl bych běžnější a tam se v odůvodněných případech nebojím navrhovat funkce vracející více hodnot (Python pro změnu neumí referencovat hodnoty. Tam jde použít jedině workaround s využitím mutable typů, ale to je stejné znásilňování jazyka jako v PHP vracení více hodnot...).

Přesto, v tomto případě ([#6] Alphard) bych pole jako návratovou hodnotu nepoužil, návrhově by se mi to nelíbilo. Vedlo by to k nutnosti všude jinde doplňovat isValid()[0], což je ošklivé. Asi bych zvažoval 3 možná řešení, řadím dle náročnosti implementace.

A) Použít referenci.

B) Vytvořit 2 funkce, přičemž původní implementující validační algoritmus bych přejmenoval např. na isValidWithMessage(), nechal ji vracet 2 parametry a pak vytvořil novou funkci isValid(): bool { return isValidWithMessage()[0]; }.

C) Provést větší refaktoring, abych pracoval s objektem, který má svůj stav. Pak bych měl metody isValid() a getMessage().
anonymníí
Profil *
Alphard:
V tom příkladu z #6, který jsem bral jako ilustrativní, by se přeci ale pole nevracelo, ne? Tam by to bylo spíše true/false/string. Pokud bych uvažoval pole, tak to by bylo vždy jednoprvkové, nebo se pletu.

Ale jinak samozřejmě díky za věcný rozbor, včetně navrhnutých řešení. C) je ideální stav, který se zase u většího projektu může vyplatit (je to individuální).

PS. Klidně to přesuň k Ledu (resp. do koše, co nesouvisí s tématem, odpověď na můj dotaz výše (string vs. array) si tam dohledám.
Alphard
Profil
anonymníí:
V tom příkladu z #6, který jsem bral jako ilustrativní, by se přeci ale pole nevracelo, ne? Tam by to bylo spíše true/false/string.
Tak taky by to šlo..., ale změnit původní návratový typ true/false na true/false/string je podle mě už opravdu hodně velká divočina. Nechci při každém volání funkce kontrolovat návratový typ.
Rozepíši to asi detailněji, mám původní funkci
function isValid(string $name): bool {
  return strlen($name) < 10;
}

A nyní ji chci rozšířit tak, aby vracela i popis chyby, takže je upravím takto
function isValidWithMessage(string $name): array {
  if (strlen($name) < 10) {
    return [true, ''];
  } else {
    return [false, 'Name is too long.'];
  }
}

Tahle funkce mi bude vracet pole, ale první prvek pole bude vždy bool a druhý vždy string, takže to v podstatě splňuje tvůj požadavek [#2] anonymníí „Funkce by měla mít jasně daný typ návratové hodnoty.“. Vracím sice komplexní, ale jasný datový typ. Tohle řešení je docela běžné třeba v Pythonu stackoverflow.com/a/38516 a lze ho použít třeba i v C++ en.cppreference.com/w/cpp/utility/tuple (ale netvrdím, že se v něm běžně používá).

Pak s tou funkcí mohu docela rozumně pracovat
if (isValidWithMessage('Alphard')[0]) { }
nebo
list($success, $message) = isValidWithMessage('Alphard');
if (!$success) { echo $message; }

avšak pro použití bez potřeby chybové hlášky bude určitě lepší vytvořit zkratku
function isValid(string $name): bool {
  return isValidWithMessage($name)[0];
}
což zajistí i zpětnou kompatibilitu.

Jak říkám, je to jedna z možností, určitě ne jediná.

C) je ideální stav, který se zase u většího projektu může vyplatit
Souhlasím.

Klidně to přesuň k Ledu (resp. do koše, co nesouvisí s tématem, odpověď na můj dotaz výše (string vs. array) si tam dohledám.
To by byla škoda, myslím, že to s tématem souvisí velice blízce. Vyhazovat to určitě nebudu.
anonymníí
Profil *
Alphard:
Díky, tohle vysvětlení je super! Už to i vlastně odpovídá na dotaz, i když jsme se k tomu dobrali oklikou.
Keeehi
Profil
Dan Charousek:
Návrh strpos() mi přijde krkolomný a hezčí mi přijde vracet -1 (int).
Problém je, že -1 se dost často používá jako označení pozice od konce řetězce. Ale ok, dejme tomu. Pak tu máme funkci strstr, která vrací část řetězce. Ovšem co dělat, když tam hledaný podřetězec nenajdeš? Nejde vymyslet nějaký řetězec, který by se mohl vrátit, jelikož jakýkoli řetězec co vymyslíš je legitimním výstupem nějakého vstupu.

Ještě pár zábavných funkcí.
strtr - variací string, false nebo null
mysqli_guery - vrací buď {true, false} nebo {mysqli_result object, false} v závislosti na položeném dotazu tedy na hodnotě parametru

Když se to však vezme kolem a kolem, tak většinou jde o to, že buď vracíme výsledek (jeden datový typ) a nebo potřebujeme oznámit chybu (druhý datový typ). Ale na oznamování chyb tu už přece způsob máme - exceptions.
iiic
Profil
no pěkně se to tady rozjelo… díky, zajímavé čtení

Jde o část apička… funkci na ukládání souborů, u stejně nazvaných (a velikostně malých) souborů porovnává obsah, rozliší jestli jde o obrázek nebo něco jiného (podle toho vybere složku na uložení), uloží a vrací bool jestli se podařilo uložit. Teď by se mi hodila i ta informace o tom co to bylo za soubor.

Vím, že jsem tam tenkrát řešil docela atomicitu operací a výkonové optimalizace, tak se mi do toho nechtělo moc vrtat.

Ale ve výsledku po pročtení této diskuse to raději předělám, protože ta funkce toho dělá fakt hodně a tak ji rozdrobím.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: