Roy uczy TDD :)

Nie lada gratka dla wszystkich, którzy chcą się nauczyć praktycznego wykorzystania TDD w swojej pracy. Choć osoby doświadczone też coś pewnie dla siebie znajdą :)

Roy Osherove publikuje nagrania, w których wraz z innym programistą tworzą od zera silnik gry Go. Oczywiście wszystko tworzą zgodnie z zasadami TDD, które są w nagraniach dokładnie omawiane. Raymond Lim, “pair programming partner” Roya, jest głównym koderem. Roy występuje głównie w roli mentora – zadając różne ciekawe pytania naprowadza Raymonda na “właściwy tor”. czytaj dalej

log4net – logujemy zdarzenia w aplikacji

Dzisiaj chciałbym poruszyć ważny element tworzenia aplikacji – logowanie zdarzeń. Odpowiednio przygotowane logi są często jedynym sposobem na zdiagnozowanie problemu w aplikacji, dlatego warto o tym pamiętać i z logowania korzystać.

Logowanie można przeprowadzić na wiele sposobów – ja chciałbym opisać przykład oparty na darmowej bibliotece log4net.

Temat ten podzieliłem na trzy części:

  • dzisiaj pokażę jak korzystać z log4net
  • w następnym poście pokażę, jak czytać/analizować logi
  • na koniec opiszę podstawową konfigurację log4net

To zaczynamy:
bibliotekę pobieramy ze strony: http://logging.apache.org/log4net/download.html. Z pobranego archiwum wypakowujemy plik: log4net.dll (incubating-log4net-1.2.10.ziplog4net-1.2.10binnet2.0releaselog4net.dll) i wgrywamy go np. do katalogu “lib“. Następnie dodajemy referencję do tego pliku.

log4net1

W swoich aplikacjach korzystam z takiej klasy:

[sourcecode language=”csharp”]
public class LogHelper
{
static LogHelper()
{
var confFile = ConfigurationSettings.AppSettings.Get("log4net.config");
var fi = new FileInfo(confFile);
XmlConfigurator.Configure(fi);
}

public static ILog GetLog()
{
return LogManager.GetLogger("WebAppLog");
}
}
[/sourcecode]

Jak widać w pliku Web.config podajemy ścieżkę do pliku konfiguracyjnego, czyli:

[sourcecode language=”xml”]
<appSettings>
<add key="log4net.config" value="conflog4net.config"/>
</appSettings>
[/sourcecode]

Brakuje jeszcze zawartości pliku log4net.config:

[sourcecode language=”xml”]
<log4net>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
<file value="logstest_log.log" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<param name="StaticLogFileName" value="true"/>
<appendToFile value="true" />
<param name="RollingStyle" value="Date"/>
<param name="DatePattern" value="yyyy-MM-dd"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %type.%method – %message%newline"/>
</layout>
</appender>

<logger name="WebAppLog">
<level value="ALL" />
<appender-ref ref="RollingLogFileAppender" />
</logger>
</log4net>
[/sourcecode]

Podana konfiguracja zapisuje logi do pliku (może to być również baza danych, e-mail, konsola lub inne źródło) – file określa, do jakiego pliku będą zapisywane logi, a layout określa format zapisu logów.

Samo logowanie jest operacją niezwykle prostą:

[sourcecode language=”csharp”]
LogHelper.GetLog().Info("My sample comments");
[/sourcecode]

lub

[sourcecode language=”csharp”]
catch (Exception ex)
{
LogHelper.GetLog().Error("Error occurred!", ex);
}
[/sourcecode]

log4net dostarcza kilka poziomów logowania:

  • Debug
  • Info
  • Warn
  • Error
  • Fatal

Nazwy poziomów logowania są bardzo czytelne i nie wymagają większego opisu.

Powyższy kod w logu zapisać może coś takiego:

[sourcecode language=”text”]
2009-12-07 22:22:33,202 [8] INFO  LogForNetWebSample._Default.Page_Load – My sample comments
2009-12-07 22:22:33,292 [8] ERROR LogForNetWebSample._Default.Page_Load – Error occurred!
System.DivideByZeroException: Attempted to divide by zero.
at LogForNetWebSample._Default.Page_Load(Object sender, EventArgs e) in Default.aspx.cs:line 14
[/sourcecode]

Jak widać log zawiera wiele cennych dla nas informacji – wiemy, kiedy i co się zdarzyło oraz w jakiej metodzie. Wiemy również, co działo się w aplikacji zanim wystąpił wyjątek.

Osobiście jestem zwolennikiem logowania jak największej ilości zdarzeń w naszej aplikacji – użytkownik wchodzi na stronę, klika button A, pobrano dane użytkownika, itp – jako poziom Debug. Przy przenoszeniu aplikacji na serwer produkcyjny możemy ograniczyć poziom logowania i logować jedynie logi z poziomu Error, Fatal czy Warn – bez zmiany kodu aplikacji!
log4net jest biblioteką bardzo elastyczną i posiada wiele parametrów konfiguracyjnych.

