SlideShare a Scribd company logo
Jak stworzyć udany system
      informatyczny?
       Jakub Wójciak
Agenda


 Słowo wstępu

 Błędy

 Choroby programistów

 Bezpieczeństwo

 Build

 Drobnostki
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
Założenia


  Aplikacja Web

     ASP.NET MVC

     C#

     .NET 4.5

  Visual Studio 2012

  SQL Server 2012

  SVN
Oczywiste oczywistości


  Kod źródłowy w repozytorium

  Jakaś architektura

  Standardy nazewnictwa, kodowania

  Może są testy

  Może jest dokumentacja
Błędy
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
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
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!
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
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
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.”
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.”
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!
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
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,
Choroby programistów
Choroby programistów


 WOMM

    Works on my machine!

 NIH

    Not Invented Here

 Architekturoza
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!
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
Architekturoza


  Krzywa olśnienia architekturowego




                  Złożoność kodu




                                      Czas
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?
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ę
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?!
Bezpieczeństwo
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
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
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
Build
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ć?
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
Jak to osiągnąć?


  Kompletne kody źródłowe w repozytorium

  Biblioteki zależne podpięte np. przez NuGet

  Baza danych wersjonowana w repozytorium
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
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
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
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
Drobnostki
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
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
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
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>
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ć
Dziękujemy za uwagę
      i zapraszamy do współpracy
                     Jakub Wójciak      SMT Software S.A.
                                        ul. Piłsudskiego 13
                                        50-048 Wrocław
                                        tel. +48 71 769 59 00
                                        fax     +48 71 769 59 01
jakub.wojciak@smtsoftware.com           www.smtsoftware.com



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

More Related Content

PPTX
Wzorce projektowe (w ASP.NET i nie tylko)
Bartlomiej Zass
 
PPTX
Co nowego w VS 2013 dla programistów ASP.NET?
Bartlomiej Zass
 
PPTX
Optymalizacja aplikacji ASP.NET
Bartlomiej Zass
 
PPTX
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
Tomasz Kopacz
 
PPTX
Mts 2013 tomasz kopacz - wydajność aplikacji dla windows 8 - jak ją mierzyć...
Tomasz Kopacz
 
PDF
KraQA #22, Filip Cynarski - Selenium Grid w chmurze Amazon Web Services
kraqa
 
PPTX
Exam: 70-511 Enhancing Usability - Windows Application
Maciej Zbrzezny
 
PPTX
Wzorce Repository, Unity of Work, Devexpress MVC w architekturze Asp.net MVC
Quick-Solution
 
Wzorce projektowe (w ASP.NET i nie tylko)
Bartlomiej Zass
 
Co nowego w VS 2013 dla programistów ASP.NET?
Bartlomiej Zass
 
Optymalizacja aplikacji ASP.NET
Bartlomiej Zass
 
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
Tomasz Kopacz
 
Mts 2013 tomasz kopacz - wydajność aplikacji dla windows 8 - jak ją mierzyć...
Tomasz Kopacz
 
KraQA #22, Filip Cynarski - Selenium Grid w chmurze Amazon Web Services
kraqa
 
Exam: 70-511 Enhancing Usability - Windows Application
Maciej Zbrzezny
 
Wzorce Repository, Unity of Work, Devexpress MVC w architekturze Asp.net MVC
Quick-Solution
 

What's hot (14)

PDF
Integracja środowiska testowego z użyciem Robot Framework, TrojQA 2014-12-16
Krzysztof Synak
 
PPTX
Bohater UI bez front end developera ?
Quick-Solution
 
PPTX
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...
Trójmiejska Grupa Testerska
 
PPTX
Olga Żądło - Robot Framework
Trójmiejska Grupa Testerska
 
PDF
e2e frameworks - czyli kij ma dwa końce
The Software House
 
PPTX
Programowanie aplikacji dla Windows 8 (WinRT)
Bartlomiej Zass
 
PDF
Wprowadzenie do implementacji architektur plug-in w PHP
PHPCon Poland
 
PDF
Jak zacząć, aby nie żałować - czyli 50 twarzy PHP
Piotr Horzycki
 
PPT
Ext js
danon123danon
 
ODP
Testy wydajnościowe - najlepsze praktyki - Kuba Gajda
Bartłomiej Cymanowski
 
PPTX
Unit testing w praktyce... czyli właściwie jak?
Bartłomiej Cymanowski
 
PDF
REvolution, czyli o bardziej obiektowym podejściu w Railsach
The Software House
 
PPTX
10 przykazań bezpiecznego programowania
SecuRing
 
PPTX
Testowanie bezpieczeństwa – jak dostosować zakres do realnych zagrożeń i budżetu
SecuRing
 
Integracja środowiska testowego z użyciem Robot Framework, TrojQA 2014-12-16
Krzysztof Synak
 
Bohater UI bez front end developera ?
Quick-Solution
 
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...
Trójmiejska Grupa Testerska
 
Olga Żądło - Robot Framework
Trójmiejska Grupa Testerska
 
e2e frameworks - czyli kij ma dwa końce
The Software House
 
Programowanie aplikacji dla Windows 8 (WinRT)
Bartlomiej Zass
 
Wprowadzenie do implementacji architektur plug-in w PHP
PHPCon Poland
 
Jak zacząć, aby nie żałować - czyli 50 twarzy PHP
Piotr Horzycki
 
Testy wydajnościowe - najlepsze praktyki - Kuba Gajda
Bartłomiej Cymanowski
 
Unit testing w praktyce... czyli właściwie jak?
Bartłomiej Cymanowski
 
REvolution, czyli o bardziej obiektowym podejściu w Railsach
The Software House
 
10 przykazań bezpiecznego programowania
SecuRing
 
