NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!
NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.

Diskuze: Faktura - OOP

V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
H*falk*W
Člen
Avatar
H*falk*W:10.5.2014 22:24

Ahoj,

pokouším se (stále) učit OOP, je to pro mě těžké - jedině Vy mi můžete poradit, jestli to dělám správně, nebo špatně, zkrátka dostat na správnou stranu.

Zkouším vytvořit generátor faktury a abych nezačal hned blbě a celé to nepředělával, chci se zeptat, zda-li ten začátek je takto vhodný.

Settery metody nejsou zatím hotově, mě jde o ten návrh (final, astract nebo kde (hlavně jak) použít rozhraní apod).

http://www.itnetwork.cz/dev-lighter/380

Script bude samozřejmě dostupný všem :)

Díky moc

 
Odpovědět
10.5.2014 22:24
Avatar
raito
Člen
Avatar
Odpovídá na H*falk*W
raito:11.5.2014 12:06

OOP není těžký, to ti jen přijde, než si to řádně ohmatáš ;) Pokud to vezmu kolem a kolem, nemáš to špatně, určitě jsou způsoby, jak to dál a dál vylepšit, prvním z nich je třeba to, že určitě bych nepoužil takovou obrovskou definici několika tříd v jednom souboru. Pokud neznáš, tak doporučuju googlit po PHP Autoloaderu, kde se potom držíš zásady 1 třída = 1 soubor. Autloader si pak soubory projde, nacachuje si kde je jaká třída a pak podle toho, kdy jsou v program využity je teprva volá (lazy loading).

První, co mě trochu zarazilo je toto:

public function __construct() {
        $this->mena = "CZK";
        $this->zaokrouhleni = true;
        $this->zaokrouhleni_typ = 1;
        $this->zaokrouhleni_zpusob = 1;
        $this->jmeno_souboru = "faktura";
        $this->dph_sazby = (object) Array("0" => "Nulová sazba", "15" => "Snížená sazba", "21" => "Základní daň");
        $this->dph_shrnuti = false;
        $this->dph_platce = false;
    }

já osobně bych constructor nenechal setovat defaulty. Tak jak to máš teď, to nemá ani žádný význam, ten kdo bude vytvářet třídu Nastaveni (kde se mu tento construct spustí) stejně nemůže žádným parametrem ovlivnit, co se v constructu stane. Trochu smysl by to dávalo, kdyby jsi plánoval to pozměnit takto:

public function __construct(string $mena = "CZK") {
        $this->mena = $mena;
        ...
    }

tedy případ, kdy si v místě vytváření instance třídy Nastaveni můžeme ovlivnit její nastavení. Jinak bych použil jednoduše toto:

final class Nastaveni {
    // Nastaveni
    /** @var boolean $zaokrouhleni */
    private $zaokrouhleni = true;

    /** @var integer $zaokhrouhleni_typ */
    private $zaokrouhleni_typ = 1;

    /** @var integer $zaokrouhleni_zpusob */
    private $zaokrouhleni_zpusob = 1;

    /** @var string $mena */
    private $mena = "CZK";

    /** @var string $jmeno_souboru */
    private $jmeno_souboru = "faktura";
    ...

A je to. Víš proč je třeba tohle lepší, než tvoje aktuální / případné? Jednoduše, zkusim to ukázat na příkladu:

Teď máš pouze obyčejné settery, které prostě vezmou parametr a narvou ho do vlastnosti. To je sice fajn ale velmi brzo zjistíš, že by bylo fajn rovnou setter použít kupříkladu k validaci. Trochu hloupě ale pro účel tedy jednoduše ho upravím takto:

public function setZaokhrouhleni($zaokrouhleni) {
        if(is_bool($zaokrouhleni){
            $this->zaokrouhleni = $zaokrouhleni;
            return $this;
        }

        throw new Exception('Parametr musi byt datoveho typu boolean!');

    }

(nebudu teď řešit, že tohle si automaticky může ošefovat PHP tím, že bych napsal public function setZaokhrouhle­ni(boolean $zaokrouhleni).. prostě jen nějaká validace na ukázku)

Teď když máš tedy v setteru nějakou validaci nebo zpracování vstupních dat do vlastnosti, tak dá přeci rozum, že jediný správný způsob, jak zapisovat do vlastnosti je přes setter a v žádném případě jinak. Tedy ani přes konstruktor, protože by ti pak mohlo nastat to, že když necháš uživatele nastavovat skrze konsturktor, tak si můžeš maximálně tak ohlídat datový typ, nikoliv však už třeba správnou délku nebo provést potřebné "zparsování". Mohl bys namítat, že přeci můžeš udělat potom tedy toto:

public function __construct(boolean $zaokrouhleni) {
        $this->setZaokrouhleni($zaokrouhleni);
        ...
    }

ale představ si ten "šok" pro někoho, kdo k tomu kódu přijde jako další, nebo sám sebe za dva roky :) Ty si instancuješ Fakturu, ta si instancuje nastavení... protože Faktura je obslužná pro Nastavení, tak budu sema pro její konstruktor vyžadovat nějaké proměnné. Ty jí je tedy při vytváření předáš a hle... když si hned potom zavoláš getterem obsah vlastnosti, kterou si o řádek vejš nastavil, tak je tam něco úplně jinýho, protože constructor s tím něco provedl! Následuje lození hlouběji a hlouběji do kódu a zjišťování, co se vlastně stalo... Pokud však použiješ způsob, co jsem popsal jako nejlepší, bude instancování probíhat takto:

$test = new Faktura;
$test->Nastaveni->setZaokrouhleni(false); //Při instancování se samo defaultně nastavilo true

P.S: Nevím, jak moc se vyznáš ale pro případ, že jsi si všiml anotací jako /** @var string $mena */ a nevíš o co jde: Doporučuju si něco málo opět nastudovat a začít to používat (php annotations) i pro metody a třídy... pokud tě PHP baví a hodláš v tom jít dál a dál, tak je to jenom další zvyk, co ti do budoucna ušetří práci s tvými dalšími projekty a učením se dalších nových věcí.

Nahoru Odpovědět
11.5.2014 12:06
Asi sem usnul. Co se dělo posledních... 5 let?
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.