Oczywiście podczas logowania trzeba uważać, żeby nie zalogować danych poufnych – np. haseł.

Dzisiaj to tyle – zachęcam do zabawy z log4net i czytaniem logów – tylko uwaga – TO UZALEŻNIA!! :)

ReSharper 5.0 Nightly Build – In Action

Od jakiegoś czasu – a dokładnie od 19 listopada – udostępniono do testów nową wersję ReSharpera –  5.0. Jest to co prawda dopiero wersja beta, ale nie mogłem odmówić sobie przyjemności przetestowania :)

Pierwsze wersje trochę mi namieszały, ale reinstall Visual Studio pomógł. Ostatnio zainstalowana przeze mnie wersja 5.0.1537 póki co działa stabilnie.

Nowy Resharper oferuje wsparcie dla VS 2008 oraz VS 2010.

resharper_1

Poza wsparciem dla nowego VS, Resharper 5.0 oferuje sporo nowych przydatnych funkcji:

Wsparcie dla ASP.NET

  • nowe okienko “File structure” pokazujące budowę pliku aspx, ascx
  • generowanie placeholedrów i automatyczne powiązanie ich z MasterPagem
  • funkcja Go to file member pozwala szybko “powędrować” do innego powiązanego pliku, np.: MasterPage, kontrolki użytkownika
  • automatyczne generowanie referencji do kontrolek :)
  • nowe templaty do generowania contentu strony oraz szablony plików

resharper_6

Wsparcie dla ASP.NET MVC

  • lepsze (niż VS) wsparcie w intellisense
  • nawigacja pomiędzy powiązanymi obiektami
  • tworzenie nowych typów i metod

Możliwość debugowania źródeł .NET oraz bibliotek, dla których posiadamy pliki pdb.

Bardzo przydatne -np. na ToString() klikamy “Go to definition” i podglądamy, co się kryje w środku.

resharper_2

resharper_3

Bookmarki

Kolejna ciekawa nowość. Dodajemy bookmarka i później możemy bardzo szybko w dane miejsce wrócić. Domyślnie za pomocą skrótów możemy zarządzać 10 bookmarkami – ctrl+shift+numer (np. ctrl+shift+1) dodajemy bookmarka, ctrl+numer “wędrujemy” do bookmarka.

resharper_5

resharper_7

Oczywiście możemy dodawać więcej bookmarków (tzw. anonymous bookmark) i tylko w tej sytuacji, chcąc do niego “powędrować”, musimy go wybrać z listy (najpierw: ctrl+shift+’)

resharper_8

“Historia wartości”

Nowe okienko pokazujące, jak “wędrowała” wartość jakiejś zmiennej pomiędzy metodami.

resharper_4

Na powyższym screenie widać, że nasza zmienna testValue została przekazana jako parametr metody SampleMethod. Wartość zmiennej przekazanej do tej metody została przekazana z GetSampleValue, a w tej metodzie przypisaliśmy jej wartość 10 – czysto i przejrzyście.

To na razie tyle z nowych funkcjonalności, które przetestowałem – kolejna wersja i kolejny raz WIELKIE WOW :). O nowych ciekawych doświadczeniach postaram się informować na bieżąco.

Więcej o nowej wersji ReSharpera na stronie: http://blogs.jetbrains.com/dotnet/2009/10/resharper-50-overview/.

Nowe wydania R# 5.0 można pobrać ze strony: http://www.jetbrains.net/confluence/display/ReSharper/ReSharper+5.0+Nightly+Builds

Jak pobrać PublicKeyToken – GetAssemblyDetails

W jednym z projektów, nad którym ostatnio pracowałem, musiałem dodać referencje do pewnej biblioteki, czyli np. standardowe:

[sourcecode language=”xml”]
<add assembly="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
[/sourcecode]

Niby wszystko ok, ale to PublicKeyToken – trochę trzeba się naklikać, żeby tą wartość uzyskać.

Jako osoba ceniąca “proste” życie napisałem program, który robi to za mnie – GetAssemblyDetails :)

GetAssemblyDetails jest standardową aplikacją konsolową, którą dodatkowo można wywołać z menu kontekstowego plików .dll oraz .exe

Jak tego programu używać:

GetAssemblyDetails -f “ścieżka do assembly” – pobiera dane assembly
np. GetAssemblyDetails -f c:Program FilesMicrosoft ASP.NETASP.NET MVC 1.0AssembliesSystem.Web.Mvc.dll

GetAssemblyDetails -r – dodaje program do menu kontekstowego

GetAssemblyDetails -u – usuwa program z menu kontekstowego

