Nazewnictwo dla klas usługowych.

Nazewnictwo dla klas usługowych.
AN
AN
  • Rejestracja:około rok
  • Ostatnio:8 miesięcy
  • Postów:30
0

Klasa usługowa zawiera metody, które pozwalają na operacje na obiektach domenowych. Zauważyłem, że nazywam te klasy zazwyczaj z postfiksem "Service", np. "MembersService", "AuthorizationService".

Co o tym sądzicie? Jak to wygląda u Was?

somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Wrocław
5

Staram się unikać tego sufiksu i nazywać jakoś konkretniej, w zależności od tego, co faktycznie robią.

edytowany 1x, ostatnio: somekind
LU
Mógłbyś podać jakiś przykład takiej nazwy klasy?
markone_dev
  • Rejestracja:około 3 lata
  • Ostatnio:około 11 godzin
  • Postów:812
7

Ciekawostka. Dawno temu trafiłem na artykuł/wpis na blogu (nie pamiętam dokładnie), gdzie ktoś sugerował unikania nazywania klas usługowych z końcówką -er Czyli handler, provider, adapter, manager, helper, itd. Pomijając oczywiście nazwy wzorców projektowych/architektonicznych gdzie mają one sens.


Programujący korpo architekt chmurowy.
Udzielam konsultacji i szkoleń w obszarze szeroko pojętego cloud computingu (Azure, AWS) i architektury systemów IT. Dla firm i prywatnie.
DevOps to proces nie stanowisko.
edytowany 1x, ostatnio: markone_dev
bakunet
  • Rejestracja:prawie 8 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Polska
  • Postów:1596
1
markone_dev napisał(a):

ktoś sugerował unikania nazywania klas usługowych z końcówką -er Czyli handler, provider, adapter, manager, helper, itd.

Ciekaw jestem czemu?

edytowany 1x, ostatnio: bakunet
markone_dev
  • Rejestracja:około 3 lata
  • Ostatnio:około 11 godzin
  • Postów:812
4
bakunet napisał(a):
markone_dev napisał(a):

ktoś sugerował unikania nazywania klas usługowych z końcówką -er Czyli handler, provider, adapter, manager, helper, itd.

Ciekaw jestem czemu?

Żeby nadawać klasom bardziej znaczace nazwy, wynikające z ich przeznaczenia czy sensu domenowego.


Programujący korpo architekt chmurowy.
Udzielam konsultacji i szkoleń w obszarze szeroko pojętego cloud computingu (Azure, AWS) i architektury systemów IT. Dla firm i prywatnie.
DevOps to proces nie stanowisko.
bakunet
  • Rejestracja:prawie 8 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Polska
  • Postów:1596
0

@markone_dev:

Rozumiem, ale na przykładzie takiego FileManagera, serwisu który odczytuje, usuwa, zapisuje, nadpisuje plik, sprawdza czy plik istnieje, jak można go nazwać inaczej? Ja mało widziałem, więc się zastanawiam.

edytowany 1x, ostatnio: bakunet
RJ
IFileService 😂 _fileService.Exists(string filepath) I idąc tropem segregacji interfejsów IDirectoryService
bakunet
Wtedy wpadamy w postfix Service ;)
RJ
Service się nie kończy na -er i jasno wskazuje, że to usługa 😉
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 6 godzin
  • Lokalizacja:Silesia/Marki
  • Postów:5505
0
Anatolijus napisał(a):

Klasa usługowa zawiera metody, które pozwalają na operacje na obiektach domenowych. Zauważyłem, że nazywam te klasy zazwyczaj z postfiksem "Service", np. "MembersService", "AuthorizationService".

Co o tym sądzicie? Jak to wygląda u Was?

Ogólnie wyglada to jak Spring sprzed 10 lat, ale nie wiem czy coś tam się zmieniło. BTW słyszałem kiedyś iż odpowiednikiem Springowo Javowego Service jest w C# Manager. Prawda to @somekind ?Tutoriale C#powe dalej tak doradzają ?


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
RJ
Zależy od projektu i ludzi. Spotkałem się z Managerem, ale Service suffix się częściej widuje
AU
Ja też się nie orientuje co jest złego w Service suffixie? albo Manager. Jak dla mnie to jeśli w ten sposób idzie przekazać co ma się na myśli to jak najbardziej powinno się tego używać.
RJ
@Autysta: no dla mnie też, tym bardziej że pierwszy człon nazwy może ładnie opisywać, co to coś robi. Manager mi się źle kojarzy trochę, ale Service FTW
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10056
2
Anatolijus napisał(a):

Klasa usługowa zawiera metody, które pozwalają na operacje na obiektach domenowych. Zauważyłem, że nazywam te klasy zazwyczaj z postfiksem "Service", np. "MembersService", "AuthorizationService".

Co o tym sądzicie? Jak to wygląda u Was?

Sądzę że to jest bezsens. Staram się nie używać takich nazw. Nazywanie klasy UserService to jest symptom nieumiejętności znalezienia odpowiedniej nazwy.

W ogóle sam podział "klasa usługa", też nie ma specjalnego sensu dla mnie. Klasa to klasa, powinna robić jedną rzecz i nie łamać Separation of Concerns. Dopisanie prefixu "Service" nie zwiększy czytelności tej klasy.

