O jakości firmy programistycznej decyduje proces wytwarzania kodu, a nie lista technologii w ofercie. Strona opisuje, jak pracuje zespół wytwórczy: kto odpowiada za jaki etap, jak wygląda historia zmian w repozytorium Git, jak działa przegląd kodu, jakie testy pisze się w C# i jak zmiany trafiają do bazy T-SQL. Opis dotyczy mechanizmów ogólnych. Służy jako lista pytań do zespołu, a nie jako regulamin pracy któregokolwiek konkretnego dostawcy.
Firma programistyczna Poznań i zespół wytwórczy
Zespół, który buduje aplikację biznesową, dzieli pracę według odpowiedzialności za wynik. Podział ma znaczenie praktyczne: każda rola zostawia po sobie artefakt, który zamawiający może zobaczyć i ocenić. Zgodnie z opisem SoftwareStudio w zespole projektowym pracują analitycy i programiści, a także testerzy oraz specjaliści od wdrożeń, którzy odpowiadają za cały cykl życia aplikacji, od pierwszej rozmowy po wsparcie po uruchomieniu.
| Rola | Wynik pracy | Co widzi zamawiający |
|---|---|---|
| Analityk | Specyfikacja funkcjonalna oraz opis procesów i integracji | Dokument do akceptacji przed rozpoczęciem programowania |
| Programista | Kod aplikacji i skrypty bazy danych | Wersje w środowisku testowym po kolejnych iteracjach |
| Tester | Scenariusze testowe i raport z wykonania | Lista usterek z priorytetami przed odbiorem |
| Wdrożeniowiec | Instalacja i migracja danych, a także szkolenie | Uruchomienie produkcyjne i instrukcje dla użytkowników |
Warstwa technologiczna SoftwareStudio opiera się na platformie .NET i bazach danych SQL Server. Aplikacje webowe są hostowane w chmurze prywatnej działającej na platformie VMware, a programiści zajmują się też integracją nowego oprogramowania z systemami klasy ERP oraz z rozwiązaniami WMS i CRM, które firma już używa. Firma pomaga również przy opisie założeń rozwiązania, na przykład w specyfikacji do wniosków o dofinansowanie unijne. Ogólne podejście do budowy aplikacji dla przedsiębiorstw opisuje strona o programowaniu aplikacji biznesowych, a rolę zewnętrznego wykonawcy w porównaniu z gotowym produktem strona o producencie oprogramowania.
Reguła: każdy etap prac kończy się artefaktem, który da się sprawdzić bez rozmowy z autorem: dokumentem, wersją do przetestowania albo raportem.
Git - gałęzie i znaczniki wersji
Repozytorium Git przechowuje kod razem z historią każdej zmiany. Standardowy układ pracy wygląda tak: programista tworzy gałąź na jedno zadanie, zapisuje zmiany w niewielkich commitach z opisem, wypycha gałąź na serwer i zgłasza ją do przeglądu. Dopiero po zaakceptowaniu zmiana trafia do gałęzi głównej, z której powstaje wersja wdrażana. Poniższe polecenia pokazują ten cykl od strony programisty.
git switch -c zmiana/rezerwacja-stanu
git add .
git commit -m "Rezerwacja: walidacja ilości względem stanu dostępnego"
git push origin zmiana/rezerwacja-stanu
git tag -a v2.4.0 -m "Wydanie 2.4.0"
Ostatnie polecenie zapisuje znacznik wersji na wskazanym commicie. Dzięki niemu na pytanie „jaki kod działa dziś u klienta” odpowiada się jednym poleceniem, a błąd zgłoszony w wersji 2.4.0 można odtworzyć na dokładnie tym samym kodzie. Pełny opis poleceń i modeli gałęzi zawiera oficjalna książka Pro Git w polskiej wersji.
| Element | Do czego służy | Sygnał ostrzegawczy |
|---|---|---|
| Gałąź na zadanie | Izoluje pracę nad jedną zmianą od reszty kodu | Wszyscy zapisują bezpośrednio do jednej gałęzi |
| Opis commita | Wyjaśnia, dlaczego zmieniono kod, a nie tylko co | Opisy typu „poprawki” lub „zmiany” |
| Znacznik wersji | Wiąże wdrożenie z konkretnym stanem kodu | Brak znaczników, wersji nie da się odtworzyć |
| Ochrona gałęzi głównej | Wymusza przegląd i testy przed scaleniem | Bezpośrednie zapisy na gałąź produkcyjną |
Przegląd kodu jako kontrola zmiany
Przegląd kodu polega na tym, że druga osoba czyta zmianę przed jej scaleniem i zostawia uwagi. Nie zastępuje testów, tylko wychwytuje błędy, których testy nie przewidziały: pomyłkę w warunku granicznym, brak sprawdzenia uprawnień, zapytanie, które przy większej tabeli zatrzyma system. Sprawdza się tym lepiej, im mniejsza jest zmiana, bo dużą zmianę recenzent przegląda pobieżnie. Dlatego zadania dzieli się tak, żeby jedna gałąź dotyczyła jednej sprawy i dawała się przeczytać w jednym posiedzeniu, a uwagi recenzenta trafiały do autora zanim ten zacznie kolejne zadanie.
- Poprawność logiki - czy zmiana robi to, co opisuje zadanie, także dla wartości granicznych.
- Bezpieczeństwo - czy zapytania są parametryzowane, a uprawnienia sprawdzane po stronie serwera.
- Wydajność - czy zapytanie korzysta z indeksu i nie wykonuje w aplikacji pętli po pojedynczych wierszach.
- Czytelność - czy nazwy i podział na metody pozwolą zrozumieć kod osobie, która nie jest jego autorem.

