Autor Zpráva
Monkeys
Profil *
Aku pouzivate strategiu pri tvorbe metod.
Je vhodne natrieskat vsetko do jednej metody ?

Napriklad ja pouzivam class v ktorej generujem casto pouzivane selecty do ktorych sa vypise obsah z DB .
Je vhodne do takejto metody zapisat dalsi kod ktory by mi generoval napr. checkboxy, alebo je vhodne si vytvorit novu metodu a riesit to v nej ?

Zamyslam sa nad tym ci je vhodne jednu metodu pouzivat pre viac vypisov (aj ked by sa vnej kod vetvil), alebo to vzdy riesit novym postupom.

M.
Tori
Profil
Mimo osobní programátorské zvyky jsou i nějaká obecně uznávaná pravidla, např.:
- funkce dělá jen jednu věc
- používat parametry na modifikaci jejího chování je špatné (z tohoto pohledu je blbě navržená i např. print_r())
- název funkce má být dostatečně popisný, a přitom ne zbytečně dlouhý (aby bylo možné číst kód a chápat co dělá, aniž bych si rozklikávala jednotlivé volané funkce). Zvolte si jednu (jakoukoli) konvenci zápisu názvu, např. camelCase, a té se důsledně držte.
- funkce by neměla být příliš dlouhá. Obvykle se uvádí max.délka na jednu obrazovku.
- pokud je v několika funkcích podobný kód, koukněte, jestli by se nedal vytknout do další (menší) funkce
- ...
V podstatě to jsou tatáž pravidla, jako pro psaní přehledného a srozumitelného kódu obecně.

Sežeňte si např. knihu Dokonalý kód od McConnella (ve větších knihovnách bude určitě), od strany 177 se mluví o funkcích konkrétně. Anebo si najděte nějaký svůj program, aspoň dva roky starý, a koukněte, jestli mu ještě rozumíte, jestli už teď s odstupem času na něm něco vnímáte jako negativní. Anebo nějaký blok kódu pošlete na djpw ke zhodnocení, určitě někdo poradí.

Aku pouzivate strategiu pri tvorbe metod.
Je vhodne natrieskat vsetko do jednej metody ?
Nevím jak ostatní, ale já třeba píšu různě - pokud je to nějaká jednoduchá funkce, tak rovnou PHP kódem. Ale všechny složitější věci si nejdřív napíšu pseudokódem, pak to rozdělím na jednotlivé funkce (pokud nevím hned jak je udělat v PHP, tak i ty si nejdřív zapíšu pseudokódem), a pak to teprv převedu do PHP. Nebo někdy je potřeba komplexní funkčnost zapouzdřit do jedné metody - pak je jakoby jedna veřejná řídící funkce (která obsahuje pouze volání podřízených fcí + zachytávání výjimek) a několik soukromých podřízených (které jsou na nižší úrovni a přímo něco provádějí, nenechávájí si to zařizovat od jiných).
Monkeys
Profil *
Tori:

Ano, tieto pravidla sa snazim dodrzovat, avsak skor som chcel vediet ci je vhodne davat metodam viac vyznamov.
V podstate ste mi nato odpovedali v poslednej casti vasho prispevku, zaco vam dakujem.

M.
Sir Tom
Profil
Tori:
používat parametry na modifikaci jejího chování je špatné (z tohoto pohledu je blbě navržená i např. print_r())
Jak to myslíš? Můžeš to, prosím, více rozvést?
Alphard
Profil
Na tom není moc co k rozvádění. Jen parametr funkce by neměl rozhodovat o tom, jesli je výsledek vypsán, nebo vrácen.
Tori
Profil
A navíc se při vypisování mění i návratová hodnota na TRUE. Kdyby aspoň vracela řetězec vždy, a parametr by byl jako "navíc kromě vrácení i vypsat", tak by to bylo lepší (neměnila by se tolik signatura funkce).
Joker
Profil
Monkeys:
Je vhodne natrieskat vsetko do jednej metody ?
Poznámka, před otazníkem se nepíše mezera

Ne.
Jak píše Tori, jedna metoda by měla dělat jednu věc. Jde to poznat, když se napíše název metody a pod to popis toho, co všechno ta metoda udělá. Pokud ten popis je dlouhý a obsahuje věci nevyplývající z názvu metody, je to špatně.
Příklad: „zobrazUzivatele(id) : Připojí se k databázi a načte uživatelova data z tabulky a sestaví je do HTML a vypíše HTML do stránky“.
Taková metoda zjevně nedělá jednu činnost, navíc třeba načítání uživatele z databáze je úplně něco jiného, než „zobrazUzivatele“.