bakunet napisał(a):

Rozumiem, ale na przykładzie takiego FileManagera, serwisu który odczytuje, usuwa, zapisuje, nadpisuje plik, sprawdza czy plik istnieje, jak można go nazwać inaczej? Ja mało widziałem, więc się zastanawiam.

No i tutaj jest serce problemu!

Dlatego że nazwa FileManager mówi zbyt mało, po samej nazwie ciężko się domyśleć co robi. Nazwa jest zbyt generyczna, i nie mówi co ta klasa robi tak na prawdę. Należałoby wejść do tej klasy i zobaczyć jaki jest sens jej istnienia w aplikacji, wtedy można by nazwać ją lepiej.

Myślę że nazwa FileManager została wymyślona przez kogoś kto chciał nadawać klasom zbyt ogólne nazwy - tak jakby miały być reużywalne w nieskończoność.

Równie dobrze mógłbyś nas zapytać: "Mam klasę dsfaffds, jak ją nazwać lepiej?" - odpowiedź brzmi: "musiałbym wejść do klasy i zobaczyć co robi".

@bakunet Pokaż klasę, to Ci zasugeruję kilka nazw, jak można by ją nazwać. W skrócie - zastanów się po co ta klasa zapisuje te pliki? Czy zapisuje je jako forma cache'? Nazwij ją Cache. Jeśli pliki są zapisywane jako backup, to nazwij klasę Backup. Jeśli pliki są jakimś dokumentem domenowym, to nazwij go Document albo Invoice. Wszystko zależy od tego do czego ta klasa jest używana, bo do czegoś na pewno jest. Natomiast jeśli faktycznie jest na tyle generyczna, że można jej użyć do wszystkiego, i nie ma faktycznie żadnego konkretnego użycia, to można ją nazwać po prostu File.

edytowany 5x, ostatnio: Riddle
IamMieszko & NieJestemHarpowymExpertem
to co zamiast usermanager lub userservice, zakladajac ze chce stworzyc byt, klase ktora zarzadza userami?
Riddle
@IamMieszko & NieJestemHarpowymExpertem: jak już mówiłem - wybranie odpowiedniej nazwy wymagałoby wiedzy co ta klasa miałby konkretnie robić z tymi userami. Określenie "zarządzanie" jest zbyt mało mówiące. Mógłbyś pokazać przykład kodu takiej klasy? Jeśli pakujesz do jednej klasy wszystko co można podpiąć pod "zarządzanie userami" to obawiam się że taka klasa może łamać SRP i przez to ciężko może być ją jakoś sensownie nazwać.
markone_dev
  • Rejestracja:około 3 lata
  • Ostatnio:około 11 godzin
  • Postów:812
3
bakunet napisał(a):

@markone_dev:

Rozumiem, ale na przykładzie takiego FileManagera, serwisu który odczytuje, usuwa, zapisuje, nadpisuje plik, sprawdza czy plik istnieje, jak można go nazwać inaczej? Ja mało widziałem, więc się zastanawiam.

W .NET do tego służą klasy File, Directory, Path, itd. Da się napisać bibliotekę do IO beż FileManagera? Da :)


Programujący korpo architekt chmurowy.
Udzielam konsultacji i szkoleń w obszarze szeroko pojętego cloud computingu (Azure, AWS) i architektury systemów IT. Dla firm i prywatnie.
DevOps to proces nie stanowisko.
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 6 godzin
  • Lokalizacja:Silesia/Marki
  • Postów:5505
0
markone_dev napisał(a):
bakunet napisał(a):

@markone_dev:

Rozumiem, ale na przykładzie takiego FileManagera, serwisu który odczytuje, usuwa, zapisuje, nadpisuje plik, sprawdza czy plik istnieje, jak można go nazwać inaczej? Ja mało widziałem, więc się zastanawiam.

W .NET do tego służą klasy File, Directory, Path, itd. Da się napisać bibliotekę do IO beż FileManagera? Da :)

W Javie tez


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0
markone_dev napisał(a):
bakunet napisał(a):

@markone_dev:

Rozumiem, ale na przykładzie takiego FileManagera, serwisu który odczytuje, usuwa, zapisuje, nadpisuje plik, sprawdza czy plik istnieje, jak można go nazwać inaczej? Ja mało widziałem, więc się zastanawiam.

W .NET do tego służą klasy File, Directory, Path, itd. Da się napisać bibliotekę do IO beż FileManagera?

Ale użycie tych klas też musisz mieć w jakiejś klasie którą musisz jakoś nazwać.

SL
  • Rejestracja:około 7 lat
  • Ostatnio:około 3 godziny
  • Postów:871
1
Anatolijus napisał(a):

Co o tym sądzicie? Jak to wygląda u Was?

Uważam, że to ok. Service jest na tyle pomocną i rozumianą nazwą, że polepsza czytelność. Manager, Helper takie nie są, bo nic nie mówią i mają wiele znaczeń

markone_dev napisał(a):

Ciekawostka. Dawno temu trafiłem na artykuł/wpis na blogu (nie pamiętam dokładnie), gdzie ktoś sugerował unikania nazywania klas usługowych z końcówką -er Czyli handler, provider, adapter, manager, helper, itd. Pomijając oczywiście nazwy wzorców projektowych/architektonicznych gdzie mają one sens.

