Stos technologiczny obejmuje języki i biblioteki oraz bazę danych z środowiskiem uruchomieniowym, w którym powstaje aplikacja. Dla zamawiającego wygląda jak szczegół wykonawczy, ale przekłada się na koszt utrzymania, dostępność programistów po latach i sposób, w jaki system będzie się skalował. Poniżej opisano techniki, których używa SoftwareStudio jako software house działający z Poznania, oraz powody, dla których poszczególne warstwy dobiera się do zadania.

Zakres usług i model rozliczenia oraz organizację pracy zespołu omawiają osobne strony: o zakresie usług software house oraz o współpracy zespołowej. Ten tekst zajmuje się wyłącznie warstwą techniczną.

Agencja reklamowa czy software house w Poznaniu

Agencje reklamowe budują strony na szablonach i gotowych systemach CMS. Efekt jest atrakcyjny wizualnie, ale rozbudowa poza przewidziane opcje szablonu zwykle wymaga obejść. Kiedy strona ma tylko prezentować treść, takie podejście wystarcza i jest tańsze.

Sytuacja zmienia się, gdy potrzebna jest interakcja: formularze z walidacją zależną od danych w bazie, uprawnienia użytkowników do poszczególnych dokumentów albo obliczenia, które dzieją się po stronie serwera. Wtedy zamawiający potrzebuje aplikacji z logiką biznesową, a nie witryny. Tego typu system opisuje strona o aplikacji webowej, która pokazuje zawartość zmienną, generowaną na serwerze przy każdym żądaniu, a nie plik statyczny z dysku.

CechaWitryna na szablonie CMSAplikacja pisana na zamówienie
Logika biznesowaograniczona do wtyczekzapisana w kodzie i procedurach bazy
Uprawnieniarole redaktorskieuprawnienia do dokumentów i operacji
Danetreści i mediarekordy transakcyjne z historią zmian
Integracjeformularze i newsletterinterfejsy do ERP i urządzeń

C# i ASP.NET po stronie serwera

W opisie oferty SoftwareStudio aplikacje internetowe powstają w technologii Microsoft ASP.NET z bazą Microsoft SQL Server, a interfejs opiera się na HTML5 i CSS3. Językiem, w którym pisze się logikę po stronie serwera, jest C#, silnie typowany i kompilowany do kodu pośredniego. Dokumentacja języka jest dostępna w Microsoft Learn, a opis samej platformy w przeglądzie ASP.NET.

Dlaczego język typowany

Aplikacje biznesowe żyją latami, a zespół programistów zmienia się w tym czasie kilkukrotnie. Typy danych, sprawdzane przy kompilacji, wychwytują całe klasy błędów, zanim kod trafi do testów. Refaktoryzacja nazwy pola lub sygnatury metody jest w takim środowisku operacją bezpieczną, bo kompilator wskaże każde miejsce użycia.

Podział na warstwy

Kod aplikacji dzieli się na warstwę prezentacji, która renderuje strony, i warstwę logiki, która wykonuje reguły procesu. Dostęp do danych pozostaje osobno, dzięki czemu zmiana zapytania nie wymusza edycji ekranów. Taki podział ułatwia przegląd kodu, bo recenzent widzi, czy reguła biznesowa nie zaszyła się w kodzie widoku.

Zapytania parametryzowane

Warstwa dostępu do danych w C# powinna wysyłać do bazy wartości jako parametry, a nie doklejać ich do tekstu polecenia. Parametryzacja chroni przed wstrzyknięciem SQL i pozwala serwerowi ponownie użyć planu wykonania. Poniższy fragment jest przykładem ilustracyjnym.

using (var conn = new SqlConnection(connectionString))
using (var cmd = new SqlCommand(
    "SELECT Id, NumerDokumentu FROM dbo.Zamowienie WHERE Status = @status", conn))
{
    cmd.Parameters.Add("@status", SqlDbType.TinyInt).Value = 1;
    conn.Open();
    using (var rd = cmd.ExecuteReader())
    {
        while (rd.Read())
        {
            var id = rd.GetInt32(0);
            var numer = rd.GetString(1);
        }
    }
}

Reguła: żadna wartość pochodząca od użytkownika nie trafia do polecenia SQL jako sklejony tekst, zawsze przechodzi przez parametr.

