\

Školení UML, OOP, Návrhové vzory, .Net Framework, compact .Net Framework, ASP.NET


 Wednesday, June 27, 2007
Pozvánka na podzimní běh kurzu Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních aplikací

Chci vás pozvat na podzimní termíny kurzu Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních aplikací.

Termíny:

24. - 26. 9. 2007
5. - 7. 11. 2007

Organizační informace ke kurzu

Program kurzu

Zaregistrované ohlasy na školení :

http://blog.renestein.net/ct.ashx?id=10d7acf8-1026-43fe-b1f1-54fccb69105b&url=http%3a%2f%2fwww.jirifabian.net%2fwordpress%2f%3fp%3d157

http://blog.renestein.net/ct.ashx?id=10d7acf8-1026-43fe-b1f1-54fccb69105b&url=http%3a%2f%2fwww.rarous.net%2fclanek%2f143-skoleni-oop-uml-a-navrhovych-vzoru.aspx

 

Omlouvám se za tento přízračně mrtvolný klid na blogu, ale kvůli neočekávaným osobním problémům nemám na blog vůbec čas. Do konce září (alespoň doufám) ale konečně změním kompletně blogovací systém a nasadím slibované wiki + fórum o  OOP a návrhových vzorech.


Wednesday, June 27, 2007 10:38:11 AM (Central Europe Daylight Time, UTC+02:00)  #     
Comments [0]  Kurzy UML a OOP | Návrhové vzory | UML


 Monday, September 11, 2006
Fórum o OOP, UML, návrhových vzorech, MDA, DSL ... - chtěli byste?

Nadpis vyjadřuje v kostce vše. Hraji si právě teď s překladem a nastavením YetAnotherForum a napadlo mě, že bych na doméně forum.renestein.net spustil fórum, kde bychom společně diskutovali o návrhu aplikací, systémovém designu, OOP, UML, Model Driven Architecture, DSL, zuřivě bychom se hádali nad best practices, vášnivě "flamovali" nad podporou OOP v různých programovacích jazycích :) nebo bychom si vyměňovali linky na zajímavé články. Pro každé větší téma by existovalo samostatné fórum.

Vím. že některá česká fóra se OOP a analýzou zabývají, ale kvůli svému neodvolatelně  finálním stavu  "mrtvé" fórum s občasnými "self" přechody, spuštěnými přijetím jedné OT zprávy s nabídkou domácích zásob viagry nějakého momentálně insolventního a celoživotně impotentního spammera, se v nich nic zajímavého neděje.

Takže - máte zájem? :) 


Monday, September 11, 2006 3:55:02 PM (Central Europe Daylight Time, UTC+02:00)  #     
Comments [19]  Návrhové vzory | Ostatní | UML


 Sunday, August 20, 2006
UPDATE 1.9. 2006 - Pozvání na kurz Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních aplikací v termínu 25-27.10.

Update 1.9. 2006  - Kurz je obsazen

Kvůli velkému zájmu o zářijový termín kurzu Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních aplikací se bude stejný kurz konat také v termínu 25-27.10. 2006. Přihlásit se je opět možné zasláním emailu na adresu petra@renestein.net

Přejít na podrobné informace o kurzu včetně přihlášky na kurz


Sunday, August 20, 2006 5:59:53 PM (Central Europe Daylight Time, UTC+02:00)  #     
Comments [0]  Kurzy UML a OOP | Návrhové vzory | UML


 Sunday, April 09, 2006
Bázová třída pro typové kolekce v .NET Frameworku 2.0

V souvislosti s uvedením generiky v .NET Frameworku se v různých článcích dočtete, jak generika usnadní vytváření a použití typových kolekcí. To je sice pravda, ale v článku se kromě zjednodušených příkladů a frikulínských hlášek o dokonalosti .NETu 2.0 z úst (respektiva pera) excitovaných jedinců po právě dokonaném intimním styku se softwarovou emanací božstva Microsoftu :-D málokdy dovíte, jak by taková typová kolekce měla vypadat v běžné aplikaci.

