Azure deployment

Kopiowanie plików z lokalnej maszyny na serwer choć proste i łatwe i szybkie, nie jest tym jak powinno się umieszczać binarki na produkcji. Muszę się przyznać, że ja tak właśnie robiłem, ale zabrałem się wreszcie za siebie i mam postanowienie poprawy.
Otóż otóż. Chciałem być trendi i chciałem skorzystać z “darmowych” rozwiązań, travis ci czy appveyor i dupa, nie umiem. Wreszcie pomyślałem skoro postawiłem aplikację na azure, to czemu nie skorzystać z azure aby zrobić deploy. Działa lepiej niż myślałem. Continue reading

Widoki w asp .net mvc

Dzisiaj trochę o samych widokach w mvc i ich organizacji.

Zgodnie z przyjętą konwencją widoki powinny znajdować się w folderze Views, tam będzie szukać ich domyślnie włączony silnik renderujący. Nazwa widoku powinna odpowiadać nazwie metody w kontrolerze (konwencja i dobre praktyki). Oczywiście w metodzie Foo można wykorzystać widok o nazwie Goo, ale nie jest to najlepszą praktyką i powodować będzie, że trudniej nam/wam/innym będzie odnaleźć się w projekcie. Continue reading

Logowanie przy pomocy Facebook, Twitter czy Google – OWIN Katana na ASP MVC 5

Następny wpis, tym razem już na nowym systemie i nowej własnej domenie. Zobaczymy czy będzie tak jak z samochodami, gdzie wizyta na myjni daje dwa konie mechaniczne więcej. Ostatnio pisałem więcej filozoficznie, dzisiaj powrót do twardej rzeczywistości.

Obejrzałem nie dawno na pluralsight fajny i krótki kurs o OWIN i Katana i częścią wiedzy chce się z wami podzielić.
Kto z was zaczynał projekt ASP MVC z włączonymi indywidualnymi kontami użytkowników? Ja na pewno! Także ja, gdy patrzyłem co się dzieje w OWINIE (w części konfiguracyjnej) i AccoutController łapałem się za głowę i zastanawiałem się WTF? Oczywiście próbowałem zrozumieć o co tam chodzi i czemu to wszystko jest tak “fajnie” napisane, niestety nie starczyło mi na to nigdy cierpliwości. Koniec końców pogodziłem się z tym faktem i korzystałem z tego tak jak jest, działało a ja nie zadawałem pytań – sprzedawać!

Teraz to wszystko może się zmienić! (dramatyczna muzyka i suspens – teraz!)

Aby to wszystko zrozumieć, zacząć należałoby od stworzenia pustego projektu MVC5 (tak, wiem staroć) – żadnych dodatkowych referencji, nic! Jak się bawić to na trylion procent. Na koniec wpisu, znajdziecie link do całego projektu. Dodajemy samodzielnie referencje do OWINowych rzeczy, tak aby moje i wasze referencje w tej kwestii się zgadzały:

  • Microsoft.Owin
  • Microsoft.Owin.Host.SystemWeb
  • Microsoft.Owin.Security
  • Microsoft.Owin.Security.Cookies
  • Microsoft.Owin.Security.Facebook
  • Microsoft.Owin.Security.Google
  • Microsoft.Owin.Security.Twitter

Z racji tego że projekt będzie oparty o MVC, nie można zapomnieć o:

  • System.Web.Mvc
Kompletna lista referencji w projekcie
Kompletna lista referencji w projekcie

Gdy to mamy ogarnięte, warto dodać plik z punktem wejścia do aplikacji, wykorzystany zostanie także do konfiguracji facebooka, twittera czy G+ oraz ogólnej authentykacji, u mnie wygląda on tak:

Co tam ciekawego? Na początku (@14) informujemy aplikację, o chęci korzystania z autentykacji opartej o ciastka. Ciastko przenosząca tajne dane nazywamy ThisCanBeAnythingYouLike. Następnie (@20-@41) wpinamy kolejne warstwy umożliwiające użytkownikom logowanie się przy pomocy FB, Twittera czy G+. Należy podać sekretne kody jednoznacznie identyfikujące waszą aplikacje.