Ilustracja budynku z szafami serwerowymi i osobami przed nim, nawiązująca do kodu aplikacji ASP.NET na serwerze
Kod C# działa na serwerze aplikacyjnym, a przeglądarka użytkownika otrzymuje wyłącznie gotowy dokument HTML i skrypty.

SQL Server i T-SQL jako warstwa danych

Baza relacyjna przechowuje dokumenty i ich statusy razem z historią operacji. Integralność gwarantują klucze obce oraz transakcje. W aplikacjach magazynowych i logistycznych szczególne znaczenie ma spójność: dwa równoległe żądania nie mogą zatwierdzić tego samego dokumentu. Referencyjny opis języka znajduje się w dokumentacji języka T-SQL.

Procedury składowane i transakcje

Operacje wieloetapowe warto zamykać w procedurze składowanej, która wykonuje się w jednej transakcji. Warunek w klauzuli WHERE sprawdza status dokumentu, więc druga próba zatwierdzenia nie zmieni żadnego wiersza i procedura zgłosi błąd. Przykład nie odzwierciedla schematu konkretnego produktu.

CREATE PROCEDURE dbo.ZatwierdzZamowienie @IdZamowienia INT
AS
BEGIN
    SET NOCOUNT ON;
    SET XACT_ABORT ON;
    BEGIN TRAN;

    UPDATE dbo.Zamowienie
       SET Status = 2
     WHERE Id = @IdZamowienia AND Status = 1;

    IF @@ROWCOUNT = 0
    BEGIN
        ROLLBACK;
        THROW 50001, N'Zamówienie nie ma statusu do zatwierdzenia.', 1;
    END;

    INSERT INTO dbo.ZamowienieHistoria (IdZamowienia, Zdarzenie, DataUtc)
    VALUES (@IdZamowienia, N'Zatwierdzono', SYSUTCDATETIME());

    COMMIT;
END;

Indeksy pod zapytania aplikacji

Ekrany listowe aplikacji najczęściej filtrują dokumenty po statusie. Indeks filtrowany obejmuje wtedy tylko wiersze o wybranym statusie, więc pozostaje mały nawet przy milionach rekordów historycznych. Zasady projektowania indeksów zbiera przewodnik po indeksach SQL Server.

CREATE NONCLUSTERED INDEX IX_Zamowienie_Otwarte
    ON dbo.Zamowienie (DataUtworzenia)
    INCLUDE (NumerDokumentu)
    WHERE Status = 1;

Wybór wersji serwera bazy to osobna decyzja. Starsze opisy oferty zalecały wersje 2012 i 2016, ale dla SQL Server 2016 rozszerzone wsparcie Microsoft zakończyło się w lipcu 2026, co widać w tabeli cyklu życia produktu. Nowe wdrożenia powinny więc startować na wersji objętej wsparciem, a stare instalacje wymagają planu migracji, takiego jak w opisie SQL Server 2008 w systemie magazynowym.

Współbieżność i poziomy izolacji

Dwie osoby otwierające ten sam dokument to sytuacja codzienna, a nie wyjątek. Domyślny poziom izolacji READ COMMITTED zakłada blokady współdzielone przy odczycie, więc długie zapytanie raportowe potrafi zatrzymać zapis w tabeli, której dotyczy. Opcja READ_COMMITTED_SNAPSHOT przełącza odczyty na wersjonowanie wierszy: czytelnik dostaje ostatnią zatwierdzoną wersję i nie czeka na zapisującego. Kosztem jest dodatkowe miejsce na wersje wierszy, dlatego zmianę włącza się po ocenie obciążenia. Mechanizm opisuje przewodnik po blokowaniu i wersjonowaniu wierszy.

ALTER DATABASE Aplikacja
    SET READ_COMMITTED_SNAPSHOT ON
    WITH ROLLBACK IMMEDIATE;

Odrębny kłopot stanowi jednoczesna edycja tego samego rekordu przez dwóch użytkowników. Rozwiązaniem jest współbieżność optymistyczna z kolumną typu ROWVERSION: aplikacja zapamiętuje wersję odczytaną przy otwarciu formularza i przekazuje ją przy zapisie. Jeśli ktoś zmienił rekord w międzyczasie, aktualizacja nie zmodyfikuje żadnego wiersza i użytkownik dostaje komunikat o konflikcie zamiast po cichu nadpisanych danych.