Testowanie bezpieczeństwa – jak dostosować zakres do realnych zagrożeń i budżetu
SecuRing
 
Ad

Similar to Jak stworzyć udany system informatyczny (20)

PDF
Clean code w Ruby
Rafal Piekarski
 
PDF
KICK ME
pkrzywania
 
PPTX
Dlaczego przejmować się bezpieczeństwem aplikacji (pol)
Pawel Krawczyk
 
PPTX
4Developers 2015: 10 przykazań bezpiecznego kodowania - Wojciech Dworakowski
PROIDEA
 
PPTX
Dwa sposoby na pisanie aplikacji bez błędów
Michal Lukaszewski
 
PDF
Wyciek danych w aplikacjach - Artur Kalinowski, 4Developers
Logicaltrust pl
 
PDF
Visual C# 2005. Zapiski programisty
Wydawnictwo Helion
 
PDF
4Developers: Artur Kalinowski- Wycieki danych w aplikacjach
PROIDEA
 
PDF
4Developers2016: Artur Kalinowski Wyciek Danych w aplikacjach
PROIDEA
 
PDF
.NET Framework 2.0. Zaawansowane programowanie
Wydawnictwo Helion
 
PDF
.Net. Najpilniej strzeżone tajemnice
Wydawnictwo Helion
 
PDF
Java. Obsługa wyjątków, usuwanie błędów i testowanie kodu
Wydawnictwo Helion
 
PDF
Język C++. Gotowe rozwiązania dla programistów
Wydawnictwo Helion
 
PPTX
Podstawy Asp.Net Mvc 1.0 W 3600 Sekund
emdzej
 
PPTX
[PL] Jak programować aby nie zwariować?
Jakub Marchwicki
 
PPTX
Getting Things Programmed
Michał Bartyzel
 
PPTX
Klasyfikacja wymagań jako sposób zarządzania nimi
Jaroslaw Zelinski
 
PDF
Evolving architecture 4 Confitura 2017
Daniel Pokusa
 
PDF
Visual Basic .NET. Księga eksperta
Wydawnictwo Helion
 
Clean code w Ruby
Rafal Piekarski
 
KICK ME
pkrzywania
 
Dlaczego przejmować się bezpieczeństwem aplikacji (pol)
Pawel Krawczyk
 
4Developers 2015: 10 przykazań bezpiecznego kodowania - Wojciech Dworakowski
PROIDEA
 
Dwa sposoby na pisanie aplikacji bez błędów
Michal Lukaszewski
 
Wyciek danych w aplikacjach - Artur Kalinowski, 4Developers
Logicaltrust pl
 
Visual C# 2005. Zapiski programisty
Wydawnictwo Helion
 
4Developers: Artur Kalinowski- Wycieki danych w aplikacjach
PROIDEA
 
4Developers2016: Artur Kalinowski Wyciek Danych w aplikacjach
PROIDEA
 
.NET Framework 2.0. Zaawansowane programowanie
Wydawnictwo Helion
 
.Net. Najpilniej strzeżone tajemnice
Wydawnictwo Helion
 
Java. Obsługa wyjątków, usuwanie błędów i testowanie kodu
Wydawnictwo Helion
 
Język C++. Gotowe rozwiązania dla programistów
Wydawnictwo Helion
 
Podstawy Asp.Net Mvc 1.0 W 3600 Sekund
emdzej
 
[PL] Jak programować aby nie zwariować?
Jakub Marchwicki
 
Getting Things Programmed
Michał Bartyzel
 
Klasyfikacja wymagań jako sposób zarządzania nimi
Jaroslaw Zelinski
 
Evolving architecture 4 Confitura 2017
Daniel Pokusa
 
Visual Basic .NET. Księga eksperta
Wydawnictwo Helion
 
Ad

Jak stworzyć udany system informatyczny

  • 1. Jak stworzyć udany system informatyczny? Jakub Wójciak
  • 2. Agenda Słowo wstępu Błędy Choroby programistów Bezpieczeństwo Build Drobnostki
  • 3. 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
  • 4. Założenia Aplikacja Web ASP.NET MVC C# .NET 4.5 Visual Studio 2012 SQL Server 2012 SVN
  • 5. Oczywiste oczywistości Kod źródłowy w repozytorium Jakaś architektura Standardy nazewnictwa, kodowania Może są testy Może jest dokumentacja
  • 7. 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
  • 8. 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
  • 9. 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!
  • 10. 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
  • 11. 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
  • 12. 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.”
  • 13. 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.”
  • 14. 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!
  • 15. 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
  • 16. 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,
  • 18. Choroby programistów WOMM Works on my machine! NIH Not Invented Here Architekturoza
  • 19. 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!
  • 20. 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
  • 21. Architekturoza Krzywa olśnienia architekturowego Złożoność kodu Czas
  • 22. 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?
  • 23. 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ę
  • 24. 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?!
  • 26. 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
  • 27. 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
  • 28. 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
  • 29. Build
  • 30. 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ć?
  • 31. 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
  • 32. Jak to osiągnąć? Kompletne kody źródłowe w repozytorium Biblioteki zależne podpięte np. przez NuGet Baza danych wersjonowana w repozytorium
  • 33. 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
  • 34. 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
  • 35. 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
  • 36. 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
  • 38. 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
  • 39. 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
  • 40. 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
  • 41. 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>
  • 42. 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ć
  • 43. Dziękujemy za uwagę i zapraszamy do współpracy Jakub Wójciak SMT Software S.A. ul. Piłsudskiego 13 50-048 Wrocław tel. +48 71 769 59 00 fax +48 71 769 59 01 [email protected] www.smtsoftware.com Wrocław Warszawa Gliwice Poznań Katowice Białystok Utrecht (Holandia)