Najczęstszą uwagą w przeglądach aplikacji bazodanowych jest sklejanie tekstu zapytania z danymi od użytkownika. Wersja z parametrem chroni przed wstrzyknięciem SQL i pozwala serwerowi ponownie użyć planu wykonania zapytania. Przykład w C# pokazuje wersję poprawną, przy założeniu, że połączenie conn jest już otwarte.
using var cmd = new SqlCommand(
"SELECT IdZlecenia, Status FROM dbo.Zlecenie WHERE Numer = @numer", conn);
cmd.Parameters.Add("@numer", SqlDbType.NVarChar, 30).Value = numer;
using var reader = cmd.ExecuteReader();
Zasady pracy nad zmianą w krótkich iteracjach, z regularnym pokazywaniem postępu, opisuje strona o zwinnym zarządzaniu projektami IT na zamówienie. Wynikiem przeglądu jest decyzja o zatwierdzeniu zmiany albo o jej poprawie, a obie zostawiają ślad w systemie repozytorium.
Testy jednostkowe i integracyjne w C#
Test jednostkowy sprawdza pojedynczą regułę bez bazy danych i sieci, więc wykonuje się w milisekundach. Test integracyjny uruchamia kod na prawdziwym SQL Server i sprawdza, czy zapytania i transakcje współpracują z mapowaniem danych. Oba poziomy uzupełniają się: pierwszy pilnuje logiki, drugi połączenia między aplikacją a bazą. Dokumentacja platformy .NET opisuje testowanie w .NET oraz dostępne biblioteki.
Przykład poniżej pokazuje regułę stanu magazynowego: nie można zarezerwować więcej, niż jest dostępne, a nieudana rezerwacja nie zmienia stanu. Klasy mają charakter poglądowy i nie odwzorowują schematu żadnego produktu.
public record WynikRezerwacji(bool Powodzenie);
public class StanMagazynowy
{
public decimal Dostepne { get; private set; }
public StanMagazynowy(decimal dostepne) => Dostepne = dostepne;
public WynikRezerwacji Zarezerwuj(decimal ilosc)
{
if (ilosc <= 0 || ilosc > Dostepne) return new WynikRezerwacji(false);
Dostepne -= ilosc;
return new WynikRezerwacji(true);
}
}
public class RezerwacjaTests
{
[Fact]
public void Rezerwacja_ponad_stan_nie_zmienia_stanu()
{
var stan = new StanMagazynowy(5m);
var wynik = stan.Zarezerwuj(8m);
Assert.False(wynik.Powodzenie);
Assert.Equal(5m, stan.Dostepne);
}
}
| Poziom testu | Co sprawdza | Kiedy się go uruchamia |
|---|---|---|
| Jednostkowy | Pojedyncze reguły i obliczenia bez zależności zewnętrznych | Przy każdej zmianie, na komputerze programisty i na serwerze |
| Integracyjny | Zapytania i procedury na testowej bazie SQL Server, w tym transakcje | Przed scaleniem zmiany oraz przed wydaniem |
| Akceptacyjny | Scenariusze biznesowe według specyfikacji | Na środowisku testowym przed odbiorem |
Proces powstawania aplikacji od analizy po odbiór opisuje strona o procesie tworzenia aplikacji biznesowych. Zamawiający może poprosić o raport z ostatniego przebiegu testów jako element odbioru, a nie tylko o ich deklarację.
T-SQL i migracje bazy danych
Zmiana w aplikacji rzadko obywa się bez zmiany w bazie. Każda zmiana schematu, czyli nowa kolumna czy indeks, musi trafić na każde środowisko w tej samej kolejności, dlatego skrypty T-SQL trzyma się w repozytorium obok kodu i numeruje. Skrypt migracji powinien być idempotentny: uruchomiony drugi raz nie psuje niczego, tylko sprawdza, czy zmiana jest już zastosowana. Rejestr wersji schematu wystarcza do tego jedna mała tabela.
IF OBJECT_ID('dbo.WersjaSchematu') IS NULL
CREATE TABLE dbo.WersjaSchematu (
Wersja int NOT NULL PRIMARY KEY,
Zastosowano datetime2 NOT NULL DEFAULT SYSUTCDATETIME()
);
GO
IF NOT EXISTS (SELECT 1 FROM dbo.WersjaSchematu WHERE Wersja = 12)
BEGIN
ALTER TABLE dbo.Zlecenie ADD Uwagi nvarchar(500) NULL;
INSERT dbo.WersjaSchematu (Wersja) VALUES (12);
END
GO

Logikę, która musi wykonać się w całości albo wcale, zamyka się w transakcji. Procedura poniżej zmienia status zlecenia i zapisuje wpis w historii, przy czym status wolno tylko zwiększyć, więc równoległe wywołanie nie nadpisze nowszego stanu starszym. Ustawienie SET XACT_ABORT ON powoduje wycofanie całej transakcji przy pierwszym błędzie wykonania. Składnię wyjaśnia dokumentacja SET XACT_ABORT w Microsoft Learn. Instrukcja CREATE OR ALTER jest dostępna od SQL Server 2016 z dodatkiem SP1.
CREATE OR ALTER PROCEDURE dbo.ZmienStatusZlecenia
@IdZlecenia int,
@Status tinyint
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
BEGIN TRANSACTION;
UPDATE dbo.Zlecenie
SET Status = @Status
WHERE IdZlecenia = @IdZlecenia AND Status < @Status;
IF @@ROWCOUNT = 1
INSERT dbo.ZlecenieHistoria (IdZlecenia, Status, Kiedy)
VALUES (@IdZlecenia, @Status, SYSUTCDATETIME());
COMMIT TRANSACTION;
END
Reguła: skrypt bazy trafia do repozytorium razem ze zmianą kodu, która go wymaga, i przechodzi ten sam przegląd.
Szerzej o projektowaniu tabel i procedur oraz o doborze indeksów pisze strona o programowaniu baz danych. Wymiana danych z innymi systemami, z własną transakcją po każdej stronie, opisano w tekście o integracji WMS z ERP przez REST i kolejki.
Warstwa przeglądarkowa - jQuery i AJAX
Aplikacje webowe SoftwareStudio budowane są w oparciu o jQuery i HTML5, a użytkownik pracuje w przeglądarce bez instalacji na stanowisku. Dla zespołu wytwórczego oznacza to jedno ograniczenie i jedną zaletę. Ograniczenie: przeglądarka jest środowiskiem niezaufanym, więc każda reguła biznesowa i każde sprawdzenie uprawnień musi istnieć także na serwerze. Zaleta: nowa wersja trafia do wszystkich użytkowników w chwili wdrożenia po stronie serwera, bez aktualizacji na komputerach.
$.ajax({
url: '/api/zlecenia/status',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({ id: 42, status: 3 })
})
.done(function () { odswiezListe(); })
.fail(function (xhr) {
if (xhr.status === 409) { pokazKomunikat('Status został zmieniony przez innego użytkownika.'); }
else { pokazKomunikat('Nie udało się zapisać zmiany.'); }
});
Kod odpowiedzi 409 oznacza konflikt: serwer odrzucił zmianę, bo stan zlecenia jest już nowszy, dokładnie tak jak w procedurze z poprzedniej sekcji. Interfejs pokazuje użytkownikowi komunikat i odświeża listę, zamiast po cichu nadpisywać cudze dane. Ten sam mechanizm, nazywany optymistyczną kontrolą współbieżności, obowiązuje w każdym miejscu, gdzie dwie osoby mogą edytować ten sam rekord. Przyciski, które wysyłają żądanie, blokuje się do czasu odpowiedzi, żeby dwukrotne kliknięcie nie wywołało operacji dwa razy. Podstawy takiej architektury omawia strona o aplikacji webowej.
Środowiska i wdrożenie zmian
Kod przechodzi przez środowisko deweloperskie i testowe, zanim trafi na produkcyjne. Na testowym zamawiający akceptuje zmiany na kopii danych, produkcja dostaje wyłącznie wersję z oznaczonego znacznikiem commita. Wdrożenie obejmuje kopię zapasową bazy przed migracją, uruchomienie skryptów w ustalonej kolejności, test dymny najważniejszych funkcji i plan powrotu do poprzedniego znacznika. Bez planu powrotu każde wdrożenie jest jednokierunkowe.

Poprawka pilna na podstawie znacznika wersji
Błąd produkcyjny naprawia się na kodzie, który faktycznie działa u klienta, a nie na aktualnej gałęzi głównej, bo ta zawiera już zmiany jeszcze niewydane. Programista tworzy gałąź poprawkową z tagu wdrożonej wersji i poprawia usterkę. Zmiana przechodzi przegląd oraz testy, po czym dostaje nowy tag. Zmianę wprowadza się następnie także do gałęzi głównej, żeby błąd nie wrócił w kolejnym wydaniu.
git switch -c poprawka/2.4.1 v2.4.0
git commit -am "Naprawa: blokada zlecenia przy jednoczesnej zmianie statusu"
git tag -a v2.4.1 -m "Poprawka 2.4.1"
Czas, w jakim taka poprawka powstaje i trafia na produkcję, zależy od priorytetu zgłoszenia i zapisów umowy. W umowie SLA usterki blokujące pracę odróżnia się od drobnych błędów i każdej z tych grup przypisuje inny czas reakcji.
Po uruchomieniu produkcyjnym zespół zapewnia wsparcie techniczne w ramach umowy SLA, czyli reaguje na zgłoszenia w ustalonym czasie. Jak czytać takie zapisy i co sprawdzić w umowie przed podpisaniem, opisuje strona o tym, jak ocenić firmę informatyczną z Poznania. Szerszy opis wytwarzania oprogramowania w tym mieście przedstawia strona o software house w Poznaniu.
Test dojrzałości procesu: poprosić zespół o pokazanie historii jednej niedawnej zmiany od zadania przez przegląd i testy aż do znacznika wersji, w której trafiła na produkcję. Firma z uporządkowanym procesem robi to w kilka minut.
Taki test da się wykonać na spotkaniu ofertowym, bez dostępu do kodu, a jego wynik mówi o zespole więcej niż lista certyfikatów czy technologii. Więcej o usługach programistycznych SoftwareStudio znajduje się na stronie usług SoftwareStudio.




