środa, 31 grudnia 2014

7a (7zip z comand line)

Kolejne przydatne narzędzie, które warto znać i używać podczas automatyzacji własnej pracy, to 7zip w wersji obsługiwanej z wiersza poleceń (comand line), czyli 7a. 7a jest osobną, samotną (standalone) instancją darmowej aplikacji do tworzenia plików z rozszerzeniem ".zip".
Warte jest zaznaczenia, że 7a nie jest dostarczane standardowo do 7zip, tylko trzeba je ściągnąć oddzielnie: link

Przykładowa komenda, to wykonania za pomocą skryptu typu "*.bat" z wykorzystaniem 7a

7za a -tzip foo_%DATE:~8,2%_%DATE:~5,2%_%DATE:~0,4%.zip bar

Gdzie: bar -> nazwa katalogu, który chcemy spakować.
Po wykonaniu tej instrukcji, otrzymamy przykładowy plik o nazwie: foo_31_12_2014.zip

Przykładowe linki z komendami:
http://www.dotnetperls.com/7-zip-examples

niedziela, 21 grudnia 2014

Wielowątkowy dostęp do zasobów "po polsku" :D

Jak każdy wie, samo programowanie jest wystarczająco trudne, a programowanie wielowątkowe jest trudne do kwadratu. O tym, że jest u nas z tym "krucho" można się było przekonać podczas tegorocznego DevDay 2014 w Krk, podczas którego Dan North wytknął to polskim programistom (głównie tym uczestniczącym na jego warsztatach).

Może ze świadomością wielowątkowości nie jest jakoś super, ale jednak pewna świadomość jest, co pokazała choćby sesja nt. "Modelu aktorów" na Warszawskiej grupie .NET.

A gdzie ja się z tym ost. spotkałem? Ano w aplikacji webowej, którą stworzyłem, a która do generowania raportów wykorzystuje SQL Server Reporting Services w trybie "local reports", tzn. do generowania raportów wykorzystywane są pliki ".rdlc" umieszczone na tym samym serwerze co serwer IIS hostujący stronę web (w moim konkretnym przypadku framework nancyfx).

I o ile przez większość czasu, te raporty generowały się poprawnie, o tyle przed wystawieniem aplikacji dla naszych doradców (pierwsza faza testów objęła ok 50-60 docelowych użytkowników systemu) razem z Adamem K. (osoba z "biznesu") postanowiliśmy przetestować to na x raportów wygenerowanych równocześnie. Zrobiliśmy tak i... klops. Pojawiły się błędy, jedne, te związane z użyciem słówka "static" udało się szybko wyeliminować, to pozostał jeszcze "concurrent access to file".

Stackoverflow.com  zaproponowało synchroniczny dostęp do plików za pomocą "lock". O ile na "początek" to miało sens, tj. wrzucam 'lock'a' "na szybko" i oddaję pierwszą wersję aplikacji użytkownikom do testów, o tyle w docelowej wersji (i kilka razy większej ilości użytkowników) taka wersja systemu była by bardzo niewygodna.

Z pomocą i pomysłem przyszedł mi Michał Kwiatos, który zaproponował rozwiązanie pt. "dla każdego requesta wygeneruj GUID, utwórz katalog z nazwą GUIDa, przekopiuj tam swoje pliki, wykorzystaj je do generowania raportu, a na koniec skasuj niepotrzebny już, śmieciowy katalog", co też zrobiłem i co... rozwiązało mój problem.

I tak sobie teraz myślę, że... najprostsze rozwiązania zwykle bywają najskuteczniejsze.

p.s. mój system docelowo będzie miał mniej niż 500 userów, czyli takie rozwiązanie wydaje się być optymalne. Gdybym tworzył system na +2k userów, to myślę, że na poważnie zastanowił bym się nad implementacją "modelu aktorów" w tym systemie.
p.s.2 wszelkie uwagi mile widziane

czwartek, 20 listopada 2014

user agent stylesheet

Wiedzieliście, może o istnieniu "user agent stylesheet" czyli o ukrytym pliku .css dokładanym przez przeglądarkę niejako "by default" ?? Ja się dowiedziałem o tym przed chwilą. I dzięki stackoveflow udało mi się temu zapobiec, dokładając plik reset.css.

Heh, taka mała ciekawostka, a jak bardzo potrafi wkurzyć :/

niedziela, 16 listopada 2014

dotPeek, czyli darmowe narzędzie do reverse engineering

dotPeek to nowe, darmowe narzędzie do deasemblacji (inżynierii wstecznej) od twórców ReSharpera, czyli JetBrains (link). Czym jest deasemblacja? Jest to próba odtworzenia kodów źródłowych na podstawie skompilowanych plików .dll lub .exe. O tym, że w .NET jest to możliwe wie każdy, kto zetknął się z mechanizmem refleksji, czyli... każdy szanujący się programista. Co jest fajnego w dotPeek, po za tym, że jest darmowe? To, że kod po deasemblacji wygląda na naprawdę zbliżony do tego, jaki widzimy w Visual Studio. Polecam zgrać i się nieco pobawić :)

poniedziałek, 29 września 2014

DevDay 2014 - relacja - dzień drugi (26.09.2014)

Dzień drugi to już właściwa konferencja. Pomijając występ początkowy oraz końcowy, przez większość dnia możliwe było wybranie jednego z dwóch wykładów, więc moja recenzja z założenia nie będzie obejmowała wszystkich dostępnych wykładów. Na szczęście, podczas sesji na salach dostępne były kamery wideo, więc w przyszłości możemy spodziewać się nagrać z sesji i nadrobić zaległości na youtubie lub innym vimeo.

Wychodząc z każdej z sesji, uczestnicy mogli wrzucić do koszyka kartkę jednego z trzech kolorów (zielony, żółty, czerwony) i w ten spos. ocenić prezentację

Dan North - Jackstones, a journey to Mastery.
No cóż. Ten wykład widziałem już wcześniej w internecie, jako zapis z którejś z poprzednich konferencji. Ogólnie wykład ciekawy i warty obejrzenia, jednak tak jak z każdym odgrzewanym kotletem, za każdym kolejnym razem smakuje nieco mniej. Jak ktoś jeszcze nie widział, to warte obejrzenia.
Kartka: zielona, bo mimo wszystko jednak warto tą prezentację obejrzeć.

Nial Merrigan - Defensive Programming 101 v5 - Common Security Mistakes in Web Applications
Bezpieczeństwo to jedna z tych rzeczy, na które warto zwracać uwagę, więc chętnie się na ten wykład wybrałem. Nial pokazał 10 najczęściej popełnianych błędów bezpieczeństwa. Zdecydowana większość była mi znana już wcześniej, ale takie perełki jak np. możliwość wyszukania plików web.config przez google, albo fakt, że iPhony nie walidują sieci wi-fi i łączą się ze wszystkim jak popadnie (np. jedziemy na lotnisko, zczytujemy nazwy darmowych sieci wifi, jedziemy w inne miejsce, tworzymy sieci wifi o takich samych nazwach i polujemy na jeleni metodą na "men in the middle" nie wiedziałem). Generalnie fajna sesja, na której zdecydowanie warto było być.
Kartka: zielona (zdecydowanie zasłużenie)

Qi - Hacking the mind: How Art can help us talk (and teach) technology
Po nazwie spodziewałem się sporo. Myślałem, że zostaną przedstawione jakieś fajne sposoby uczenia się. Po prowadzącym też spodziewałem się sporo. W końcu myślałem, że będzie albo coś o hakerstwie, albo o technikach uczenia. Niestety sporo się zawiodłem. Sesja była mdła, nieco zbyt nudna i bez pomysłu. Niby autor coś chciał nam przekazać np. pokazując fragment gazety mówił, że wiadomość ma być krótka i zwięzła przy czym... strasznie usypiał nas całą prezentacją, która zresztą trwała więcej niż było na nią przeznaczone. Generalnie, przez większość czasu się wynudziłem. Całą prezentację "uratowała" końcówka, dosłownie ost. 5 min. Czy było warto? Hmmm, ja tam się wynudziłem i generalnie żałowałem, że nie wybrałem się na konkurencyjną sesję.
Kartka: żółta (gdyby zakończył "o czasie", czyli bez ost. 5-7 min., z całą pewnością była by czerwona).

Rob Ashton - React + NPM for Great Good
Nie ma co ukrywać, na ten występ poszedłem specjalnie dla Roba. Temat jego wystąpienia był rzeczą względną. Był Rob i miało być fajnie. I w sumie tak też było. Rob pokazywał na scenie swoją żywiołowość oraz umiejętności posługiwania się VIM'em, opowiadając o kolejnym super-duper javoscriptowym frameworku przy okazji nabijając się z Angular.JS. Sam temat prezentacji wyglądał na taki niezbyt skomplikowany tutorial, Rob mówił bardzo żywiołowo i.. szybko. Tak szybko, że czasami nawet za szybko i momentami miałem problemy ze zrozumieniem o czym mówi. O ile do samej prezentacji można się było przyczepić, o tyle żywiołowa forma prezentacji była jakże miłą odmianą po usypiającej sesji Qi.
Kartka: zielona, głównie za sympatię do prowadzącego (i żywiołowość wystąpienia).

