Diskuze: Správný návrh třídy

C# .NET .NET (C# a Visual Basic) Správný návrh třídy American English version English version

Aktivity (3)
Avatar
Luboš Hnědý:15. srpna 15:08

Zdravím mám jen dotaz jak správně pracovat v kódu. Řekněme, že mám třídu Connector ve které chci mít pouze přístupk sql připojení. V poslední době mi bylo řečeno, že dnes es spíše používá skládání tzn. použiju privátní objekt SqlConnection a doprogramuji si metody co potřebuju. Druhá možnost udělat vlastnost jako public a přistupovat přes ní k metodám. A poslední možnost zdědit třídu sqlconnection. Nevím co přesně je nejlepší a rád bych své třídy navrhl správně. Díky moc za každou radu. :)

Zkusil jsem: ..

Chci docílit: Efektivity.

 
Odpovědět 15. srpna 15:08
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:16. srpna 9:09

Ja treba moc dotazu nerozumim. Muzes treba pridat ukazku kodu ke kazde variante?
V php bych to resil tak, ze mam tridu, ktera resi pripojeni k db a prijima odesila dotazy. A pak mam druhou tridu, ktera je napojena na tuhle db tridu a v ni mam jednotlive dotazy. Takze db tridu pouzivam jenom 1x.
Pseudo-kod nejak takto:

class classDb
function __construct() {..}
function connect () {...}
function disconnect () {...}
function query () {... return $dataToArray;}
function error () {...}
---
class classQueries()
var $db, $queries;
function __construct($db) {
    $this->db = $db;
    $this->db->connect();...
    $this->queries = array();
    $this->queries['rozumnynazev'] = 'SELECT ... FROM tab';
    }
function query($name) {return this->db->query($this->queries[$name]);}
---
$db = new classDb;
$queries = new classQueries($db);
$data = $queries->query('rozumnynazev');

Vyhoda tehle konstrukce je, ze ted treba se hromadne meni mysql na pdo. Tady si jen prepises tridu db, aby davala stejne vysledky. Opravis sql dotazy na jednom miste, pokud bude treba. A vse bude fungovat jako driv.
Take muzes chtit udelat neco jako web-services:

adresa.cz/ws?query=rozumnynazev&format=xml

Tady pak si ale musis pohlidat opravneni uzivatele.
A kdyz jsme u opravneni, tak je dobre u pristupu k db nastavit pro kazdy druh uzivatele i specialniho uzivatele pro db. Cili, kdyz se nekdo naloguje do systemu jako user, tak i k db ma pristup jako user a userovi nedas pravo menit tabulku users v db. Takze hacker si nemuze zmenit sve opravneni, protoze ho sql nepusti k editaci tabulky.
(coz na free hostingu moc nejde delat, tam mas jedineho usera v db, ktery muze vsechno jako admin :) )

Editováno 16. srpna 9:11
 
Nahoru Odpovědět 16. srpna 9:09
Avatar
Odpovídá na Peter Mlich
Luboš Hnědý:16. srpna 13:38

Děkuji za odpověď, ale příklad v PHP opravdu nechci...
Mám na mysli jak třídu navrhnout a i jiné třídy co budu dělat.

1. Pouze vytvořit objekt a přes ten se dostávat k metodám a vlastnostem

public class Ukazka {
        public SqlConnection con { get; set; }

        public Ukazka() {
                con = new SqlConnection(connetionString);
        }
}

2. Doprogramovat si metody (skládání)

public class Ukazka {
        public SqlConnection con { get; set; }

        public Ukazka() {
                con = new SqlConnection(connetionString);
        }

        public void Open() {
                con.Open();
        }
}

3. Dědičnost

public class Ukazka : SqlConnection {
        public Ukazka() : this(connetionString) {
        }
}

Použití:

1. Connector.Con.Open();
2. Connector.Open();
3. Connector.Open();

Jde mi prostě jenom o to co je lepší použít, jak tady tak i například u jiných tříd díky moc. :)

 
Nahoru Odpovědět 16. srpna 13:38
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:16. srpna 13:55

Poradi jini :)
Ja bych pouzil vlastni tridu, ktera se na sql odvolava. Viz, jak jsem psal. Z duvodu, ze pak staci upravit moji tridu a uz treba misto sql ziskava data z csv souboru nebo oracle sql, ldap tree a pod.
Pokud das ten objekt connector dovnitr tridy, pak bys jej mel volat jen a pouze uvnitr a nikoliv pres Connector.Con­.Open(). Cili: 1 je spatne, 2 je spravne, 3 nemuzu posoudit (diky neznalosti, co to presne dela). 3, podle mne klonuje tridu pod jiny nazev. To asi v pripade connection postrada smysl. Leda bys k tomu chtel pripojit jeste dalsi vlastni funkce.

Editováno 16. srpna 13:56
 
Nahoru Odpovědět 16. srpna 13:55
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:16. srpna 14:02

1 je pouzitelna na strukturovane pole pro ukladani dat. Nejsem si jisty, zda jsem to pouzil i jinak.
Misto 3 je lepsi 2. Ty vlastne klonujes celou tridu. To je ok. Ale, kdyz z venci pouzijes funkci te tridy, tak jsi zavisly na shode nazvu. Zitra nastane update, rozhodnou se prejmenovat funkci open na openConnection a ty v celem svem programu budes muset prepisovat open na openConnection. Nebo se rozhodnes pouzit oracle a to pracuje s db jinak, uprednostnuje transakce. Tam mas openConnection a openTransaction (kdo vi, jak to pojmenovava c#), ale urcite oboje neni open a open.

 
Nahoru Odpovědět 16. srpna 14:02
Avatar
vosa53
Člen
Avatar
vosa53:16. srpna 20:13

Upřesni co chceš udělat. K čemu je ta třída Connector a hlavně co má dělat navíc než SqlConnection?

 
Nahoru Odpovědět 16. srpna 20:13
Avatar
Odpovídá na vosa53
Luboš Hnědý:17. srpna 6:25

Navíc nic dělat nemá. Jediné co je, že v ní bude natvrdo zadaný connection string. Myslím si, že vysvětlení od Petra je celkem v pohodě. Že nejlepší bude to skládání. A ani mi ted nejde o tu sql třídu jde mi o to jak obecně ty třídy nejlíp navrhovat. Díky

 
Nahoru Odpovědět 17. srpna 6:25
Avatar
vosa53
Člen
Avatar
Odpovídá na Luboš Hnědý
vosa53:17. srpna 12:27

Ten connectionstring se většinou dává do nějakýho configu ven z kódu aplikace. Není tak úplně dobrý nápad dávat ho přímo do kódu. Takže tato třída nemá podle mě smysl. :)
Jinak obecně k těm třem řešením

  • veřejné by mělo být jen to nejnutnější co zároveň není vnitřní stav objektu. Jde o to aby se změnou nějaké vlastnosti zvenčí objekt teď nebo potenciálně v budoucnu nerozbil. Např. nikdy veřejně nevystavujte List<T>, takhle nad ním nemáte žádnou kontrolu, co když někdy v budoucnu budete potřebovat třeba notifikaci o přidání prvku? Lepší je veřejně použít IEnumerable<T>, IReadOnlyCollec­tion<T> nebo ICollection<T> s tím že interně to bude ten list. Dále všechny veřejné data by měly být "properties" a ne "fields", protože změna z property na field je breaking change. Zase kvůli notifikacím nebo různé api počítají s veřejnými properties (WPF bindingy, serializace, ...).
  • závislosti tříd by měly být předávány z vnějšku dovnitř, třída by své zavislosti(třídy se kterými potřebuje pracovat) měla dostat explicitně zvenčí jako parametr konstruktoru/vlas­tnosti/metody místo toho, aby si je sama vytáhla z nějakého singletonu nebo statické třídy. Například když třída potřebuje logovat svou aktivitu někam tak nepoužije přímo třídu System.Console ale nechá si (například v parametru konstruktoru) poslat třídu implementující ILogger s metodou Log(string, ...), což v implementaci může být třída logující do konzole, nebo naopak do souboru nebo někam do sítě. Výhodou je mnohem větší flexibilita, modulárnost, testovatelnost, a i přehlednost o tom co se vlastně děje. Často je kvůli flexibilitě lepší pracovat s obecným rozhraním než konkrétní implementací.
  • Dědičnost se používá převážně jen když s ní autor základní třídy počítá. Odvozené třídy by funkčnost měli jen přidávat nikoli odebírat. Prostě všude kde lze použít předek by měl bez problémů fungovat i potomek. Používá se ve vztahu potomek JE rodič. Tomu použití skládání místo dědičnosti se říká composition over inheritence. Dědičnost je někdy velice těžkopádná například představte si hru kde máme herní objekty, třída HerniObjekt, pak chceme objekty které budou mít fyziku třída FyzikalniObjekt : HerniObjekt, pak chceme poskoditelne objekty které budou mít svůj život, metodu poškodit(int), ... jenže ne každý poškoditelný objekt musí mít nutně fyziku nějaký ano, ale ne každý a to je ten problém kde dědičnost není vhodná a lepší je kompozice tříd s jeho vlastnostmi (poškoditelnost, fyzika, vykreslitelnost, ..) do konkrétního herního objektu a použití rohraní.
Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
 
Nahoru Odpovědět  +2 17. srpna 12:27
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 9 zpráv z 9.