Aplikacja internetowa a strona z szablonu
Agencje reklamowe budują serwisy na gotowym szablonie systemu CMS i zmieniają głównie wygląd. Taki serwis prezentuje treści, ale nie prowadzi procesu: nie zapisuje transakcji i nie egzekwuje reguł biznesowych. Gdy potrzebna jest interakcja i zaawansowana logika, praca przechodzi do software house, który projektuje model danych i warstwę serwerową razem z interfejsem.
Tworzenie aplikacji internetowej zaczyna się więc od pytania, jakie dane system ma zapisać i kto może je zmienić. Wygląd strony jest wtórny wobec tego, co dzieje się po kliknięciu przycisku. Tabela zestawia obie klasy rozwiązań.
| Kryterium | Strona z szablonu CMS | Aplikacja internetowa na zamówienie |
|---|---|---|
| Logika | Wyświetlanie treści, formularz kontaktowy | Reguły biznesowe wykonywane na serwerze |
| Dane | Wpisy i podstrony w bazie CMS | Model relacyjny w SQL Server z kluczami i ograniczeniami |
| Integracje | Wtyczki dostawców | Interfejsy REST projektowane pod istniejące systemy |
| Uprawnienia | Kilka ról edytorskich | Role i zakresy danych wynikające z procesu |
| Zmiana wymagań | Wymiana szablonu lub wtyczki | Modyfikacja kodu i migracja schematu bazy |
Reguła: funkcja, która zapisuje dane i sprawdza warunki biznesowe, należy do serwera aplikacji. Skrypt w przeglądarce może ją tylko wywołać.

Model dostarczania bywa różny. Platforma do tworzenia i wdrażania aplikacji biznesowych może działać jako oprogramowanie jako usługa, czyli SaaS z integracją aplikacji, albo zostać zainstalowana na serwerze przedsiębiorstwa. Decyzja wpływa na sposób aktualizacji i na to, kto odpowiada za kopie zapasowe.
Wybór platformy i języka programowania
Platforma i język wynikają z wymagań, a nie z mody. Aplikacja wewnętrzna firmy, która ma działać w sieci lokalnej i łączyć się z bazą SQL Server, naturalnie pasuje do C# i ASP.NET. Aplikacja z rozbudowanym interfejsem po stronie przeglądarki dodatkowo korzysta z JavaScriptu lub TypeScriptu. Stos technologiczny SoftwareStudio opiera się na C# i JavaScript z jQuery, a bazą jest SQL Server z językiem T-SQL.
Programiści zewnętrznej firmy powinni znać HTML i CSS oraz język skryptowy przeglądarki. Frameworki, takie jak React, Angular czy Vue.js, porządkują komponenty interfejsu, lecz wprowadzają własny łańcuch narzędzi i wymagają osobnej kompilacji. Przy aplikacji z kilkoma formularzami i tabelami często wystarcza lżejsze podejście z jQuery.
| Warstwa | Rozwiązanie | Kiedy ma sens |
|---|---|---|
| Przeglądarka | HTML i CSS z jQuery albo z frameworkiem SPA | Framework SPA przy dużej liczbie stanów widoku, jQuery przy prostszych formularzach |
| Serwer aplikacji | C# i ASP.NET na serwerze IIS | Środowisko Windows Server z uwierzytelnianiem domenowym |
| Dane | SQL Server, procedury składowane T-SQL | Transakcje i raporty na jednym silniku |
| Integracje | REST, w razie potrzeby wymiana plików | Połączenie z systemem ERP albo z systemem raportowym |
Praktyczne kryterium wyboru to kompetencje zespołu, który będzie aplikację utrzymywał po wdrożeniu. Rzadki język w produkcji oznacza trudniejszą rekrutację i droższy serwis, dlatego stos ustala się razem z klientem. Opis podejścia do projektu na poziomie architektury zawiera artykuł o projektowaniu aplikacji webowych.
Projekt modelu danych i interfejsu
Przed pierwszą linią kodu powstaje specyfikacja: lista ról i słowników oraz przepływ statusów dokumentów. Interfejs projektuje się na podstawie tych ustaleń, więc każdy ekran odpowiada jednemu zadaniu użytkownika. Formularz z dwudziestoma polami zwykle oznacza, że proces nie został rozbity na etapy. Etap analizy opisuje szerzej tekst o analizie przedwdrożeniowej.