Proč nevyhovuje obyčejné použití generického typu List? (deklarace typové kolekce objednávek ve tvaru List<Order> orderCollection = new List<Order>()).

  • Jednou z dobrých praktik u generik je co nejvíce před uživateli (dalšími vývojáři) skrývat informaci, že pracují s generickým typem. Ač mně syntaxe pro práci s generickými typy připadá intuitivní, nemusí si to myslet všichni, a mnoho vývojářů stále asi raději používá důvěrně známý kód OrderCollection orderCollection = new OrderCollection() místo výše zmíněného kódu List<Order> orderCollection = new List<Order>()).  Tento požadavek by ale List<T> splnil  - typová kolekce může být potomkem List<T>.
  • Ve třídě List nejsou metody Add a Remove virtuální. To znamená, že nemůžete po přidání nebo odebrání položky z/do kolekce vyvolávat vlastní události. A to je problém, protože po přidání/odebrání položek z kolekce můžeme chtít nastavit/zrušit rodiče nebo přepočítát sumární hodnoty za položky v kolekci apod.

Bázová třída pro všechny kolekce, kterou používám, je otevřeným generickým typem a jejím předkem je třída Collection<T> z jmenného prostoru System.Collections.ObjectModel. Třída Collection<T> nabízí virtuální chráněné metody InsertItem a RemoveItem, ve kterých můžete vyvolávat potřebné události. Jestliže používate návrhový vzor Layer SuperType a máte tedy jednu bázovou třídu pro všechny business objekty (BusinessObjectBase), je vhodné, aby bázová třída pro kolekce kladla na generický typ T omezení, že musí být potomkem třídy BusinessObjectBase. Omezení slouží k tomu, abyste ve svých kolekcích mohli intuitivně používat všechny atributy a metody deklarované na úrovni společného předka BusinessObjectBase.

Kód kolekce:

   public class BusinessCollectionBase<T> : Collection<T> 
                                        where T : BusinessObjectBase
    {
        #region Events
        public event EventHandler<CollectionChangeEventArgs> ItemAdded;
        public event EventHandler<CollectionChangeEventArgs> ItemRemoved;
        #endregion Events
        #region Protected methods
        /// <summary>
        /// Přidání položky do kolekce
        /// </summary>
        /// <param name="index">Index položky</param>
        /// <param name="item">Vkládaná položka</param>
        protected override void InsertItem(int index, T item)
        {
            base.InsertItem(index, item);
            OnItemAdded(new CollectionChangeEventArgs(item));
        }

        /// <summary>
        /// Přidání položky do kolekce
        /// </summary>
        /// <param name="index">Index položky</param>        
        protected override void RemoveItem(int index)
        {
            T item = this[index];
            base.RemoveItem(index);
            OnItemRemoved(new CollectionChangeEventArgs(item));
        }

        /// <summary>
        /// Metoda odpovědná za vyvolání události ItemRemoved
        /// </summary>
        /// <param name="e">Argumenty události</param>
        protected void OnItemRemoved(CollectionChangeEventArgs e)
        {
            if (ItemRemoved != null)
            {
                ItemRemoved(this, e);
            }
            
        }
        
        /// <summary>
        /// Metoda odpovědná za vyvolání události ItemAdded
        /// </summary>
        /// <param name="e"></param>
        protected void OnItemAdded(CollectionChangeEventArgs e)
        {
            if (ItemAdded != null)
            {
                ItemAdded(this, e);
            }
         
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual T FindById(Guid id)
        {
            List<T> mylist = (List<T>) Items;
            T objectMeetsCriteria = null;
            objectMeetsCriteria = mylist.Find(delegate(T iterObject)
                                  {
                                      if (iterObject.Id == id)
                                      {
                                          return true;
                                      }
                                      else
                                      {
                                          return false;
                                      }
                                                                
                                  });

            return objectMeetsCriteria;
        }

        /// <summary>
        /// Nalezení všech objektů splňujících zadanou podmínku
        /// </summary>
        /// <param name="criteria">Podmínka výběru</param>
        /// <returns>List s objekty, které splňují zadanou podmínku</returns
        public virtual List<T> Find(Predicate<T> criteria)
        {
            List<T> mylist = (List<T>) Items;           
            return (mylist.FindAll(criteria));
            
        }
        
        /// <summary>
        /// Spuštění akce nad všemi elementy v kolekci
        /// </summary>
        /// <param name="action">Akce, která se má provést</param>
        public virtual void ForEach(Action<T> action)
        {
            List<T> mylist = (List<T>)Items;
            mylist.ForEach(action);            
        }
    
        #endregion Protected methods
    }
}