Wystarczy skopiować tekst wygenerowany przez program i voila :)

POBIERZ  GetAssemblyDetails.exe

I jeszcze parę screenów:

assembly1

assembly2

Quick Tip: 04. przeszukuj kolekcje z where zamiast foreach

LINQ udostępnia metodę where, która umożliwia przeszukiwanie kolekcji tak jak foreach.

Przykładowo, zamiast:

[sourcecode language=”csharp”]
var polishCustomers = new List<Customer>();

foreach (var customer in customers)
{
if (customer.Country == "Poland")
polishCustomers.Add(customer);
}
[/sourcecode]

możemy użyć

[sourcecode language=”csharp”]
var polishCustomers = customers.Where(x => x.Country == "Poland");
[/sourcecode]

czyli krótko, zwięźle i na temat :)

Oczywiście wcześniej musimy dodać using System.Linq;

Quick Tip: 01. C# operator ??

Podczas tworzenia oprogramowania jedną z częściej wykonywanych operacji jest sprawdzanie, czy dany obiekt nie jest nullem. Często wygląda to tak:
[sourcecode language=”csharp”]
MyType result;
if(Object1 != null)
{
result = Object1;
}
else
{
result = Object2;
}
[/sourcecode]
lub
[sourcecode language=”csharp”]
MyType result = Object1 != null ? Object1 : Object2;
[/sourcecode]
Kod ten możemy sobie uprościć stosując operator ?? (podwójny znak zapytania). Operator ten zwraca obiekt będący “z lewej strony”, jeżeli jest on różny od null lub jeżeli jest nullem obiekt będący z jego “z prawej strony”.

Podany przykład będzie wyglądał tak:
[sourcecode language=”csharp”]
MyType result = Object1 ?? Object2;
[/sourcecode]
lub
[sourcecode language=”csharp”]
MyType result = Object1 ?? Object2 ?? Object3;
[/sourcecode]

Oczywiście Object1 może być również funkcją zwracającą obiekt, np:
[sourcecode language=”csharp”]
public MyType MyObject
{
get { return myObject ?? (myObject = objectFactory.Create()); }
}
[/sourcecode]
zamiast:
[sourcecode language=”csharp”]
public MyType MyObject
{
get
{
if (myObject == null) myObject = objectFactory.Create();
return myObject;
}
}
[/sourcecode]

Korzystając z tego operatora należy pamiętać, że pusty string nie jest nullem!

Microsoft Web Platform Installer Beta

Microsoft udostępnił kolejną zabawkę ułatwiającą życie programistom www. Tym razem jest to pakiet instalacyjny przygotowujący kompletne środowisko programistyczne.

Instalator zawiera w sobie m.in.: IIS7, Visual Web Developer 2008 Express Edition, SQL Server 2008 Express Edition oraz najnowszą wersję .NET Frameworka i może być uruchomiony na Windows Vista lub Windows 2008. Instalacja WPI jest bardzo prosta i dostarcza nam kilka gotowych konfiguracji: np. dla programisty ASP.NET, ASP czy PHP. Oczywiście każdą z konfiguracji możemy dowolnie modyfikować. Sam instalator nie zawiera w sobie żadnego oprogramowania – każda wybrana opcja jest pobierana z internetu. Pozwala nam to zawsze cieszyć się najnowszą wersją instalowanych programów.

WPI (600kb) można pobrać ze strony: http://www.microsoft.com/web/channel/products/WebPlatformInstaller.aspx

Przy okazji pobierania WPI warto zwrócić uwagę na nową stronę http://www.microsoft.com/web przeznaczoną dla osób związanych z tworzeniem apikacji www :) Fajnym bajerem jest możliwość filtrowania zawartości strony wg własnych zainteresowań, czyli: “customize site by role” :)

Przykładowe screeny:

C# Interview Questions

Do tej pory głównie tworzyłem aplikacje ASP.NET w VB.NET. Tak się jednak narobiło, że w życiu mi się trochę pozmieniało i muszę nadrobić zaległości w C#. Więcej szczegółów podam wkrótce. Teraz chciałbym przedstawić Wam ciekawą listę pytań dotyczących C#. Aktualnie lista zawiera 427 pytania ale ciągle się powiększa. Jest to takie forum, gdzie każdy może pytanie zadać i każdy może udzielić odpowiedzi.
Moim zdaniem świetny materiał na odświeżenie oraz sprawdzenie swojej wiedzy.

Lista dostępna pod adresem:
http://www.geekinterview.com/Interview-Questions/Microsoft/C-Sharp

Warto dodać, że strona zawiera wiele podobnych list dotyczących np. ADO.NET 2.0, ASP.NET czy baz danych. Pełna lista dostępna jest pod adresem: http://www.geekinterview.com/Interview-Questions

Jeśli znacie podobne strony podajcie je w komentarzach.