Kasia Mrowca - Art of Saying NO
Kolejny wykład, po którym spodziewałem się dowiedzieć czegoś ciekawego i... na którym się srodze zawiodłem. Może i Kasia się przygotowała, ale... mówiła dużo ogólników, mało konkretów. O ile na normalnej konferencji na jakiejś grupie .NET pewnie by to było ok, ale... na DevDay jednak publika jest nieco inna. Tutaj przyjechali sami entuzjaści, którzy "samorozwój" katują w praktyce na lewo i prawo od iluś tam lat. Osobiście byłem zawiedziony tym wystąpieniem i zdecydowanie spodziewałem się czegoś lepszego.
Karta: żółta (choć zastanawiałem się nad czerwoną).

Paul Stack - What is DevOps and How It Can Help My Bussiness Succeed?
Mimo iż stwierdzenie "DevOps" od dawna krąży w środowisku, to osobiście nie wiedziałem o co w tym chodzi, więc postanowiłem się dowiedzieć. I myślę, że moje oczekiwania zostały spełnione. Podczas prezentacji dowiedziałem się, że termin ten odnosi się do "Dev" (programistów), którzy równocześnie są też "Ops" (Administratorzy/Sieciowcy wdrażający ich rozwiązania w korpo). Tyle w teorii, jednak w praktyce, nie ma takiego stanowiska jak "devops", a sam termin "devops" to raczej kwestia kultury przedsiębiorstwa i panujących tam stosunków między różnymi specjalizacjami (płynne przechodzenie z admina w deva i na odwrót). Resztę prezentacji Paul pokazywał narzędzie do badania ruchu sieciowego opartego na logach linuxa oraz jak poprzez analizę tych logów sprawdzać, czy "jest jeszcze jest ok, czy już nie jest ok".
Kartka: zielona (całkiem przyjemna sesja).

Simon Brown - Software Architecture vs Code
Autor w założeniu starał się pokazać, że światy architektów i ich UML oraz programistów i ich "kodu" są wspólne i da się je połączyć, przy okazji starając się uzmysłowić kontekst i potrzebę samodoskonalenia poprzez analogię z łódką i łowieniem ryb, a... wyszło nie do końca wiadomo co. Jak tak sobie to teraz przypomnę, to w gruncie rzeczy trudno jest mi sobie uzmysłowić, co pozytywnego wyniosłem z tej sesji? To że samo przeczytanie książki o łowieniu ryb nic nam nie da, bo jeszcze trzeba zawartą tam wiedzę dostosować do otaczających nas warunków? Hmmm? Chyba to jednak nieco za mało jak na taką konferencję.
Kartka: zielona (bo było nieco śmiesznie, choć obecnie dałbym nieco gorszą ocenę). 

Po ost. sesji, nastał "beer time", czyli dalsze debaty. Najpierw na korytarzach uczelnii medycznej, na której odbywała się konferencja, a nast. w wynajętej knajpie.

Podsumowanie: Konferencja jak najbardziej na plus. Warsztaty z Danem były na całkiem fajnym poziomie (kilka nowych, inspirujących rzeczy), wykłady podczas konferencji ok (ale raczej takie sobie), organizacja na najwyższym możłiwym poziomie (wszystko blisko, koło siebie, dobra sala itp), spotkanie Krakowskiej grupy .NET (fajny dodatek) i możliwość spotkania się i pogadania z mnóstwem innych pasjonatów (najfajniejsza część konferencji). Fajnie było, chyba głównie z uwagi, na możliwość wyjścia ze swojej "jaskini" i spotkania innych, podobnych do siebie "geeków", których okazało się być zdecydowanie więcej niż się spodziewałem ;).
Fajnie było i do zobaczenia w przyszłości :)

DevDay 2014 - relacja - dzień pierwszy (25.09.2014)

Za nami najpopularniejsza, a przynajmniej najbardziej oczekiwana konferencja związana ze środowiskiem programistów .NET w 2014 roku, czyli Devday 2014.

Organizowana przez ABB konferencja była od dawna oczekiwana w środowisku, a problemy z dostaniem wejściówki tylko to potwierdziły. Pierwsza tura darmowych biletów rozeszła się w 5 min, druga w 2 min., więc postanowiłem nie czekać i wykupiłem płatne warsztaty, dzięki czemu bilet na bądź co bądź darmową konferencję dostałem gratis.

W związku z powyższym pozwoliłem pokusić się o małą recenzję tego, bądź co bądź bardzo wyczekiwanego eventu.

Dzień 1, 25.09.2014 (czwartek)
W czwartek odbyły się dwa szkolenia. Jedno z Angular.Js z Tiberu Covaci, oraz drugie  "Accelerated Agile: from months to minute" z Dan'em North. Ja wybrałem się na szkolenie z Agile ponieważ zarówno temat jak i prowadzący wydawali mi się bardziej interesujący. Inna sprawa, iż uważam, że angulara dużo lepiej i taniej można się nauczyć z jakiś książek/tutoriali niż z jednodniowego szkolenia.

Szkolenie składało się z 5 części tematycznych, trwających 50-70 min. każda z przerwami na kawę, toaletę oraz obiad. Podczas szkolenia byliśmy podzieleni na 7 sześcioosobowych zespołów, wewnątrz których mieliśmy wykonywać mniej lub bardziej skomplikowane zadania w stosunkowo krótkich okresach czasu (2-3 min.). Idea była prosta -> jest x ludzi w zespole i bardzo ograniczony czas, a trzeba dojść do konsensusu i wystosować wspólne stanowisko grupy wobec podanego tematu. A tematy? Różne, od tego, jak ma się nazywać zespół, na czym ma się skupić prowadzący podczas zajęć, po różne elementy cyklu wytwarzania oprogramowania. Szkolenie odbywało się więc w formie mniej lub bardziej luźniej zabawy, za to z elementem "tykającego zegarka".

Ok. A gdzie w tym to całe "mięcho", po które przyszliśmy? Hmmm, pierwsze sesje były raczej takie "zapoznawcze" oraz mniej lub bardziej ogólnikowe np. tworzenie oprogramowania składa się z 3 faz: 
- badawcza (testujemy technologię, narzędzia, koncepcję itp.)
- działającego prototypu (jesteśmy w stanie pokazać klientowi coś co działa mniej lub bardziej zgodnie z założeniami)
- odtwarzalnej produkcji na masową skalę (cykl zmniejszania kosztów i zwiększania zysków, czyli ktoś inny może odtworzyć naszą pracę mniejszym nakładem sił)

Była też cała sesja poświęcona tworzeniom wersji "spike" oraz "prod". Znałem wcześniej pojęcie PoF, ale nie znałem pojęcia spike
Jedak największe wrażenie na mnie wywarły 2 ostatnie sesje. 

Pierwsza z nich, związana z ryzykiem utrzymywania aplikacji i związanymi z nią testami, próbowała odpowiedzieć na pytanie, czy "pokrycie kodu testami" to najlepszy sposób mierzenia oprogramowania? Zdaniem prowadzącego niekoniecznie. Zamiast bawić się w automat, powinniśmy rozdzielić naszą funkcjonalność, pod względem "skomplikowania" oraz "konsekwencji wystąpienia błędu (jak bardzo nas to zaboli)" w odniesieniu do "kontekstu" w jakim działamy (kontekst zazwyczaj zna tylko "biznes"). Idea, którą starał nam się przekazać Dan, polegała na tym, że nie każda część syst. musi być równo przetestowana (np. unit testami). Że czas, który poświęcili byśmy na pisanie testów dla mało znaczącego i stosunkowo prostego elementu, dużo lepiej jest spożytkować na dodatkowe testy tam, gdzie jak coś się wywali to nas (i nasz biznes) mocno zaboli. Dan wspomniał też, że zazwyczaj jak trafimy na element, który jest zarówno bardzo skomplikowany jak i bardzo istotny biznesowo, to... najczęściej da się go rozdzielić na kilka mniejszych elementów i... choćby testowanie jest wtedy łatwiejsze.

Druga, sesja, która mi się bardzo podobała, to była sesja związana z wycenianiem czasu trwania projektów. Coś, z czym często programiści mają problem. Jak się okazało, z ok ~40 os. na sali, tylko 4-5 czuły się w tym w miarę mocne. Dan podszedł do tematu nieco inaczej. Nie pokazywał nam jakiś "magicznych" metodologii przepowiadania przyszłości, a posłużył się metaforą przewidywania pogody. O ile w przypadku prognoz pogody, mamy do czynienia z 4 zmiennymi i... nikt nie wymaga od prognoz specjalnej dokładności, o tyle w przypadku tworzenia oprogramowania tych zmiennych jest znacznie więcej (często od 8 w górę), a... wszyscy wymagają od nas dokładnego przewidywania, nawet na kilka mieś. do przodu.
Zamiast tradycyjnego wróżenia z fusów nt. pracochłonności, Dan zaproponował odwrócenie procesu, tzn. biznes powinien się zadeklarować, ile jest w stanie na dany projekt wydać oraz ile planuje na nim zarobić. Podając pewne widełki, np. 50-150 tyś. dolarów, można przyjąć pewien okres prac programistycznych, np. 3-9 mieś., i na tej podstawie prognozować, czy skończenie projektu jest prawdopodobne. Nast. wraz z upływem czasu i wzrostem wydanych kosztów, śledzić na bieżąco i doprecyzowywać szacowanie np. po wydaniu 40 tyś. dol. spróbować oszacować, czy już mamy połowę, czy dopiero 1/3. I później, wraz z biegiem czasu i coraz lepszym poznawaniem tematu prognozować, czy dany projekt w ogóle ma sens.
Może i nie jest to super opis tego, o czym mówił Dan, ale jest to mniej więcej pogląd na wycenianie, jaki warto jest zacząć rozważać, skoro wcześniejsze próby wyceniania zwyczajnie się nie sprawdzają.