Jeśli klasa zapewnia metody do których pasuje jeden czasownik to dodanie er i umieszczenie go w nazwie klasy poprawia czytelność. Zresztą po to są nazwy, żeby użytkownik danego API wiedział co dane coś robi. Np. Base64Encoder albo Base64EncoderDecoder to według mnie dobre nazwy. Taki zabieg pasuje IMO do klas, które są zwykłymi funkcjami tj. trzymają mało stanu (lub w ogóle) i są tylko po to, bo trzeba bawić się w obiekty w językach OOP, żeby było konsystentnie

Problem zaczyna się, gdy czasownik jest zbyt ogólny np. help, manage bo to wtedy jest to zbyt ogólne.

bakunet napisał(a):

Rozumiem, ale na przykładzie takiego FileManagera, serwisu który odczytuje, usuwa, zapisuje, nadpisuje plik, sprawdza czy plik istnieje, jak można go nazwać inaczej? Ja mało widziałem, więc się zastanawiam.

Ja bym dał FileSystem. Oczywiście większość API tego nie robi, bo są zaprojektowane pod przypadek najbardziej ogólny tj. uderzają do lokalnego file systemu i ich funkcjonalność rozbita jest na funkcje, które są prostsze do wywołania np. os.Rename(from, to) niż zabawa w obiektowość

Riddle napisał(a):

Ale użycie tych klas też musisz mieć w jakiejś klasie którą musisz jakoś nazwać.

Możesz użyć zwykłych funkcji. Twój kod jest mniej rozszerzalny i przyspawany do lokalnego file systemu, ale jest prostszy. Jak potrzebujesz obiektowej abstrakcji to też możesz ją zbudować samemu zamiast polegać na takiej z biblioteki standardowej

edytowany 1x, ostatnio: slsy
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0
slsy napisał(a):
Anatolijus napisał(a):

Co o tym sądzicie? Jak to wygląda u Was?

Uważam, że to ok. Service jest na tyle pomocną i rozumianą nazwą, że polepsza czytelność. Manager, Helper takie nie są, bo nic nie mówią i mają wiele znaczeń

A "Service" mówi? :D To jest buzzword, szum informacyjny. Nie dostajesz żadnych nowych informacji widząc dodatkowo słowo "Service".

markone_dev napisał(a):

Ciekawostka. Dawno temu trafiłem na artykuł/wpis na blogu (nie pamiętam dokładnie), gdzie ktoś sugerował unikania nazywania klas usługowych z końcówką -er Czyli handler, provider, adapter, manager, helper, itd. Pomijając oczywiście nazwy wzorców projektowych/architektonicznych gdzie mają one sens.

Jeśli klasa zapewnia metody do których pasuje jeden czasownik to dodanie er i umieszczenie go w nazwie klasy poprawia czytelność. Zresztą po to są nazwy, żeby użytkownik danego API wiedział co dane coś robi. Np. Base64Encoder albo Base64EncoderDecoder to według mnie dobre nazwy. Taki zabieg pasuje IMO do klas, które są zwykłymi funkcjami tj. trzymają mało stanu (lub w ogóle) i są tylko po to, bo trzeba bawić się w obiekty w językach OOP, żeby było konsystentnie

Słaby przykład, bo po co do tego dwie klasy? Czemu nie Base64.encode() i Base64.decode()?

bakunet napisał(a):

Rozumiem, ale na przykładzie takiego FileManagera, serwisu który odczytuje, usuwa, zapisuje, nadpisuje plik, sprawdza czy plik istnieje, jak można go nazwać inaczej? Ja mało widziałem, więc się zastanawiam.

Ja bym dał FileSystem. Oczywiście większość API tego nie robi, bo są zaprojektowane pod przypadek najbardziej ogólny tj. uderzają do lokalnego file systemu i ich funkcjonalność rozbita jest na funkcje, które są prostsze do wywołania np. os.Rename(from, to) niż zabawa w obiektowość

Ten sam problem co z FileManager, czyli zbyt generyczna nazwa, która w żaden sposób nie mówi co ta klasa robi.

Riddle napisał(a):

Ale użycie tych klas też musisz mieć w jakiejś klasie którą musisz jakoś nazwać.

Możesz użyć zwykłych funkcji. Twój kod jest mniej rozszerzalny i przyspawany do lokalnego file systemu, ale jest prostszy. Jak potrzebujesz obiektowej abstrakcji to też możesz ją zbudować samemu zamiast polegać na takiej z biblioteki standardowej

Czyli Twoja rada to:

  • Albo - zamiast używać FileManager, to usuń ją i używaj funkcji
  • Albo - zbuduj abstrakcję, i na niej polegaj i nazwij ją "jakoś".

No faktycznie takie ma opcje: usuń albo nazwij ją "jakoś".

Całkowicie ignorujesz to, że ta klasa FileManager czy FileSystem w tej aplikacji jest dodana po coś. Istnieje jakiś powód, czemu jest w tej klasie i tym powodem nie jest tylko "operacje na plikach", tylko jakaś potrzeba użytkownika - cache, backup, edycja, serializacja, etc. I ta klasa w której przebywają te operacje powinna być właśnie nazwana tym celem, a nie tylko tym że "opertuje na plikach".