Model relacyjny zabezpiecza się ograniczeniami w bazie, a nie tylko walidacją w przeglądarce. Poniższy przykład, z nazwami poglądowymi, pokazuje tabelę zgłoszeń z kluczem obcym i ograniczeniem statusu.
CREATE TABLE dbo.Zgloszenie (
ZgloszenieId int IDENTITY PRIMARY KEY,
KlientId int NOT NULL
REFERENCES dbo.Klient (KlientId),
Status tinyint NOT NULL DEFAULT 0
CONSTRAINT CK_Zgloszenie_Status CHECK (Status IN (0, 1, 2)),
Opis nvarchar(500) NOT NULL,
UtworzonoUtc datetime2(0) NOT NULL DEFAULT SYSUTCDATETIME()
);
Ograniczenie CHECK odrzuci status spoza dozwolonej listy nawet wtedy, gdy zapis pochodzi z innego klienta interfejsu niż przeglądarka. Wersja z kluczem obcym uniemożliwia dodanie zgłoszenia do nieistniejącego klienta.
Implementacja i wywołania AJAX
Po stronie przeglądarki interakcja z serwerem odbywa się asynchronicznie. Strona nie przeładowuje się przy zapisie, a wynik operacji wraca jako dane w formacie JSON. Zapis z obsługą błędu wygląda następująco.
async function zapiszZgloszenie(dane) {
const odp = await fetch('/api/zgloszenia', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(dane)
});
if (!odp.ok) {
throw new Error('Zapis odrzucony, kod ' + odp.status);
}
return odp.json();
}
Kod odpowiedzi 400 oznacza błąd walidacji po stronie serwera, a 401 brak uwierzytelnienia. Interfejs pokazuje wtedy komunikat przy właściwym polu, zamiast ogólnego błędu. Ten sam punkt końcowy obsługuje później aplikacje mobilne, dlatego kontrakt danych opisuje się osobno. Łączenie aplikacji z innymi systemami omawia artykuł o integrowaniu aplikacji webowych.
Punkt wyjścia do budowy takiego interfejsu w środowisku .NET zawiera dokumentacja tworzenia interfejsu web API w ASP.NET Core w Microsoft Learn. Zakres usług SoftwareStudio obejmuje także oprogramowanie na zamówienie.
Zakres pierwszej wersji aplikacji
Pierwsza wersja obejmuje ten fragment procesu, który daje mierzalny efekt przy najmniejszej liczbie ekranów. Reszta trafia do kolejnych wydań. Wersja MVP pozwala sprawdzić założenia na prawdziwych danych, zanim rozbudowa podniesie koszt każdej zmiany. Kolejność funkcji ustala się według dwóch parametrów.
- Częstość użycia - funkcja wykonywana codziennie trafia do pierwszego wydania, a raport kwartalny może poczekać.
- Koszt błędu - operacja, której pomyłka generuje straty finansowe, dostaje pełną walidację i dziennik zmian już w pierwszej wersji.
Zakres zapisuje się jako lista historyjek użytkownika z kryteriami akceptacji. Przykładem jest zdanie: po zapisie zgłoszenie ma numer i status 0, a operator widzi je na liście w ciągu sekundy. Kryterium, które da się zmierzyć, zamienia odbiór w test, a nie w spór o interpretację.
Bezpieczeństwo aplikacji internetowej
Najczęstszym błędem w aplikacji z bazą SQL jest wstrzyknięcie kodu, które występuje, gdy tekst z formularza jest doklejany do zapytania. Zapytanie parametryzowane oddziela polecenie od danych, więc wartość z formularza nie zostanie wykonana jako kod. Przykład w C# z nazwami poglądowymi wygląda następująco.
using (var cmd = new SqlCommand(
"SELECT ZgloszenieId, Status FROM dbo.Zgloszenie WHERE KlientId = @klient",
conn))
{
cmd.Parameters.Add("@klient", SqlDbType.Int).Value = klientId;
using (var reader = cmd.ExecuteReader())
{
while (reader.Read()) { /* odczyt wiersza */ }
}
}
Mechanizm i dobre praktyki opisuje dokumentacja o wstrzykiwaniu kodu SQL w Microsoft Learn. Ochrona nie kończy się na zapytaniach, bo każdy typ zagrożenia ma własny mechanizm obrony.
| Zagrożenie | Mechanizm ochrony |
|---|---|
| Wstrzyknięcie kodu SQL | Zapytania parametryzowane i procedury składowane |
| Wstrzyknięcie skryptu do strony | Kodowanie danych przy wyświetlaniu w HTML |
| Przejęcie sesji | Połączenie HTTPS i ciasteczko oznaczone jako HttpOnly |
| Nadmierne uprawnienia | Konto aplikacji w bazie z minimalnym zestawem uprawnień |
Uprawnienia sprawdza serwer przy każdym żądaniu. Ukrycie przycisku w menu nie jest zabezpieczeniem, bo adres punktu końcowego można wywołać ręcznie. Hasła przechowuje się jako skróty z solą, a nie jawnym tekstem.
Wydajność zapytań i indeksy
Lista zgłoszeń klienta z filtrem po statusie jest wywoływana częściej niż jakakolwiek inna operacja, więc zasługuje na indeks. Bez niego SQL Server przegląda całą tabelę, a czas rośnie wraz z liczbą wierszy. Indeks na kolumnach filtra i sortowania pozwala silnikowi wykonać wyszukiwanie zamiast skanowania.
CREATE INDEX IX_Zgloszenie_Klient_Status
ON dbo.Zgloszenie (KlientId, Status)
INCLUDE (UtworzonoUtc);
SELECT ZgloszenieId, Status, UtworzonoUtc
FROM dbo.Zgloszenie
WHERE KlientId = @klient AND Status = 0
ORDER BY UtworzonoUtc DESC
OFFSET 0 ROWS FETCH NEXT 50 ROWS ONLY;
Klauzula INCLUDE dopisuje kolumnę do liści indeksu, więc zapytanie nie sięga do tabeli po dodatkowe dane. Stronicowanie przez OFFSET i FETCH ogranicza liczbę wierszy przesyłanych do przeglądarki. Skuteczność indeksu sprawdza się w planie wykonania, a nie na podstawie przypuszczeń.
Repozytorium i przeglądy kodu przed wydaniem
Kod źródłowy aplikacji trzyma się w repozytorium z historią zmian. Gałąź główna zawiera wersję gotową do wydania, a każda funkcja powstaje w osobnej gałęzi i wraca do głównej dopiero po przeglądzie kodu. Recenzent sprawdza nie tylko styl, lecz także obsługę błędów oraz zgodność z ustaleniami z analizy.
Automatyczny serwer budowania kompiluje projekt przy każdej zmianie i uruchamia testy jednostkowe. Zepsuta kompilacja blokuje połączenie gałęzi, więc błąd wykrywa się w minutach, a nie na etapie odbioru. Gotowy pakiet wdrożeniowy jest tym samym plikiem w środowisku testowym i produkcyjnym, zmieniają się tylko ustawienia połączeń.
| Praktyka | Jaki problem usuwa |
|---|---|
| Przegląd kodu przed połączeniem gałęzi | Błędy logiczne i niespójności, których autor nie widzi we własnym kodzie |
| Automatyczna kompilacja i testy | Regresje wprowadzone przez zmianę w innym module |
| Skrypty wdrożeniowe w repozytorium | Ręczne pomyłki przy kopiowaniu plików na serwer |
| Wersjonowane migracje bazy | Rozbieżność schematu między środowiskami |
Dobrą praktyką jest też plan wycofania. Przed wdrożeniem zapisuje się poprzednią wersję pakietu i kopię bazy, by w razie błędu przywrócić poprzedni stan w kilkanaście minut. Aplikacje mobilne korzystające z tego samego interfejsu, opisane w artykule o tworzeniu aplikacji mobilnych, wymagają wtedy zachowania zgodności wstecznej punktów końcowych.
Reguła: zmiana kontraktu interfejsu, na przykład usunięcie pola z odpowiedzi, wchodzi w osobnym wydaniu po okresie przejściowym, w którym działają obie wersje.
Testowanie i wdrożenie
Aplikacja przed wdrożeniem przechodzi kilka rodzajów testów. Każdy z nich sprawdza inną klasę błędów i działa na innym poziomie kosztu.
| Rodzaj testu | Co sprawdza | Kiedy się uruchamia |
|---|---|---|
| Jednostkowy | Pojedyncza funkcja z regułą biznesową | Przy każdej zmianie kodu |
| Integracyjny | Współpraca aplikacji z bazą i interfejsami | Przed połączeniem gałęzi |
| Akceptacyjny | Zgodność z wymaganiami klienta na danych testowych | Przed wdrożeniem produkcyjnym |
| Obciążeniowy | Czas odpowiedzi przy wielu równoległych użytkownikach | Przy większej zmianie zapytań |
Wdrożenie przebiega w dwóch środowiskach: testowym, na kopii struktury bazy, i produkcyjnym. Zmiany schematu wykonuje się skryptami migracji zapisanymi w repozytorium, dzięki czemu środowiska nie rozchodzą się w czasie. Przed uruchomieniem produkcyjnym wykonuje się kopię bazy i sprawdza jej odtworzenie na osobnym serwerze.
Środowisko testowe wymaga danych zbliżonych do produkcyjnych, bo błędy wydajności i formatowania ujawniają się dopiero na realnych wolumenach. Kopię danych klienta przenosi się tam po zanonimizowaniu pól osobowych, na przykład nazwisk i numerów telefonów. Testy akceptacyjne prowadzi wskazany przedstawiciel klienta według listy przypadków z analizy, a wynik każdego przypadku jest zapisywany w protokole odbioru.
Ostatnim elementem wdrożenia jest szkolenie użytkowników i przekazanie instrukcji. Osoba odpowiedzialna po stronie klienta dostaje konto administracyjne i opis procedur, na przykład zakładania użytkowników czy sprawdzania dziennika błędów. Bez tego pierwsze zgłoszenia po uruchomieniu dotyczą obsługi, a nie usterek aplikacji.
Reguła: kopia zapasowa, której odtworzenia nie sprawdzono, nie jest zabezpieczeniem. Test przywrócenia wchodzi do listy odbiorowej wdrożenia.
Hosting i utrzymanie aplikacji
Po wdrożeniu aplikacja działa na serwerze należącym do firmy programistycznej albo do klienta. Przeglądarka wysyła zapytanie, serwer odpowiada, a użytkownik potrzebuje tylko urządzenia z przeglądarką i zwykle dostępu do Internetu. Część funkcji może działać także bez sieci, jeśli aplikacja zapisuje dane lokalnie i synchronizuje je później.
SoftwareStudio wskazuje w opisie oferty chmurę prywatną na platformie VMware jako jedno z miejsc uruchamiania aplikacji. Wirtualizacja pozwala przenieść maszynę na inny host bez zmiany aplikacji, co upraszcza prace serwisowe. Szersze omówienie środowiska serwerowego zawiera artykuł o dedykowanych aplikacjach webowych.
Utrzymanie obejmuje poprawki błędów i aktualizacje bibliotek, a także kontrolę miejsca w bazie. Umowa powinna określać czas reakcji na zgłoszenie oraz sposób przekazania kodu źródłowego. Sam proces wytwarzania i rozwoju systemów biznesowych opisano w tekście o programowaniu aplikacji biznesowych, a rolę firmy programistycznej w całym cyklu przedstawia strona software house.
| Element umowy utrzymaniowej | Co powinien określać |
|---|---|
| Czas reakcji | Godziny od zgłoszenia do pierwszej odpowiedzi, osobno dla awarii i drobnych uwag |
| Kod źródłowy | Sposób przekazania repozytorium i dokumentacji technicznej |
| Kopie zapasowe | Częstotliwość i miejsce przechowywania oraz test odtworzenia |