UPDATE dbo.Zamowienie
   SET Uwagi = @uwagi
 WHERE Id = @id AND Wersja = @wersja;   -- Wersja: kolumna ROWVERSION

-- @@ROWCOUNT = 0 oznacza konflikt edycji

Reguła: zapis, który nie zmienił żadnego wiersza, traktuje się jako konflikt i zgłasza użytkownikowi, a nie ignoruje.

JavaScript i jQuery w przeglądarce

Po stronie klienta aplikacja używa HTML5 i CSS3 do układu oraz JavaScriptu do zachowania ekranu. W opisie oferty pojawia się jQuery, a przy części interfejsów także biblioteka Vue. Podstawowy wzorzec to żądanie asynchroniczne AJAX: przeglądarka wysyła dane w tle, serwer zwraca odpowiedź, a skrypt aktualizuje tylko fragment strony.

$.ajax({
    url: '/api/zamowienia/zatwierdz',
    method: 'POST',
    contentType: 'application/json',
    data: JSON.stringify({ id: 42 })
}).done(function (odp) {
    $('#status').text(odp.status);
}).fail(function (xhr) {
    $('#blad').text(xhr.responseText);
});

Ten mechanizm ma konsekwencję projektową: walidacja w przeglądarce służy wygodzie użytkownika, ale ostateczna kontrola musi działać na serwerze. Skrypt można wyłączyć albo podmienić, więc reguły biznesowe zapisane wyłącznie w JavaScripcie nie dają żadnej gwarancji.

Bezpieczeństwo aplikacji webowych

Aplikacja dostępna z przeglądarki jest widoczna z sieci, więc zabezpieczenia projektuje się od pierwszego etapu. Punktem odniesienia jest lista najczęstszych zagrożeń publikowana przez projekt OWASP Top 10. Poniższa tabela zestawia cztery zagrożenia z mechanizmami obrony stosowanymi w opisanym stosie.

ZagrożenieMechanizm obronyWarstwa
Wstrzyknięcie SQLzapytania parametryzowane i konto bazy z uprawnieniami ograniczonymi do procedurC# i SQL Server
Przejęcie sesjiciasteczka z flagami HttpOnly i Secure oraz połączenie szyfrowane HTTPSserwer WWW
Fałszowanie żądań (CSRF)token weryfikowany przy każdym żądaniu zmieniającym daneASP.NET
Nadmierne uprawnieniasprawdzanie roli przy każdej operacji po stronie serweralogika aplikacji

Osobną kwestią są hasła. Nie przechowuje się ich jawnie ani w formie zwykłego skrótu, tylko jako skrót z solą, liczony funkcją celowo wolną. Szczegóły implementacji w ASP.NET zawiera dokumentacja zabezpieczeń ASP.NET Core.

Aplikacje mobilne i raporty

Poza przeglądarką stos obejmuje aplikacje na terminale z systemem Android. W ofercie SoftwareStudio pojawiły się w 2015 roku jako następcy programów dla kolektorów z Windows CE i Windows Mobile. W typowej architekturze terminal komunikuje się z serwerem zapytaniami HTTP, więc dane skanowane w magazynie trafiają do tej samej bazy co dane wprowadzane w biurze. Przykład zastosowania opisuje strona o aplikacji magazynowej na Androida.

Osobną warstwą są wydruki i raporty. Dokumenty generuje się w usługach raportowych SQL Server, a szablony przygotowuje w narzędziu Report Builder, co omawia strona o raportach RDL i wydrukach dokumentów w SSRS. Dzięki temu wygląd dokumentu zmienia się bez ingerencji w kod aplikacji.

Hosting na IIS i eksploatacja aplikacji

Aplikacje ASP.NET uruchamia się na serwerze Microsoft IIS, a w opisie oferty SoftwareStudio jest to standardowe środowisko dla aplikacji webowych. Podstawy działania serwera opisuje przegląd usług IIS, a zagadnienia administracji systemem Windows Server omawia strona o obsłudze Windows Server w Poznaniu.