Uwaga (@32) tutaj null oznacza, że nie interesuje mnie walidacja certyfikatów Twittera, oznacza to nie mniej, nie więcej, że jeśli ktoś podszyje się do Twittera i sprzeda mi swój certyfikat, ja to łyknę jak młody pelikan. Taka zagrywka przejdzie na blogu. Na żywej produkcji, należy odnaleźć aktualnie używane certyfikaty Twittera i dodać jest do walidacji. Dodatkowo zwracam uwagę, że wszystkie formy authentykacji korzystają z tego samego ciastka, znowu na blogu nie robi mi to różnicy skąd i jak i czym logują się moi użytkownicy. Produkcja rządzić może się swoimi prawami.
“/Auth/Login” (@14) ta linijka mówi, gdzie należy się przekierować gdy użytkownik nie będzie zalogowany, a aplikacje będzie tego wymagać.
Dla przypomnienia odpowiednio atrybuty AllowAnonymousAttribute oraz AuthorizeAttribute.

Skoro już powiedziałem o przekierowaniu do “/Auth/Login” (Auth controller, Login action) zajrzyjmy co kryje się w tej klasie:

Wielkiej ilości kodu nie ma (gdzie jest AccountController?!). Zaczynając od metody [HttpGet]Login (@15) tworzymy prosty pusty model do logowania się użytkownika. Z OWINa wyciągamy informacje o zarejestrowanych providerach (dostarczycielach?) logowania i wpychamy do modułu, który potem renderujemy.

W parach pracuje się lepiej, dlatego istnieje także [HttpPost]Login (@29) który przyjmuje ten sam model(pamiętamy, że to tylko wpis na blogu i nie maiłczymy że model!=dto!=viewmodel). W klasie są informacje o nazwie i haśle, następuje skomplikowana weryfikacja i jeśli dane są poprawne tworzymy w locie użytkownika. Nadajemy mu także pewne cechy: nazwę oraz identyfikator. Tak zdefiniowanego użytkownika logujemy przy wykorzystaniu OWINa. I wracamy do domu, jeśli weryfikacja się nie powiedzie, dajemy kolejną szansę.

Dla znudzonych oferujemy opcję wylogowania (@47) jak zawsze wszystko kręci się wokół OWINa.

Wreszcie! WRESZCIE! Jak zobaczycie zaraz na przykładzie z razora, tutaj obsługujemy kliknięcie użytkownika, gdy wybierze ono (!on i !ona) opcję logowania się przy pomocy FB, Twitter czy G+. Jako parametr wejściowy przyjdzie nazwa providera. Następnie na OWINie i autentykacji wywołujemy metodę Challange z parametrem informującym, że chcemy wrócić do “/secret”. Kod tego kontrolera pokaże na końcu. Po wywołaniu zwracamy jeszcze odpowiedni kod HTTP aby wszystkim formalnościom stało się zadość. Status Unauthorized jest bardzo ważny i nie może zostać pominięty.

No dobrze, skoro tutaj tak mało kodu, to pewnie razor będzie przekombinowany, pomyślało teraz ono. Aby nie trzymać w niepewności:

Pierwsze linie wynikają z braku pełnej integracji z MVC, odpowiednich wpisów w web.config etc. Ignoruj. Linie (@15-@30) to forma gdzie można się zalogować jako aplikacyjny użytkownik. Linie (@32-@37) to pętla, która wyciąga z modelu (ono przypomina sobie teraz AuthController::Login) listę providerów, na jej podstawie tworzy proste linki z nazwą providera oraz odpowiednim id (“Facebook”, “Twitter”, “Google”), które zostanie przekazane do metody SocialLogin (AuthController::SocialLogin) i użyte to rozróżnienia providera.

Co teraz? Gdzie jest reszta, gdzie jest ACCOUNTCONTROLLER? Nie ma i nie potrzeba. Póki co, nie będę nigdzie zapisywać użytkowników. Demo pokazuje tylko jak zalogować się przy pomocy providerów wymienionych powyżej.

Co znaczy zalogowanie? Otóż mniej więcej tyle:

Będziemy w stanie przejść do metody Index, która jest klasie wymagającej autoryzacji. Czyli User.Identity.IsAuthenticated zwróci TRUE. To całkiem fajnie. Oprócz tego, mamy kilka dodatkowych informacji:
Oraz widok:

W widoku widać że interesują nas cechy nadane nam przez system. Nie ważne czy to FB, Twitter, G+ czy my sami (AuthController, Login w wersji POST). Po uruchomieniu aplikacji wynik operacji wyglądają tak:

Wersja lokalna (user:jaroslaw/pass:stadnicki):

http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier : jaroslaw
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name : jaroslaw

Wersja z G+