edytowany 1x, ostatnio: Riddle
SL
  • Rejestracja:około 7 lat
  • Ostatnio:około 3 godziny
  • Postów:871
0
Riddle napisał(a):

A "Service" mówi? :D To jest buzzword, szum informacyjny. Nie dostajesz żadnych nowych informacji widząc dodatkowo słowo "Service".

Nic nie mówi, ale ta nazwa jest po prostu w użyciu i dlatego jest pomocna.

Słaby przykład, bo po co do tego dwie klasy? Czemu nie Base64.encode() i Base64.decode()?

SRP

Ten sam problem co z FileManager, czyli zbyt generyczna nazwa, która w żaden sposób nie mówi co ta klasa robi.

Dalej FileSystem jest znanym terminem w branży i dlatego użycie tej nazwy jest pomocne. Jak dla mnie Javowy https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html jest całkiem dobrze zaprojektowany i twórcy uznali, że ta nazwa ma sens.

Całkowicie ignorujesz to, że ta klasa FileManager czy FileSystem w tej aplikacji jest dodana po coś. Istnieje jakiś powód, czemu jest w tej klasie i tym powodem nie jest tylko "operacje na plikach", tylko jakaś potrzeba użytkownika - cache, backup, edycja, serializacja, etc. I ta klasa w której przebywają te operacje powinna być właśnie nazwana tym celem, a nie tylko tym że "opertuje na plikach".

Jakbyś inaczej to nazwał takie "coś" (tj. FileManager, FileSystem)? IMO sens tej nazwy wynika z tego, że wszystkie te metody operują na pewnym określonym file systemie. Takim file systemem mógłby być lokalny file system, ale też np. adapter do cloud storage

AN
AN
  • Rejestracja:około rok
  • Ostatnio:8 miesięcy
  • Postów:30
0

W c# zdarzają mi się kolizje namespace oraz klas gdy staram się stosować krótsze nazwy.
Ostatnio w solucji miałem projekt: Example.Boards, a w nim public sealed class BoardsFacade(Boards boards, ...){}

Pomijając tę kolizję nazw. Patrząc teraz na ten kod myślę, ze powinienem rozbić tę klasę na 2: Boards i BoardsMembership.
Kusi mnie, żeby dodać Manager do tej drugiej. Co do Boards to ta nazwa mi się nie podoba.

Kopiuj
public sealed class Boards(...) {
  public Either<IError, Board> Add(...) {} //mapowanie DTO, zapis do bazy
  public Either<IError, Unit> Remove(...) {} // usunięcie z bazy
  public Either<IError, Unit> AddMember(BoardId boardId, UserId userId) {}
  public Either<IError, Unit> RemoveMember(BoardId boardId, UserId memberId) {}
}
edytowany 2x, ostatnio: Anatolijus
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Wrocław
3
markone_dev napisał(a):
bakunet napisał(a):
markone_dev napisał(a):

ktoś sugerował unikania nazywania klas usługowych z końcówką -er Czyli handler, provider, adapter, manager, helper, itd.

Ciekaw jestem czemu?

Żeby nadawać klasom bardziej znaczace nazwy, wynikające z ich przeznaczenia czy sensu domenowego.

CreateInvoiceHandler czy CustomerDataProvider to jak najbardziej nazwy wynikające z przeznaczenia czy domeny.
Co do helper czy manager, bo takie nazwy sugerują, że klasa ma potencjalnie nieskończoną odpowiedzialność, więc każdy dopisuje tam sobie metody, które mu pasują.
Chyba z raz widziałem Managera, który miał sens - klasa ta była odpowiedzialna za tworzenie/usuwanie serwisów ServiceFabricowych.

KamilAdam napisał(a):

Ogólnie wyglada to jak Spring sprzed 10 lat, ale nie wiem czy coś tam się zmieniło. BTW słyszałem kiedyś iż odpowiednikiem Springowo Javowego Service jest w C# Manager. Prawda to @somekind ?Tutoriale C#powe dalej tak doradzają ?

Nie widziałem nigdy tutoriala, który by tak doradzał, w swojej karierze zawodowej widziałem też setki Service, i może z kilka Managerów. Ale może po prostu nie trafiam na projekty tworzone przez takich tytanów nazewnictwa, nie wiem.

bakunet napisał(a):

@markone_dev:

Rozumiem, ale na przykładzie takiego FileManagera, serwisu który odczytuje, usuwa, zapisuje, nadpisuje plik, sprawdza czy plik istnieje, jak można go nazwać inaczej? Ja mało widziałem, więc się zastanawiam.

FileSystem

slsy napisał(a):

Nic nie mówi, ale ta nazwa jest po prostu w użyciu i dlatego jest pomocna.

Nie jest, bo tak samo jak Helper czy Manager na ogół nie opisuje do czego służy, za to jest workiem na wszystko.

Słaby przykład, bo po co do tego dwie klasy? Czemu nie Base64.encode() i Base64.decode()?

SRP

Jeśli klasa odpowiada za obsługę Base64, to ciężko tu o łamanie SRP.

Anatolijus napisał(a):

Kusi mnie, żeby dodać Manager do tej drugiej.

