Jak stworzyć udany system informatyczny

43
Jak stworzyć udany system informatyczny? Jakub Wójciak

description

Prezentacja z IT Academic Days 2012 w Białymstoku.

Transcript of Jak stworzyć udany system informatyczny

Page 1: Jak stworzyć udany system informatyczny

Jak stworzyć udany system informatyczny?

Jakub Wójciak

Page 2: Jak stworzyć udany system informatyczny

Agenda

Słowo wstępu

Błędy

Choroby programistów

Bezpieczeństwo

Build

Drobnostki

Page 3: Jak stworzyć udany system informatyczny

Udany system informatyczny?

Marketing

Znany produkt z wieloma użytkownikami

CFO

Zwrócił koszty i zarabia na siebie

Programiści

Łatwość wprowadzania zmian

Szybkie zrozumienie kodu

Administratorzy

Monitoring i diagnozowanie

Skalowanie

Page 4: Jak stworzyć udany system informatyczny

Założenia

Aplikacja Web

ASP.NET MVC

C#

.NET 4.5

Visual Studio 2012

SQL Server 2012

SVN

Page 5: Jak stworzyć udany system informatyczny

Oczywiste oczywistości

Kod źródłowy w repozytorium

Jakaś architektura

Standardy nazewnictwa, kodowania

Może są testy

Może jest dokumentacja

Page 6: Jak stworzyć udany system informatyczny

Błędy

Page 7: Jak stworzyć udany system informatyczny

Obsługa błędów – grzechy

Zawiłe konstrukcje try/catch

Łapanie każdego możliwego wyjątku

Logika biznesowa oparta na łapaniu wyjątków

Logowanie rozsiane w kodzie aplikacji

Połykanie wyjątków

Prezentowanie szczegółów każdego wyjątku użytkownikowi

Nie pokazywanie wyjątków w ogóle

Page 8: Jak stworzyć udany system informatyczny

Wyjątki – poprawnie

Zasadniczo trzy klasy wyjątków

LogicException

BusinessException

ChainedException

Dodatkowe wyjątki po to, aby na szczególne sytuacje zareagować w szczególny

sposób

Dlatego jest ich zwykle bardzo mało, pojedyncze klasy

Jedno miejsce, gdzie obsługiwane i logowane są wszystkie wyjątki

Czasami obsługa to zalogowanie błędu

Czasami obsługa to zaprezentowanie błędu użytkownikowi

Łatwy dostęp do metody LogException z każdego miejsca kodu

Page 9: Jak stworzyć udany system informatyczny

LogicException

LogicException(string format, params object[] values)

Wykryłeś błąd techniczny, który nie mógł wystąpić z winy użytkownika i na który

użytkownik nic nie poradzi

Czyli błąd innego programisty!

Treść wyjątku może być w dowolnym, jednym języku i może zawierać słowa

niecenzuralne ;-)

Wyjątek ze stack trace trafia do logu, nigdy nie jest prezentowany użytkownikowi

Ten log monitorujesz często i znalezione wyjątki naprawiasz!

Page 10: Jak stworzyć udany system informatyczny

BusinessException

BusinessException(string format, params object[] values)

Wykryłeś błąd logiczny, który ma być zaprezentowany użytkownikowi i na który

użytkownik może coś zaradzić

Treść rzucanego wyjątku jest z zasobów, w języku użytkownika

Treść prezentujesz użytkownikowi, wyjątek logujesz, ale do osobnego dziennika

Ten log monitorujesz i zastanawiasz się, jak ułatwić pracę użytkownikom

Page 11: Jak stworzyć udany system informatyczny

ChainedException

ChainedException(Exception innerException, string format, params object[] values)

Złapałeś wyjątek i rzucasz go dalej z dodatkowymi informacjami

Czyli błąd jest gdzieś wewnątrz, ty tylko zostawiasz ślad co się wykonywało

Podobnie jak LogicException:

Treść wyjątku może być w dowolnym, jednym języku i może zawierać słowa

niecenzuralne ;-)

Wyjątek ze stack trace trafia do logu, nigdy nie jest prezentowany użytkownikowi