Model chmurowy SoftwareStudio wykorzystuje profesjonalne centrum danych ATM w Warszawie i środowisko wirtualizacyjne VMware vSAN. Wirtualizacja pozwala przenosić maszyny między hostami i szybciej odtwarzać środowisko, a szczegóły modelu opisuje strona o programach na zamówienie a chmurze i VMware.

Ilustracja chmury zbudowanej z kolorowych klocków na ciemnym tle, symbolizująca hosting aplikacji w chmurze
Aplikacja hostowana w chmurze jest dostępna z przeglądarki, a administracja serwerem pozostaje po stronie wykonawcy.

Diagnostyka w środowisku produkcyjnym

Błąd zgłoszony przez użytkownika bez śladu w logach jest trudny do odtworzenia, dlatego aplikacja zapisuje wyjątki z kontekstem: identyfikatorem żądania i nazwą użytkownika. Zapisuje się też parametry operacji, ale hasła i dane wrażliwe w takich wpisach nie mogą się pojawiać. Identyfikator żądania pozwala połączyć wpis w dzienniku aplikacji z wpisem serwera IIS i z zapytaniem, które trafiło do bazy. Dobrą praktyką jest osobna tabela lub plik dziennika, do którego zapis nie blokuje głównej operacji.

Po stronie bazy narzędziem pierwszego wyboru jest plan wykonania zapytania. Pokazuje, czy serwer użył indeksu, czy przeszukał całą tabelę, i ile wierszy oszacował w porównaniu z rzeczywistą liczbą. Rozbieżność między tymi wartościami zwykle wskazuje nieaktualne statystyki albo zapytanie nieprzystające do indeksu. Sposób czytania planów opisuje dokumentacja planów wykonania.

Wersjonowanie i wdrożenia między środowiskami

Stos technologiczny obejmuje także sposób dostarczania zmian. Każda zmiana kodu i bazy powinna przejść tę samą ścieżkę, zanim trafi do użytkowników, a ścieżka ta składa się z kilku stałych elementów.

  • Kontrola wersji - repozytorium z historią zmian, w którym każda modyfikacja ma autora i opis.
  • Przegląd kodu - drugi programista czyta zmianę przed włączeniem do głównej gałęzi.
  • Skrypty migracji bazy - zmiany schematu zapisane jako numerowane skrypty, a nie ręczne poprawki na produkcji.
  • Środowisko testowe - kopia produkcji z danymi zanonimizowanymi, na której sprawdza się wdrożenie przed właściwym.

Skrypty migracji dają tę korzyść, że schemat bazy testowej i produkcyjnej da się porównać jednym poleceniem. Ręczna zmiana indeksu na produkcji, której nikt nie opisał, jest częstą przyczyną różnic w wydajności między środowiskami. Podobną rolę odgrywa konfiguracja: adresy połączeń i klucze przechowuje się poza kodem, w plikach konfiguracyjnych osobnych dla każdego środowiska.

Reguła: na produkcję trafia wyłącznie to, co wcześniej przeszło wdrożenie na środowisku testowym tą samą procedurą.

Kryteria doboru technik do projektu

Nie każdy projekt wymaga pełnego stosu. Prosty formularz zamówień nie potrzebuje osobnej biblioteki interfejsu, a system z wieloma integracjami skorzysta z procedur składowanych i warstwy usług. Poniższa tabela zestawia kryteria, według których zwykle podejmuje się decyzje.

KryteriumPytanie kontrolneWpływ na dobór
Środowisko klientajaki serwer i jaka baza już działająogranicza wybór bazy i systemu operacyjnego
Obciążenieilu użytkowników pracuje równolegledecyduje o indeksach i buforowaniu
Integracjez jakimi programami dane mają się wymieniaćwymusza interfejsy REST lub bazę pośrednią
Utrzymaniekto będzie rozwijał kod za kilka latprzemawia za technologiami szeroko znanymi

Warto dodać jedno zastrzeżenie: lista technik z opisu oferty dotyczy różnych projektów. Nie oznacza, że jedna aplikacja korzysta ze wszystkich naraz. Wybór zawsze wynika z konkretnego zamówienia, co tłumaczy również strona o producencie aplikacji webowych.

Przykładowe aplikacje SoftwareStudio można obejrzeć w demo online, a opis usług programistycznych znajduje się na stronie oprogramowania na zamówienie. Szersze tło rynkowe daje artykuł o producencie aplikacji internetowych.