Idź się wyspowiadaj z tego pomysłu.

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10056
1
slsy napisał(a):

Słaby przykład, bo po co do tego dwie klasy? Czemu nie Base64.encode() i Base64.decode()?

SRP

A z jakiej racji? Ty wiesz o chodzi w SRP?

Jedna klasa odpowiada tekst w base64, i tą klasą mogłoby być Base64. To że ona umie jednocześnie zakodować i odkodować to nie znaczy że łamie SRP (chociażby dlatego że i tak gdybyś chciał je zmienić to musiałbyś zmienić obie).

Gdyby to co mówisz było prawdą, i każda funkcja klasy jest osobną odpowiedzialnością, to w klasie File albo Database nie mógłbyś mieć File.read() i File.write(), bo przecież odczytywanie i zapisywanie byłby osobnymi odpowiedzialnościami. Jak miałbyś transaction.commit(), to nie mógłbyś mieć już transaction.rollback(). Tak na prawdę każda klasa musiałaby mieć tylko jedną publiczną metodę, bo gdyby miała dwie to łamałaby SRP. Nie byłoby sensu używać obiektów, bo każdą klasę z pojedynczą metodą możnaby zastąpić jedną funkcją. Jasno widać że takie rozumienie SRP jest bez sensu.

Jak więc rozumieć SRP i czemu ma służyć?

SRP ma pomóc nam minimalizować skutki niepożądanej zmiany zachowania przy edycji kawałka kodu - np zmieniamy nazwę pola w widoku, i nagle integracja z paypalem przestaje działać. Takie zjawisko jest bardzo popularne w projektach gdzie SRP się nie stosuje. W jaki sposób więc SRP chroni nas przed takimi nieoczekiwanymi zmianami? "R" w SRP to nie jest to co klasa robi, tylko jej powód do zmiany. "Zasada pojedynczej odpowiedzialności" oznacza "Zasada pojedynczego powodu do zmiany". Dlatego moim zdaniem klasa Base64 która ma metody zarówno encode() jak i decode() nie łamie SRP. Łamałaby ją gdyby miała metody np zarówno Base64.encode() jak i Base64.sendHttpAuthorizationHeader(). Nie chodzi też o ilość metod, bo jedna klasa może mieć 10 bardzo ze sobą spójnych metod, a z kolei inna klasa może mieć dwie zupełnie odstające.

slsy napisał(a):

Całkowicie ignorujesz to, że ta klasa FileManager czy FileSystem w tej aplikacji jest dodana po coś. Istnieje jakiś powód, czemu jest w tej klasie i tym powodem nie jest tylko "operacje na plikach", tylko jakaś potrzeba użytkownika - cache, backup, edycja, serializacja, etc. I ta klasa w której przebywają te operacje powinna być właśnie nazwana tym celem, a nie tylko tym że "opertuje na plikach".

Jakbyś inaczej to nazwał takie "coś" (tj. FileManager, FileSystem)? IMO sens tej nazwy wynika z tego, że wszystkie te metody operują na pewnym określonym file systemie. Takim file systemem mógłby być lokalny file system, ale też np. adapter do cloud storage

Jeśli klasa jest generyczna - tak że nie ma tam absolutnie nic z logiki biznesowej, ale nic, żadnej stałej, żadnej zmienne, żadnej wartości z domeny, to w takim razie, jeśli ta klasa faktycznie jest generyczna, to powinna się nazywać File. Nie ma po co dodawać Manager albo System, co niby tym zyskasz?

Natomiast jeśli ma coś z domeny (jakąś ścieżkę, jakąś wartośc, cokolwiek) to należałoby nazwać tą klasę tym co robi (np Cache, Backup, Document, etc.)

edytowany 8x, ostatnio: Riddle
LU
  • Rejestracja:około 11 lat
  • Ostatnio:około 11 godzin
  • Lokalizacja:Gdańsk
1

Szczerze mówiąc ja przyzwyczaiłem się do postfixu Service bo to się wszędzie widzi w projektach i od razu wiadomo, że zwykle taka klasa zawiera jakąś procedurę biznesową, która spina inne elementy w całość. Zresztą nawet sama nazwa service layer w architekturze warstwowej wskazuje na to, że tam są serwisy więc to jest imho naturalne.


somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Wrocław
1
lukascode napisał(a):

Szczerze mówiąc ja przyzwyczaiłem się do postfixu Service bo to się wszędzie widzi w projektach i od razu wiadomo, że zwykle taka klasa zawiera jakąś procedurę biznesową, która spina inne elementy w całość.

I zwykle błędnie - często łączone są elementy, które nie mają ze sobą nic wspólnego poza tym, że łączy je jakieś słowo kluczowe.

Zresztą nawet sama nazwa service layer w architekturze warstwowej wskazuje na to, że tam są serwisy więc to jest imho naturalne.

No, to może nie stosować architektury, która każe robić dziwne rzeczy.

SL
  • Rejestracja:około 7 lat
  • Ostatnio:około 3 godziny
  • Postów:871
0
Riddle napisał(a):

Jeśli klasa jest generyczna - tak że nie ma tam absolutnie nic z logiki biznesowej, ale nic, żadnej stałej, żadnej zmienne, żadnej wartości z domeny, to w takim razie, jeśli ta klasa faktycznie jest generyczna, to powinna się nazywać File. Nie ma po co dodawać Manager albo System, co niby tym zyskasz?