http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier : 1#6#9#9#9#2#4#7#1#2#6 (odrobina prywatności)
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname : Jarosław
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname : Stadnicki
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name : Jarosław Stadnicki
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress : jaroslaw.stadnicki@gmail.com
urn:google:profile : https://plus.google.com/+JarosławStadnicki

Itp, itd. Warto zwrócić uwagę, że z G+ (inne też), dostajemy już identyfikator użytkownika, który możemy powiązać ze swoim lokalnie tworzonym kontem. I gdy ponownie przyjdzie gościu z G+ i się zaloguje się i dostaniemy jego ID, będziemy wiedzieć, że on to on, a nie ktoś inny.

Na koniec jeszcze ważna sprawa, oczywiście należy pamiętać aby samodzielnie stworzyć swoje aplikacje odpowiednio na stronach:
https://developers.facebook.com/
https://apps.twitter.com/
https://console.developers.google.com/home/dashboard

Należy także ustawić poprawnie callbacki w tych systemach, u mnie wartość które działały poprawnie to: http://www.xoxox.com

Ej, ale co to za dziwny adres? No tak tak, bo Twitter nie lubi localhost (FB i G+ sobie z tym radzą). Dlatego dla Twittera robi się wyjątek i należy zaatakować windows\sytem32\drivers\etc\host dopisać taką linijkę:

127.0.0.1         www.xoxox.com

Od tej pory www.xoxox.com będzie wskazywać na wasz komputer. Ale jeszcze! Należy na normalnym IIS dodać stronę i pokazać jej, że binarki leżą u was w źródłach. Dodać binding w IIS. I na końcu w Visual Studio przełączyć się z IIS express na normalnego i też korzystać z www.xoxox.com. Można też zignorować twittera i dla testów sprawdzić tylko FB i G+ i korzystać z IIS express na 127.0.0.1

Tyle, od tej pory ja i wy (jaka jest liczna mnoga od ono?) będziemy mogli w prosty sposób logować się społecznościami. Aplikacja dostępna jest pod linkiem:
https://bitbucket.org/jstadnicki/simplesociallogin

Kod do aplikacji zostały zmienione przed publikacją, także aby zadziałały należy wygenerować własne oraz podmienić. Projekt działa pod kontrolą pełnego IIS, to także należy/można zmienić.

To tyle. Życzę miłej zabawy.

NDepend4 – co potrafi statyczna analiza kodu.

Dostałem NDepend4 w zamian za jego opis 🙂 Nie muszę o nim mówić w samych słodkich komentarzach, także można wpis czytać do końca.
NDepend służy to statycznej analizy kodu napisanego w .NET. Potrafi ocenić kod po wieloma względami, np: ze względu na skomplikowanie, ilość linii kod czy instrukcji IL, ilość zmiennych, łatwość modyfikacji, może zasugerować zmianę typów z referencyjnych na wartościowe (ref type –> value type).
Sama instalacja jest banalnie prosta, ściągamy paczkę ze strony, rozpakowujemy oraz wrzucamy plik z licencją :> Chyyyba że jej nie macie, wtedy można skorzystać z darmowej wersji 14 dniowej. To wszystko, potem wystarczy odpalić i załadować plik z solucją, którą chcielibyśmy się bliżej przyjrzeć.

Do opisu wykorzystam swoją pierwszą aplikację na Windows Phone. Trochę wstyd, ale dla dobra ludzkości trzeba się czasem trochę poświęcić. Przy okazji, jest ona dostępna na Baazar (nieoficjalny marketplace dla Windows Phone 7) – nazywa się CompactCal

Po uruchominiu NDepend można załadować plik solucji, którą chcemy poddać analizie. Następnie zostanie wyświetlona lista assemblies, które zostaną przeanalizowane:

Jak widać może się okazać, że czegoś będzie brakować, wtedy można dodać ręcznie brakujące pliki (np. używając drag’n’drop) walnąć OK. Warto zwrócić uwagę z której konfiguracji będą brane: debug czy release.

Czary mary, czekamy chwilę i wybieram opcje Close dialog – chce wszystko sam zobaczyć.
Pierwsze ciary na plecach, bo widzę bałagan w kodzie. Wszytko przez diagram zależności klas, u mnie wygląda on tak:

