Jednoznaczna definicja określenia "utrzymywanie projektu"

0

Często ludzie o to pytają pracodawcę, czy jest utrzymywanie projektu czy nowy projekt, ale co konkretnie kryje się pod "utrzymywaniem", jak to się rozumuje w branży, czy to jest kwestia umowna i każdy trochę inaczej? Czy utrzymanie to tylko poprawianie bugów w zastanym projekcie, czy dopisywanie nowych funkcjonalności do gotowego projektu, który ma ...no właśnie ile lat? Czy jak napiszę się jakiś projekt który nie ma wiele featerów np. w pół roku, i potem biznes wymyśla nowe featury - to też jest "utrzymywanie"?

3

Różni ludzie rozumieją ten termin inaczej.

Kiedy na rozmowie kwalifikacyjnej rekruter mówi "utrzymanie aplikacji", to z automatu zakładam że ma na myśli aplikację która już stoi chwile, i nie działa tak dobrze, i trzeb ją ponaprawiać.

3

Bardziej, że została już napisana a teraz trzeba tylko grzebać w kodzie i naprawiać błędy.

7

Utrzymanie prawie zawsze znaczy naprawianie bugów i dopisywanie ficzerów do już działającej aplikacji. Samo naprawianie bugów to raczej przy "wygaszaniu" aplikacji (bo np. wejdzie nowa wersja).

Pardoksalnie utrzymanie dość często oznacza więcej swobody (w technologiach) i ciekawsze wyzwania niż tzw. greenfield - ale oczywiście wszystko zależy.

3

Z mojego doświadczenia powiedziałbym że utrzymanie aplikacji/systemu zawsze wiązało się z łataniem bugów i wprowadzaniem niewielkich zmian.

Za to rozwój aplikacji/systemu to zarówno naprawianie błędów oraz dodawanie nowych funkcjonalności.

8

To może inaczej, na zasadzie kontrastu/przeciwności - łatwiej powiedzieć, czym utrzymanie nie jest. Jest ono przeciwieństwem tzw. greenfield, czyli NIE:

  • nie masz wyboru technologi (bo już jest wybrana)
  • nie wybierasz architektury (bo już jest wybrana)
  • nie odpowiadasz za tworzenie wizji nowego softu - bo program już działa
  • nie piszesz (przynajmniej - za często) nowych ficzerów, raczej szukasz powodów, dlaczego coś nie działa (albo działa źle)
  • rozszerzając poprzedni punkt: w sumie się cieszysz z powodu braku nowości, bo kod jest napisany totalnie chaotycznie, brak dokumentacji, nikt nie wie jak to działa ;)
  • nie rozwijasz się, bo zamiast pracy twórczej czujesz się jak archeolog z branży IT
  • nikt nie docenia Twojej pracy - bo jest żmudna i mało efektowna. Nie masz jakichś fajerwerków do pokazania, duża część tego co robisz jest w ogóle niewidoczna dla innych zespołów, szefostwa czy klientów
  • największe ryzyko/niebezpieczeństwo: granica między utrzymaniem a legacy jest bardzo płynna.
1

Bardzo mi się podoba post @cerrato z góry, dodatkowo mogę dopisać kilka charakterystyk, tylko ja może dopiszę czym utrzymanie jednak jest?

  • Jeśli coś zepsujesz, to jest na Ciebie; ale jeśli perfekcyjnie zakodzisz jakiś feature, to nikt nawet tego nie zauważy

  • Praca jest często z zależnościami/bibliotekami które są przestarzałe, i ma to dwie konsekwencje:

    • Często zgłoszony feature od project managera, wymaga aktualizacji zależności
    • A jednocześnie, aktualizacja tych zależności powoduje nowe błędy

    O tym jak dysfunkcyjne to jest, niech rozsądzi sam czytający - bo dochodzimy do momentu, że (za pośrednictwem takiej aktualizacji) naprawiamy jeden błąd, dodając inny.

  • Często znajdujesz w kodzie miejsca/funkcje/klasy/moduły/biblioteki które "wydawać by się mogło że są po nic" - nie wiadomo po co są, i należałoby je usunąć. Raz na jakiś czas one jednak są używane po coś, tylko w bardzo niejsany sposób, i nie widać co robią.

  • Wchodzisz do projektu w którym nie ma testów, albo są bardzo słabiej jakości.

  • Często zachodzi efekt, że ktoś kto pracował poprzednio nad projektem wziął bardzo dużo długu technologicznego, jednocześnie dowożąc feature'y i został uznany za dobrego programmera; Ty jednak musisz spłacać ten dług, i to już takie fajne nie jest.

@cerrato: Daj znać co myślisz :D

1

Wielokrotnie się niezgadzam z poniższym,

cerrato napisał(a):

To może inaczej, na zasadzie kontrastu/przeciwności - łatwiej powiedzieć, czym utrzymanie nie jest. Jest ono przeciwieństwem tzw. greenfield, czyli NIE:

  • nie masz wyboru technologi (bo już jest wybrana)

W zasadzie tak, ale i ciekawe przykłady refaktoringu na nowsze technologie się zdarzają,

  • nie wybierasz architektury (bo już jest wybrana)

Prawda

  • nie odpowiadasz za tworzenie wizji nowego softu - bo program już działa

Za to odpowiadasz za wizję działającego softu

  • nie piszesz (przynajmniej - za często) nowych ficzerów, raczej szukasz powodów, dlaczego coś nie działa (albo działa źle)

Przeważnie piszesz nowe ficzery. Czasem nowe ficzery są kamuflowane jako bugi.

  • rozszerzając poprzedni punkt: w sumie się cieszysz z powodu braku nowości, bo kod jest napisany totalnie chaotycznie, brak dokumentacji, nikt nie wie jak to działa ;)

Zależy. Choć zwykle jest tak, że "zrobilibyśmy to lepiej" - to czasem są projekty, że naprawdę docenia się dobry kod i brak ton durnej dokumentacji (za to dostępe jest kilka przydatnych Readme)

  • nie rozwijasz się, bo zamiast pracy twórczej czujesz się jak archeolog z branży IT

Praca archeologa w IT jest super. Czuje wtedy, że się rozwijam, zwłaszcza jak wykopuje się jakieś ciekawe pomysły sprzed wieków.

  • nikt nie docenia Twojej pracy - bo jest żmudna i mało efektowna. Nie masz jakichś fajerwerków do pokazania, duża część tego co robisz jest w ogóle niewidoczna dla innych zespołów, szefostwa czy klientów

Odblokowanie produkcji, która umiera i uratowanie firmy przed grubymi stratami zwykle daje jednak poczucie "wejścia cało na biało". Bywa dobrze.

  • największe ryzyko/niebezpieczeństwo: granica między utrzymaniem a legacy jest bardzo płynna.

Nie wiem co autor miał na myśli.

IMO główna różnica w działaniu z utrzymaniem/legacy to ile kasy ten produkt przynosi - jeśli jest to dochodowy/istotny dla firmy projekt, to można robić godne utrzymanie, z testami, refaktoringiem, czystym kodem i na luzie.
Jeśli jednak trafiamy na projekt, który przynosi straty, a firma chce go po prostu wygasić bez ponoszenia dramatycznej straty wizerunkowej to bywa źle, z tendencją do bardzo źle.

0
jarekr000000 napisał(a):

Wielokrotnie się niezgadzam z poniższym,

No i mniej więcej to miałem na mysli, kiedy pisałem wyżej że różne osoby rysują różne granicę w kontekście tego co to znaczy "utrzymanie aplikacji".

Nie znajdziesz jasnej bariery, żeby obiektywnie stwierdzić jakie akcje tyczą się utrzymania a jakie nie.

0

największe ryzyko/niebezpieczeństwo: granica między utrzymaniem a legacy jest bardzo płynna.
[...]
Nie wiem co autor miał na myśli

Chodzi o granice między naprawianiem 10-letniego Mondeo, a klejeniem na plaster i poxipol 50-letniego trabanta ;)
Przyjmujesz się na utrzymanie, a po jakimś czasie nawet sam nie wiesz kiedy okazuje się, że siedzisz z taśmą klejącą przed trabantem czy innym rozpadającym się Matizem.

IMO główna różnica w działaniu z utrzymaniem/legacy to ile kasy ten produkt przynosi

Ale to piszesz od strony biznesowej/menażmętu firmy. To oni decydują, czy rozwijają program, czy robią takie minimum, żeby apka nie padła i przynosiła kasę. Tylko jako programista za wiele nie masz na to wpływu, a nawet możesz nie wiedzieć, jakie szefostwo ma plany. Dostajesz zadanie w projekcie X trzeba zmienić wygląd okna z listą klientów, a także zobacz, dlaczego źle się drukuje raport z zamówień i nie masz za bardzo możliwości ocenienia, czy to już legacy, czy nadal utrzymanie.
Ogólnie - uwaga bardzo słuszna i w sumie to właśnie tam ta granica leży, ale ciężko ją wyczuć z perspektywy kodera. Zwłaszcza szeregowego, a nie jakiegoś PM czy kogoś stojącego wyżej w łańcuchu pokarmowym.

1

projekt nad którym pracuję w firmie generalnie pasuje do kategorii projektów utrzymaniowych, ale i tak wprowadzamy tam czasem nowości. projekt ma ok. 10 lat (chyba nawet więcej) i kilkadziesiąt obecnie działających (na produkcji) mikroserwisów (a kilka już zdechło całkiem i zostało zastąpionych nowymi rozwiązaniami). niektóre mikroserwisy są oparte o stare umierające technologie (np. https://liftweb.net/) i te mikroserwisy są już trochę na wymarciu (jednak nie ma pośpiechu, mogą sobie leżeć jeszcze). niektóre najnowsze mikroserwisy oparte są o https://zio.dev/ czyli względnie świeżynkę. wiele lat temu nie mieliśmy kafki, ale teraz kafka to podstawa w komunikacji między nowymi mikroserwisami. kiedyś wszystko stało na jednej maszynce, dzisiaj większość rzeczy stoi na wewnętrznej chmurze, a przymierzamy się do przenosin na google clouda. stare mikroserwisy przepisujemy na nową architekturę systemu (tzn. ten sam język, ale tworzymy od nowa kod realizujący starą funkcjonalność i dodatkowo nową) i nadal mamy tak, że stara architektura i nowa architektura działają jednocześnie, tzn. refaktorujemy sobie system po kroku, bez rewolucji. chociaż z drugiej strony, mała rewolucją było zastąpienie gujacza z wspomnianego liftweba (czyli gui pisane przez backendowców - było brzydkie i działało kiepsko, bo generowało ciężki stan sesyjny po stronie serwera) przez gui oparte o reacta (ogarnianego przez frontendowca) i bezstanowy backend.

1

Ja obecnie pracuję nad kilkoma projektami, jeden z nich właśnie jest "utrzymywany" - ma 15 lat, czasem przez miesiące nic się przy nim nie robi, czasem poprawi jakiegoś buga, podniesie wersje frameworka lub zaktualizuje zależności a czasem trzeba dodać kilka nowych, zazwyczaj małych featurów. Inny projekt przez rok był uznawany za nowy, ale teraz już jest w miarę stabilny i też przechodzi w fazę utrzymywania więc chyba w każdej pracy w końcu się utrzymuje jakiś projekt bo chyba żadna firma nie każe pisać nowych projektów, po czym uznaje je za skończone i zwalnia pracowników lub każe pisać kolejny od nowa. W ogóle nie ma chyba "skończonych" projektów, są tylko porzucone.

To że będziesz pracował nad utrzymywaniem projektu znaczy tylko tyle że nie będziesz nic pisał od zera i tak jak wyżej pisano - nie będziesz mógł wybrać technologii ani projektować systemu. To czy będziesz go rozwijał i ile ma lat to już dodatkowe pytania

2
cerrato napisał(a):

Ale to piszesz od strony biznesowej/menażmętu firmy. To oni decydują, czy rozwijają program, czy robią takie minimum, żeby apka nie padła i przynosiła kasę. Tylko jako programista za wiele nie masz na to wpływu, a nawet możesz nie wiedzieć, jakie szefostwo ma plany. Dostajesz zadanie w projekcie X trzeba zmienić wygląd okna z listą klientów, a także zobacz, dlaczego źle się drukuje raport z zamówień i nie masz za bardzo możliwości ocenienia, czy to już legacy, czy nadal utrzymanie.

Po pierwsze primo Legacy nie oznacza niczego złego, to po prostu kod zastany - odziedziczony po jakimś innym zespole. Może być dobry, może być średni. Może być zły.
Na etapie rekrutacji interesuje mnie projekt i jeśli mam trafić do utrzymania to kalkuluję sobie jak bardzo ten projekt jest istotny dla firmy - przeważnie da się to ocenić - choć faktycznie bywało, że po roku/dwóch zmieniały się priorytety, ale to się zdarzyć może zawsze - greenfieldy też potrafią się zamknąć lub zmienić w koszmar z dnia na dzień, bo jakiś szef w stanach wstanie lewą nogą.

1

Tak mi się skojarzyło
screenshot-20230127155543.png

0

Legacy nie oznacza niczego złego

No tutaj to się totalnie nie zgodzę. OK, rozumiem Twoje podejście, ale podejrzewam, że u większości osób (ze mną włącznie) legacy jest synonimem rzeźbienia w brązie. Ale, żeby nie było, że ja wymyślam - wpisałem na google co to jest kod legacy i widzę, że większość wyników twierdzi podobnie (znaczy - wydźwięk zdecydowanie pejoratywny):

legacy code oznacza nic innego, jak „kod dziedziczony”, czyli kod, który de facto otrzymujemy w spadku po innych programistach, na przykład w momencie dołączenia do nowego projektu. Taki kod budzi lęki i obawy – kod działa, lecz nie znamy jego zawiłej logiki. Szczególny postrach sieje trudny do zrozumienia i okiełznania spaghetti code. Legacy code to również kod, który… piszemy w danej chwili, ale nie został jeszcze pokryty testami, zatem nie jest przygotowany na zmiany w przyszłości.

Legacy code to kod, który został stworzony najczęściej lata temu. Oczywiście w międzyczasie różne osoby dodały do niego "na szybko" kilka nowych funkcji lub zmian. Dzięki temu otrzymujemy swoiste "spaghetti" na dokładkę bez jakiejkolwiek dokumentacji. Przez to do końca nie wiadomo jak się zachowa ani jakie są możliwe schematy jego działania, a więc nie wiemy w jaki sposób możemy go zmienić. Legacy code jako przestarzały kod, który przez brak nowoczesnych rozwiązań nie pasuje do obecnej technologii i ciężko jest go do niej dopasować. Inni generalizują tę nazwę, aby określić kod, który jest niezrozumiały i trudny do zmiany.

Legacy code (kod odziedziczony lub zastany), jest to kod działający już pewien czas na produkcji. Tworzony przez ludzi, którzy nie są już obecni w naszej organizacji lub firmy zewnętrzne, które już nie istnieją na rynku. Bardzo często taki kod nie posiada dokumentacji, a początkowe założenia w trakcie jego działania ulegały wielu zmianom. Z różnych powodów nie znajdziemy w nim również testów jednostkowych ani integracyjnych lub napisane wcześniej testy na skutek zbyt wielu zmian i wprowadzania dodatkowych zależności przestały być miarodajne.

Legacy Code, czyli ten stary kod lub oprogramowanie, którego nikt nie chce dotknąć, nikt nie wie, kto go napisał, a wszyscy boją się go zastąpić. Większość deweloperów doświadczyła tego niepokojącego uczucia konieczności dłubania w starym komponencie, aby go rozszerzyć lub naprawić błąd. W najlepszym przypadku jest to niejasny fragment kodu, który jest odpowiedzialny za niewielką funkcję, w najgorszym to rdzeń całego systemu.

Czasami (zawsze) deweloperzy boją się zmienić starszy kod. To nie jest nierozsądne. Strach może wynikać z niewystarczającego pokrycia testów, braku dokumentacji, przestarzałej technologii lub skomplikowanej zależności między modułami. Zmiana tego stwarza duże ryzyko, ponieważ zmiana może skutkować nieprzewidzianym wpływem na cały kod, który jest od tej zmiany zależny.

W wielu przypadkach praca ze starym kodem to jak czytanie starosłowiańskich tekstów. Nigdy nie jesteśmy w stanie być w 100% pewni, czy zły lub niekompletny kod, na który patrzymy, to efekt słabej pracy programisty, słabych warunków programowania, czy po prostu realia czasów kodu łupanego. Nie zmienia to faktu, że zanim kod ten stanie się kompatybilny z naszą pracą, minie dużo czasu na jego naprawę. A może nawet przepisanie?

0

@cerrato: w cytatach jest sporo prawdy, ale też sporo uproszczeń imo

legacy code oznacza nic innego, jak „kod dziedziczony”, czyli kod, który de facto otrzymujemy w spadku po innych programistach, na przykład w momencie dołączenia do nowego projektu. Taki kod budzi lęki i obawy – kod działa, lecz nie znamy jego zawiłej logiki.

Legacy code (kod odziedziczony lub zastany), jest to kod działający już pewien czas na produkcji.

Hiperbolizując.
Za każdym razem jak dołączasz do projektu który miał już pierwszy komit do repo to jest to legacy code wg powyższych definicji.

Wiem, ekstremalnie, ale de facto o ile nie idziesz za każdym razem do projektu który tworzony jest od zera to zawsze to będzie legacy code albo legacy architecture (bo co ci po tym że tworzysz swój mikroserwisik od zera jak on jest częścią zastanej większej całości).

Nie zmienia to faktu, że zanim kod ten stanie się kompatybilny z naszą pracą, minie dużo czasu na jego naprawę.

Taka moim zdaniem jest specyfika pracy z każdym kodem który nie jest mój, zastanym, czy nawet skomitowanym przez kolegę godzinę temu. Nie koniecznie legacy.

1
opiszon napisał(a):

@cerrato: w cytatach jest sporo prawdy, ale też sporo uproszczeń imo

legacy code oznacza nic innego, jak „kod dziedziczony”, czyli kod, który de facto otrzymujemy w spadku po innych programistach, na przykład w momencie dołączenia do nowego projektu. Taki kod budzi lęki i obawy – kod działa, lecz nie znamy jego zawiłej logiki.

Legacy code (kod odziedziczony lub zastany), jest to kod działający już pewien czas na produkcji.

Hiperbolizując.
Za każdym razem jak dołączasz do projektu który miał już pierwszy komit do repo to jest to legacy code wg powyższych definicji.

Wiem, ekstremalnie, ale de facto o ile nie idziesz za każdym razem do projektu który tworzony jest od zera to zawsze to będzie legacy code albo legacy architecture (bo co ci po tym że tworzysz swój mikroserwisik od zera jak on jest częścią zastanej większej całości).

Nie zmienia to faktu, że zanim kod ten stanie się kompatybilny z naszą pracą, minie dużo czasu na jego naprawę.

Taka moim zdaniem jest specyfika pracy z każdym kodem który nie jest mój, zastanym, czy nawet skomitowanym przez kolegę godzinę temu. Nie koniecznie legacy.

No to zależy co oznacza "legacy":

  • Jeśli rozumieć słowo "legacy" (aka. @cerrato) to to jest kod, który spadł na Ciebie w długu (aka. "kod zastany"), czyli jakiś zespół nad czymś pracował, zespół zniknął, kod przekazano Ci jako "spadek" - "legacy".
  • Ale można też rozumieć słowo "legacy", tak jak się przyjęło, że "legacy" to jest dowolny kod o nisjkiej jakości lub oparty na starej technologii, nie zależnie od tego czy faktycznie go po kimś dostałeś czy nie.

Cała debata rozbija się o nazewnictwo.

2
cerrato napisał(a):

Legacy nie oznacza niczego złego

No tutaj to się totalnie nie zgodzę. OK, rozumiem Twoje podejście, ale podejrzewam, że u większości osób (ze mną włącznie) legacy jest synonimem rzeźbienia w brązie. Ale, żeby nie było, że ja wymyślam - wpisałem na google co to jest kod legacy i widzę, że większość wyników twierdzi podobnie (znaczy - wydźwięk zdecydowanie pejoratywny):

moim zdaniem legacy nie oznacza niczego złego, ale zazwyczaj jest to coś złego. Znaczy jak napiszesz jakiś kod i ktoś inny go po tobie przejmie nawet po godzinie to już jest legacy a często nie lubimy cudzych kodów bo zawsze jest coś zrobione inaczej niż byśmy to zrobili sami. Nie widzę sensu w zdaniu:

  • największe ryzyko/niebezpieczeństwo: granica między utrzymaniem a legacy jest bardzo płynna.

utrzymywanie = legacy. Ale rozumiem o co chodzi i skąd pejoratywny odbiór i że dla większości legacy to wieloletni projekt z dużym długiem.

Ale na dowód anegdotyczny opowiem historyjkę że pracowałem w wieloletnim projekcie który był napisany w starej technologii ale ogólnie z głową. Devy się skarżyły że to straszne legacy i że trzeba to przepisać na coś nowszego (bo chcieli pracować z czymś nowszym). W końcu po zrzucaniu winy o każdym bugu na starą technologię padła decyzja przepisania projektu, zajęło to 2 lata i większego syfu szczerze mówiąc nie widziałem - ludzie się chwytali wszystkiego co nowe mimo że nie mieli w tym żadnego doświadczenia, przepisywali fragmenty projektu niezależnie, nieraz kilkukrotnie i na różne sposoby implementując corowe funkcje. Jakakolwiek architektura poszła się walić, nawet nie było żadnych spotkań żeby ją omówić. Testów w starym projekcie nie było a w nowym to jakiś mock hell. Ogólnie porażka, wolałem już to "legacy". To że kod jest świeży nie znaczy że lepszy.

Riddle napisał(a):

Nie prawda; bo jeśli tak, to każdy open source jest legacy. Poza tym, czemu ograniczać się do nie-swojego kodu; jeśli prawdą jest to co mówisz, to mój projekt który zacząłem dwa dni temu to legacy;

No bo tak jest. Tzn dla ciebie to nie jest legacy, ale gdybym po tobie przejął ten kod to jest to już legacy. Legacy znaczy "dziedzictwo" / spuścizna" / "spadek", nic więcej. Nie ma żadnych ram czasowych.

4

Można narzekać na projekty legacy i ich jakość, ale nic tak nie uczy pokory jak utrzymywanie systemów na produkcji z których korzystają setki lub tysiące użytkowników. W końcu trzeba przeprosić się z memory profilerem żeby zidentyfikować wycieki pamięci, nauczyć się optymalizacji SQLa/ORMa, zrozumieć w końcu jak działa ta mityczna wielowątkowość w popularnych frameworkach żeby zrobić to lepiej niż poprzedni programista, który źle użył biblioteki takiej jak TPL (Task Parallel Library w .NET), nauczyć się refaktoryzacji, pisania testów i tak dalej.

Za każdym razem jak realizowałem projekt greenfield to najlepiej mi się pracowało właśnie z takimi osobami, które miały doświadczenie w utrzymywaniu legacy aplikacji. Osoby które cały czas robiły greenfield bardzo często miały problem z analizą istniejącego kodu (napisanego przez innego deva), pisaniem wydajnych zapytań/wydajnego kodu, optymalnym użyciu kolejek jak RabbitMQ, a jak spytałem takiego o indeksy na bazie to robił oczy jak pięć złoty bo przecież wszystko działa. Tylko ze działało dopóki aplikacja nie wyszła z fazy dev do fazy test/qa, gdzie do bazy ładowało się kilka milionów rekordów i aplikacja padała na testach, bo lazy loading w ORMie, bo bezmyślnie joiny bo brak indeksów albo nieoptymalny model danych, bo message broker się zapycha, bo cośtam.

O dziwo te osoby z projektów greenfield nie miały problemów z krytykowaniem kodu napisanego przez innych (nie mając wiedzy dlaczego ten kod został napisany w taki a nie inny sposób) w którym musieli coś zmienić.

1

Utrzymanie projektu - wchodzisz w kod już zrobiony.

Kod zwykle ma jedną lub więcej następujących charakterystyk:

  • kod spaghetti (pisane na kolanie funkcje, które odwołują się do masy innych funkcji albo strzelają kosmiczne ify nie wiadomo co robiące)
  • big ball of mud (kod może być ładny na poziomie pojedynczych modułów, ale pod kątem architektury jeden wielki chaos)
  • kod przeinżynierowany (kod, który miał mieć ładną architekturę, ale coś nie pykło i wiele rzeczy trzeba robić naokoło tylko dlatego, bo tak ktoś wymyślił)
  • kod niedziałający - np. bugi (szczególnie przy braku rozsądnych testów). Albo coś, co nie działa, bo np. jest reliktem z przeszłości (więc działało w poprzedniej wersji, w poprzedniej architekturze) albo jest czymś, co ktoś zaczął i nie skończył, ale teraz może posłużyć tobie jako przykład "jak zrobić nowy ficzer".

1 użytkowników online, w tym zalogowanych: 0, gości: 1