Na przykładzie javowego FileSystem mamy File, które pozwala na operacja na jednym pliku i FileSystem

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
5

Używam XYZService i nie mam z tym problemu. IMO dość sensowny sposób wyróżnienia gdzie szukać API/Fasady w module.


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 1x, ostatnio: jarekr000000
markone_dev
  • Rejestracja:około 3 lata
  • Ostatnio:około 11 godzin
  • Postów:812
1
Riddle napisał(a):
markone_dev napisał(a):
bakunet napisał(a):

@markone_dev:

Rozumiem, ale na przykładzie takiego FileManagera, serwisu który odczytuje, usuwa, zapisuje, nadpisuje plik, sprawdza czy plik istnieje, jak można go nazwać inaczej? Ja mało widziałem, więc się zastanawiam.

W .NET do tego służą klasy File, Directory, Path, itd. Da się napisać bibliotekę do IO beż FileManagera?

Ale użycie tych klas też musisz mieć w jakiejś klasie którą musisz jakoś nazwać.

No i tu wchodzi Service albo Handler jako nazwy klas reprezentujących styl architektoniczny. Klasy typu ApplicationService, DomainService, CommandHandler, QueryHandler mają swój odpowiednik w stylach architektonicznych i jak są umieszczone w odpowiednich miejscach zgodnie ze stylem architektonicznym, to takie nazwy mają sens i są wręcz pożądane.

Problem zaczyna się gdy z braku laki i chęci, ktoś zaczyna wszystkie klasy nazywać service, manager, helper czy provider


Programujący korpo architekt chmurowy.
Udzielam konsultacji i szkoleń w obszarze szeroko pojętego cloud computingu (Azure, AWS) i architektury systemów IT. Dla firm i prywatnie.
DevOps to proces nie stanowisko.
edytowany 2x, ostatnio: markone_dev
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0
markone_dev napisał(a):

Problem zaczyna się gdy z braku laki i chęci, ktoś zaczyna wszystkie klasy nazywać service, manager, helper czy provider

Zgadzam się, co do tego — faktycznie to jest lipa. Jak ktoś wsadza te nazwy wszędzie, to faktycznie jest to słabe.

markone_dev napisał(a):

No i tu wchodzi Service albo Handler jako nazwy klas reprezentujących styl architektoniczny. Klasy typu ApplicationService, DomainService, CommandHandler, QueryHandler mają swój odpowiednik w stylach architektonicznych i jak są umieszczone w odpowiednich miejscach zgodnie ze stylem architektonicznym, to takie nazwy mają sens i są wręcz pożądane.

Argument z tym, żeby nazywać klasy od "stylu architektonicznego" nie koniecznie musi być zły (tutaj plus), ale nie koniecznie musi też być dobry. Co stoi na przeszkodzie klasę ApplicationService nazwać po prostu Application?

Chyba to co chcę powiedzieć to to, że jest kilka ograniczonych przypadków w których użycie słów "service" i "handler" jest uzasadnione, więc tutaj @markone_dev się zgadzam; ale niemniej w znacznej większości są one nagminnie nadużywane, i słowa "service" albo "handler" są dowalane do klasy w sumie nie wiadomo po co - chyba żeby się przystosować do jakiegoś bardziej "industrialnego" stylu czy coś. Ktoś może pomyśleć że jak jego aplikacja składa się z service'ów, handlerów i providerów to będzie "bardziej pro". A jak mamy krótkie, proste nazwy takie jak np Application albo File, to że wyglada "amatorsko". Tymczasem dodając taki suffix zyskujemy... no właśnie, w sumie nic. I efekt jest w zasadzie odwrotny.

edytowany 8x, ostatnio: Riddle
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Wrocław
1
markone_dev napisał(a):

No i tu wchodzi Service albo Handler jako nazwy klas reprezentujących styl architektoniczny. Klasy typu ApplicationService, DomainService, CommandHandler, QueryHandler mają swój odpowiednik w stylach architektonicznych i jak są umieszczone w odpowiednich miejscach zgodnie ze stylem architektonicznym, to takie nazwy mają sens i są wręcz pożądane.

Jaki styl architektoniczny wymaga nazywania klas AbcService albo XyzHandler?

markone_dev
  • Rejestracja:około 3 lata
  • Ostatnio:około 11 godzin
  • Postów:812
0
somekind napisał(a):
markone_dev napisał(a):

No i tu wchodzi Service albo Handler jako nazwy klas reprezentujących styl architektoniczny. Klasy typu ApplicationService, DomainService, CommandHandler, QueryHandler mają swój odpowiednik w stylach architektonicznych i jak są umieszczone w odpowiednich miejscach zgodnie ze stylem architektonicznym, to takie nazwy mają sens i są wręcz pożądane.

Jaki styl architektoniczny wymaga nazywania klas AbcService albo XyzHandler?