Jak vidíme:

  1. Třída BusinessCollectionBase je potomkem třídy Collection<T> a vyžaduje, aby typ T byl vždy potomkem BusinessObjectBase. Motivace pro toto rozhodnutí jspu popsány výše.
  2. Nadeklarovali jsme dvě události ItemAdded a ItemRemoved, které jsou vyvolávany v přepsaných metodách InsertItem (ItemAdded) a RemoveItem (ItemRemoved). Pokud bych měl zájem, mohu jednoduše přidat i události vyvolávané před přidáním/odebráním položky z kolekce.
  3. Do rozhraní BusinessCollectionBase jsem také přidal několik zajímavých metod.
    1. Metoda FindById nalezne podle předaného Id (unikátní identifikátor instance) objekt v kolekci. V této metodě opět používáme nové konstrukce z .Net Frameworku 2.0. Implementační objekt kolekce (starý známý List<T> ) vystavuje metodu Find, která očekává generického delegáta Predicate z jmenného prostoru System.
      public delegate bool Predicate( T obj);
      Delegát Predicate je "ukazatelem" na metodu, která očekává jeden generický argument T a vrací true nebo false. Delegát Predicate tedy zastupuje metodu s podmínkou, která je pro předaný argument obj pravdivá nebo nepravdivá. My pro vytvoření podmínky použijeme anonymní metodu, která vrátí true pouze tehdy, když se Id objektu v kolekci shoduje s předaným Id. Atribut Id u generického typu T kolekce můžeme používat právě proto, že jsme zavedli pro typ T omezení (musíš být potomkem  BusinessObjectBase) a atribut Id je deklarován ve třídě BusinessOBjectBase.
    2. Pro pokročilejší operace s elementy kolekce jsme z objektu List<T> zveřejnili metody FindAll A ForEach. Metoda FindAll podle předané podmínky (delegát Predicate) nalezne a vrátí všechny objekty, které jí vyhovují. Metoda ForEach spustí pro všchny elementy v kolekci "akci - činnost" implementovanou v metodě, na níž "ukazuje" další užitečný delegát Action<T>.

      public delegate void Action<T> ( T obj);

      Když tedy budete chtít všechny objekty v kolekci zrušit, místo psaní cyklu foreach napíšete kód podobný tomuto:

      myCol.ForEach(delegate(OrderItem item)
      
                  {
      
                       item.Discard();
      
                  });
      

Vytváření vlastních typových kolekcí je jednoduché:

    /// <summary>
    /// Kolekce objektů OrderItem
    /// </summary>
    public class OrderItemCollection : BusinessCollectionBase<OrderItem>
    {

    }
 

Pro úplnost sem dávám triviální kód třídy pro argumenty události CollectionChanged.

    /// <summary>
    /// Objekt v kolekci
    /// </summary>
    public class CollectionChangeEventArgs : EventArgs
    {
        #region Private variables
        private BusinessObjectBase m_collectionObject;
        #endregion Private variables
        
        #region Constructors
        /// <summary>
        /// Konstruktor
        /// </summary>
        /// <param name="collectionObjekt">Objekt v kolekci, kterého se událost týká</param>
        public CollectionChangeEventArgs(BusinessObjectBase collectionObject)
        {
            BasicValidations.AssertNotNull(collectionObject, "collectionObject");
            m_collectionObject = collectionObject;
        }

        /// <summary>
        /// Objekt v kolekci, kterého se událost týká
        /// </summary>
        public BusinessObjectBase CollectionObject
        {
            get
            {
                return m_collectionObject;
            }
        }
        #endregion Constructors
    }
Související články:

Bázová třída pro business objekty - návrhový vzor Layer Supertype
Cachování řádků z databáze pro business objekty - třída DataCacheHelper
Ukázka použití třídy BusinessObjectBase


Sunday, April 09, 2006 3:34:33 PM (Central Europe Daylight Time, UTC+02:00)  #     
Comments [7]  .NET Framework | Compact .Net Framework | Návrhové vzory


 Sunday, March 05, 2006
Termíny kurzů o OOP a UML, partnerství s EIITE, InHouse školení

UPDATE:

Podrobné a aktuální informace o dalších termínech školení a nabídce dalších služeb naleznete nyní zde.


 

Jak jsem již naznačil v předchozím spotu, uzavřel jsem "strategické partnerství" s novým školícím střediskem - se společností EIITE. Mé kurzy budou pořádány pod hlavičkou Skilldrive.

Všechny kurzy se budou konat v Praze.

Přesná adresa:

EIITE Praha
Karlovo nám. 17
120 00 Praha 2

 

Termíny kurzů:

  • Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních aplikací - 3-5.5 2006 (každý den od 9:00 do 16:00). Program a další informace o kurzu naleznete v předchozím spotu. Přihlášky na kurz je možné stále posílat na adresu petra@renestein.net.
    Kurz je obsazen: Pokud máte stále  zájem o kurz, napište nám prosím opět na adresu petra@renestein.net a my Vás budeme informovat ihned po vyhlášení  dalšího termínu školení. Je také možné stále objednávat InHouse školení (viz níže).
  • Kurz UML pořádaný a administrativně zajišťovaný společností EIITE - 28-29.8. 2006. Přihlášení na kurz.

InHouse školení

Pokud máte zájem o inhouse školení zaměřené na OOP, návrhové vzory, UML, .NET Framework, Compact .Net Framework nebo chcete vytvořit kompletní systémový design aplikace včetně naprogramování klíčových částí, napiště prosím svůj požadavek také na adresu petra@renestein.net nebo nás kontaktujte na telefonním čísle +420 603 266 732. Omezení pro inhouse školení, o kterých jsem zde psal dříve, již neplatí!


Sunday, March 05, 2006 12:36:23 PM (Central Europe Standard Time, UTC+01:00)  #     
Comments [0]  Kurzy UML a OOP | Návrhové vzory | UML


 Sunday, February 26, 2006
Několik informací ke kurzům UML a OOP

Takže předběžně ke kurzům UML a OOP, protože se mi nechce psát stále stejné věci každému zvlášť do mailu. V souvislosti se změnou zaměstnání se mění i některé věci ke kurzům.

  1. Kurzy OOP a UML již nebudou pořádány ve školícím středisku DIGI TRADE, ale ve velmi pěkných prostorách jiné společnosti, s níž jsem uzavřel "strategické partnerství" a jejíž jméno oznámím příští týden.
  2. První termín (pravděpodobně konec dubna/začátek května) patří kurzu Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních aplikací., na kterém již mnozí z vás byli. Pro připomenutí níže vkládám program kurzu. Pokud máte již nyní zájem předběžně si zarezervovat místo na kurzu, pošlete prosím email na adresu petra@renestein.net. Cena kurzu je 13 000 Kč.
  3. Dále cca za měsíc zveřejním podrobný program a termín dalšího mého školení s pracovním podtitulem "Design aplikací a návrhové vzory prakticky  - od chaosu k řádu".
  4. S novým školícím střediskem budeme také pořádat "jednodušší" (přesněji řečeno jinak zaměřený a více na základní znalosti orientovaný) kurz, uvádějící posluchače prakticky do světa UML (2.0). Podrobnosti a termín zveřejním do 14 dnů.
  5. Fungovat to bude takto - první dva kurzy je po administrativní stránce zcela na mě, kurz o UML bude po admistrativní stránce plně zajišťovat nové školící středisko. I program kurzu o UML jsem samozřejmě připravil i já, nikdy bych nemohl školit nějaké "předžvýkané" řečičky někoho jiného. Uvádím to zde jen proto, aby vás nemátlo, když se u některých kurzů objeví informace, že máte přihlášky posílat mně (respektive mé ženě) a u jiných budete přihlášky směřovat rovnou na nové školící středisko. Kurzy se ale budou vždy konat na stejném místě.
  6. Omlouvám se těm, kdo absolvovali první kurz a čekají na již poměrně dlouho slibované uvolnění studijních materiálů. Prozatím jsem nenašel čas (respektive vždy jsem našel zajímavější práci ;) , než je "vyčištění" materiálů k veřejnému použití) a také se mi nechce kvůli špatným zkušenostem uvolňovat materiály před konáním dalších kurzů, protože jsem se už v reálu setkal s tím, jak materiály neurčené široké veřejnosti začnou po internetu rychle kolovat, po čemž opravdu nijak netoužím. :(

1. den

  1. Přivítání účastníků kurzu.
  2. Úvodní informace o zaměření a organizaci kurzu.
  3. Základní pojmy OOP a UML..
  4. Mýty o OOP a UML.
  5. Vysvětlení rozdílů mezi business analýzou, systémovým designem a implementací aplikace na konkrétní platformě.
    1. Světlo v temnotách – Model Driven Architecture (MDA)
  6. Základní architektura a rozvrstvení aplikace.
  7. Statický pohled na systém – vytváříme základní diagram tříd a ověřujeme, že jsou v něm zaneseny všechny informace, jež jsou nám známy z případů užití.
    1. Zvolení složitosti diagramu tříd. Potřebujeme vždy flexibilní doménový model?
    2. Zapouzdření objektů, polymorfismus, návrh metod.

                                                               i.      Důležitost principů kovariance a kontravariance.

                                                             ii.      Různé typy soudržnosti metod.

                                                            iii.      Rozhodnutí o typu viditelnosti u každého člena třídy.

                                                           iv.      Jaké konstruktory by měl nabízet každý objekt z problémové domény? Jak určit vlastnosti pouze pro čtení.

                                                             v.      Ověření bezpečného chování třídy vůči potenciálním klientům.

    1. Precizní definice vztahů mezi třídami. Asociace, kompozice, agregace, závislost, realizace, generalizace.
    2. Vysvětlení rozdílů mezi abstraktní třídou a rozhraním (interface).

                                                               i.      Vztah mezi typem a podtypem.

                                                             ii.      Rozpoznání primárního účelu (hlavního smyslu) třídy i jejich sekundárních odpovědností vynucených vztahy s objekty z různých vrstev.

  1. Praktický příklad - ukázka implementace vzorových vztahů mezi objekty, perzistence objektů z problémové domény a zobrazování dat.  (jazyk C#)
    1. Separace kódu pro ukládání a obnovení objektů z perzistentního úložiště v samostatné vrstvě.
    2. Jak zajistíme, že v paměti počítače existuje nanejvýš jedna instance objektu se stejnou identitou.
    3. Ukázky různých způsobů mapování agregace, kompozice, generalizace a asociace do databáze.
    4. Zajištění existence maximálně jedné instance objektu v systému.
    5. Efektivní ukládání a nahrávání kolekcí.
    6. Jak se slučuje objektový přístup a přímé použití DataSetu (recordsetu) v uživatelském rozhraní?
  2. Odpovědi na dotazy frekventantů kurzu.

2. den

  1. Vysvětlení pojmu návrhový vzor.
  2. Kdy byste měli používat návrhové vzory?
  3. Základní vzory (GoF vzory)
    1. Vzory pro řízení vzniku objektů.
    2. Strukturální vzory.
    3. Vzory pro chování objektů.
  4. Začlenění návrhového vzoru do designu aplikace. Kreativní aplikace vzorů.
  5. Kompozice vzorů do vyšších sémantických celků.
  6. Příklady odvozených návrhových vzorů často používaných při designu informačního systému.
  7. Kdy byste neměli používat návrhové vzory?
  8. Příklad - ukázky implementace složitějších vzorů. (jazyk C#).
  9. Odpovědi na dotazy frekventantů kurzu.

3. den

  1. Typické problémy při modelování informačního systému a jejich řešení.
  2. Modelování  složitých organizačních struktur.
  3. Výhody vytváření fasád (Facade) pro aplikace s více než jedním typem uživatelského rozhraní (lehký klient, těžký klient).
  4. Evidence kompletní historie objektu.
  5. Aplikační role a práva uživatelů.
  6. Vytvoření flexibilního systému, jehož chování je změněno bez rekompilace aplikace.
  7. Příklad – ukázky řešení problémů při modelování informačního systému. (jazyk C#).
  8. Odpovědi na dotazy frekventantů kurzu.
  9. Ukončení kurzu.

Sunday, February 26, 2006 8:27:49 PM (Central Europe Standard Time, UTC+01:00)  #     
Comments [0]  Kurzy UML a OOP | Návrhové vzory | UML


 Sunday, February 05, 2006
Ukázka použití třídy BusinessObjectBase

Máme-li napsanou třídu BusinessObjectBase, která hraje roli společného předka všech objektů v business vrstvě všech našich aplikací, je čas ukázat, jak vypadají typičtí potomci.



Předchozí spoty

Bázová třída pro business objekty - návrhový vzor Layer Supertype
Cachování řádků z databáze pro business objekty - třída DataCacheHelper

Zobrazit kód

Třída Order reprezentuje v našem systému objednávku. U objednávky nás zajímá, jakému patří zákazníkovi (vlastnost Customer), rozhodli jsme se, že budeme vyžadovat u každé instance objednávky popisek (vlastnost Description) a samořejmě samotná objednávka je složena z položek objednávky (kolekce Items). Položkou objednávky budeme rozumět třídu, v níž je uloženo, jaké zboží a kolik kusů si zákazník objednal a celková cena položky (kusová cena objednaného zboží * počet). Celková cena objednávky je sumou cen jednotlivých položek. Pro jednoduchost vidíte v kódu zatím jen třídu Objednávka.

  1. Třída Objednávka má dva konstruktory. Prvni konstruktor, přijímající popisek objednávky a zákazníka, vyvolává bezparamerický konstruktor třídy BusinessObjectBase. Jak jsem psal v předchozím spotu, bezparametrický konstruktor slouží k sestrojení objektů bez obrazu v databázi. Chcete-li založit novou objednávku, stačí když si uložíte odkazy na objekty předané v konstruktoru a zbytek práce delegujete na BusinessObjectBase, která nastaví všechny potřebné příznaky nutné pro práci s objektem bez perzistence. Druhý konstruktor přijímá Id (unikátní identifikátor) objednávky, která je uložena v databázi. Jeho tělo je prázdné, veškerou činnost provádí BusinessObjectBase - nastavení příznaků a uložení Id pro pozdější nahrání objektu z databáze. Objekt je po vykonání konstruktoru "prázdnou schránkou", duchem (GHOST), který načte svá data z databáze teprve tehdy, když použijeme některou metodu nebo vlastnost pracující s instančními a perzistovanými proměnnými. Z hlediska uživatele naší třídy (myšleno programátora)  je ale vše ve starých kolejích - rozhraní objektu bude reagovat tak, jak očekává,  a existenci pozdní incializace objektu (Lazy Load) může ignorovat. Poslední větu si přečtěte ještě jednou a tiše s k ní přidejte pravidlo: Nikdy nesmím nutit uživatele svých tříd volat nějaké speciální "Init" metody předtím, než začnou s třídou pracovat. Jedinou legální "Init" metodou je konstruktor.
  2.  Jak k pozdní incializaci a tedy nahrání dat objektu dojde? Vlastnosti, jejichž hodnoty jsou uložené v databázi (Id zákazníka jako klíč v tabulce Objednávek a popisek (Description) objednávky) mají na prvním řádku svých get/set přístupových metod volání metody TriggerLoad. Jak víme, jde o volání metody z BusinessObjectBase, která sama rozhoduje, zda již byla data objektu nahrána z databáze. Pokud data nebyla nahrána, třída BusinessObjectBase řídí scénář nahrávání objektu v metodě Load. Jestliže jsou data pro objednávku v třídě DataCacheHelper, je volána metoda DoInternalLoad(DataRow row), která načte data objednávky z předaného řádku. Když v třídě DataCacheHelper data pro aktuální instanci nemáme, BusinessObjectBase volá variantu metody DoInternalLoad bez argumentů. Metoda DoInternalLoad vyzvedne řádek z databáze s využitím databázové komponenty (což je Singleton nebo Thread specific storage - jednoduše třída zapoudřující