Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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:

  1. Získáme si aktuální datum (bez času) pomocí DateTime.Today.
  2. 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.
  3. 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.
  4. 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:

  1. Získáme si aktuální datum (bez času).
  2. Získáme datum dalších narozenin přičtením věku + 1 k datu narození.
  3. Data odečteme a celkový rozdíl ve dnech vrátíme. Jelikož je rozdíl typu double, musíme ho zkonvertovat na int.
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 Práce se 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 1143x (342.7 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

Předchozí článek
Upomínač narozenin - Návrh formulářů
Všechny články v sekci
Windows Forms - Okenní aplikace v C# .NET
Přeskočit článek
(nedoporučujeme)
Upomínač narozenin - Propojení prezentační a logické vrstvy
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
45 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity