poniedziałek, 8 września 2008

Active Record - Aktywny Rekord

Dziś weźmiemy na warsztat - Active Record, który jest stosunkowo bardzo prostym wzorcem. Chodzi w nim o to, że tworzymy obiekt złożony z danych zawierający zachowanie (metody [w tym biznesowe]).

Przypuśćmy, że mamy do napisania obiekt Active Record - Owoc, który ma zawierać -metody CRUD,
-i jakieś 2 metody biznesowe

Mapujemy sobie tabelę Owoc:



   1:  class Owoc

   2:  {

   3:    // "Dane" owocu

   4:    public int Id { get; set; }

   5:    public int Nazwa { get; set; }

   6:    public decimal Cena { get; set; }

   7:    public decimal Rabat { get; set; }

   8:  }



Dopiszmy metody CRUD na samym początku:



   1:  class Owoc

   2:  {

   3:    public Owoc() {}

   4:    

   5:    public Owoc(int id)

   6:    {

   7:      Owoc o = Find(id);

   8:      this.Id = o.Id;

   9:      this.Nazwa = o.Nazwa;

  10:      this.Cena = o.Cena;

  11:      this.Rabat = o.Rabat;

  12:    }

  13:   

  14:    public static Find(int id)

  15:    {

  16:      Owoc o = // Wyciagniecie owocu z bazy i zmapowanie go

  17:      return o;

  18:    }

  19:   

  20:    public Owoc Save()

  21:    {

  22:      // Zapis

  23:    }

  24:    

  25:    public void Update()

  26:    {

  27:      // Update

  28:    } 

  29:    

  30:    public void Delete()

  31:    {

  32:      // Usunięcie

  33:    }

  34:  }



Tutaj trzeba zwrócić uwagę na metodę Find, która musi być statyczna.
Jeśliby nie była, to nie moglibyśmy w stanie jej użyć do konstrukcji obiektu.

Rzućmy okiem na użycie Rekordu Aktywnego:


   1:  // Wyciagamy owoc o id 4

   2:  Owoc o = new Owoc(4);

   3:  Owoc o = Owoc.Find(4);

   4:   

   5:  // Zapisujemy nowy owoc do bazy

   6:  Owoc o = new Owoc() { Nazwa = "jablko", Cena = 20, Rabat = 50 };

   7:  o.Save();

   8:   

   9:  // Updatujemy dane owocu

  10:  o.Nazwa = "Gruszka";

  11:  o.Update();

  12:   

  13:  // Usuwamy go

  14:  o.Delete();



Bardzo wygodne, prawda? ;)

Teraz podepnijmy getter biznesowy obliczający cenę jabłka z rabatem:


   1:  class Jablko

   2:  {

   3:    // ...

   4:    public decimal CenaZrabatem

   5:    {

   6:      get

   7:      {

   8:        return cena - rabat;

   9:      }

  10:    }

  11:  }



No to jak nam tak dobrze idzie, to dopiszmy kolejny getter biznesowy
określający czy jabłko jest na promocji:


   1:  class Jablko

   2:  {

   3:    // ...

   4:    public bool CzyNaPromocji

   5:    {

   6:      get

   7:      {

   8:        return rabat > 0;

   9:      }

  10:    }

  11:  }



Szybki przykład użycia (trochę bezsensowny, no ale trzeba z obrazować problem ;) ):



   1:  decimal cenaOwocu = 0;

   2:   

   3:  Owoc jablko = new Owoc(5);

   4:   

   5:  cenaOwocu = jablko.Cena;

   6:   

   7:  if ( jablko.CzyNaPromocji )

   8:  {

   9:    cenaOwocu = jablko.CenaZrabatem;

  10:  }



No i git, wszystko ładnie i pięknie... czy aby do końca jest to prawda?
Jak to zwyklę bywa... nie.
-Active Record nie powinniśmy stosować gdy mamy do czynienia ze złozoną logiką
biznesową
-AC wiąże się z konkretną bazą (np. CRUD zawiera SQL dla konkretnej bazy, nie jesteśmy go w stanie podmienić)

Niby tylko dwa minusy, ale za to jakie ;)

sobota, 6 września 2008

Videocasts

Coś na noc jak komuś się nudzi w sobotę wieczorem (e jasne ;) ), to może sobie pooglądać bardzo fajne podcasty

DSL - Martin Fowler


RailsConf - Martin Fowler
(ten link coś mi teraz nie działa ale może zacznie)

Piękno Ruby'iego


na deser polecam coś na rozluźnienie http://pl.youtube.com/user/envyads, na prawdę polecam jak chce się pośmiać pozostając w klimatach prograMistycznych.

Link do wzorców projektowych