A gdzie napisałem, że wymaga? Napisałem że klasy typu ApplicationService, DomainService czy CommandHandler mają swoje odpowiedniki w stylach architektonicznych jak DDD, CQRS czy Onion i ogólnie przyjęło się, że klasy nazywamy w ten sposób czyli OrderService, PlaceOrderHandler, FindUserOrdersHandler, itd. Tak samo jak swoje miejsce mają klasy typu Controller w MVC czy Presenter w MVP i jakoś nikt się o to nie pruje.

Oczywiście nikt ci nie broni nazywać sobie tych klas inaczej. Niemniej utarł się pewien schemat i o nim piszę.


Programujący korpo architekt chmurowy.
Udzielam konsultacji i szkoleń w obszarze szeroko pojętego cloud computingu (Azure, AWS) i architektury systemów IT. Dla firm i prywatnie.
DevOps to proces nie stanowisko.
edytowany 1x, ostatnio: markone_dev
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0
markone_dev napisał(a):

A gdzie napisałem, że wymaga? Napisałem że klasy typu ApplicationService, DomainService czy CommandHandler mają swoje odpowiedniki w stylach architektonicznych jak DDD, CQRS czy Onion i ogólnie przyjęło się, że klasy nazywamy w ten sposób czyli OrderService, PlaceOrderHandler, FindUserOrdersHandler, itd. Tak samo jak swoje miejsce mają klasy typu Controller w MVC czy Presenter w MVP i jakoś nikt się o to nie pruje.

Oczywiście nikt ci nie broni nazywać sobie tych klas inaczej. Niemniej utarł się pewien schemat i o nim piszę.

Tylko dla mnie określenia "przyjęło się" oraz "utarł się schemat" znaczą praktycznie to samo co "nie ma powodu żeby tak robić"? (oprócz tego że inni tak robią, też bez powodu, ad. infinitum?)

KamilAdam
Brakuje tylko "to tradycja" XD
markone_dev
  • Rejestracja:około 3 lata
  • Ostatnio:około 11 godzin
  • Postów:812
2
Riddle napisał(a):
markone_dev napisał(a):

A gdzie napisałem, że wymaga? Napisałem że klasy typu ApplicationService, DomainService czy CommandHandler mają swoje odpowiedniki w stylach architektonicznych jak DDD, CQRS czy Onion i ogólnie przyjęło się, że klasy nazywamy w ten sposób czyli OrderService, PlaceOrderHandler, FindUserOrdersHandler, itd. Tak samo jak swoje miejsce mają klasy typu Controller w MVC czy Presenter w MVP i jakoś nikt się o to nie pruje.

Oczywiście nikt ci nie broni nazywać sobie tych klas inaczej. Niemniej utarł się pewien schemat i o nim piszę.

Tylko dla mnie określenia "przyjęło się" oraz "utarł się schemat" znaczą praktycznie to samo co "nie ma powodu żeby tak robić"? (oprócz tego że inni tak robią, też bez powodu, ad. infinitum?)

Nie chce mi się wchodzić w filozoficzne dyskusje. Chcesz robić inaczej to rób. Przecież nikt ci nie zabroni w architekturze MVC zamiast EmployeeController nazwać klasę EmployeeHttpRequestProcessor bo twoim zdaniem ma więcej sensu. Na szczęście większość programistów idzie utartym schematem przez co nie muszę się zastanawiać nad tym co autor chciał przez to wyrazić? Swoje ego, swój indywidualizm czy jeszcze coś innego.


Programujący korpo architekt chmurowy.
Udzielam konsultacji i szkoleń w obszarze szeroko pojętego cloud computingu (Azure, AWS) i architektury systemów IT. Dla firm i prywatnie.
DevOps to proces nie stanowisko.
SO
Przecież nikt ci nie zabroni w architekturze MVC zamiast EmployeeController nazwać klasę EmployeeHttpRequestProcessor bo twoim zdaniem ma więcej sensu. Nikt też zgodnie z niektórymi rekomendacjami wyżej nie zabroni nazwać jej Employee, bo wszystkie sufiksy to tylko niepotrzebny narzut :D
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0
markone_dev napisał(a):

Nie chce mi się wchodzić w filozoficzne dyskusje. Chcesz robić inaczej to rób. Przecież nikt ci nie zabroni w architekturze MVC zamiast EmployeeController nazwać klasę EmployeeHttpRequestProcessor bo twoim zdaniem ma więcej sensu. Na szczęście większość programistów idzie utartym schematem przez co nie muszę się zastanawiać nad tym co autor chciał przez to wyrazić? Swoje ego, swój indywidualizm czy jeszcze coś innego.

Pojęcie "architekturze MVC" to jakiś żart (bo rozumiem że odnosisz się do takiego "mvc" jaki jest np prezentowany w domyślnych scaffoldach frameworków Spring, Laravel, Rails czy Django?).