Ogólnie warsztaty z Danem były całkiem miłe i przyjemne. Gdybym miał je ocenić to? Hmmm, z całą pewnością były inspirujące i coś z nich wyniosłem, a pewne przemyślenia będę się starał włączyć do rzeczywistych projektów. Czego zabrakło? Z całą pewnością narzędzi, SCRUM-u, i innych "sformalizowanych" specyfik. Ale czy na pewno zabrakło? Hmmm.
A ocena? Pocz. myślałem o 7/10, ale obecnie, po powrocie do domu bardziej skłaniał bym się do 8/10.

Po warsztatach, poszedłem wziąć prysznic i nieco odpocząć, ponieważ tego samego dnia swoje spotkanie miała również Krakowska grupa .NET.

Do siedziby ABB dotarłem tuż przed rozpoczęciem prelekcji przez Maćka Aniserowicza i nie żałuję, bo wcześniejszą prezentację Michała o F# miałem okazję już wcześniej zobaczyć na spotkaniu Warszawskiej grupy .NET.
Maciek mówił o Dependency Injection i jak ktoś czyta jego bloga to w sumie niczego zaskakującego się podczas tej prezentacji nie dowiedział, za to to, co było miłe podczas tego spotkania, to ilość ludzi, jaka się zebrała (były problemy z miejscami stojącymi na sali), a także darmowe piwo i pizza (na koszt tretton37) podczas spotkania o losowaniu licencji na R# nie wspomnę ;)

Po spotkaniu większość devów udała się na miasto w celu dalszej dyskusji mniej lub bardziej palących nas spraw. Fajnie było znowu pobyć w wśród większej ilości, często bardziej doświadczonych devów i powymieniać się własnymi, często jakże różnymi doświadczeniami.

czwartek, 18 września 2014

Generowanie PDF z wykorzystaniem Nancy, Pechkin, wkhtmltopdf

Jednym z zadań, jakie dostałem było wygenerowanie raportu, który równocześnie miał się wyświetlać jako html, jak i pdf. Moją pierwszą myślą, było stworzenie tego raportu jako www, a nast. zamiana tego www w pdf. Dodatkowo, chciałem dać użytkownikowi, aby sam wybrał, czy rezultat raportu chce otrzymać jako html, czy jako pdf. Jako web frameworku wykorzystałem nancyfx.

Jako bibliotekę, która zamienia html na pdf, wykorzystałem darmową bibliotekę, dostarczoną przez google, czyli wkhtmltopdf. Ta biblioteka jest dużo lepsza, od konkurencyjnej itextsharp ponieważ itextsharp na chwilę obecną nie radzi sobie z bardziej skomplikowanymi html'ami (w moim przypadku był to brak chart'ów o których wspomniałem w moim poprzednim wpisie).

Aby korzystać płynnie z wkhtmltopdf w .NET, skorzystałem z darmowej biblioteki Pechkin (link do githuba). Przykład wykorzystania pechkin'a z wkhtmltopdf można znaleźć na githubie ale również np. na blogu Ulises Reyes.
Ulises po za kilkoma przykładami użycia, informuje nas również o kilku ważnych aspektach korzystania z Pechkina:

  • It's trivial, here are some gotchas though:
  • GIF Images are not supported
  • Paths to images must be fully qualified as URLs (http://example.com/a/b/image.jpg) or file URIs (file://host/path)
  • Resources over HTTPS cannot be fetched through URLs. You can get around this by specifying the path as a file URIs.
  • References CSS files are supported, I found it easier to write inline CSS (classes in the same document enclosed in a style tag)
Ok. Mamy bibliotekę (napisaną w C), do zamiany html'a w pdf. Mamy adapter, aby wykorzystać tą bibliotekę w .NET. Brakuje nam jeszcze odpowiedniego kodu, aby wykorzystać to w naszej ukochanej Nancy. Na szczęście, natknąłem się na podobny wpis na blogu Shane Mitchell link. Tam wprawdzie była wykorzystywana inna biblioteka, ale nic nie stało na przeszkodzie, aby wszystko połączyć w jedną całość i utworzyć klasę, generującą odpowiedni widok:


using Nancy;
using Nancy.Responses;
using Nancy.ViewEngines;
using Pechkin;
using Pechkin.Synchronized;
using System.Drawing.Printing;
using System.IO;

namespace Nancy.MVC
{
    public static class ResponseAsPDF
    {
        public static Response RenderToPdfPechkin(NancyModule module, string viewName, dynamic model)
        {
            string content = GetPageContent(module, viewName, model);
            SynchronizedPechkin sc = new SynchronizedPechkin(new GlobalConfig().SetMargins(new Margins(0, 0, 0, 0))
                .SetDocumentTitle("Ololo").SetCopyCount(1).SetImageQuality(100)
                .SetLosslessCompression(true).SetMaxImageDpi(-1).SetOutlineGeneration(true).SetOutputDpi(-1).SetPaperOrientation(true)
                .SetPaperSize(PaperKind.Letter));
         
            byte[] pdfBuf = sc.Convert(new ObjectConfig().SetLoadImages(true)
            .SetPrintBackground(true)
            .SetAllowLocalContent(true)
            .SetScreenMediaType(true)
            .SetRunJavascript(true)
            .SetCreateExternalLinks(true), content);
         
            return new StreamResponse(() =>
            {
                var pdfOutput = new MemoryStream(pdfBuf);
                pdfOutput.Seek(0, SeekOrigin.Begin);
                return pdfOutput;
            }, "application/pdf");
        }
        private static string GetPageContent(NancyModule module, string viewName, dynamic model)
        {
            ViewLocationContext viewLocationContext = new ViewLocationContext()
            {
                Context = module.Context,
                ModuleName = module.GetType().Name,
                ModulePath = module.ModulePath
            };
            var rendered = module.ViewFactory.RenderView(viewName, model, viewLocationContext);
            var content = "";
            using (var ms = new MemoryStream())
            {
                rendered.Contents.Invoke(ms);
                ms.Seek(0, SeekOrigin.Begin);
                using (TextReader reader = new StreamReader(ms))
                {
                    content = reader.ReadToEnd();
                }
            };
            return content;
        }
    }
}






Google Charts w ASP.MVC (Razor)

Do rysowania wykresów za pośrednictwem ASP.MVC postanowiłem użyć darmowej biblioteki dostarczonej przez google, czyli chart. Wykresy rysuje się w tym w sposób bardzo prosty i przyjemny, tj. za pomocą javascriptu. Przykłady są dobrze opisane, oraz zawierają odnośnik do jsfiddle.
Całość sprowadza się, do odniesienia się do wgrania zew. biblioteki rys.
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1','packages':['corechart']}]}"></script>
wybrania miejsca, w którym ma się ten wykres narysować:
     <div id="piechart" style="width: 900px; height: 500px;"></div>
stworzenia metody rysującej oraz "podpięcie" jej pod delegata:
      google.setOnLoadCallback(drawChart);
      function drawChart() {
        var data = google.visualization.arrayToDataTable([
          ['Task', 'Hours per Day'],
          ['Work',     11],
          ['Eat',      2],
          ['Commute',  2],
          ['Watch TV', 2],
          ['Sleep',    7]
        ]);
        var options = {
          title: 'My Daily Activities'
        };
        var chart = new google.visualization.PieChart(document.getElementById('piechart'));
        chart.draw(data, options);
      }

Ok.Mamy javascript, mamy jsfiddle, na którym możemy przetestować nasz odpowiednik wykresu, a nawet kilka wykresów pod sobą. A co jeżeli jako źródło danych, chcieli byśmy wykorzystać model z naszego ASP.MVC ??

Na szczęście istnieje znacznik (tag) <text>  </text> który możemy wykorzystać.
Poniżej przykład takiej metody:

        function drawCurrency() {
            @if (Model.Tasks != null && Model.Tasks.Count > 0)
            {
                <text>
                var data = google.visualization.arrayToDataTable([
                ['Task', 'Hours per Day'],
                @foreach (var task in @Model.Tasks)
                {
                    <text>
                    ['@task.name', parseFloat('@task.hour')],
                    </text>
                }
                ]);
                var chart = new google.visualization.PieChart(document.getElementById('piechart'));
                chart.draw(data, options);
                </text>
            }
        }

piątek, 29 sierpnia 2014

SQL Update dst set xyz, from src

Jest to wzór przykładowego update tabeli w t-sql, w oparciu o wyniki innej tabeli, z innej bazy danych. Często go stosuję,  a ciągle zapominam tej składni, więc... postanowiłem to sobie zachować "na przechowanie".


USE [dstInstancja]
GO

UPDATE dst
   SET [zakup] = src.[zakup]
          ,[oplata] = src.[oplata]
 FROM [dbo].[typ_transakcji] dst join [SRVxy\NazwaSerwera].[srcInstancja].[dbo].[typ_transakcji] src
 on dst.Id = src.Id

GO

środa, 20 sierpnia 2014

??

Od jakiegoś czasu mam okazję korzystać z ReSharpera (kto jeszcze nie zna tego pluginu, to niech jak najszybciej nadrobi zaległości) i dzisiaj podpowiedział mi pewną fajną, nieznaną mi wcześniej konstrukcję języka C#

Zamiast klasycznego:
var y = x.ProductName != null ? x.ProductName : string.Empty;

Można zastosować
var y = x.ProductName ?? string.Empty;

Krótszy i czytelniejszy kod zawsze na propsie, więc jak dla mnie jest git.

sobota, 2 sierpnia 2014

Console2, czyli ulepszony cmd.exe

Jak to napisał Roy Osherove na swoim twitterze:
If you’re using git from the vs menus, you’re not getting out of your comfort zone and not really learning a new skill.

Konsola i skrypty bashowe to potężne narzędzie. Wiedzą o tym linuksiarze, ale również i w świecie M$ ręczne wpisywanie komend powoli wraca do łask. Zaczynając od informacji administracyjnych, poprzez korzystanie z Git'a oraz Bash'a, na korzystaniu z NuGet'a kończąc (wewnętrzna konsola VS). Konsola w wielu przypadkach potrafi być bardzo użyteczna. Ale czy skazani jesteśmy na standardowe cmd.exe? Nie koniecznie. Na szczęcie są dostępne na rynku różne nakładki, które rozbudowują jej funkcjonalność. Jedną z takich nakładek na cmd.exe, jest opisana przez Scotta Hanselmana 'Console2'.

Po więcej informacji szczegółowych, odsyłam do bloga Scotta: Console2ABetterWindowsCommandPrompt

Od siebie dodam jeszcze, że w połączeniu z Git-em sprawuje się naprawdę fajnie (swobodny resize, konfigurowanie kolorów pod Git'a i wiele innych bajerów).
Generalnie, takie nowe, fajniejsze cmd.exe.

P.S. Do korzystania z konsoli przekonał mnie Mateusz, czyli mój nowy kolega w zespole
P.S.2 Krótki "mini tutorial" jak dodać skrót "git'a" do cmd (Mój komputer -> zaawansowane ustawienia systemu -> Zaawansowane -> Zamienne środowiskowe -> Path -> dopisujemy naszą ścieżkę, w której mamy Gita).


P.S.3 Plik konfiguracyjny, zachowany dla potomności:


<?xml version="1.0"?>
<settings>
    <console change_refresh="10" refresh="100" rows="36" columns="104" buffer_rows="500" buffer_columns="0" shell="" init_dir="C:\Users\zchpit" start_hidden="0" save_size="1">
        <colors>
            <color id="0" r="0" g="0" b="0"/>
            <color id="1" r="0" g="0" b="128"/>
            <color id="2" r="0" g="150" b="0"/>
            <color id="3" r="0" g="150" b="150"/>
            <color id="4" r="170" g="25" b="25"/>
            <color id="5" r="128" g="0" b="128"/>
            <color id="6" r="128" g="128" b="0"/>
            <color id="7" r="192" g="192" b="192"/>
            <color id="8" r="128" g="128" b="128"/>
            <color id="9" r="0" g="100" b="255"/>
            <color id="10" r="0" g="255" b="0"/>
            <color id="11" r="0" g="255" b="255"/>
            <color id="12" r="255" g="50" b="50"/>
            <color id="13" r="255" g="0" b="255"/>
            <color id="14" r="255" g="255" b="0"/>
            <color id="15" r="255" g="255" b="255"/>
        </colors>
    </console>
    <appearance>
        <font name="Consolas" size="15" bold="0" italic="0" smoothing="0">
            <color use="0" r="0" g="255" b="0"/>
        </font>
        <window title="Console" icon="" use_tab_icon="1" use_console_title="0" show_cmd="1" show_cmd_tabs="1" use_tab_title="1" trim_tab_titles="20" trim_tab_titles_right="0"/>
        <controls show_menu="0" show_toolbar="0" show_statusbar="0" show_tabs="1" hide_single_tab="1" show_scrollbars="1" flat_scrollbars="0" tabs_on_bottom="1"/>
        <styles caption="1" resizable="1" taskbar_button="1" border="1" inside_border="2" tray_icon="1">
            <selection_color r="255" g="255" b="255"/>
        </styles>
        <position x="-1" y="-1" dock="-1" snap="0" z_order="0" save_position="0"/>
        <transparency type="1" active_alpha="215" inactive_alpha="215" r="0" g="0" b="0"/>
    </appearance>
    <behavior>
        <copy_paste copy_on_select="1" clear_on_copy="1" no_wrap="1" trim_spaces="1" copy_newline_char="0" sensitive_copy="1"/>
        <scroll page_scroll_rows="0"/>
        <tab_highlight flashes="3" stay_highligted="1"/>
    </behavior>
    <hotkeys use_scroll_lock="1">
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="83" command="settings"/>
        <hotkey ctrl="0" shift="0" alt="0" extended="0" code="112" command="help"/>
        <hotkey ctrl="0" shift="0" alt="1" extended="0" code="115" command="exit"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="84" command="newtab1"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="113" command="newtab2"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="114" command="newtab3"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="115" command="newtab4"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="116" command="newtab5"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="117" command="newtab6"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="118" command="newtab7"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="119" command="newtab8"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="120" command="newtab9"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="121" command="newtab10"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="49" command="switchtab1"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="50" command="switchtab2"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="51" command="switchtab3"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="52" command="switchtab4"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="53" command="switchtab5"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="54" command="switchtab6"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="55" command="switchtab7"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="56" command="switchtab8"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="57" command="switchtab9"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="48" command="switchtab10"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="9" command="nexttab"/>
        <hotkey ctrl="1" shift="1" alt="0" extended="0" code="9" command="prevtab"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="87" command="closetab"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="0" code="82" command="renametab"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="1" code="45" command="copy"/>
        <hotkey ctrl="1" shift="0" alt="0" extended="1" code="46" command="clear_selection"/>
        <hotkey ctrl="0" shift="1" alt="0" extended="1" code="45" command="paste"/>
        <hotkey ctrl="0" shift="0" alt="0" extended="0" code="0" command="stopscroll"/>
        <hotkey ctrl="0" shift="0" alt="0" extended="0" code="0" command="scrollrowup"/>
        <hotkey ctrl="0" shift="0" alt="0" extended="0" code="0" command="scrollrowdown"/>
        <hotkey ctrl="0" shift="0" alt="0" extended="0" code="0" command="scrollpageup"/>
        <hotkey ctrl="0" shift="0" alt="0" extended="0" code="0" command="scrollpagedown"/>
        <hotkey ctrl="0" shift="0" alt="0" extended="0" code="0" command="scrollcolleft"/>
        <hotkey ctrl="0" shift="0" alt="0" extended="0" code="0" command="scrollcolright"/>
        <hotkey ctrl="0" shift="0" alt="0" extended="0" code="0" command="scrollpageleft"/>
        <hotkey ctrl="0" shift="0" alt="0" extended="0" code="0" command="scrollpageright"/>
        <hotkey ctrl="1" shift="1" alt="0" extended="0" code="112" command="dumpbuffer"/>
        <hotkey ctrl="0" shift="0" alt="0" extended="0" code="0" command="activate"/>
    </hotkeys>
    <mouse>
        <actions>
            <action ctrl="0" shift="0" alt="0" button="1" name="copy"/>
            <action ctrl="0" shift="0" alt="0" button="1" name="select"/>
            <action ctrl="0" shift="0" alt="0" button="3" name="paste"/>
            <action ctrl="1" shift="0" alt="0" button="1" name="drag"/>
            <action ctrl="0" shift="0" alt="0" button="2" name="menu"/>
        </actions>
    </mouse>
    <tabs>
        <tab title="Console2" use_default_icon="0">
            <console shell="" init_dir="" run_as_user="0" user=""/>
            <cursor style="0" r="255" g="255" b="255"/>
            <background type="0" r="0" g="0" b="0">
                <image file="" relative="0" extend="0" position="0">
                    <tint opacity="0" r="0" g="0" b="0"/>
                </image>
            </background>
        </tab>
        <tab title="PowerShell" use_default_icon="0">
            <console shell="C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" init_dir="C:\Users\zchpit" run_as_user="0" user=""/>
            <cursor style="0" r="255" g="255" b="255"/>
            <background type="0" r="0" g="0" b="0">
                <image file="" relative="0" extend="0" position="0">
                    <tint opacity="0" r="0" g="0" b="0"/>
                </image>
            </background>
        </tab>
    </tabs>
</settings>

Polecane laptopy/netbooki

Całkiem niedawno miałem problem z moim laptopem. Całe szczęście, problem dotyczył jedynie modułu zasilania mojego laptopa i  do przywrocenia go do stanu używalności wystaczyła wizyta w serwisie komputerowym. Nie zmienia to jednak faktu, że przez moment liczyłem się z koniecznością zakupu nowego sprzętu. I powiem, miałem z tym niemały ból głowy. Jaki laptop wybrać, skoro zgodnie z prawem Moora moc obliczeniowa komputerów podwaja się co każde 2 lata?

Co więc zrobiłem? Zapytałem się znajomego z "help desku", który w sprzęcie siedzi na co dzień. I jaką odp. dostałem? Że nawet on tego wszystkiego nie ogarnia bo zmiany idą za szybko. Za to skierował mnie na fora branżowe. Pomocny okazał się mój nowy kolega w zespole , który podesłał mi link do forum PC FORMAT, na którym to analizują aktualnie dostępne komputery i analizują na bierząco co się opłaca kupować link.

Dodatkowo, na tym forum raz w mieś. pojawia się temat z "zestawieniem miesiąca". Link do aktualnego zestawienia (lipiec 2014)

P.S. Gdyby ktoś potrzebował namiary na sprawdzony serwis komputerowy na Mokotowie, to polecam Centrum Serwisowe MAGNUS  na Puławskiej 107D

Trello

Kolejnym fajnym narzędziem, którego stosowanie warto jest rozważyć jest trello. Trello jest darmową aplikacją internetową, spełniającą rolę znanej i lubianej "tablicy z mazakami/karteczkami". "Tablica z karteczkami" to nic innego, jak stojąca w pokoju tablica z karteczkami, ewentualnie tablica z pisakami, na której wpisuje się zadania (najczęśniej są to nr. zgłoszeń z bugtrackera), osoby do których są przypisane, oraz stan danego zadania (todo, doing, done). W ten sposób, managment wchodząc do pokoju, jest w stanie ocenić "stan aktualnych prac" bez przerywania pracy programisty. Z zastosowaniem trello, nawet nie musi wchodzić do pokoju :D

O ile niektóre, rozbudowane 'bugtrackery" posiadają wbudowaną podobną funkcjonalność lub można ją dokupić (np jira), o tyle wielu z nich nadal im tego brakuje. Jedną z zalet trello jest fakt, ze w podstawowej wersji jest w pełni darmowe (syst. płatności oparty o mikropłatności za rozszerzenia).

Kolejną zaletą, która mi się osobiście spodobało, to pełna integracja z kontem  google (gmail), dzięki czemu nie muszę pamiętać dodatkowego hasła. Wprawdzie przy stosowaniu keepass teoretycznie nie muszę, ale mimo wszystko dla mnie takie rozwiązanie jest dużo wygodniejsze ;)).

P.S. Trello można też używać w życiu prywatnym, np. do kontrolowania prac związanych z remontem/zakupem mieszkania lub innych czynności dających podzielić się na mniejsze, skończone taski ;-)

MS SQL - DEADLOCK

Czasami zdarzy nam się, że procesy pracujące na bazie danych mogą się zakleszczyć. Nie wdając się w szczegóły, chodzi o równoczesne blokowanie jednych zasobów, oczekując na zwolnienie pozostałych. Szerzej to zagadnienie zostało opisane jako problem ucztujących filozofów.

A co, gdy taka syt. zdarzy nam sie na bazie danych?
a) dobrze by było się dowiedzieć, dlaczego dochodzi do zakleszczeń (np. sql profiler)
b) pomyśleć nad zmianą poziomu izolacji tranzakcji
c) wyśledzić odpowiedni proces za pomocą sp_who2 a nast. ubić zawieszony process, odblokowując tym samym zasoby dla innych procesów
exec sp_who2
kill SPID
 

czwartek, 31 lipca 2014

Rekruter

W czerwcu oraz na pocz. lipca miałem okazję uczestniczyć podczas rozmów kwalifikacyjnych na stanowisko młodszego programisty .NET (junior developer). Było to dla mnie spojrzenie na proces rekrutacji z tej nieco innej strony.  Jako, że od mojej opinii o kandydacie również nieco zależało, więc postaram się opisać moje wrażenia z tego procesu po "tej drugiej stronie".

Najpierw umieściliśmy ogłoszenie na kilku przeznaczonych do tego stronach oraz ulotki na kilku Warszawskich uczelniach. Po jakimś czasie, gdy pojawiła się grupa na fb o wdzięcznej nazwie netDevelopersPolandJobMarket to umieściłem tam nasze ogłoszenie z "widełkami płacowymi" oraz nieco większą ilością szczegółów nt. tego stanowiska (stos. technologia, zakres obowiązków itp. itd.).

A jak wyglądała sama rozmowa?
a) krótka, 5-20 min. rozmowa, podczas której my (Ja oraz dyrektor IT) opowiadaliśmy o firmie, naszym dziale IT, tym czym ewentualnie zajmował by się kandydat. Zadawaliśmy też kilka pytań nt. CV, które podesłał nam kandydat.
b) 30 min. codding test na laptopie w mojej obecności
c) "pytania z kartki", czyli mniej lub bardziej szczegółowe "pytania otwarte" nt. C#, .NET, MS SQL itp. itd.
d) ewentualna dalsza rozmowa z szefem IT

Zadania praktyczne były 4. Dwa z SQL oraz dwa z C#. Zadania były o zróżnicowanym stopniu trudności. Wydawało mi się, ze te z C# są trudniejsze, ale tylko do momentu, gdy jeden z kandydatów przyznał się, ze jedno z zadań mieli w SGGW na egaminie ;-)
To co mnie osobiście mocno zaskoczyło to... bardzo słaba znajomość T-SQL wśród kandydatów, którzy byli przepytywani. Dwie os., które "kumały cza-czę" zrobiły oba zadania w ok. 5-6 min. (mniej więcej ok 2-3 min. na zadanie). Niestety ponad połowa kandydatów nie zrobiła zadań z SQL w ogóle.

Z pytaniami "otwartymi" zazwyczaj było całkiem nieźle. Była to też okazja do "bardziej wnikliwego" porozmawiania z kandydatami (tymi co przeszli codding test). Podczas tej rozmowy, oprócz samych odp. na pytania, celem było też zwykłe poznanie kandydata. Tego, czy się interesuje technologią i w czym czuje się mocny, ale też, czy można z nim normalnie porozmawiać i czy da się z nim wytrzymać 8h*5 dni w tyg.

Jak ktoś przeszedł wszystkie etapy w miarę ok (codding test, pytania otwarte, sposób bycia) to zostawał na rozmowę z dyrektorem IT.

Wnioski:
a) 30 min. siedzenia i patrzenia jak ktoś koduje, to jednak zdecydowanie zbyt dużo zmarnowanego mojego czasu. Dobrze było by ten proces jakoś zautomatyzować, ale pozostając przy zadaniach praktycznych. Może jakieś codility, ale któreś z tych podst. poziomów trudności (ponieważ te wyższe zazwyczaj niewiele mają wspólnego z praktyką zastaną później w realnym życiu).
b) najlepszy możliwy kandydat, jaki nam się pojawił, przyszedł na rozmowe po umieszczeniu ogłoszenia o pracę na grupie fb (ogłsozenie z zakresem obowiązków, stos. technologią oraz widełkami płacowymi).



czwartek, 10 lipca 2014

Nie testuj na serwerze testowym!!!

Ten oto wpis, to nic innego jak konkluzja z ost. kilku dni w pracy. I broń boże, nie wykonuj na tych danych, żadnych aktualizacji "notowań, kursu walut" ani innych "co nocnych" jobów. Taka niestety nasuwa się konkluzja z ost. kilku dni.

A co to dokładnie oznacza?
Ano nic innego, ze Piotrek nie umie rozmawiać z ludźmi. Przejmując x syst. informatycznych po swoich poprzednikach, nie zawsze potrafił się dopytać, czy wersje testowe (aplikacji oraz bazy danych) służą do tego, aby programiści mogli na nich cokolwiek testować i broń boże puścili na tym, jakiś update. Szczególnie taki, który działa co noc na prod. i kilka dni temu się wysypał, a ja własnie zrobiłem na niego fixa. O to to nie. Aplikację powinno się przetestować lokalnie, a później, po stwierdzeniu że "u mnie działa" wgrywać od razu na produkcję :/

Jakiś czas temu, podjąłem się zadania przejęcia całej infrastruktury programistycznej w pewnej firmie po tym, gdy odszedł z niej ost. programista i przez kilka tyg. żadne ze stanowisk programistycznych nie było obsadzone. Dużo ich nie było, tj. 2, ale w zasadzie przejmowałem 12 mniej lub bardziej rozbudowanych syst,. informatycznych (największa baza 16 GB danych), a w praktyce żyjący własnym życiem mechanizm naczyń połączonych. Oczywiście, większość aplikacji miała swoich opiekunów biznesowych. O ile miałem parę spotkań z moim poprzednikiem, jednak w praktyce najczęściej koncentrowały się one wokół spraw bieżących, lub przyszłego, nowego syst. który trzeba dopiero napisać.

O ile, z ludźmi z IT rozmawiałem i... np. Adam mnie uprzedził, ze w jego syst. aplikacje "test" oraz "test2" nie są dla mnie dostępne (i stworzył mi inne środ. testowe) o tyle ludzi "biznesowych", którzy zazwyczaj obrażają się o to, ze mówię techniczne słowa, których nie rozumieją, o takie zmiany za bardzo nie podejrzewałem. I masz tu babo placek.

Wysypał się job robiący aktualizację. Znalazłem błąd, poprawiłem go i sru na test. Na teście przeszło to na prod. Fix zrobiony, sprawa rozwiązana i super. A tu niestety nie ma tak dobrze. Opiekun biznesowy, który nie umie pisać skryptów (bo po co mu to), ani tym bardziej zrobić backupu bazy... miał tam jakieś swoje dane, który nocny import mu nadgrał.

Oj Piotrek, Piotrek, I co żeś ty uczynił?
I co ważniejsze? Co też masz teraz zrobić? Porobić własne instancje testowe wszystkich działających usług, skryptów, aplikacji, baz danych? Co noc backupować bazy testowe? A może jednak rozwiązaniem jest, aby dziennie spędzać więcej czasu  na tel. rozmawiając z opiekunami biznesowymi, niż na faktycznym kodowaniu tych systemów?

Normalnie murarz, tynkarz, akrobata...

czwartek, 29 maja 2014

Task Scheduler - Windows Server 2000 vs 2008R2

Przenosząc skrypty .bat pomiędzy serwerami z serwera Windows 2000 na Windows 2008r2 napotkałem pewne problemy. Dlaczego warto robić skrypty .bat można się dowiedzieć choćby z książki A.Hunt, D.Thomas Pragmatyczny programista. Od czeladnika do mistrza w rozdziale "Wszechobecna automatyzacja".

Przenosząc te skrypty, miałem okazję spotkać się z dwoma niemiłymi dla mnie niespodziankami. 
Po pierwsze, zmienił się format daty, jaki stosuje się w skryptach. Aby uzyskać format daty yyyy-MM-ss (rok-miesiąc-dzień) w starszym windowsie (win xp, win server 2000) wystarczyło podać:
echo %DATE:~0,4%-%DATE:~5,2%-%DATE:~8,2%

W windows 7 oraz server 2008r2 trzeba to zrobić nieco inaczej:
@echo off
For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%a-%%b)
@echo on
echo  %mydate%


UWAGA: echo to... taki Console.Writeline w bashu... czyli... komenda na wypisanie zmiennej na ekran konsoli.


Drugim problemem z jakim się napotkałem to... uruchomienie programu w task schedulerze. Aby nie było zbyt łatwo, w ustawieniach (settings) task schedulera nie można podać pełnej ścieżki skryptu/programu tylko trzeba... wykorzystać 2 osobne, przeznaczone do tego pola (osobne pole na nazwę skryptu, osobne na nazwę programu):




P.S. Z innych spraw, jakie wynikły przy okazji przenoszenia tych skryptów na inny serwer, to ustawianie uprawnień do baz danych, linked serwerów i innych kwestii bezpieczeństwa, ale... to by trzeba było ustawić niezależnie typów serwerów (źródłowych/docelowych).
















sobota, 24 maja 2014

KeePass – przechowuj hasła bezpiecznie

Jednym z problemów, z jakimi spotykają się różni użytkownicy komputerów, posiadający dostęp do wielu zasobów (np. aplikacji internetowych, baz danych itp.) jest problem związany z ilością potrzebnych loginów i haseł. W teorii hasło do każdego konta powinno być inne, jednak w praktyce bardzo trudno jest pamiętać 20-50 różnych haseł do różnych kont. Na szczęście, z pomocą przychodzi nam darmowa aplikacja "KeePass", która będzie przechowywała za nas odpowiednie loginy i hasła w sposób bezpieczny (zaszyfrowany). My, jako użytkownicy, jedynie potrzebujemy znać hasło do naszego pliku z zaszyfrowanymi danymi w KeePass (który możemy przenosić między komputerami, np. za pośrednictwem pendrive), a już szczegółowe loginy i hasła do konkretnych stron, aplikacji, usług, baz danych znajdować się będą w KeePass-ie. 

Linki: 

środa, 14 maja 2014

Korzystanie z kilku plików konfiguracyjnych (*.config)

Jak powszechnie wiadomo, w jednej solucji możemy mieć wiele projektów. Każdy z tych projektów może posiadać własny plik konfiguracyjny. Problem może się pojawić w sytuacji, gdy w jednej solucji chcemy korzystać z wielu plików konfiguracyjnych. Przyjrzyjmy się pewnemu realnemu scenariuszowi.

Mamy nasza przykładową aplikację konsolową, która poprawnie działa. Zaszła jednak potrzeba wykorzystania web serwisu (WCF). Zgodnie z dobrymi praktykami, do obsługi WCF tworzymy nowy, osobny projekt jako bibliotekę DLL ('class library'). Aplikacja konsolowa, posiadała już swój plik konfiguracyjny (App.config), więc próba odwołania się konfiguracji naszej biblioteki za pomocą obiektu "ConfigurationManager" spowodowała przeglądanie pliku konfiguracyjnego aplikacji. Ponieważ chcemy oddzielić konfigurację biblioteki od konfiguracji aplikacji potrzebujemy mieć oba pliki rozdzielone oraz możliwość czytania z obu plików.

Jak to należy zrobić?
Rozwiązanie można podzielić na dwa etapy. Konfiguracyjny oraz programistyczny:

W projekcie:
a) zmieniamy nazwę pliku konfiguracyjnego biblioteki, aby oba pliki konfiguracyjne miały różne nazwy
b) we właściwościach pliku konfiguracyjnego biblioteki ustawiamy właściwość "Copy to output Directory" na "Copy always"
c) w projekcie z aplikacją ustawiamy referencję na projekt z biblioteką

W kodzie biblioteki, będziemy się odwoływać do nowego pliku konfiguracyjnego w "niestandardowy" sposób. Pisząc "niestandardowy" mam na myśli w sposób inny niż za pomocą obiektu "ConfigurationManager".

W kodzie, wykorzystujemy obiekt Configuration (System.ServiceModel.Configuration) poprzez wykorzystanie jego właściwości. Przykładowa klasa, za pomocą której będziemy korzystali z nowego pliku konfiguracyjnego wygląda tak:

    public class ConfigurationManagerWrapper
    {
        private Configuration cfg;
        public ConfigurationManagerWrapper()
        {
            var path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            var fileMap = new ExeConfigurationFileMap
            {
                ExeConfigFilename = string.Concat(path, "\\mail.config")
            };
            cfg = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
        }
        public string GetSetting(string key)
        {
            AppSettingsSection section = (cfg.GetSection("appSettings") as AppSettingsSection);
            var value = section.Settings[key].Value;
            return value;
        }
        public ChannelEndpointElement GetClient(string key)
        {
            var serviceModel = ServiceModelSectionGroup.GetSectionGroup(cfg);
            var endpoints = serviceModel.Client.Endpoints;
            if (endpoints.Count > 0)
                return endpoints[0];
            return null;
        }
        public T GetSection<T>(string sectionName)
        {
            return (T)ConfigurationManager.GetSection(sectionName);
        }
    }
Bardziej zaawansowany przykład wykorzystania takiego pliku .config można zobaczyć w przeznaczonym do tego projekcie na github mojego autorstwa stworzonym w celu demonstracji kodu.

Pomocne linki:
stackoverflow.com - how-do-i-retrieve-appsettings-from-the-assembly-config-file
weblogs.asp.net - cibrax - getting-wcf-bindings-and-behaviors-from-any-config-source.aspx

poniedziałek, 17 marca 2014

Szata kolorystyczna Visual Studio (VS color theme)

Przez bardzo długi okres czasu, programowałem na standardowych ustawieniach kolorów Visual Studio. Niedawno zobaczyłem u kolegi zupełnie inne ustawienie motywu graficznego, tj. kolorowe litery na czarnym tle. Poszukałem nieco po necie i znalazłem kilka stron, z gotowymi motywami:
galeria z motywami na blogu Scota Hanselmana
galeria z motywami na studiostyle.es

Interesuje okazało się pytanie na forum stackoverflow.com, które doprowadziło mnie do postu na blogu Jeffa Atwooda, z bardzo interesującą skórką zenburn. Jak na razie, ta skórka mi się podoba najbardziej, ponieważ jasno można odróżnić 0 od O oraz I od 1 (kolorami), a przy tym, kolory są bardzo stonowane (oszczędzają wzrok przy dłuższej pracy).

Git

Czym jest Git, mam nadzieję, że każdy szanujący się programista doskonale wie, a pozostałym przypomnę, że jest to rozproszony system kontroli wersji. Git powszechnie uważany jest, za najlepszy, dostępny na rynku system kontroli wersji. Porównanie Git-a z TFS, jakiś czas temu napisał mój ulubiony bloger .NET, czyli Maciej Aniserowicz -> 'w-czym-git-jest-lepszy-od-tfs'

Pomijając już wszelkie 'ohy i ahy' Maćka, które wygłasza za każdym razem, gdy tylko ktoś pozwoli mu się odezwać, Git ma kilka zalet, które na chwilę obecną bardzo mi się podobają:
- możliwość pracy off-line -> niestety w przeszłości, zdarzyła nam się syt., w której padł nam dysk na serwerze, na którym mieliśmy nasz serwer SVN. Dysk, a dokładniej dane dało się w końcu odzyskać, jednak te kilka dni programowania bez kontroli wersji do najprzyjemniejszych, a przynajmniej do najbardziej komfortowych nie należały. Wrzucając kod na git-a, można pracować 'off-line', a po podłączeniu się 'on-line' mamy pewność, że serwery będą działały tak jak należy i nie musimy się martwić o "spalenie się dysku"
- możliwość umieszczenia mojego kodu źródłowego w bardziej przyjaznej programiście formie, niż wklejanie go tutaj, co delikatnie mówiąc było lekko "wieśniackie".

Jako hosting, na pierwszy ogień poszedł GitHub ponieważ dla publicznych repozytoriów, jest darmowy link. Owszem, Github nie jest monopolistą i  istnieje konkurencja w postaci Bitbucket, który w dodatku pozwala na kilka prywatnych repozytoriów, ale od czegoś trzeba zacząć. Zawsze najpierw trzeba zrobić ten pierwszy krok.

Możliwe, że kiedyś się przeniosę na Bitbucket, albo inne podobne rozwiązanie, ale puki co, zapraszam na moje konto na github, gdzie w miarę możliwości będę się starał wrzucać moje programistyczne wypociny.

czwartek, 6 marca 2014

Przekierowanie poczty MS Exchange

Tak jak już wspomniałem w moim poprzednim wpisie nt. tworzenie konta mailowego w ms-exchange jako jedno z dodatkowych zadań dostałem opiekę administracyjną nad serwerem, na którym oprócz aplikacji CRM, zainstalowany jest również serwer pocztowy Exchange.

W poprzednim poście opisałem jak utworzyć nowe konto, oraz dodać je do grupy. W tym opiszę przypadek przekierowywania (forwardowania) maili do innej skrzynki pocztowej.

Jeżeli chcemy zrobić forward dla klienta wewnątrz domeny, to dobrze jest dla niego utworzyć konto w AD, jeżeli jednak mamy do czynienia forwardem do skrzynki pocztowej po za naszym AD, wtedy należy utworzyć nowy kontakt mailowy.

Na pocz. otwieramy klienta ms exchange i przechodzimy do zakładki "Recipient Configuration", gdzie tworzymy nowy kontakt mailowy ("New mail contact"). Uwaga: wykonujemy to na zakładce  'Recipient Configuration", a nie "Mail":

New contact, next, a nast. w oknie wpisujemy odpowiednie dane:

Teraz wchodzimy we właściwości (properties) istniejącego kontaktu, dla którego chcemy dołożyć forward.
Z opcji wybieramy "Mail Row Settings", a nast. zaznaczamy "Delivery Options" i właściwości (Properties). W nowo utworzonym okienku wybieramy "Browse", a nast. utworzony przez nas przed chwilą kontakt mailowy:

Nast. zaznaczamy (lub nie) checkbox z, czy maile mają przychodzić na obie skrzynki pocztowe, czy tylko na nową skrzynkę ("Deliver message to both forwarding address and mailbox").

Ok. Apply i... już działa nam nasz forward wiadomości.


wtorek, 4 marca 2014

Tworzenie konta mailowego w MS Exchange

Od pewnego czasu, jako jedno z moich zadań pobocznych dostałem "opiekę administracyjną" nad zewnętrznym serwerem, na którym oprócz aplikacji CRM jest również zainstalowany serwer mailowy. "Opieka administracyjna" obejmuje również opiekę nad serwerem "exchange", czyli serwer pocztowy.

W niniejszym wpisie, opiszę procedurę tworzenia/konfigurowania nowego użytkownika, ponieważ co jakiś czas zachodzi taka potrzeba, a podręczny manual z instrukcją obsługi zawsze lepiej mieć, niż nie mieć ;).

Zaczynamy od otworzenia aplikacji do zarządzania użytkownikami oraz komputerami 'Active Directory". W tym celu, w "kafelkach" w wyszukiwarce wpisujemy "active", a nast. wybieramy odpowiedni program:


W programie "Użytkownicy i komputery usługi Active Directory" do grupy "Users" dodajemy nowego użytkownika:

i uzupełniamy jego dane

na 'moim' serwerze był problem z 'wygasaniem' haseł, więc zaznaczam opcję, aby hasło nigdy nie wygasało:

Później już tylko okienko z podsumowaniem i zatwierdzenie stworzenia nowego usera.

Teraz otwieramy aplikację do usługi serwera pocztowego Exchange:

W ustawieniach serwera pocztowego tworzymy nową skrzynkę pocztową:


nast, wybieramy "User Mailbox",
Existing users, a nast. usera którego wcześniej utworzyliśmy:


później już tylko "next, next" i... mamy gotowe poczto kontowe.


Konto pocztowe możemy przetestować za pomocą przeglądarki internetowej wpisując do adresu przeglądarki:
https:/webmail.myexchangeemail.com/owa/
W moim konkretnym przypadku było to:
https://mail.nazwaHosta.pl/owa/auth/logon.aspx

 Blog, na którym bardziej szczegółowo opisano jako zrobić opisane jest tutaj. Do logowania się, przez przeglądarkę używamy samego loginu konta (bez małpy).

Teraz, kiedy mamy utworzone i działające konto pocztowe powiązane z kontem w AD, może zajść potrzeba dodania usera do grupy np. "wszyscy", "działX", "departamentY". Jeżeli grupy zostały utworzone w podobny sposób, to możemy to zrobić w AD:

Wybieramy naszego użytkownika, prawy przycisk myszy na "właściwości, a nast. zakładka "Członek grupy"
Wybieramy przycisk "Dodaj...", w polu tekstowym wpisujemy nazwę naszej grupy, nast. klikamy przycisk "Sprawdź nazwy" (jeżeli grupa istnieje, to jej nazwa w polu tekstowym zostanie podkreślona)
oraz "OK".

Teraz we właściwościach wybranego użytkownika, w zakładce "Członek grupy" powinna się pojawić nazwa grupy, do której użytkownik został dodany.



P.S. Jestę adminę  :-D

AutoMapper

    Jednym z ćwiczeń praktycznych podczas "Zaawansowanego szkolenia z .NET 4.0" organizowanego przez Comarch (opis szkolenia tutaj), było napisanie własnego "AutoMappera" na kilka możliwych sposobów (refleksja, dynamic).
    A czym właściwie jest "AutoMapper"? AutoMapper to biblioteka, która udostępnia funkcjonalność automatycznego przepisywania wartości pól jednej klasy do drugiej. Potrzeba posiadania takiej funkcjonalności często zachodzi w sytuacji wykorzystywania w projekcie ORM. Zamiast pisać kod, służący do mapowania pól/właściwości z jednej klasy do drugiej, lepiej jest wykorzystać gotowe, darmowe rozwiązanie jakim jest AutoMapper, szczególnie, że jego wykorzystanie jest banalnie proste:

Najpierw, przed pierwszym użyciem tworzymy konfigurację mapowania (w jednym miejscu dla całego AppDomain). Najczęściej będzie to 'global.asax' lub 'bootstraper', ale może być też bezpośrednio przed metodą:
public static IMappingExpression<TSource, TDestination> CreateMap<TSource, TDestination>();
np.: Mapper.CreateMap<ClassA, ClassB>();

a nast. w kodzie produkcyjnym do mapowania wykorzystujemy metodę Map:
public static TDestination Map<TDestination>(object source);
np: ClassA classAB = Mapper.Map<ClassA>(classAA);  
//classAA will be copied to classAB and both will have values of classAA

Testowanie:
Najpierw musimy zainicjować konfigurację mapowania (np. poprzez wywołanie Bootstrapera), a nast. wywołać metodę:
Mapper.AssertConfigurationIsValid();

Linki:
Kod źródłowy znajduje się na github, a udost. jest na licencji MIT.
AutoMapper Getting-started
Artykuł na Visual Studio Magizne opisujący bardziej zaawansowane przypadki użycia: link

środa, 26 lutego 2014

NancyFx - Polskie znaki

Podczas pracy nad nowym projektem, z wykorzystaniem frameworka Nancy (NancyFx) zauważyłem, że mam problem z wyświetlaniem polskich znaków w widoku (Razor). Rozwiązaniem okazało się dodanie metataga <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> do części <head>

Przykładowa część strony wygląda więc tak:

<head>
    <title>Input</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>

 Źródło, z którego wziąłem rozwiązanie.

środa, 19 lutego 2014

MS SQL - Edycja wierszy w edytorze wg. zapytania SQL

W MS SQL Managment Studio istnieje opcja, aby edytować wiersze w edytorze. Standardowo, jest to opcja na edytowanie pierwszych 200 wierszy (top 200 rows), jednak edytor udostępnia możliwość, aby edytować wiele, dowolnie wybranych wierszy.

Aby tego dokonać, należy, najpierw wybrać standardową opcję "Edit Top 200 Rows", a nast. na uzyskanym zbiorze wynikowym, prawy przycisk myszy, "Pane->SQL", a nast. edytujemy zapytanie SQL tak, aby uzyskać zakres danych, który chcemy później edytować w edytorze.

Link do pytania na stackoverflow.com/

wtorek, 11 lutego 2014

Szkolenie Comarch - Programowanie .NET 4.0 - kurs zaawansowany

W dniach od 05.02.2014 do 07.02.2014 (3 dni) miałem przyjemność wziąć udział w szkoleniu, zorganizowanym przez firmę Comarch nt. ' Programowanie .NET 4.0 - kurs zaawansowany'.

Szkolenie przeprowadził Marcin Najder (techblog), ale zanim przejdę do konkretów najpierw kilka spraw "formalnych". Szkolenie odbyło się w Warszawskiej siedzibie firmy, przy ul. Leśna 2 (przecznica ul. Puławskiej 525), czyli... na Ursynowie, przy ul. Puławskiej, drugie światła od zjazdu z południowej obwodnicy Warszawy, czyli... bardzo dobra lokalizacja dla zmotoryzowanych (w okoliczny jest gdzie zaparkować).

Co do oferty szkoleniowej, to można ją przejrzeć tutaj, natomiast szczegóły szkolenia, na którym ja byłem, można obejrzeć tutaj. Pod każdym szczegółowym opisem szkolenia jest niebieski przycisk "Terminarz i Rejestracja", więc jeżeli ktoś jest zainteresowany, to wiadomo co i jak.

Jeżeli chodzi o samo szkolenie, to nie będę ukrywał, że cena 3 dniowego szkolenia, była jak na Warszawę bardzo konkurencyjna  (w promocji, 1400zł + VAT).

A jak wyglądało samo szkolenie?
    Należy zacząć od tego, że sam prowadzący, to bardzo sympatyczny, a przy tym doświadczony programista. Prawdziwy pasjonat w swoim fachu, fan zarówno języków funkcyjnych jak i obiektowych i to m.in. próbował nam przekazać podczas szkolenia. Ponieważ w naszej 7 os. grupie, były os. o bardzo zróżnicowanym doświadczeniu programistycznym, Marcin musiał się nieco wysilić, szczególnie że był niemal przez cały czas pod porządnym gradobiciem pytań.
     Były więc os. zaraz po studiach (i kursie podstawowym), które prosiły o więcej wyjaśnień związanych z lambdami, delegatami itp., jak i doświadczony programista PHP pragnący spróbować swoich sił w .NET, jak i 2-3 bardziej doświadczonych programistów, pytających co chwila o bardziej zaawansowane tematy oraz różnego rodzaju "wątki poboczne".
     Na wszystkie te tematy, prowadzący odpowiadał spokojnie i rzeczowo. W efekcie, w trakcie kursu, przerobiliśmy też fragment "kursu podstawowego", to co było w agendzie związane z zaawansowanymi aspektami programowania w .NET (linq, lambdy, refleksja, więcej lambd, T4, wzorce projektowe, programowanie współbieżne, jeszcze więcej lambd itp. ;)), ale również tematy okołoprogramistyczne, takie jak np. rozproszone kontrole wersji (github, bitbucket), "NoSQL" (MongoDb, RavenDb), JSON, frameworki javascriptowe (Angular.JS, Node.JS). Wspomniany został nawet ServiceStack (niestety aktualnie płatny) Jeżeli doliczymy do tego ćwiczenia praktyczne z wykorzystaniem nUnit oraz Resharpera, oraz rozmowy programistyczne oraz  około programistyczne, czy w czasie kursu, czy też w czasie wspólnego posiłku to daje nam naprawdę intensywnie spędzone 3 dni..
     Wprawdzie to nie Ja płaciłem za szkolenie(firma płaciła), ale uważam, że naprawdę warto było pójść na to szkolenie. Fajnie jest przebywać w towarzystwie inteligęnych (i nierzadko mądrzejszych) ludzi od siebie i tak "na spokojnie" się czegoś nowego dowiedzieć/nauczyć. Taki miłe urozmaicenie w stosunku do samotnego przerabiania tutoriali / dokumentacji / oglądania podcastów w domu ;)

Z tego co Marcin mówił, to obok pracy na etacie, prowadzi również szkolenia ASP.MVC, programowanie reaktywne, jak i kurs podstawowy. Inna sprawa, że kurs podstawowy, czasami prowadzi też inna zupełnie inna osoba.

To tyle. Gdyby ktoś kiedyś miał okazję udać się na takie szkolenie, to szczerze polecam. Fajnie było :)

wtorek, 28 stycznia 2014

Rysowanie diagramów UML z ArgoUML

Czym jest UML wie zapewne każdy. Czy, a raczej kiedy należy go stosować zależy w dużej mierze od projektu oraz zdrowego rozsądku. Są sytuacje, gdy stworzenie kilku diagramów UML może stanowić ważny element dokumentacji projektowej, a są też sytuacje, gdy tworzenie zbyt dużej ilości może się okazać zwykłą stratą czasu.

W momencie, w którym zdecydujemy, że warto wzbogacić naszą dokumentację techniczną o diagram(y) UML warto użyć do tego odpowiedniego narzędzia, szczególnie, że niektóre z nich posiadają takie opcje, jak np. autogenerowanie części kodu źródłowego.

Przy wyborze narzędzia, ważne jest to, jakiej funkcjonalności oczekujemy od narzędzia, tj. czy chcemy rysować, modelować, eksportować wyniki do metamodeli, a może jednak najważniejsze jest generowanie fragmentów kodu z diagramu? Bardzo dobry przegląd narzędzi, ze względu na rodzaje funkcjonalności znajduje się w jednym z pytań na forum stackoverflow.com.

W moim przypadku, właśnie skończyłem pracę nad rozbudowanym architektonicznie projektem, w którym mieliśmy 4 nasze serwery, z czego 3 schowane za "firewallem" oraz 6-7 usług zewnętrznych, z którymi porozumiewały się różne serwery. Diagram wdrożeniowy pokazał istniejące zależności w sposób jasny i klarowny, pozwalając zrozumieć istniejące zależności nawet nowym osobom w projekcie.

Do narysowania diagramu użyłem darmowego programu ArgoUML dostępnego na licencji Eclipse Public License - v 1.0.

ArgoUML w porównaniu ze swoim głównym konkurentem Visio:
- jest darmowy
- jest prosty, a szata graficzna lekko spartańska
- można za jego pomocą wygenerować tylko 6 typów diagramów (klas, przypadków użycia, sekwencji, maszyny stanowej, czynności, wdrożeniowy)
- nie do końca spełnia (implementuje) wszystkie standardy języka UML
- posiada możliwość generowania kodu w językach takich jak java, c++, c#, itp.
- posiada możliwość inżynierii wstecznej plików JAR

dodatkowo, wynik naszej pracy możemy eksportować do:
- XML
- pliku graficznego

Pełny opis na http://en.wikipedia.org/wiki/ArgoUML

Mnie osobiście ArgoUML przekonało funkcjonalnością, oraz darmowością. Program, mimo iż nie jest w 100% zgodny ze standardami UML, oraz posiada nieco spartańską oprawę graficzną, to jednak, Moim zdaniem jest wystarczająco dobry do zobrazowania "clou problemu" i zwyczajnie 'robi swoją robotę'.

poniedziałek, 20 stycznia 2014

Testowanie ConfigurationManager (xUnit, FakeItEasy)

Tworząc testy jednostkowe ważne jest, aby testy działały bardzo szybko, oraz niezależnie od zewnętrznych zasobów, takich jak np. web servicedostęp do plików itp. Mówi o tym, m.in. Roy Osherove podczas swoich szkoleń, np. Understanding Test Driven Development

Jednym z takich zewnętrznych zasobów dla aplikacji internetowych, jest plik konfiguracyjny web.config. Przykładowy sposób, jak skutecznie zastosować DI oraz testy jednostkowe dla tego rozwiązania pokazuje na swoim blogu KAZI MANZUR RASHID. Niestety dla mnie, Kazi pokazuje to z wykorzystaniem "Mock", natomiast Ja, pod wpływem postów Macieja Aniserowicza jako narzędzie 'mockujące' postanowiłem wykorzystywać FakeItEasy.  Poniżej prezentuję działające rozwiązanie wykorzystujące bibliotekę FakeItEasy.

Ponieważ zmieniam tylko bibliotekę 'Mock' na "FakeItEasy' to podstawowe klasy, pozostały takie same, jak w kodzie Kazi Manur'a

    public interface IConfigurationManager
    {
        NameValueCollection AppSettings
        {
            get;
        }
        string ConnectionStrings(string name);
        T GetSection<T>(string sectionName);
    }
    public class ConfigurationManagerWrapper : IConfigurationManager
    {
        public NameValueCollection AppSettings
        {
            get
            {
                return ConfigurationManager.AppSettings;
            }
        }
        public string ConnectionStrings(string name)
        {
            return ConfigurationManager.ConnectionStrings[name].ConnectionString;
        }
        public T GetSection<T>(string sectionName)
        {
            return (T)ConfigurationManager.GetSection(sectionName);
        }
    }
Aby pokazać bardziej realistyczny przykład użycia, utworzyłem klasę BL (Business Logic), która do swojej pracy wykorzystuje dane, pobrane z web.config. Założyłem również, że plik web.config posiada wpis o nazwie customAppSetting z wartością "test".

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
public class BL
{
    private readonly IConfigurationManager configuration;
public BL()
{
        this.configuration = new ConfigurationManagerWrapper();
}
    public BL(IConfigurationManager configuration)
    {
        this.configuration = configuration;
    }
    public string GetAppSetting(string customAppSettingName)
    {
        string customAppSetting = configuration.AppSettings[customAppSettingName];
        //TODO: some business logic
        return customAppSetting;
    }
}
Praktyczne wykorzystanie klasy BL przez solucję produkcyjną:
    private void ProductionWebConfig()
    {
        BL businessLogic = new BL(new ConfigurationManagerWrapper());
        string customAppSetting = businessLogic.GetAppSetting("customAppSetting");
    }
Praktyczne wykorzystanie klasy BL przez bibliotekę testującą:
    [Fact]
    public void GetAppSetting_PositiveString_StringTest()
    {
        var customAppSetting = new NameValueCollection { { "customAppSetting", "test" } };
        IConfigurationManager fakeConfiguration = A.Fake<IConfigurationManager>();
        A.CallTo(() => fakeConfiguration.AppSettings).Returns(customAppSetting);
        BL bl = new BL(fakeConfiguration);
        string fakeString = bl.GetAppSetting("customAppSetting");
        string realString = "test";
        Assert.Equal(fakeString, realString);
    }