Global Azure Bootcamp we Wrocławiu!

Witajcie!

zapraszamy na dziewiąty odcinek codingtv();

Dzisiaj omawiamy to co udało nam się zrobić podczas poprzedniej próby nagrania tego odcinka, czyli dodanie biblioteki NLog oraz stworzenie repozytorium dla klasy User.

Zapraszamy do oglądania i czekamy na Wasze komentarze!

Zamieszczamy również przydatne linki:

31 komentarzy

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

  • Szkoda że tak krótko dzisiaj, ale to pewnie dlatego że kod nie był pisany „na żywo” tylko omawiany.
    Tak myślę, że gdybyście w następnych częściach pisali kod wcześniej, a później „na wizji” go tylko omawiali, to pozwoliło by to na prezentacje większych porcji materiału w odcinku(nie tracąc czasu na samo pisanie).
    konkurs

    • No tak to już będzie – czasami dłużej, czasami krócej 🙂

      Co do Twojej propozycji – kod i tak musimy sobie omówić i napisać – tak więc późniejsze jego omawianie to trochę dodatkowa robota.

      Poza tym w takim podejściu nie byłoby za bardzo jak pokazać dyskusji na temat tworzonego kodu, które czasami prowadzimy.

  • Odnośnie loggera:
    1) instancja loggera bez problemu może być statycznym polem (pewnie readonly) inicjalizowanym inline, nie ma potrzeby każdorazowo pobierać takiej instancji z LogManagera:

    private static readonly Logger _log = LogManager.GetCurrentClassLogger();

    2) polecam rozbicie logów na kilka plików, ja stosuję podział na debug.txt (wszystko), info.txt (poziom >= INFO), errors (poziom >= ERROR) oraz dodatkowo pliki łapiące jakąś rodzinę błędów (np mam osobny plik do błędów wylatujących z klasy wysyłającej SMSy, które prawdopodobnie będą oznaczać że skończyła się kasa na koncie w używanej bramce)

    3) w nLog bardzo prosto można zawrzeć w logach informacje pochodzące z Request/Session itd, dzięki czemu pliki takie łatwo jest wzbogacić w IP, typ przeglądarki użytkownika itd – bardzo pomocne szczególnie przy błędach javascript (gdy się np. okazuje że jakiś konkretny błąd wyskakuje tylko w IE7)

    Części z repozytorium nie komentuję bo samo założenie „stwórzmy warstwę repo” jest wg mnie błędne.

    No i czekam na dalsze części:).

    • Dzięki za konkretny komentarz – kwestie logowania omówimy w następnym odcinku.

      Natomiast możesz rozwinąć tą część:
      „Części z repozytorium nie komentuję bo samo założenie „stwórzmy warstwę repo” jest wg mnie błędne.” ?

    • We własnych systemach nie tworzę repozytoriów i nie widzę żadnych korzyści płynących z tej dodatkowej pracy. Ba, rozwijam jeden projekt posiadający warstwę repozytoriów i moim zdaniem tylko utrudnia ona prace. Więc „błędne” to może za mocne słowo… bardziej pasuje chyba „bezcelowe”.

    • W sumie to racja 🙂 Mamy jednak w planach (kiedyś) pokazać inny sposób korzystania z bazy danych (ADO.NET, nHibernate) i stwierdziliśmy, że takie rozwiązanie nam później pomoże.

      Struktura projektu zawsze była ciekawym tematem i myślę, że to byłaby fajna propozycja na posta na Twoim blogu 🙂

    • Opinia dotycząca bezcelowości warstwy repozytorium jest dosyć mało przekonująca. Przykładem może być np. korzystanie z QueryOver lub ICriteria w Nhibernate. Wtedy pisanie testów jednostkowych staje się niemożliwe jeżeli nie używamy prawdziwej bazy dla nich. Pewnie można takich przykładów mnożyć wiele dotyczących konkretnych ORM-ów. Natomiast w prostych aplikacjach które nie wymagają korzystania z zaawansowanych technik rzeczywiście warstwa repozytorium jest „bezcelowa”.

      konkurs

    • Łukasz,
      Na temat repository pisałem i na blogu (chociaż pewnie nie w osobnym, dedykowanym poście.. może faktycznie pora na to:) ), i na devPytaniach.
      Promowanie wzorca repository jako drogi do „łatwej podmiany ORMa” jest… kontrowersyjne. Nie da się tego łatwo zrobić, nie tracąc jednocześnie cech charakterystycznych dla danego rozwiązania (co jest oczywiste) – sprowadzając wszystkie ORMy do jednego wspólnego mianownika okaleczamy wykorzystywaną bibliotekę.

      Jedynym sensownym powodem wykorzystania repository w projekcie takim jak platforma blogowa jest wg mnie wsparcie dla całkowicie różnych metod przechowywania danych – czyli np RDMS i XML. Z jednym zastrzeżeniem: te sposoby dostępu do danych są tak różne, że i podejście do ich wykorzystania nie powinno być identyczne… Ciężki orzech do zgryzienia i sama abstrakcja wszystkich możliwych operacji na danych nie jest rozwiązaniem gwarantującym sukces.

    • aiker,
      To o czym piszesz jest właśnie jedą z wad repozytorium – z góry decydujesz się na wykorzystanie QueryOver/ICriteria, zamykając sobie drogę do użycia np providera LINQ z NH czy bezpośrednio HQL. A każdy z tych sposobów potrafi wygenerować INNY sql wynikowy dla analogicznych konstrukcji. Dlatego moim zdaniem każde zapytanie powinno być dedykowane dla konkretnego scenariusza, z wykorzystaniem najlepszej w danym przypadku drogi.
      Testy jednostkowe bez bazy danych? A co komuś przeszkadza baza danych w teście jednostkowym? Stworzenie dla każdego testu lekkiej bazy (sqlite, sql ce) i wypełnienie jej danymi spełnia to samo zadanie co mockowanie repozytorium, zajmuje tyle samo czasu i jest bardziej praktyczne (bo w logach każdego testu mamy prawdziwy sql w nim wygenerowany, możemy podpiąć do tego profiler itd).
      Dodatkowo: warstwa repozytorium praktycznie uniemożliwia elastyczne wykorzystanie lazy/eager loading, ogranicza 2nd level cache (bo wymusza cache na poziomie zapytania a nie na poziomie zaimlementowanego wymagania biznesowego)…
      Po prostu decydując się na takie rozwiązanie sami sobie nakładamy na łapy kajdany, które wcale nie są potrzebne.

    • @Maciej

      Zgodze sie z tym, ze testy jednostokwe z baza nie musza stwarzac problemu, tyle jak zwykle wszystko zalezy od przypadku. W aktualnym projekcie wykorzystujemy w naszym zespole MongoDB i w przypadku tej bazy nie ma potrzeby mockowania bazy danych, dlatego ze baza MongoDB jest rewelacyjnie szybka(cache w pamieci RAM). Mimo tego stosujemy warstwe dostepu do danych(repozytoria) dlatego, ze w momencie kiedy rozpoczynalismy projekt nie bylo pewnosci co do tego, ktora biblioteka(sterownik) bedzie standardem dla tej bazy.

      Mimo tego zastosowanie repozytorium nie pozwoli nam na latwe przejscie na inny rodzaj bazy danych(zreszta dlaczego mielbysmy?), np relacyjne, dlatego ze wykorzystanie bazy dokumentowej rozni sie w wielu aspekatach w porownaniu do bazy relacyjnej.

      Nawet w przypadku zmiany biblioteki dostepu danych np. ORM’a w przypadku baz relacyjnych, zawsze natrafia sie na pewne problemy zwiazane z uzyciem specjalnych funkcji danej biblioteki. Dlatego za kazdym razem rozpoczynajac projekt nalezy sie zastanowic czy tworzenie aplikacji z architektura pozwalajaca na zastapienie warswty dostepu do danych ma sens w danym projekcie. Sam probowalem stworzyc tego typu rozwiazanie i w efekcie koncowym bylem z niego bardzo nie zadowolony.

  • Po pierwsze prosiłbym o podanie całego motywu, gdyż VS w tym ubranku prezentuje się bardzo ciekawie. 🙂

    Po drugie, wg mnie wzorzec repository, jako samo opakowanie do EF faktycznie nie ma za bardzo sensu, gdyż X % (dużo) metod w repository będzie posiadało praktycznie tylko jedną linijkę – wywołanie zapytania w ef. Jeśli zaś w repository umieścimy np. swoje odwołania do cachu, wzorzec ten staje się bardziej praktyczny. Jeszcze bardziej przydaje się, gdy korzystamy z np DataReaderów i możemy tak upchnąć całe tworzenie obiektu z DR i na odwrót. Podany wyżej argument też jest bardzo trafny, czyli możemy podmienić bazę i repository a reszta kodu może zostać niezmieniona. Osobiście nigdy nie spotkałem się z tym, aby ktoś przechodził z jednego systemu bazodanowego na drugi, oraz ze zmianą sposobu łączenia np. ADO.NET i samodzielnie tworzenie zapytań => np. EF, no ale… zawsze dajemy sobie taką możliwość.

  • Bardzo przydatne info dla mnie o NUnit i korzystaniu z TestCase. Dotychczas nie widziałem jak takie parametryzowane coś zrobić.
    Dzięki.
    konkurs

  • Zastanawiam się czy to już nie pora abyście wspomnieli coś o podejściu z użyciem EmptyObject. Nie wiem czy to właściwa nazwa… Mianowicie chodzi mi o fragment repozytorium które zwraca użytkownika metodą SingleOrDefualt() co narzuca każdorazowe sprawdzenie czy użytkownik nie jest aby null i zamiast tego zwracać pustą encję User. Nie wiem jak takie podejście działa w praktyce, a strasznie mnie męczy żmudne sprawdzanie if(obj != null) 🙂
    konkurs

  • Kiedy można się spodziewać uaktualnienia repozytorium kodu?
    A może tak na zakończenie każdego odcinka commit?

    konkurs

  • Co w przypadku gdy pod jakimś tam przyciskiem w UI jest akcja która korzysta z serwisu / lub serwisów które korzystają z kilku repozytoriów i chcesz to wszystko objąć transakcją bazodanową?
    konkurs

  • Proponuję poprawić metodę EmailIsInUse w UserRepository, aby nie brała pod uwagę wielkości liter w emailach. To samo dla GetUserByEmail.

  • Wzorzec Repository, Przypadek Coding TV Blog Project

    Fakty
    1. Sa UnitTesty
    2. Chcecie korzystac z roznych zrodel danych w aplikacji (mozliwe, ze nawet nie macie do konca sprecyzowe jakie te zrodla beda).
    3. Nie goni Was czas.
    4. Chcecie, by inni czegos sie nauczyli (po to jest CTV :))

    Wniosek
    Dla ogarniecia 1,2 nie potrzeba korzystac z Repository Pattern. Na minimalistyczne potrzeby produkcji produktu dla klientajak najbardziej wystarczy sam ORM. Punkt 3 to w zasadzie dogodnosc, ktora macie, wiec mozecie zainwestowac troche czasu w pisanie wiecej kodu. Natomiast zeby osiagnac punkt 4 i w 100% go pokryc, czyli przekazac jakas nauke sluchaczom, moim zdaniem nalezalo by zaimplementowac Repository Pattern.

    Wytrwalosci zycze

    ps.
    Za wszystkimi:
    konkurs

  • Bardzo ciekawa seria podcastów. Dopiero niedawno trafiłem na waszą stronę więc aktualnie nadrabiam zaległości.
    Tak jak już ktoś wcześniej pisał warto by robić commity po każdym odcinku.

    konkurs

  • Witam,
    1. Zauważyłem małą literówkę w kodzie w pliku nlog.config, w sekcji „rules” napisaliście: „mminlevel” (zdublowana literka „m”). O dziwo tak też działa 😀
    2. Czekam cały czas na pokaz DotCover’a.
    3. Co do architektury aplikacji wydaje mi się, że wybrane podejście (repozytorium i serwis) jest OK, gdyż tak jak chyba mówiliście już wcześniej, w serwisie będzie dodatkowa logika np. walidacja.

    konkurs

  • Witam w końcu przebrnąłem przez wszystkie odcinki.
    Kilka propozycji.
    1) CreateBlog – jeżeli mamy już w Blog property CreateTime to miło by było już tej zmiennej nie przekazywać tylko w samej metodzie dać DateTime.UtcNow opcjonalnie można userowi dodać proprty DST a metoda GetCreateDate niech zwraca datę z poprawką na strefę czasową Usera. To samo się tyczy Postu,
    2) Trochę brakuje property CreateTime dla Comment
    3) Chyba pozostały stare nazwy katalogów CodingBlog.Service. i CodingBlog.Service.Test

    Co do repo jak już @Jan wspomniał widząc jak działa EF większość Metod będzie jednowersowa. Pytanie brzmi czy faktycznie zamierzacie w połowie projektu zmienić sposób korzystania z bazy danych i czy ten nadmiar pracy jest konieczny.

    W którymś z odcinków ktoś chyba mówił że pokaże jak działa dotCover. Albo mi się przesłyszało 😀

    Co Do projektu Codingtv Właśnie tego mi brakowało przyznam szczerze że jestem fanem channel9 a tu bach rodowita produkcja 🙂

    A nich tam:
    Konkurs

  • Kurcze fajna inicjatywa. Niezależnie od tego czy i kiedy stosować Repository – wielkie dzięki za materiał.
    Konkurs

  • Czy korzystamy z repo, czy czegokolwiek innego. Ważne, aby zachowywać Persistance ignorance obiektów biznesowych.