4. díl - Upomínač narozenin v VB.NET - Logická vrstva

Ostatní jazyky Visual Basic .NET Windows Forms Upomínač narozenin v VB.NET - Logická vrstva

V minulém dílu seriálu tutoriálů o tvorbě formulářových aplikací v Visual Basicu jsme navrhli kompletně formuláře pro naši aplikaci. V tomto dí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.

Vlastnosti

Osoba bude mít 2 vlastnosti: jméno a narozeniny. Jméno bude String, Narozeniny budou typu DateTime. Tyto vlastnosti nastavíme pomocí parametrického konstruktoru.

Public Class Osoba
        Public Jmeno As String
        Public Narozeniny As DateTime

        Public Sub New(jmeno As String, narozeniny As DateTime)
                Me.Jmeno = jmeno
                Me.Narozeniny = narozeniny
        End Sub
End Class

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 Function SpocitejVek() As Integer
        Dim dnes = DateTime.Today
        Dim vek = dnes.Year - Me.Narozeniny.Year
        If dnes < Narozeniny.AddYears(vek) Then
                vek -= 1
        End If
        Return vek
End Function
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 Function ZbyvaDni() As Integer
        Dim dnes = DateTime.Today
        Dim dalsiNarozeniny As DateTime = Narozeniny.AddYears(SpocitejVek() + 1)

        Dim rozdil As TimeSpan = dalsiNarozeniny - dnes

        Return Convert.ToInt32(rozdil.TotalDays)
End Function
ToString

Jelikož budeme osoby vypisovat, přepíšeme metodu ToString() tak, aby vracela jméno osoby:

Public Overrides Function ToString() As String
        Return Jmeno
End Function

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.

Vlastnosti a atributy

Jedinou veřejnou vlastností třídy je seznam osob. Seznam je typu BindingList. S touto kolekcí jsme se v seriálu 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 kontrolky 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 kontrolek 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 Osoby. BindingList bude vyžadovat import System.Componen­tModel. Visual studio ho naimportuje za vás, stačí mu to říct přes chytrou značku.

Chytrá značka ve Visual Studiu

Pokud bychom chtěli implementovat i editace osob, musela by třída Osoba implementovat rozhraní INotifyProper­tyChanged. Jakákoli změna (např. jména) by se poté automaticky projevila ve všech kontrolká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 Property Osoby As BindingList(Of Osoba)

        Public Sub New()
                Osoby = New BindingList(Of Osoba)
        End Sub
End Class

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 VB.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 Sub Pridej(jmeno As String, datumNarozeni As DateTime)
        If jmeno.Length < 3 Then
                Throw New ArgumentException("Jméno je příliš krátké")
        End If
        If datumNarozeni.Date > DateTime.Today Then
                Throw New ArgumentException("Datum narození nesmí být v budoucnosti")
        End If

        Dim osoba As New Osoba(jmeno, datumNarozeni)
        Osoby.Add(osoba)
End Sub
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 Sub deber(osoba As Osoba)
        Osoby.Remove(osoba)
End Sub
NajdiNejblizsi

Metoda najde a vrátí osobu, která má nejbližší narozeniny. K vyhledání osoby v listu použijeme LINQ, to osoby uspořádá podle toho, kolik dní zbývá do jejich narozenin. Výsledek uložíme do kolekce, jejíž typ neuvedeme, jak je u LINQu zvykem. Následně vrátíme první osobu.

Public Function NajdiNejblizsi() As Osoba
        Dim serazeneOsoby = From o In Osoby Order By o.ZbyvaDni

        Return serazeneOsoby.First()
End Function

Pokračovat budeme příště, kdy aplikaci zprovozníme. Dosavadní zdrojový kód je ke stažení níže.


 

Stáhnout

Staženo 172x (203.29 kB)
Aplikace je včetně zdrojových kódů v jazyce VB.NET

 

  Aktivity (1)

Článek pro vás napsal Michal Žůrek (misaz)
Avatar
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.

Jak se ti líbí článek?
Celkem (1 hlasů) :
55555


 



 

 

Komentáře
Zobrazit starší komentáře (3)

Avatar
Michal Štěpánek:

Měl jsem na mysli, kdybych to místo do Správce dával rovnou do té třídy Osoby...
V podstatě, když budu dělat program, kde budou např. uživatelé, budovy, střediska, produkty a já nevím co ještě, tak bych měl ke každému vytvořit třídu a k tomu ještě ke každému správce?

Odpovědět 14.9.2014 19:49
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Odpovídá na Michal Štěpánek
Michal Žůrek (misaz):

pokud pracuješ s kolekcí/polem a nějak sním manipuluješ, větinou se dělá správce, takže ano spravceStredisek, spravceBudov, .... Pokud však používáš tu kolekci/pole, že ti stačí tak jak je a bude to konzistentní, tak by to neměl být problém.

Odpovědět  +1 14.9.2014 20:06
Nesnáším {}, proto se jim vyhýbám.
Avatar
Odpovědět 14.9.2014 20:37
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Vetva
Člen
Avatar
Vetva:

serazeneOsoby sú po :
Dim serazeneOsoby = From o In Osoby Order By o.ZbyvaDni
typu OrderedEnumera­ble`2
Ako ich pretypovať späť ?

 
Odpovědět 19.4.2015 14:22
Avatar
Odpovídá na Vetva
Michal Žůrek (misaz):

třeba

Dim serazeneOsoby = (From o In Osoby Order By o.ZbyvaDni).ToList();

nebo

Dim serazeneOsoby = (From o In Osoby Order By o.ZbyvaDni).ToArray();

akorát je to zbytečné, OrderedEnumerable tam vůbec nevadí. Ono se to (na první pohled) chová podobně jako list nebo vzdáleněji jako pole.

Odpovědět  +1 19.4.2015 14:29
Nesnáším {}, proto se jim vyhýbám.
Avatar
Vetva
Člen
Avatar
Odpovídá na Michal Žůrek (misaz)
Vetva:

To bolo rýchle. Viem že tu to nie je nutné.
Vďaka.

 
Odpovědět 19.4.2015 14:35
Avatar
Vetva
Člen
Avatar
Vetva:

Ak by som do projektu pridal picturebox s fotom - je lepšie pridať do vlastnosti osoby adresu obrázka alebo riešiť inak ?

 
Odpovědět 5.8.2015 15:42
Avatar
Odpovídá na Vetva
Ondřej Štorc:

Nejlepší by bylo ukládat do té instance přímo ten obrázek (do třídy Image)

Odpovědět  +1 5.8.2015 15:46
Život je příliš krátký na to, abychom bezpečně odebírali USB z počítače..
Avatar
Vetva
Člen
Avatar
Vetva:

Myslíš ich nasypať do ImageListu ?

 
Odpovědět 5.8.2015 18:02
Avatar
Odpovídá na Vetva
Michal Žůrek (misaz):

to záleží na tom kolik obrázků máš, když jeden, tak ho normálně ulož do Image, a když více, tak záleží zdali chceš použít imagelist nebo popř. něco inteligentnějšího jako generickou kolekci.

Odpovědět 5.8.2015 18:17
Nesnáším {}, proto se jim vyhýbám.
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 10 zpráv z 13. Zobrazit vše