Lekce 4 - Upomínač narozenin - Logická vrstva
V minulé lekci, Upomínač narozenin - Návrh formulářů, jsme navrhli kompletně formuláře pro naši aplikaci.
V tomto tutoriálu se budeme zabývat návrhem logické vrstvy, tedy tříd, které obsahují logiku aplikace.
Osoba
V naší aplikaci budou zcela jistě figurovat osoby, vytvořme jim tedy
třídu. Před třídu nezapomeňte dát modifikátor public.
Vlastnosti
Osoba bude mít 2 vlastnosti: jméno a narozeniny. Jmeno bude
string, Narozeniny budou typu DateTime.
Tyto vlastnosti nastavíme pomocí parametrického konstruktoru.
public class Osoba { public string Jmeno { get; set; } public DateTime Narozeniny { get; set; } public Osoba(string jmeno, DateTime narozeniny) { Jmeno = jmeno; Narozeniny = narozeniny; } }
Metody
Kromě konstruktoru bude třída disponovat metodami SpoctiVek()
a ZbyvaDni().
SpoctiVek
Metoda vypočítá a vrátí aktuální věk osoby v celých letech.
Výpočet bohužel není jen o tom odečíst dva datumy, jelikož
TimeSpan neumí zjistit počet let, pouze počet dní. Výpočet
věku tedy provedeme následujícím způsobem:
- Získáme si aktuální datum (bez času) pomocí
DateTime.Today. - Věk spočítáme jako rozdíl roků v aktuálním datu a datu narozenin. Asi je vám jasné, že tento věk není přesný. Pokud jsme se narodili 1.2.1990 a je 1.1.2010, není nám 20 let, ale jen 19. Z toho důvodu provedeme korekci.
- V případě, že je aktuální datum menší (dříve) než datum narození po přidání námi vypočítaných let, nastal výše uvedený případ a my věk o rok snížíme.
- Hotový věk vrátíme.
Kód metody bude následující.
public int SpoctiVek() { DateTime dnes = DateTime.Today; int vek = dnes.Year - Narozeniny.Year; if (dnes < Narozeniny.AddYears(vek)) vek--; return vek; }
ZbyvaDni
Metoda nám vrátí kolik dní zbývá do narozenin osoby. To zjistíme následujícím způsobem:
- Získáme si aktuální datum (bez času).
- Získáme datum dalších narozenin přičtením věku + 1 k datu narození.
- Data odečteme a celkový rozdíl ve dnech vrátíme. Jelikož je rozdíl
typu
double, musíme ho zkonvertovat naint.
public int ZbyvaDni() { DateTime dnes = DateTime.Today; DateTime dalsiNarozeniny = Narozeniny.AddYears(SpoctiVek() + 1); TimeSpan rozdil = dalsiNarozeniny - DateTime.Today; return Convert.ToInt32(rozdil.TotalDays); }
ToString
Jelikož budeme osoby vypisovat, přepíšeme metodu ToString()
tak, aby vracela jméno osoby:
public override string ToString() { return Jmeno; }
Správce osob
Další logickou komponentou aplikace bude správce osob. Třída se bude starat o osoby, bude je umět přidávat, odebírat a jejich seznam ukládat do souboru a opětovně načíst. Konečně bude umět mezi osobami vyhledat tu, která má nejbližší narozeniny.
Přidejte si k projektu tedy třídu SpravceOsob a učiňte ji
veřejnou.
Vlastnosti a atributy
Jedinou veřejnou vlastností třídy je seznam osob. Seznam je typu
BindingList. S touto kolekcí jsme se v kurzu ještě nesetkali.
Jedná se o chytřejší List, který na sobě umí vyvolat
událost změny v případě, že se změní jeho obsah. Díky tomuto mechanismu
se automaticky obnoví všechny prvky na formuláři, které mají nastavený
jako zdroj dat právě tento BindingList. Asi si dokážete
představit, že obnovovat ručně desítky prvků na formuláři v případě
změny může být velice nepřehledné. Jakmile v naší aplikaci přidáme
novou osobu, bude ihned vidět v seznamu osob aniž bychom ho obnovovali,
obnoví se sám. BindingList inicializujeme v konstruktoru.
Pokud bychom chtěli implementovat i editaci osob, musela by třída
Osoba implementovat rozhraní INotifyPropertyChanged.
Jakákoli změna (např. jména) by se poté automaticky projevila ve všech
prvcích všech formulářů, kde osoba figuruje. Tímto se však pro
zjednodušení zabývat nebudeme.
Třída zatím vypadá takto:
public class SpravceOsob { public BindingList<Osoba> Osoby { get; set; } public SpravceOsob() { Osoby = new BindingList<Osoba>(); } }
Metody
Kromě přidávání a odebírání bude třída umět i nalézt osobu s nejbližšími narozeninami. Ukládání a načítání osob do/ze souboru necháme na později.
Pridej()
Metoda přidá novou osobu do BindingListu. Jelikož osobu
přidáváme formulářem, hodí se nám, aby metoda brala v parametrech
vlastnosti osoby a na jejich základě vytvořila novou instanci. Z data
narození uložíme pouze část s datem, tedy bez času.
Před přidáním zkontrolujeme, zda jméno není příliš krátké nebo není zadané datum v budoucnosti. Pokud nějaká z těchto situací nastane, vyhodíme výjimku. Právě výjimky jsou správným způsobem, jak s chybami v objektových aplikacích pracovat.
Výjimky jsou detailněji popsané v sekci Soubory v C# .NET. Pokud jste se s nimi ještě
nesetkali, bude vám stačit vědět, že výjimka se vyvolá pomocí
klíčového slova throw, za kterým následuje instance výjimky.
Výjimek máme několik typů včetně možnosti vytvořit si vlastní. V našem
případě se nám hodí ArgumentException (chyba v argumentu). Do
konstruktoru výjimky zadáváme text chyby. Jakmile je výjimka vyvolána,
metoda již dále nepokračuje. Jak na chybu reagovat si ukážeme až budeme
metodu volat z formuláře.
public void Pridej(string jmeno, DateTime datumNarozeni) { if (jmeno.Length < 3) throw new ArgumentException("Jméno je příliš krátké"); if (datumNarozeni.Date > DateTime.Today) throw new ArgumentException("Datum narození nesmí být v budoucnosti"); Osoba osoba = new Osoba(jmeno, datumNarozeni.Date); Osoby.Add(osoba); }
Odeber
Metoda odebere osobu z BindingListu. Protože vždy budeme
chtít odebírat již hotovou osobu, bere metoda v parametru právě tu.
public void Odeber(Osoba osoba) { Osoby.Remove(osoba); }
NajdiNejblizsi
Metoda najde a vrátí osobu, která má nejbližší narozeniny. K
vyhledání osoby v listu použijeme LINQ
metodu OrderBy(), která osoby uspořádá podle toho, kolik dní
zbývá do jejich narozenin. Výsledek uložíme do kolekce, jejíž typ
neuvedeme a použijeme místo toho klíčové slovo var, jak je v
LINQ zvykem. Následně vrátíme první osobu. Metodu bychom měli volat jen
tehdy, když jsou v listu nějaké osoby. Ačkoli by z kódu mělo být jasné,
co metoda dělá, můžete se samozřejmě podívat na tutoriály v sekci Kolekce a LINQ v C# .NET, kde je technologie
LINQ detailně popsána.
public Osoba NajdiNejblizsi() { var serazeneOsoby = Osoby.OrderBy(o => o.ZbyvaDni()); return serazeneOsoby.First(); }
Pokračovat budeme v příští lekci, Upomínač narozenin - Propojení prezentační a logické vrstvy, kdy aplikaci zprovozníme. Dosavadní zdrojový kód je ke stažení níže.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 1160x (342.7 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

David se informační technologie naučil na