Napriklad ja pouzivam class v ktorej generujem casto pouzivane selecty do ktorych sa vypise obsah z DB .
Je vhodne do takejto metody zapisat dalsi kod ktory by mi generoval napr. checkboxy, alebo je vhodne si vytvorit novu metodu a riesit to v nej ?
Kromě toho, že jedna metoda by měla dělat jednu činnost, jak píše Tori, by i jedna konkrétní třída měla být odpovědná za jednu konkrétní oblast.
„Single responsibility principle“ říká: Jedna třída má být odpovědná za jednu věc a zároveň tato odpovědnost má být úplně uzavřená v té třídě.

Nějak z toho popisu nevidím, jak ty dvě věci spolu souvisí. Jak by se jmenovala ta společná třída?
Jestli něco jako Utils nebo RuzneNastaveni, tak je to špatně.
Monkeys
Profil *
Joker:
Jak by se jmenovala ta společná třída?

Vola sa jednoducho inputs.class.php

no a v tejto triede mam metody ktore vracaju obsah casto pouzivanych selectov do stranky.
takze takto:

class Inputs {

private $register;

public function __construct($register)
{
$this->register = $register;    
}

public function getSelectString($data, $getVal)
{
$option = "";
while(list($value, $label) = each($data))
{
if(isset($getVal))
{
($value == $getVal) ? $slected = 'selected="selected"' : $slected = "";
}
else
{
$slected = "";
}
$option .= '<option value="'.$value.'" '.$slected.' >'.$label.'</option>' . "\n";    
}
return $option;
}

// ostatne metody
//...


}//end class    

Ja len dufam ze to takymto sposobom robim spravne :)

M.
Tori
Profil
Monkeys:
Na první pohled mi (kromě chybějícího odsazení) vadí názvy. getSelectString bych přejmenovala na getOptions nebo spíš createOptions; $slected je překlep; sloveso v $getVal je vůbec nelogické - proměnná přeci nemůže nic vracet, spíš $selected nebo $currentValue apod.

Mít v jedné třídě metody, kterými vyrábím různé formulářové prvky, mi přijde snesitelné. Ale kdybyste mohl použít i nějaký šablon.systém, tak bych třídu přejmenovala na FormTemplate Form a nechala ji generovat rovnou celý HTML kód formuláře. Např. něco takového:

class Form
{
    // vlastnosti bych dala radši chráněné než soukromé, kvůli možnosti dědění
    protected $register;
    protected $fields = array(); // jednotlivá formulářová pole v pořadí, jak je přidáte
    protected $method = 'GET';
    protected $template = '';
    protected $xhtml = false;
    
    // konstruktor nastaví výchozí název formulářové šablony (nějaká form.tpl)

    // různé settery na změny výchozí podoby formuláře
    public function setTemplate(string $tplFile) { }
    public function setMethod(string $method) { }
    public function setXhtml(bool $status) { }

    public function getMethod() { } // vrací aktuálně nastavenou metodu
    public function isXhtml() { }

    // metody na přidání jednotlivých typů polí
    public function addSelect(string $name, array $values, string $currentValue = '') {
        $data = array(
            'name' => $name, 
            'type' => 'select',
            'options' => array(),
        );
        // anebo by šlo vyžadovat na vstupu pole ve tvaru: value => label
        while(list($value, $label) = each($values)) {
            $data['options'][] = array(
                'value' => $value,
                'label' => $label,
                'selected' => ($value == $currentValue),
            );
        }
        $this->fields[] = $data;
    }

    public function addRadio(string $name, array $values, string $currentValue = '') { }
    // ... atd další typy
                
    public function render() { } // vykreslí (vypíše) formulář podle šablony
}
Je to jen narychlo nahozené, jednotlivé typy polí by ideálně měly být taky reprezentovány objekty, chybí možnost multipleSelect, ... (a samozřejmě jsem si vzpomněla na Nette\Forms). :)
Sir Tom
Profil
Alphard, Tori:
Na tom není moc co k rozvádění. Jen parametr funkce by neměl rozhodovat o tom, jesli je výsledek vypsán, nebo vrácen.
A navíc se při vypisování mění i návratová hodnota na TRUE. Kdyby aspoň vracela řetězec vždy, a parametr by byl jako "navíc kromě vrácení i vypsat", tak by to bylo lepší (neměnila by se tolik signatura funkce).