Na prośbę BielszegoNizBlask publikuje linka do na prawdę dobrego artykułu o wzorcach projektowych http://www.go4expert.com/forums/showthread.php?t=5127 dziękuje za linka i zapraszam wszystkich do lektury :)

Sposób mapowania tabeli - Foreing Key Mapping

[Szybki post]

Odwzorowanie do klucza obcego "Odwzorowuje asocjacje między obiektami jako klucz obcy tabeli", hmm a po ludzku można to przedstawić tak, że:

Jeśli mamy tabele:

Owoc
id : int
nazwa : varchar

i

Koszyk
id : int
owoc_id : int
nazwa : varchar

Oczywiście tutaj występuje asocjacja "Owoc znajduje się w koszyku"

Aby to odwzorować Foreign Key tworzymy 2 klasy:

class Owoc
{
public int Id { get; set; }
public string Nazwa { get; set; }
}


i

class Koszyk
{
public int Id { get; set; }
public int OwocId { get; set; }
public string Nazwa { get; set; }
}


Jak widać teraz asocjacja jest "wykonywana" przez Owoc.Id --- Koszyk.OwocId, czyli tak na prawdę przez klucz obcy.

Wsadzenie owoca do koszyka będzie wyglądało w taki sposób:
Owoc jablko = new Owoc() { Id = 1, Nazwa = "Jabłko" };
Koszyk koszyk = new Koszyk() { Id = 1, OwocId = jablko.Id, Nazwa = jablko.Nazwa };


Oczywiście jest to przypadek kiedy koszyk jest na prawdę mały ;) i można do niego wsadzić tylko JEDEN owoc :)

II System płacowy (cz. 3) - Model dziedziny (Mapowanie)

Skoro mamy już warstwę dostępu do danych, to przyszedł czas na zrobienie modelu dziedziny.

Najpierw musimy się zastanowić jakie tabele w bazie będziemy mieli hmm

1. Zawód - będą przechowywane tutaj nazwy zawodów
2. Pracownik - jak się nie trudno domyśleć będą tutaj pracownicy
3. Przepracowane godziny- ilość przepracowanych godzin

To chyba tyle (przynajmniej na teraz).

Bierzmy się zatem do stworzenie modelu dziedziny.

A tak w ogóle to co to jest ten cały model? Można skrócić wywód ;) i zapisać go w jednym zdaniu: Model dziedziny są to obiekty, które modelują jakąś dziedzinę (wow odkrycie ;)). U nas będą to po prostu zmapowane (jeden do jednego) tabele.

Okey skoro już wiemy co to jest, zatem przejdźmy do akcji. Ale pierwsze... czas na obiad ;)

[po 30 min. przerwy obiadowej nasz zespół pełny (jedzenia ;)) zapału wkracza do pokoju by kontynuować pracę]


Na czym to skończyliśmy hmm... coś tam poudawaliśmy, pogadaliśmy sobie potem była przerwa... a tak! mapowanie tabel :)

Użyjemy sposobu mapowania: Foreign Key Mapping

Ale zaraz na razie nie mamy czego mapować, musimy utworzyć tabele:

zawod
id : int,
nazwa : varchar

pracownik
id : int,
imie : varchar
zawod_id : int

przepracowane_godziny
id : int,
pracownik_id : int
ilosc_godzin : int
data : dateTime

Mapnijmy to ;)

Zawód:
public class Zawod
{
public int Id { get; set; }
public string Nazwa { get; set; }

public Zawod(int id, string nazwa)
{
this.id = id;
this.Nazwa = nazwa;
}
}


Pracownik:
public class Pracownik
{
public int Id { get; set; }
public string Imie { get; set; }
public int ZawodId { get; set; }

public Pracownik (int id, string imie, int zawodId)
{
this.Id = id;
this.Imie = imie;
this.ZawodId = zawodId;
}
}


Przepracowane godziny:
public class PrzepracowaneGodziny
{
public int Id { get; set; }
public int PracownikId { get; set; }
public int IloscGodzin { get; set; }
public DateTime Data { get; set; }

public PrzepracowaneGodziny(int id, int pracownikId, int iloscGodzin, DateTime data)
{
this.Id = id;
this.PracownikId = pracownikId;
this.IloscGodzin = iloscGodzin;
this.Data = data;
}
}


Job done...

piątek, 5 września 2008

Nowy portal skupiający społeczność NHibernate

Jak w temacie, link znajduje się tutaj http://www.nhforge.org/. Widać, że dopiero się rozwija, no ale poczekamy i zobaczymy co z tego się wykluje.

A co do projektu Systemu Płacowego to mam nadzieję, że mi się uda w przyszłym tygodniu zamieścić jakieś notki.