Page 12: Jak stworzyć udany system informatyczny

Logowanie błędów

Dzwoni klient i mówi:

„Ale macie zepsuty system, za każdym razem jak kliknę w ten guzik, dostaję inny

błąd!”

„Wchodzę do systemu i nic nie widzę!”

Ze względów bezpieczeństwa nie prezentujemy szczegółów wyjątku użytkownikowi

(stack trace szczególnie zakazany!)

Logujemy więc błędy na serwerze i każdemu błędowi w dzienniku nadajemy numerek

Użytkownikowi prezentujemy komunikat „Wystąpił błąd {numerek}. Administrator

został o tym fakcie powiadomiony.”

Page 13: Jak stworzyć udany system informatyczny

Jaki numerek nadać błędowi?

Kolejny sekwencyjny?

Użytkownik zobaczy jak bardzo zepsuty jest nasz system ;-)

Losowy (random)? Unikatowy(guid)?

„Za każdym razem mam inny błąd, wasz system jest nic-nie-warty”

Numerek unikatowy dla każdego rodzaju błędu!

Policz sumę kontrolną ze stack trace (MD5 / SHA1)

Z fragmentu sumy kontrolnej zrób numer błędu

„Wystąpił błąd 154-776-923. Administrator został o tym powiadomiony.”

Page 14: Jak stworzyć udany system informatyczny

Błędy w JavaScript

Błędy występują nie tylko na serwerze

Zdarza się, że połowa kodu aplikacji jest po stronie użytkownika, w przeglądarce

Błąd JavaScript może mieć wyjątkowo wredne skutki

Klikam w przycisk i nic się nie dzieje

Kręcidełko AJAX kręci się i kręci i kręci• Ale ten wasz system jest wolny!

Page 15: Jak stworzyć udany system informatyczny

Co zrobić z JavaScript?

Jedno wspólne miejsce łapania i logowania błędów JavaScript w przeglądarce

window.onerror

$.ajax.onerror

Po złapaniu:

Wysłać pod specjalny adres na serwerze• adres bieżącej strony,• szczegóły błędu,• informacje o przeglądarce (co najmniej agent-string)

Po stronie serwera zalogować do specjalnego dziennika

Page 16: Jak stworzyć udany system informatyczny

Wszystko albo nic

Większość operacji na serwerze może być w pełni transakcyjna

Jeśli operacja jest read-only

Jeśli modyfikacje są robione, ale tylko w lokalnej bazie danych

Z defaulta warto:

rozpoczynać transakcję na początku requestu HTTP,

komitować po udanym zakończeniu requestu HTTP,

rollbackować w przypadku wyjątku,

Bardziej precyzyjne sterowanie transakcją potrzebne gdy są inne efekty uboczne

operacji:

komunikacja z zewnętrznym systemem,

nieodwracalne zmiany poza transakcyjną bazą danych,

wysłano maila,

Page 17: Jak stworzyć udany system informatyczny

Choroby programistów

Page 18: Jak stworzyć udany system informatyczny

Choroby programistów

WOMM

Works on my machine!

NIH

Not Invented Here

Architekturoza

Page 19: Jak stworzyć udany system informatyczny

WOMM

Musi istnieć łatwo dostępne, wspólne środowisko testowe

Najlepiej codziennie buildy

Continous Integration?

Jeśli nie działa, ale WOMM, to spraw, aby zadziałało na środowisku testowym

Koniecznie podaj potem zdiagnozowaną przyczynę problemu!

Page 20: Jak stworzyć udany system informatyczny

NIH

„Musimy napisać własny kod rozmawiający z WebService’em, bo WCF jest zepsuty”

„Musimy mieć własny framework MVC, ten od Microsoftu jest niedobry”

„Musimy mieć własną klasę String, ta w .NET jest poroniona”

NIH jest podstępny:

Z jednej strony nasza dziedzina jeszcze raczkuje, co widać po dynamicznym

rozwoju• Nie wszystkie „oficjalne” rozwiązania spełniają dziś nasze wymagania• Czasami naprawdę trzeba coś zrobić samemu lepiej

Z drugiej strony wybranie ścieżki NIH skazuje na nią do końca projektu, nawet jeśli

„oficjalna” technologia nas dogoni

Decyzja o NIH musi zapaść za zgodą wszystkich udziałowców projektu: PM, właściciel

biznesowy, główni deweloperzy

Page 21: Jak stworzyć udany system informatyczny

Architekturoza

Krzywa olśnienia architekturowego

Czas

Złoż

onoś

ć ko

du

Page 22: Jak stworzyć udany system informatyczny

Jak rozpoznać architekturozę

Ile kodu faktycznie wykonuje jakieś operacje, a ile stanowi przelotki, interfejsy,

abstrakcje, adaptery i warstwy pośrednie?

Czy interfejsy mają zwykle tylko jedną implementację?

Czy implementacje interfejsów są faktycznie wymienne ze sobą?

Czy masz dużo kodu, który kopiuje strukturę w strukturę?

Czy twoja prosta aplikacja składa się z rozproszonych serwisów hostowanych na

osobnych serwerach?

Czy musisz stosować transakcje rozproszone?

Page 23: Jak stworzyć udany system informatyczny

Przykład architekturozy

Model danych zbudowany w Entity Framework (klasy POCO generowane z edmx)

Każda z klas modelu danych implementuje ręcznie napisany interfejs, potwtarzający

jeszcze raz wszystkie pola z modelu

Dostęp do danych wyłącznie za pośrednictwem klas-repozytoriów, które:

parametry castują z interfejsów do klas modelu danych

wyniki kastują z klas modelu danych do interfejsów

każde repozytorium implementuje swój interfejs – jest jego jedynym

implementatorem

Klasy serwisów z logiką biznesową:

każdy serwis implementuje swój interfejs – jest jego jedynym implementatorem

parametry i wyniki metod serwisów (struktury danych) są opisane interfejsami,

które posiadają dokładnie jedną implementację

Page 24: Jak stworzyć udany system informatyczny

Tylko spokój może nas uratować

Każdy interfejs musi być uzasadniony:

faktycznie będzie kilka jego implementacji,

na potrzeby testów jednostkowych będziesz dostarczał mockup inną jego

implementację,

Inversion of Control / Dependency Injection wcale nie wymaga interfejsów!

Korzystasz z Entity Framework? LinqToSql?

To jest twoja implementacja repozytorium, nie twórz kolejnej warstwy!

Niech twoje serwisy wywołują zapytania Linq bezpośrednio na twoim ObjectContext• Mogą je też prekompilować w zmiennych statycznych

Nie ma nic zdrożnego, aby twój widok MVC przy renderowaniu wyciągał dane

bezpośrednio z obiektów modelu EF

Byleby samo pobieranie danych było realizowane przez kontroler + serwis

Czy ten kod jest w ogóle potrzebny?!

Page 25: Jak stworzyć udany system informatyczny

Bezpieczeństwo

Page 26: Jak stworzyć udany system informatyczny

Bezpieczeństwo

Zbuduj bezpieczeństwo w oparciu o przywileje / prawa

Przywilej / prawo opisane jest czasownikiem opisującym operację:

CanAddNewUser, CanDeleteUsers, CanViewHomeScreen

Przywileje zawsze dodają coś nowego, nigdy nie odbierają:

tzw. addytywny model uprawnień

nie można mieć: CannotBookExpensiveHotel, musi być: CanBookExpensiveHotel

Nie posiadasz przywileju dopóki go nie dostaniesz

Zbiór przywilejów jest stały dla danej wersji systemu

Page 27: Jak stworzyć udany system informatyczny

Skąd się biorą przywileje

Możesz przewidzieć zbiór przywilejów dostępny nawet anonimowym, niezalogowanym

użytkownikom:

Przywilej: CanViewLoginScreen, CanSendPasswordReminder

Możesz przewidzieć zbiór przywilejów dostępny każdemu zalogowanemu użytkownikowi:

Przywilej: CanLogoff, CanChangeUserLanguage, CanViewHelp

Możesz przypisywać przywileje bezpośrednio użytkownikom

Lepiej: możesz zgrupować przywileje w role i przypisywać użytkownikom wiele ról

Role można definiować dynamicznie, np. w bazie danych

Nazwa roli mówi o tym, kim użytkownik będzie w systemie:• DepartmentAccountant• GeneralAccountant• TechnicalAdministrator – może wszystko!• UsersAdministrator

Mogę coś zrobić, jeśli którakolwiek z moich ról posiada dany przywilej

Role specjalne:• ANONYMOUS• EVERYONE

Page 28: Jak stworzyć udany system informatyczny

Rodzaje przywilejów

Osobny przywilej dla każdego punktu wejścia do systemu:

Każda strona aspx

Każda akcja każdego kontrolera

Każda metoda każdego WebService’u

Sprawdzanie takich przywilejów jest automatyczne i nie do ominięcia, w jednym

miejscu kodu

Osobny przywilej do czynności biznesowych:

Każdy rodzaj encji ma swój zbiór przywilejów

Często wystarczy prawo do oglądania i prawo do modyfikacji:• CanViewInvoices• CanManageInvoices (dodawanie, modyfikacja, usuwanie)

Sprawdzanie takich przywilejów jest explicite w kodzie, dba o to programista:• W kontrolerze brak uprawnień to „miękki” komunikat błędu• W serwisie brak uprawnień to krytyczny wyjątek

Page 29: Jak stworzyć udany system informatyczny

Build

Page 30: Jak stworzyć udany system informatyczny

Przychodzi nowy programista...

Na wejściu otrzymuje:

Komputer z zainstalowanym oprogramowaniem (Windows, IIS, Visual Studio, SQL

Server Developer, klient SVN)

Namiary na repozytorium kodu źródłowego (url, login, hasło)

Namiary na swoje pierwsze zadanie w postaci ticketu w systemie zarządzania

projektem

Po ilu minutach ma uruchomiony na swoim komputerze kompletny system i może

realizować zadanie?

Ile kroków musiał wykonać?

Page 31: Jak stworzyć udany system informatyczny

Tylko dwa kroki

Pobierz kod źródłowy z repozytorium

Wykonaj „Build solution” w Visual Studio

Voila!

Bonus: odtworzenie lokalnie bazy produkcyjnej to wykonanie pojedynczego

polecenia

Page 32: Jak stworzyć udany system informatyczny

Jak to osiągnąć?

Kompletne kody źródłowe w repozytorium

Biblioteki zależne podpięte np. przez NuGet

Baza danych wersjonowana w repozytorium

Page 33: Jak stworzyć udany system informatyczny

Wersjonowanie bazy danych

Baza danych musi być wersjonowana!

Musi!

Każdy deweloper pracuje u siebie na lokalnej kopii bazy danych

Repozytorium zawiera kolejno numerowane skrypty różnicowe SQL

W bazie jest tabelka przechowująca numery już wykonanych skryptów

Podczas build zawsze uruchamia się narzędzie, które łączy się z bazą i sprawdza, czy

są skrypty do wykonania

Page 34: Jak stworzyć udany system informatyczny

Nasze rozwiązanie

Skrypty różnicowe:

0001.sql, 0002.sql, 0003.sql itd

Pierwszy skrypt zakłada, że baza jest świeżo stworzona

Kolejne opierają się na stanie bazy po wykonaniu poprzednich skryptów

Wersjonujemy: tabele, indeksy, dane słownikowe

Każdy skrypt jest transakcyjny (wszystko albo nic)

Skrypty obiektowe:

ProcedureCleanHotels.sql, TriggerAfterInsertReservation.sql

Obiekty łatwo tworzone oraz zależne od tabel

Funkcje, procedury, widoki

Page 35: Jak stworzyć udany system informatyczny

Nasze rozwiązanie

Połącz się z bazą

Jeśli nie istnieje, to stwórz albo zakończ się błędem

Pobierz z bazy listę wykonanych skryptów

Pobierz z dysku listę wszystkich dostępnych skryptów

Jeśli są na dysku skrypty, których nie ma jeszcze w bazie:

Uruchom procedurę DropObjects.sql, która kasuje wszystkie widoki, funkcje i

procedury

Wykonaj po kolei wg numerów plików wszystkie skrypty różnicowe, których

jeszcze w bazie nie ma• Każdy pomyślnie wykonany plik „odhacz” w bazie• Każdy błąd powoduje od razu stop całego procesu

Wykonaj wszystkie skrypty obiektowe, alfabetycznie wg nazw plików

Page 36: Jak stworzyć udany system informatyczny

Automatyczne migracje

Obecne frameworki potrafią automatycznie porównać schemat bazy ze schematem

logicznym np. w edmx i automatycznie zmodyfikować bazę

Należy traktować to jako rozwiązanie ułatwiające pisanie skryptów różnicowych, a nie

jako docelowy sposób wgrywania wersji na produkcję

Treść każdego skryptu musi być widoczna gołym okiem jako SQL, a skrypt musi być

opatrzony loginem programisty, który się pod nim „podpisał”

Jak ktoś coś zepsuje, to nie może się wykręcać WOMM

Inni członkowie zespołu natychmiast egzekwują poprawkę od winnego

Page 37: Jak stworzyć udany system informatyczny

Drobnostki

Page 38: Jak stworzyć udany system informatyczny

Data i czas

Różne rodzaje czasu i daty

Punkt w czasie: data i czas, zawsze operuj i przechowuj jako UTC

DateTime.UtcNow

Wprowadzone przez użytkownika w jego strefie lokalnej, kowertuj od razu do UTC

Przed pokazaniem użytkownikowi, kowertuj z UTC na strefę lokalną

Użytkownik może sobie zmienić strefę czasową

Sama data, np. data ważności dokumentu

Przechowuj z obciętym czasem: date.Date

Porównuj z datą i czasem w bieżącej strefie czasowej użytkownika

Ten sam dokument w tej samej chwili może być w różnych częściach świata

jeszcze ważny i już nieważny!

Sam czas

Page 39: Jak stworzyć udany system informatyczny

Tekst

Praca z tekstem, zawsze w Unicode

Wczytując tekst nie-Unicode daj wybrać kodowanie źródłowe lub umożliw

odpowiednią konfigurację

Zapisując tekst, wybieraj format Unicode

Jeśli nie może być Unicode, daj wybrać kodowanie docelowe

Page 40: Jak stworzyć udany system informatyczny

Liczby losowe

Random

Pseudolosowy, inicjalizowany z seed

Korzystaj z jednej, mutowanej instancji

Synchronizuj kod wielowątkowy

Guid

Unikatowy, nie losowy!

Guid można zgadnąć!

Kolejny Guid może po prostu różnić się jedną cyfrą!

RandomNumberGenerator

prawdziwe źródło bezpiecznej losowości

Page 41: Jak stworzyć udany system informatyczny

Refleksja

Bardzo przydatne narzędzie do meta-programowania

Niestety, powolne

Unikaj używania refleksji bezpośrednio w kodzie

Zbuduj sobie helpery do refleksji

Zaimplementuj po prostu z użyciem refleksji

Potem pomierz wydajność

Potem zoptymalizuj w jedym miejscu

Szybszy lecz bardziej skomplikowany mechanizm: Expression<T>

Page 42: Jak stworzyć udany system informatyczny

Linq

Linq jest potężne!

zapytanie możesz prekompilować

zapytania możesz składać

zapytania możesz budować zupełnie dynamicznie

zapytania możesz transformować

zapytania możesz analizować

Page 43: Jak stworzyć udany system informatyczny

SMT Software S.A.ul. Piłsudskiego 1350-048 Wrocławtel. +48 71 769 59 00fax +48 71 769 59 01www.smtsoftware.com

Dziękujemy za uwagę i zapraszamy do współpracy

Wrocław Warszawa Gliwice Poznań Katowice Białystok Utrecht (Holandia)

Jakub Wójciak

[email protected]