Zde jsme si asi nerozuměli. Nechtěl jsem řešit konkrétně fci print_r(), nýbrž chtěl jsem řešit obecné metody ve třídě. Tori napsala, že používat parametry na modifikaci chování metody je špatné. V čem a proč? Je zde nějaké riziko do budoucna? Jak například poznám, že daná metoda už je špatná?
Řekněme, že mám metodu:
public function getColor($notation = "HEX"){
  $color = ... // do proměnné se uloží barva v notaci v uvedené v parametru
  return $color;
}
Moc jsem o té metodě nepřemýšlel a je i možné, že v aplikaci by byla úplně zbytečná, ale někdy vrátí #ff0000, nebo rgb(255, 0, 0), atd. Je to špatná metoda?
Tori
Profil
Sir Tom:
do proměnné se uloží barva v notaci v uvedené v parametru
Tohle mi přijde v pořádku, funkce dělá i vrací jednu věc, parametrem jen určujete formát vrácených dat - podobné jako date() vlastně.
Nenapadá mě teď vhodný špatný příklad. Typický znakem bude, že funkce obsahuje hlavně jeden velký switch nebo if-else a z každé větve vrací jinou hodnotu / dat.typ (viz Joker #7).

edit: Pokud v tom dlouhém switchi jsou jen volání jiných funkcí, je to v pořádku - ta hlavní funkce např. zapouzdřuje nějakou posloupnost kroků nebo poskládání nějaké datové struktury po částech. Kdyby tam ale byl přímo kód, který ty jednotlivé věci provádí, tak to není fajn. Jednotlivé části se budou lépe měnit / optimalizovat jako samostatné fce, než jako jedna větev switche. Ještě citace: „Nejdůležitějším důvodem pro tvorbu nové rutiny (tj. funkce) je snížení míry složitosti programu. Vytvářejte rutiny tak, aby ukrývaly informace, o nichž nebudete chtít na vyšších úrovních programu uvažovat. (McConnell, Steve - Dokonalý kód, s. 180. Computer Press, Brno, 2005)
Alphard
Profil
Sir Tom [#10]:
Zvláště u nepovinných parametrů to znepřehleňuje kód. Představte si, že byste kód důsledně dokumentoval. Pokud nedokážete jednoduše popsat, co metoda vrátí, je to špatně.
Takže by zřejmě bylo ideální

public function getColor() { return [...]; } 
public function getColorHex(array $color) { return ...; }
public function getColorRgb(array $color { return ...; }

Uvedl jsem to na vašem příkladu, ale myslím to spíš principiálně. Kdybych k tomu neměl další důvod, taky bych kvůli takové „drobnosti“ taky nepsal 3 metody.
Protože dalším rozborem bychom se dostali k tomu, že by ještě lepší bylo:

public function getColor() { return new Color(...); }
// ...
$color->getFormatHex();
$color->getFormatRgb();

Napsat to takhle detailně by bylo nepochybně pracné. Kdybyste ale měl k dispozici dobrý framework, který má již třídu Color vhodně implementovánu, bylo by její využití zřejmě jednodušší než váš postup, protože by pravděpodobně již obsahovala některé věci, které jste si jinak musel psát sám.
Je to spíš teorie, život je plný kompromisů. Někdo staví objektový model téměř dokonale, někomu (třeba mně) zůstal dost v krvi procedurální styl (proto se taky tady na diskusi na téma OOP moc nevyjadřuji).
Sir Tom
Profil
Tori, Alphard:
Jo, s tím souhlasím. Otázkou tedy jenom je, kdy už metoda je vhodná k "rozkouskování" do dalších.
Tori
Profil
Sir Tom:
kdy už metoda je vhodná k "rozkouskování" do dalších.
A když píšete normální text, jak poznáte, kdy je vhodné začít další odstavec? To je přeci skoro totéž. :)
Jan Tvrdík
Profil
Sir Tom:
Otázkou tedy jenom je, kdy už metoda je vhodná k "rozkouskování" do dalších.
Jednoduché pravidlo pro začátek – pokud jsi na pochybách, zda metodu rozdělit, tak ji vždy rozděl. Časem najdeš balanc.

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: