Czy ktoś jeszcze uważa klasy i metody nazewnictwa za jedną z najtrudniejszych części w programowaniu? [Zamknięte]


275

Pracuję więc nad tą klasą, która ma żądać dokumentacji pomocy od dostawcy za pośrednictwem usługi internetowej. Staram się go nazwać DocumentRetriever, VendorDocRequester, DocGetter, ale po prostu nie brzmi dobrze. Skończyło się przeglądając dictionary.com przez pół godziny próbując wymyślić odpowiedniego słowa.

Rozpoczęcie programowania przy złych nazwach jest jak bardzo zły dzień z rana, a reszta dnia zaczyna się stokiem. Poczuj mnie?


2
Dlaczego miałbyś chcieć zajęć, skoro potrzebujesz tylko funkcji? Upewnij się, że sprawdziłeś steve-yegge.blogspot.com/2006/03/ ... czasownika jako problemu z nazwą klasy.
user51568

Lub przejdź do przodu i dokonaj refaktoryzacji, kiedy w końcu wiesz, jak to się nazywa.
Esteban Araya

16
Co nazywasz ? : metody : używaj czasowników , takich jak get, set, save, itp. Klasy i zmienne : używaj rzeczowników , takich jak interfejsy dokument, użytkownik, kontekst itp .: Używaj przymiotników , takich jak drukowalne, klonowalne, iterowalne itp. Po przeczytaniu tego wątku podoba mi się sugestia Spolsky'ego dotycząca klas i zmiennych (używa rzeczowników) oraz sugestia TravisO dotycząca metod (używa czasowników). Również nie robią obiekty końcowym „er” .
Daniel Gasull

5
„Istnieją dwa trudne problemy w informatyce: unieważnienie pamięci podręcznej, konwencje nazewnictwa i ciche przepełnienie”.
Karakuri,

6
@karakuri Wersja, którą usłyszałem, brzmi „istnieją 2 trudne problemy w informatyce: nazewnictwo i przesunięcie o 1 błąd”.
Haoest

Odpowiedzi:


121

To, co teraz robisz, jest w porządku i gorąco polecam trzymanie się obecnej składni, ponieważ:

kontekst + czasownik + jak

Używam tej metody do nazywania funkcji / metod, przechowywanych procedur SQL itp. Zachowując tę ​​składnię, utrzymasz twoje Intellisense / Code Panes o wiele bardziej czyste. Więc chcesz EmployeeGetByID () EmployeeAdd (), EmployeeDeleteByID (). Kiedy użyjesz bardziej poprawnej gramatycznie składni, takiej jak GetEmployee (), AddEmployee (), zobaczysz, że staje się to naprawdę bałagan, jeśli masz wiele Gets w tej samej klasie, ponieważ niezwiązane ze sobą rzeczy zostaną zgrupowane razem.

Przypominam to nadawaniu nazw plikom z datami, chcesz powiedzieć 2009-01-07.log, a nie 1-7-2009.log, ponieważ po ich zgrupowaniu zamówienie staje się całkowicie bezużyteczne.


28
Wolę mieć kontekst wywnioskowany z nazwy typu podczas nazewnictwa metod ... class EmployeeRepository {void Add (pracownik pracownika); void Get (int id); void GetAll (); void GetAll (filtr Action <FilterCriteria>); } Co myślisz?
Vyas Bharghava

5
Pomaga również, jeśli masz standardową listę czasowników domowych. Więc zawsze jest Pobierz, a nie Załaduj / Czytaj / Pobierz / Wybierz / Znajdź .... itd.
Martwe konto

2
Richard, masz rację w scenariuszach OOP, moja odpowiedź cofnęła się nieco i była raczej ogólną sugestią kodowania. Wydaje mi się, że technicznie dotyczy to w większym stopniu języków innych niż OOP. Employee.Add () i Employee.GetByID () byłyby najlepszym zastosowaniem w OOP.
TravisO

6
Podoba mi się efekt twojej sugestii Intellisense, ale wolę podejście nieco bardziej kompetentne. Wolę więc Employee.SetSupervisor () niż Employee.SupervisorSet (), ponieważ czyta (bardziej jak naturalny angielski.
Matthew Maravillas

12
Ale @TravisO, to nie brzmi dobrze po angielsku. Nie dostajesz pracownika, dostajesz pracownika. Co się stanie, jeśli masz bardziej złożone działania z użyciem przymiotników, takie jak InvalidateObsoleteQueries? QueriesInvalidateObsoletejest trudny do odczytania i nie ma sensu. Poza tym w C #, szczególnie w Resharper, kolejność alfabetyczna jest nieistotna. Jeśli zaczniesz wpisując „EMP” Resharper da wam GetEmployee, SetEmployeei jeszcze PopulateInactiveEmployeesList.
Ilya Kogan

54

Nauczyłem się jednej lekcji, że jeśli nie możesz znaleźć nazwy klasy, prawie zawsze coś jest z nią nie tak:

  • nie potrzebujesz tego
  • robi za dużo

13
Lub robi za mało.
user51568

4
Dziękuję, to było dla mnie istotne.
Haoest,

52

Dobra konwencja nazewnictwa powinna minimalizować liczbę możliwych nazw, których możesz użyć dla dowolnej zmiennej, klasy, metody lub funkcji. Jeśli istnieje tylko jedna możliwa nazwa, nigdy nie będziesz mieć problemów z jej zapamiętaniem.

W przypadku funkcji i klas singletonowych analizuję funkcję, aby sprawdzić, czy jej podstawową funkcją jest transformacja jednego rodzaju rzeczy w inny rodzaj rzeczy. Używam tego terminu bardzo swobodnie, ale odkryjesz, że OGROMNA liczba funkcji, które piszesz, zasadniczo przyjmuje coś w jednej formie i tworzy coś w innej formie.

W twoim przypadku wygląda na to, że twoja klasa przekształca adres URL w dokument. To trochę dziwne myśleć o tym w ten sposób, ale całkowicie poprawne, a kiedy zaczniesz szukać tego wzoru, zobaczysz go wszędzie.

Kiedy znajduję ten wzorzec, zawsze nazywam funkcję x Fromy .

Ponieważ twoja funkcja przekształca adres URL w dokument, nazwałbym go

DocumentFromUrl

Ten wzór jest niezwykle powszechny. Na przykład:

atoi -> IntFromString
GetWindowWidth -> WidthInPixelsFromHwnd // or DxFromWnd if you like Hungarian
CreateProcess -> ProcessFromCommandLine

Możesz także użyć, UrlToDocumentjeśli czujesz się bardziej komfortowo z tym zamówieniem. Czy powiesz xFrom y czy y Tox, jest prawdopodobnie kwestią gustu, ale wolę Fromkolejność, ponieważ w ten sposób początek nazwy funkcji mówi ci, jaki typ zwraca.

Wybierz jedną konwencję i trzymaj się jej. Jeśli starasz się używać tych samych nazw, co nazwy klas w xFrom funkcjach y , o wiele łatwiej będzie zapamiętać, jakich nazw używałeś. Oczywiście ten wzorzec nie działa na wszystko, ale działa tam, gdzie piszesz kod, który można uznać za „funkcjonalny”.


Miłe przypomnienie, że w językach OOP nazwy klas nie zawsze muszą być rzeczownikami, ale czasami mogą być „werbalne”. Dlatego też praktykujący OOP często się potykają (jak osoba zadająca pytanie), ponieważ zbyt mocno podkreślają, że zajęcia muszą być „rzeczą” w prawdziwym świecie.
Ray

7
XFromY-Convetion w zasadzie powtarza to, co znajduje się na liście typów zwracanych i parametrów: Foo fooFromBar (pasek pasków). To od Ciebie zależy, czy nazwiesz to konsekwencją lub redendancją.
Lena Schimmel

„W twoim przypadku wygląda na to, że Twoja klasa przekształca adres URL w dokument”. Od kiedy klasy mają „robić” rzeczy zamiast reprezentować koncepcje?
user51568

6
@Brian: jest zbędny tylko w jednym miejscu ... w deklaracji. Wszędzie, gdzie go używasz, miło jest przypomnieć o typach danych. Sprawia, że ​​kod jest bardziej czytelny bez konieczności powrotu do deklaracji.
Joel Spolsky

3
@ stefan - W niektórych językach, takich jak C # i Java, cały kod musi być zamknięty w klasie, inaczej niż w C ++. Funkcje nie są obywatelami pierwszej klasy w tych językach, jeśli chcesz zmodularyzować kod. Dlatego czasami kończy się klasa, która może „robić” rzeczy takie jak funkcja.
Ray

31

Czasami nie ma dobrego imienia dla klasy lub metody, zdarza się to nam wszystkim. Często jednak niemożność wymyślenia nazwy może wskazywać na coś złego w twoim projekcie. Czy twoja metoda ma zbyt wiele obowiązków? Czy twoja klasa zawiera spójny pomysł?


3
Bardzo dobra uwaga, naprawdę.
Camilo Martin

27

Wątek 1:

function programming_job(){
    while (i make classes){
         Give each class a name quickly; always fairly long and descriptive.
         Implement and test each class to see what they really are. 
         while (not satisfied){
            Re-visit each class and make small adjustments 
         }
    }
}

Wątek 2:

while(true){
      if (any code smells bad){
           rework, rename until at least somewhat better
      }
}

Nigdzie tutaj nie ma Thread.sleep (...).


24

Sporo czasu spędzam też martwiąc się nazwami czegokolwiek, co można nazwać podczas programowania. Powiedziałbym, że to się bardzo opłaca. Czasami, kiedy utknęłam, zostawiam to na chwilę, a podczas przerwy na kawę pytam trochę, czy ktoś ma dobrą sugestię.

Dla twojej klasy sugerowałbym VendorHelpDocRequester.


1
> VendorHelpDocRequester Dobry. Właściwie przejrzałem Google Requestor zamiast Requester, oba wydają się być autentycznymi angielskimi słowami.
Haoest,

1
Zrobiłem to raz lub dwa razy :)
willcodejavaforfood

1
Posiadanie czasownika w nazwie klasy zawsze brzmi dla mnie źle. Ponadto zawsze prowadzi to do pewnego powielenia użycia (tj .:) VendorHelpDocRequester.request(). Wolałbym taką liczbę mnogą jak `VendorHelpDocs.request () '
Edson Medina


15

Myślę, że to efekt uboczny.

To nie jest prawdziwe nazewnictwo, które jest trudne. Trudne jest to, że proces nazywania sprawia, że ​​stajesz wobec okropnego faktu, że nie masz pojęcia, co do cholery robisz.


12

Właśnie wczoraj usłyszałem ten cytat za pośrednictwem Signal vs. Noise bloga na 37Signals iz pewnością się z nim zgadzam:

„W informatyce są tylko dwie trudne rzeczy: unieważnienie pamięci podręcznej i nadawanie nazw”. - Phil Karlton


simonwillison.net/2007/Jul/5/hard zaprowadził mnie na tbray.org/ongoing/When/200x/2005/12/23/UPI, który zaprowadził mnie na karlton.hamilton.com i dalej na karlton.hamilton.com/quotes /showallquotes.cgi , który nie zawiera cytatu! (Ale rozpoznaję numer 5 ze Scruma.)
Daryl Spitzer

1
„Dwie trudne rzeczy w informatyce: unieważnienie pamięci podręcznej, nazywanie rzeczy i błędy indywidualne”.
Dan Lugg

7

Dobrze, że to trudne. Zmusza cię do zastanowienia się nad problemem i tym, co klasa powinna właściwie zrobić. Dobre nazwy mogą prowadzić do dobrego projektu.


6

Zgoda. Lubię, aby moje nazwy i zmienne typów były jak najbardziej opisowe, ale nie były zbyt strasznie długie, ale czasami istnieje tylko pewna koncepcja, dla której nie można znaleźć dobrego słowa.

W takim przypadku zawsze pomaga mi poprosić współpracownika o dane wejściowe - nawet jeśli ostatecznie nie pomagają, zwykle pomaga mi przynajmniej wyjaśnić to na głos i spowodować, że moje koła się obracają.


6

Właśnie pisałem o konwencjach nazewnictwa w zeszłym miesiącu: http://caseysoftware.com/blog/useful-naming-conventions

Istota tego:

verbAdjectiveNounStructure - ze strukturą i przymiotnikiem jako częściami opcjonalnymi

W przypadku czasowników trzymam się czasowników czynności: zapisuj, usuwaj, powiadamiaj, aktualizuj lub generuj. Od czasu do czasu używam „procesu”, ale tylko w celu odniesienia się do kolejek lub zaległości roboczych.

W przypadku rzeczowników korzystam z interakcji klasy lub obiektu. W web2project jest to często Zadania lub Projekty. Jeśli JavaScript obsługuje interakcję ze stroną, może to być treść lub tabela. Chodzi o to, że kod wyraźnie opisuje obiekt, z którym wchodzi w interakcje.

Struktura jest opcjonalny, ponieważ jest unikatowy dla danej sytuacji. Ekran listy może poprosić o listę lub tablicę. Jedną z podstawowych funkcji używanych na liście projektów dla web2project jest po prostu getProjectList. Nie modyfikuje podstawowych danych, tylko reprezentację danych.

The przymiotniki to coś zupełnie innego. Są używane jako modyfikatory rzeczownika. Coś tak prostego, jak getOpenProjects, można łatwo wdrożyć za pomocą getProjects i parametru przełącznika, ale zwykle generuje to metody, które wymagają sporego zrozumienia podstawowych danych i / lub struktury obiektu ... niekoniecznie coś, co chcesz zachęcać. Mając bardziej wyraźne i specyficzne funkcje, możesz całkowicie owinąć i ukryć implementację przed kodem, używając go. Czy to nie jeden z punktów OO?


4

Bardziej niż nazywanie klasy, tworzenie odpowiedniej struktury pakietu może być trudnym, ale satysfakcjonującym wyzwaniem. Musisz rozważyć oddzielenie obaw modułów i ich związku z wizją aplikacji.

Zastanów się teraz nad układem swojej aplikacji:

  • App
    • VendorDocRequester (odczyt z serwisu internetowego i podanie danych)
    • VendorDocViewer (użyj requestera, aby dostarczyć dokumenty dostawcy)

Zaryzykowałbym przypuszczenie, że w kilku klasach wiele się dzieje. Jeśli przełożysz to na podejście bardziej oparte na MVC i pozwolisz małym klasom poradzić sobie z indywidualnymi obowiązkami, możesz skończyć z czymś takim:

  • App
    • VendorDocs
      • Model
        • Dokument (zwykły obiekt przechowujący dane)
        • WebServiceConsumer (radzić sobie z nitty gritty w serwisie internetowym)
      • Kontroler
        • DatabaseAdapter (obsłużyć obsługę przy użyciu ORM lub innej metody)
        • WebServiceAdapter (wykorzystaj Konsumenta, aby pobrać dokument i umieścić go w bazie danych)
      • Widok
        • HelpViewer (użyj DBAdapter, aby wypluć dokumentację)

Następnie nazwy klas polegają na przestrzeni nazw, aby zapewnić pełny kontekst. Same klasy mogą być nieodłącznie związane z aplikacją, bez potrzeby jawnego mówienia o tym. W rezultacie nazwy klas są prostsze i łatwiejsze do zdefiniowania!

Jeszcze jedna bardzo ważna sugestia: zrób sobie przysługę i podnieś kopię Wzorów Głównego Projektu. To fantastyczna, łatwa w czytaniu książka, która pomoże ci uporządkować aplikację i napisać lepszy kod. Docenianie wzorców projektowych pomoże ci zrozumieć, że wiele napotkanych problemów zostało już rozwiązanych, a będziesz w stanie wprowadzić rozwiązania do swojego kodu.


4

Leo Brodie w swojej książce „Thinking Forth” napisał, że najtrudniejszym zadaniem dla programisty było dobre nazywanie rzeczy i stwierdził, że najważniejszym narzędziem programistycznym jest tezaurus.

Spróbuj użyć tezaurusa na stronie http://thesaurus.reference.com/ .

Poza tym nie używaj NIGDY notacji węgierskiej, unikaj skrótów i zachowaj spójność.

Wszystkiego najlepszego.


1
+1 z notatką, że nie powinieneś używać tego, co to jest system caled węgierski; węgierska aplikacja może być czasem pomocna, szczególnie w języku programowania bez dobrego systemu pisania.
user51568

Nigdy nie słyszałem o węgierskiej notacji systemowo-aplikacyjnej, ale nigdy nie jest to dobry pomysł w żadnym środowisku - zawsze powinieneś wymieniać na podstawie CO, a nie JAK, a węgierski jest całkowicie o tym, jak.
Rob Williams

@RobWilliams Myślę, że odnosili się do artykułu Joela
Spolsky'ego

1
@RobWilliams Czy jesteś pewien, że „nigdy nie słyszałem o X vs. Y, ale żaden z nich nigdy nie jest dobrym pomysłem ...” ...? :)
Alois Mahdal

4

Krótko mówiąc:
zgadzam się, że dobre nazwiska są ważne, ale nie sądzę, że trzeba je znaleźć przed wdrożeniem za wszelką cenę.

Oczywiście lepiej mieć dobre imię od samego początku. Ale jeśli nie możesz wymyślić jednego w ciągu 2 minut, zmiana nazwy później będzie kosztować mniej czasu i jest właściwym wyborem z punktu widzenia produktywności.

Długi:
Generalnie często nie warto zbyt długo zastanawiać się nad nazwą przed wdrożeniem. Jeśli zaimplementujesz swoją klasę, nadając jej nazwę „Foo” lub „Dsnfdkgx”, podczas implementacji zobaczysz, co powinieneś nazwać.

Zwłaszcza w przypadku Java + Eclipse zmiana nazwy rzeczy nie jest wcale trudna, ponieważ dokładnie obsługuje wszystkie odwołania we wszystkich klasach, ostrzega przed kolizjami nazw itp. I dopóki klasa nie znajduje się jeszcze w repozytorium kontroli wersji, nie „ sądzę, że jest coś złego w zmianie nazwy 5 razy.

Zasadniczo chodzi o to, jak myślisz o refaktoryzacji. Osobiście podoba mi się, chociaż czasami denerwuje moich kolegów z zespołu, ponieważ wierzą, że nigdy nie dotykają działającego systemu . A ze wszystkiego, co możesz refaktoryzować, zmiana nazw jest jedną z najbardziej nieszkodliwych rzeczy, jakie możesz zrobić.


3

Dlaczego nie HelpDocumentServiceClient w rodzaju kęsa lub HelpDocumentClient ... nie ma znaczenia, że ​​to sprzedawca, chodzi o to, że jest klientem usługi internetowej, która zajmuje się dokumentami pomocy.

I tak, nazywanie jest trudne.


3

Jest tylko jedna rozsądna nazwa dla tej klasy:

HelpRequest

Nie pozwól, aby szczegóły implementacji odwróciły uwagę od znaczenia.


Półtora roku później miałem zamiar zasugerować HelpLibraryklasie, ale jest to co najmniej tak samo dobre. Najpierw warto przeczytać odpowiedzi!
Jeff Sternal

2

Zainwestuj w dobre narzędzie do refaktoryzacji!


lol. Czasami refaktoryzacja nie jest najlepszą opcją (duże projekty w C ++), ale z pewnością wcześniej tego używałem. Czasami muszę po prostu załatwić sprawę, a nazwiska przychodzą do mnie później.
Steve S

2

Trzymam się podstaw: VerbNoun (argumenty). Przykłady: GetDoc (docID).

Nie musisz się fantazjować. Za rok będzie łatwo zrozumieć, czy to ty, czy ktoś inny.


Chociaż brzmi to dobrze, źle się organizuje, ponieważ jest odwrócone. Lepiej powiedzieć DocGet (), ponieważ kiedy utworzysz DocAdd () DocRemove () itp., Wszystkie pojawią się razem na liście. Twoja metoda naprawdę pokazuje, jak brzydko robi się, gdy masz dziesiątki pobrań lub coś w tym stylu.
TravisO,

Doskonała sugestia, TravisO.
Jon Smock

Nie używałbym czasownika dla klasy normalnie.
willcodejavaforfood

2

Dla mnie nie obchodzi mnie, jak długo nazwa metody lub klasy jest tak długa, jak jej opisowa i poprawna biblioteka. Dawno minęły czasy, w których należy pamiętać, gdzie znajduje się każda część interfejsu API.

Intelisense istnieje dla wszystkich głównych języków. Dlatego podczas korzystania z interfejsu API innej firmy lubię używać jego inteligencji do dokumentacji, a nie używać „rzeczywistej” dokumentacji.

Mając to na uwadze, mogę stworzyć nazwę metody, taką jak

StevesPostOnMethodNamesBeingLongOrShort

Długi - ale co z tego. Kto obecnie nie używa ekranów 24-calowych!


1

Muszę się zgodzić, że nazywanie to sztuka. To staje się trochę łatwiejsze, jeśli twoja klasa postępuje zgodnie z pewnym „wzorcem desigh” (fabryka itp.).


1

Jest to jeden z powodów posiadania standardu kodowania. Posiadanie standardu pomaga wymyślać nazwiska, gdy jest to wymagane. Pomaga uwolnić umysł od innych ciekawych rzeczy! (-:

Poleciłbym przeczytać odpowiedni rozdział Kodeksu Steve'a McConnella ( link Amazon ), który zawiera kilka zasad ułatwiających czytelność, a nawet łatwość konserwacji.

HTH

Twoje zdrowie,

Obrabować


1

Nie, debugowanie jest dla mnie najtrudniejszą rzeczą! :-)


debugowanie zwykle sprowadza się do zadania właściwego pytania. Jest taka gra liczbowa, w której musisz odgadnąć liczbę od 1 do 1000. Jeśli twoje przypuszczenie jest za niskie lub za wysokie, konsola ci to mówi i masz tylko 10 prób. Co robisz?
Haoest,

1

Moduł pobierania dokumentów? Trudno powiedzieć bez kontekstu.

Może pomóc zachowywać się jak matematyk i pożyczać / wymyślać leksykon dla swojej domeny w drodze: zadowalaj się krótkimi, prostymi słowami, które sugerują tę koncepcję, bez wypowiadania jej za każdym razem. Zbyt często widzę frazy długo latinate który się zamienił akronimów, co trzeba słownika dla akronimów i tak .


1

Językiem używanym do opisania problemu jest język, którego należy używać dla zmiennych, metod, obiektów, klas itp. Luźno rzeczowniki pasują do obiektów, a metody do czasowników. Jeśli brakuje słów do opisania problemu, brakuje również pełnego zrozumienia (specyfikacji) problemu.

Jeśli po prostu wybiera między zestawem nazw, powinien być oparty na konwencjach używanych do budowy systemu. Jeśli znalazłeś się w nowym miejscu, odkrytym przez poprzednie konwencje, zawsze warto poświęcić trochę wysiłku, aby spróbować je rozszerzyć (odpowiednio, konsekwentnie), aby objąć tę nową sprawę.

W razie wątpliwości śpij na nim i wybierz pierwsze najbardziej oczywiste imię następnego dnia rano :-)

Jeśli obudzisz się pewnego dnia i zdasz sobie sprawę, że się mylisz, zmień to natychmiast.

Paweł.

BTW: Document.fetch () jest dość oczywiste.


1

Uważam, że mam najwięcej problemów ze zmiennymi lokalnymi. Na przykład chcę utworzyć obiekt typu DocGetter. Więc wiem, że to DocGetter. Dlaczego muszę nadać mu inną nazwę? Zwykle nadaję mu nazwę dg (dla DocGetter) lub temp lub coś równie nieopisowego.


1

Nie zapominaj, że wzorce projektowe (nie tylko GoF) to dobry sposób na zapewnienie wspólnego słownictwa, a ich nazwy powinny być używane zawsze, gdy pasuje do sytuacji. Pomoże to nawet początkującym, którzy znają się na nomenklaturze, w szybkim zrozumieniu architektury. Czy ta klasa, nad którą pracujesz, powinna działać jak pełnomocnik, czy nawet fasada?


1

Czy dokumentacja dostawcy nie powinna być przedmiotem? Mam na myśli, że ten jest namacalny, a nie tylko jako antropomorfizacja części twojego programu. Więc możesz miećVendorDocumentation klasę z konstruktorem, który pobiera informacje. Myślę, że jeśli nazwa klasy zawiera czasownik, często coś poszło nie tak.


1

Zdecydowanie cię czuję. I czuję twój ból. Każde imię, o którym myślę, wydaje mi się śmieciem. Wszystko wydaje się takie ogólne i chcę w końcu nauczyć się, jak wprowadzić odrobinę talentu i kreatywności w moje nazwiska, dzięki czemu naprawdę odzwierciedlają to, co opisują.

Jedną z moich sugestii jest skonsultowanie się z tezaurusem. Słowo ma dobre, podobnie jak Mac OS X. To naprawdę może mi pomóc wydostać głowę z chmur i dać mi dobre miejsce startu, a także trochę inspiracji.


0

Jeśli nazwa wyjaśniłaby się laikowi, to prawdopodobnie nie trzeba jej zmieniać.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.