Frameworki te narzucają warstwową strukturę projektu, często dodając dodatkowe (np warstwa controllerów, warstwa modelów, warstwa widoków, warstwa middleware'ów, warstwa kolejek, etc.) - i taka warstwowość to jest wymysł autorów tych frameworków, a nie faktyczna cecha wzorca MVC - przez to wielu ludzi myśli teraz że MVC == "warstwy". W MVC żadnych warstw nie było. Argumenty czemu takie warstwowanie jest słabe można mnożyć. Jednym z nich jest to, że nawet sami użytkownicy tych frameworków zaczynają zauważać że takie warstwy dodają zbyt silne powiązania i starają się to obchodzić, proponując np. vertical slicing - według niektórych super pomysł. Tylko że pomysł z vertical slicing tylko dlatego stał się konieczny, żeby obejśc warstwy które są sztucznie nałożone przez framework - tych warstw w ogóle nie powinno być.

Autor MVC, Trygve Reenskaug, zapoczątkował wzorzec w latach ~1970-którymś. Nie było w nim mowy o żadnych warstwach, ani o niczym takim.

Więc, odpowiadając @markone_dev na Twój argument:

markone_dev napisał(a):

Przecież nikt ci nie zabroni w architekturze MVC zamiast EmployeeController nazwać klasę EmployeeHttpRequestProcessor bo twoim zdaniem ma więcej sensu.

Dodając takie klasy jak EmployeeController, to co tak na prawdę robisz, to dopasowujesz się do schematu nałożonego przez framework (który próbuje Cię przekonać że ten schemat to MVC).

markone_dev napisał(a):

Na szczęście większość programistów idzie utartym schematem przez co nie muszę się zastanawiać nad tym co autor chciał przez to wyrazić?

To że to jest "czytelniejsze" albo to że "nie musisz się zastanawiać nad tym co autor chciał przez to wyrazić", to tak na prawdę chodzi o to żebyś wiedział do której szufladki frameworkowej autor feature chciał go wsadzić. Tylko że to nie byłoby konieczne, gdyby nie te szufladki frameworka.

edytowany 7x, ostatnio: Riddle
markone_dev
  • Rejestracja:około 3 lata
  • Ostatnio:około 11 godzin
  • Postów:812
0
Riddle napisał(a):
markone_dev napisał(a):

Nie chce mi się wchodzić w filozoficzne dyskusje. Chcesz robić inaczej to rób. Przecież nikt ci nie zabroni w architekturze MVC zamiast EmployeeController nazwać klasę EmployeeHttpRequestProcessor bo twoim zdaniem ma więcej sensu. Na szczęście większość programistów idzie utartym schematem przez co nie muszę się zastanawiać nad tym co autor chciał przez to wyrazić? Swoje ego, swój indywidualizm czy jeszcze coś innego.

Pojęcie "architekturze MVC" to jakiś żart (bo rozumiem że odnosisz się do takiego "mvc" jaki jest np prezentowany w domyślnych scaffoldach frameworków Spring, Laravel, Rails czy Django?).

Mówiłem o przyjętej konwencji nazewniczej na przykładzie nazw kontrolerów architekturze MVC. Nie pisałem nic o warstwach ani niczym takim. Zamiast MVC wstaw sobie MVP. Nieważne. Przyjęło się nazewnictwo Controller, Presenter i tego się trzymajmy.

A jak chcesz uprawiać filozofię to nie że mną bo ja już swoje powiedziałem i nie mam nic więcej do dodania w tym temacie


Programujący korpo architekt chmurowy.
Udzielam konsultacji i szkoleń w obszarze szeroko pojętego cloud computingu (Azure, AWS) i architektury systemów IT. Dla firm i prywatnie.
DevOps to proces nie stanowisko.
edytowany 1x, ostatnio: markone_dev
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0
markone_dev napisał(a):

Mówiłem o przyjętej konwencji nazewniczej na przykładzie nazw kontrolerów architekturze MVC.

Ale ta konwencja nie przynosi nic dobrego. Tylko zachęca jeszcze bardziej do dopasowania swojego projektu pod framework.

Okej, może powiem inaczej:

Jeśli chcesz się dopasować pod framework, i pisać wszystko przez pryzmat tego frameworka (np Spring, Rails, Laravel), to nazywaj klasy tak jak dokumentacja tego frameworka mówi: dodaj Controller, widok, model ORM'owy etc. (tylko nie ubieraj tego w jakieś wzniosłe terminy jak architektura czy MVC).

Natomiast jeśli chcesz po prostu stworzyć aplikację, a framework trzymać "at-arms-length", czyli innymi słowy mieć loose-coupling z tym frameworkiem, to warto nie stosować tych konwencji. I nie mam na myśli tutaj żeby teraz zrobić rename klas UsersController na Users, nie o to chodzi - ja mówię o tym, że czysto zrobiona aplikacja w ogóle nie powinna mieć struktury takiej jaka wychodzi jak odpalisz scaffold frameworka. I w takiej aplikacji nie ma sensu dodawać zarostków Service, Handler, etc, bo wszystko jest pogrupowane po odpowiedzialnościach, i można łatwo się rozeznać co jest gdzie i do czego służy po odpowiednich nazwach.

Większość programistów nie wyobraża sobie aplikacji Laravel która nie miałaby w roocie projektu katalogów app/, bootstrap/, config/, database/, routes/ czy storage/. Tylko że sama taka struktura narzucona przez framework ogranicza zaprojektowanie dobrej architektury takiej aplikacji, i praktycznie przywiązuje nas do schematu narzuconego przez framework - do tego stopnia że nie wyobrażamy sobie programować bez niego (co moim skromnym zdaniem jest szalone trochę). A to totalnie można łatwo zrobić - jeśli się zbuduje odpowiednią abstrakcję.

edytowany 5x, ostatnio: Riddle
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)