(Trochę się obrazek rozjechał)
Ci z nas, którzy posiadają Visual Studio wyższą niż expres (i chyba pro też), mogą znać już taki obrazek. Podobny widok można utworzyć w MVSC z menu Architecture -> Generate Dependency Graph -> By Assembly.
Ogólnie rzecz ujmując widać na nim, co od czego zależy i jak bardzo, im grubsza kreska tym więcej zależności w kodzie. Może być taka sytuacja że już tutaj zauważymy zależności których
nie powinno być. Może z jakiegoś powodu nasz View sięga bezpośrednio
do serwisów z danymi, a miał to robić tylko ViewModel. Po rozwiązaniu takich problemów, ja najczęściej usuwam  zależności od systemowy plików, tak jest dla mniej przejrzyściej.
Niestety ND (żeby nie pisać ciągle całej nazwy) nie potrafi sobie poradzić z ułożeniem kwadracików tak, aby linie się nigdzie nie przecinały. Nad czytelnością trzeba diagramu trzeba popracować samodzielnie. Nie wiem czemu, ale lubię właśnie w ten sposób mieć ułożone wszelkie diagramy.
Kolejnym innym widokiem zależności jest Matrix view, jest czytelniejszy niż diagram powyżej, w przypadkach gdy jest bardzo dużo obiektów do analizy.

U mnie tego nie widać, ale gdy pojawią się cyferki na czarnym tle, oznaczać to będzie zależności cykliczne. Choć muszę się przyznać, że gdy po raz pierwszy uruchomiłem ND na tym projekcie pewnie znalazło by się kilka czarnych miejsc. Na szczęście od tamtego czasu zdążyłem poprawić kod, a ten wpis powstaje dużo później. Widać na nim dokładnie zależności modułów, możemy badać zależność na podstawie ilości wykorzystywanych metod, pól, namespaces, typów zmiennych, i jeszcze kilku innych. ND potrafi także wykryć zależności nie bezpośrednie.
Po kliknięciu na jedno ze skrzyżowań, zobaczymy jeszcze dokładniejszy diagram tego, gdzie i jak są wykorzystywane te zależności, np. ViewModel vs. Helpers:

Do tego można wygenerować ciekawszy graph (Export Matrix Code Elements to Graph):

Co w wyniku da coś takiego:

W tym przypadku diagram zależności jest czytelny (linie się nigdzie nie przecinają).

To dopiero początek, jeśli już pogodziliśmy się ze skalą zależności w naszym kodzie warto przejść dalej i zobaczyć jakie reguły złamaliśmy oraz gdzie. ND dostarcza ponad 80 zdefiniowanych reguł. Możemy samodzielnie je modyfikować, dodawać nowe oraz usuwać te z nich , które naszym lub architekta odpowiedzialnego za projekt są z jakiegoś powodu nie potrzebne.

Tak bardzo źle nie jest, brak czerwonych kółeczek.

Jak widać powyżej istnieje kilka różnych grup zasad, z których część została w brzydki sposób naruszona, a część jest akceptowalna. Zobaczmy co zrobiłem źle, sprawdźmy Code Quality (dwuklik i widać szczegóły):

Każda grupa składa się znowu z kilku mniejszych reguł, tutaj jak widać mam najwyraźniej problem ze zbyt dużymi klasami i metodami. Brakiem komentarzy się nie przejmuje. Mój kod komentuje się sam – tak go wytresowałem.

Ważne jest to że parametry definiujące te reguły możemy samodzielnie zmieniać. Dla przykładu domyślne aby metoda została oznaczona za posiadającą zbyt duża ilość parametrów,  musi posiadać ich więcej niż pięć:

Metody zbyt duże muszą mieć więcej niż 30 linii kodu lub więcej niż 200 instrukcji IL.

Gdy już zdecydujemy się obejrzeć listę przewinień służy do tego osobny panel, ja sprawdzę którą z metod tak strasznie spasłem kodem:

Ja mam dwa takie przypadki, gdzie ten drugi jest bliski wartości granicznej. Aby obejrzeć kod wystarczy dwuklik na wybranym przypadku. W wersji darmowej trzeba niestety ręcznie znaleźć kod w MSVC.

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, “Courier New”, Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #a31515; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}

.csharpcode .lnum { color: #606060; }

   1:  public static WriteableBitmap GenerateBitmapImage(string aHeading, IEnumerable<string> aItems)
   2:  {
   3:      WriteableBitmap wbm = null;
   4:      StackPanel sp = new StackPanel();
   5:      sp.Margin = new Thickness { Left = 6, Bottom = 0, Right = 6, Top = 0 };
   6:      sp.Height = 173;
   7:      sp.Width = 173;
   8:      sp.Background = new SolidColorBrush(Colors.Transparent);
   9:   
  10:      if (!string.IsNullOrEmpty(aHeading))
  11:      {
  12:          TextBlock heading = new TextBlock();
  13:          heading.Style = (Style)Application.Current.Resources["PhoneTextTitle3Style"];
  14:   
  15:          heading.Text = aHeading;
  16:          heading.Height = 35;
  17:          heading.Width = 173;
  18:   
  19:          sp.Children.Add(heading);
  20:      }
  21:   
  22:      int maxitems = (string.IsNullOrEmpty(aHeading)) ? 5 : 6;
  23:      int c = 0;
  24:   
  25:      foreach (var item in aItems)
  26:      {
  27:          TextBlock tbAction = new TextBlock();
  28:          tbAction.Foreground = (SolidColorBrush)Application.Current.Resources["PhoneAccentBrush"];
  29:          tbAction.Text = item;
  30:          tbAction.Style = (Style)Application.Current.Resources["PhoneTextNormalStyle"];
  31:          tbAction.Margin = new Thickness(4, 0, 0, 0);
  32:          tbAction.Height = 27;
  33:          tbAction.Width = 173;
  34:          sp.Children.Add(tbAction);
  35:          if (c++ > maxitems)
  36:          {
  37:              break;
  38:          }
  39:      }
  40:   
  41:      //call measure, arrange and updatelayout to prepare for rendering
  42:      sp.Measure(new Size(173, 173));
  43:      sp.Arrange(new Rect(0, 0, 173, 173));
  44:      sp.UpdateLayout();
  45:   
  46:      wbm = new WriteableBitmap(173, 173);
  47:      wbm.Render(sp, null);
  48:      wbm.Invalidate();
  49:      return wbm;
  50:  }

Rzeczywiście całkiem sporo, kod z bloków IF oraz FOREACH można wyrzucić do osobnych metod, tak samo ostatnie linijki z kodem który wymusza render na bitmapie. Poprawię to później 😉
To tylko jeden z wielu przypadków, który jest możliwy do przeanalizowania w kodzie. Jak już napisałem ND domyślnie ma ich ponad 80. Na stronie domowej są przykłady jak pisać własne CQL (code query language) i analizować kod na inny sposób, np:

  • Ostrzegaj gdy code coverage poniżej n%
  • Nazwy interfejsów nie zaczynające się od litery I
  • Wykorzystanie wątków inaczej niż przez ThreadPool
  • Zmiany wartości zmiennych, bez wykorzystania mechanizmów synchronizacji
  • Zbyt długa lista typów dziedziczących po X

Oprócz tego co wymieniłem powyżej, generowany jest także dodatkowy raport podsumowujący cały projekt, wykresy, liczby, inne pierdółki, coś co menadżerowie i klienci lubią najbardziej.
Skupmy się na najważniejszej grupie, na programistach.Są tam także informacje, które nam także się przydadzą.
Dodatkowy wykres wyświetlający stopień abstrakcji oraz stabilność waszego kodu. Gdzie stabilność nie oznacza dobrego kodu, a raczej współpracę z innymi typami (wsparcie dla polimorfizmu). W zasadzie ciężko wytłumaczyć ten parametr. Scott Hanselman ma podobny wpis o ND, tam tłumaczy trochę lepiej ten wykres: post Scotta.
Teraz będzie siara, bo o ile jestem zwolennikiem abstrakcji, to w tym projekcie pojechałem bez niej:

Warto trzymać się zielonej strefy.
I tak Service oraz GeocodeService był już tworzony z myślą o testach czy zastosowaniem innego źródła danych, dlatego znajduje się wyżej jeśli chodzi o oś Y (abstrakcję), natomiast Model, Extension (tam są metody rozszerzające), Helpery, etc jest płaskie jak deska. Położenie na osi X działa w taki sposób: jeśli assembly jest nie rozszerzalne, brakuje mu/jej jakiejkolwiek wirtualności, a dodatkowo wiele innych typów od niej zależy tym bliżej strefy bólu (na lewo) będzie się znajdować. U mnie wygląda to tak, że kod nie jest abstrakcyjny (są momenty), jednak nie posiadam klas które są wykorzystywane przez wszystkie inne. Brak tutaj typowych “utilsów” czy klas statycznych, do których wszyscy sięgają. Może dzięki temu jestem z pięknej zielonej strefie szczęścia. Model mógłby dodać od siebie trochę abstrakcji (może ISP), mógłbym sprawdzić czy wszędzie gdzie jest on wykorzystywany jest to potrzebne, może rozbić część klas na trochę mniejsze. Natomiast patrząc na Service widać że zbliża się on do powoli do zbyt wielkiej abstrakcji, lub braku wykorzystania części jego funkcjonalności. Warto sprawdzić czy wszystkie jego metody są potrzebne, może da się część z nich tak zmienić, aby wykorzystywały jakiś wspólny kod.

Z dodatkowych w raporcie ND można zobaczyć ile jest w sumie klas, metod w klasach, właściwości w klasach, linii kodu w projekcie, klasach, metodach, wszystko to co wymieniłem można także badać pod względem ilości poleceń w IL.

Po co utrzymywać kod z którego nikt nie korzysta? W moim przypadku zostało kilka metod, które zostały domyślnie stworzone przez wizarda podczas tworzenia projektu na Windows Phone, np. cała seria ApplicationLaunching, ApplicationActivated, ApplicationDeactivated czy ApplicationClosing. z której nigdzie nie korzystam. Takie proste rzeczy, a czynią kod z którym się pracuje przyjemniejszym w utrzymaniu.

ND wspiera MSVC 2008, 2010 oraz 2012. Umożliwia badanie kodu prosto z menu kontekstowego w edytorze:
Raporty można zapisywać, a następnie porównywać czy zmiany wprowadzane idą ku lepszemu. Dzięki integracji z VS można także prosto edytować i uruchamiać zapytania CQL – prosto ze środowiska pracy.
Na krótkich filmikach widziałem także, że ND potrafi porównywać ze sobą poszczególne wersje aplikacji. Niestety nie wiem jak do tego dojść, podejrzewam, że trzeba pilnować numerów wersji w assembly.
Odpalany z linii poleceń powinien być prosty do integracji z system CI (w domu takiego czegoś nie posiadam) i generować odpowiednio konfigurowalne raporty – menadżerowie się ucieszą. Możliwość zdefiniowania własnych reguł przy pomocy CQL umożliwi generowanie ostrzeżeń podczas budowania kodu, który np. nie posiada testów.

Pisałem wcześniej o tym, że warto rozmawiać. Zadawać pytania i czytać kod nie tylko swój. Poprosić znajomego o sprawdzenie tego co stworzyliśmy. ND wydaje się być czymś co może ten proces częściowo zastąpić. Nie warto jednak od razu usuwać ludzi z listy kontaktów. Jasna sprawa, że dla mnie czy innego Kowalskiego (pozdrawiam Tomka jeśli to czyta) jest on raczej drogim narzędziem 299 euro, szczególnie gdy w domu piszemy kod do szuflady. Ale gdy zarabia się na oprogramowaniu to świetne rozwiązanie, senior czy inny architekt może na początku projektu ustalić pewne zasady, który kod musi spełniać i dopiero gdy czekin w repozytorium spełni je wszystkie, zostanie przesłany do osobistego review. Pozwali to zaoszczędzić wszystkim dużo czasu (czas to pieniądz) oraz pominąć głupie i często powtarzające się błędy, np. brak słowa sealed przy klasie nie przeznaczonej do dziedziczenia.

TL;DR; (podsumowanie)
NDepend to dobre narzędzie do statycznego sprawdzenia kodu. Szczególnie przydatne w komercyjnych projektach, pozwoli automatycznie pilnować porządku w kodzie, zapewni przestrzeganie przyjętych zasad w projekcie. Zadowoli menadżerów wymagających nudnej papierologii. Nawet jeśli piszesz do szuflady, to na koniec lub po zakończeniu projektu, wykorzystaj wersję 14 dniową i sprawdź swój kod. Może się okazać, że da się lepiej.
Jeśli miałbym narzekać, to mogliby dać wersję darmową do domowego użytku.

Jest także NDepened dla Javy oraz dla C++. Niestety nie wiem jak dobre/złe są.

Linki:
NDepend strona domowa: http://www.ndepend.com/Default.aspx
Cennik: http://www.ndepend.com/Purchase.aspx
Lista ficzerów, część z nich posiada filmiki. Zabawne jest to, że korzystają z syntezatora mowy: http://www.ndepend.com/Features.aspx

Jeśli macie pytania to proszę o kontakt, jeśli chcecie żebym opisał jakąś część funkcjonalności ND to piszcie. Jeśli chcecie abym sprawdził jakiś kod to piszcie.