Jak dobrze podzielić program na moduły lub mikroserwisy?

Jak dobrze podzielić program na moduły lub mikroserwisy?
NO
  • Rejestracja:ponad 2 lata
  • Ostatnio:11 dni
  • Postów:135
0

W jaki sposób dzielić aplikację na moduły (modularny monolit) lub mikroserwisy w optymalny sposób? Wiem, że jest to związane z bounded contextem czy domeną jak zwał, tak zwał, ale szukam konkretnych wskazówek i przykładów. Takie 2 głównie problemy jakie widzę, to raz, żeby nie skończyć z rozproszonymi monolitem czyli sytuacją kiedy każdy moduł/mikroserwis ściśle zależy od całej reszty i muszą być wdrażane jednocześnie, a 2 żeby też nie zrobić za dużych modułów/mikroserwisów, które ciężko ogarnąć i rozwijać. Jak to wyważyć? W ogóle czy jeden moduł/mikroserwis powinien ciągnąć dane z drugiego? Czy komunikacja synchroniczna nie powinna być opcjonalna i komponenty nie powinny się komunikować tylko eventami czy czymś podobnym?

edytowany 1x, ostatnio: Riddle
AN
  • Rejestracja:prawie 11 lat
  • Ostatnio:około godziny
  • Postów:973
4

Mikroserwisy mają wiele problemów, które trzeba rozwiązywać wynikające z komunikacji między nimi więc jeśli to mały projekt (poniżej 10 programistów) sugerowałbym raczej monolit dobrze podzielony na moduły.

Nie ma uniwersalnego podejścia co do modułów ale warto się skupić na tym, żeby nie było sytuacji, że moduł A korzysta z modułu B a moduł B korzysta z modułu A


Zdalna praca dla Senior Python Developerów --> PW
markone_dev
  • Rejestracja:około 3 lata
  • Ostatnio:3 dni
  • Postów:809
4

@Nofenak:

W jaki sposób dzielić aplikację na moduły (modularny monolit) lub mikroserwisy w optymalny sposób?

Na podstawie wymagań biznesowych.

Wiem, że jest to związane z bounded contextem czy domeną jak zwał, tak zwał,

Nie. Pojęcie domena i bounded context to nie są tożsame pojęcia. W ramach jednej domeny może występować kilka bounded contextów lub/oraz poddziedzin ponieważ nie zawsze (poza światem idealnym) bounded context mapuje się 1:1 na poddziedzinę.

Takie 2 głównie problemy jakie widzę, to raz, żeby nie skończyć z rozproszonymi monolitem czyli sytuacją kiedy każdy moduł/mikroserwis ściśle zależy od całej reszty i muszą być wdrażane jednocześnie, a 2 żeby też nie zrobić za dużych modułów/mikroserwisów, które ciężko ogarnąć i rozwijać. Jak to wyważyć?

Nigdy nie zaczynamy od mikroserwisów. Zacząć od modularnego monolitu jak wspomniał @anonimowy i wydzielać moduły jako mikroserwisy tylko jeżeli zajdzie potrzeba biznesowa. W przeciwnym wypadku to nic innego jak onanizm techniczny.

W ogóle czy jeden moduł/mikroserwis powinien ciągnąć dane z drugiego? Czy komunikacja synchroniczna nie powinna być opcjonalna i komponenty nie powinny się komunikować tylko eventami czy czymś podobnym?

A to zależy. Od czego? Od wielu czynników. Jak popatrzymy na system z punktu widzenia domain driven design, to zobaczymy, że mamy różne typy poddziedzin: główne (core subdomains), wspierające (supporting domains) oraz generyczne (generic subdomains). Jeżeli rozważymy sobie system w którym główną rolę gra dziedzina związana z analizą danych (core subdomain) to konieczność wystawienia faktury dla klienta, być może według prawa podatkowego obowiązującego w jego kraju, to w przypadku rozwiązania obsługującego klientów z wielu krajów może być problematyczne. W tej sytuacji ostanie czego chcemy to zajmować się implementacją reguł podatkowych według kraju/kontynentu. Dlatego w tej hipotetycznej sytuacji poddziedzina fakturowania (invoicing) będzie domeną generyczną i dla dziedzin generycznych kupujemy gotowe rozwiązanie. W naszym przypadku system księgowy, który integrujemy z naszym systemem. W tej sytuacji może się okazać że system księgowy nie wspiera integracji w stylu event-driven, tylko wystawia proste synchroniczne API po HTTP do którego musimy wysłać request i czekać na odpowiedź. Odpada więc możliwość bezpośredniej integracji opartej o zdarzenia.

Do tego asynchroniczna (przez kolejkę/message broker) integracja za pomocą wiadomości wprowadza duplikację danych. Bo jeżeli wysyłamy wiadomość z A do B (na przykład o kliencie) to zakładamy że B posiada kopię danych tego klienta i nie musi wykonywać już zapytania o jego dane do przykładowo C.

I tak dalej i tak dalej.

A jak to cię nie przekonuje to popatrz na success story takich firm jak Netflix, Amazon, Google, Microsoft, Instagram, Facebook, czy Allegro. Każda z tych firm zaczynała jako monolit ponieważ ma najszybszy time to market. Jest różnica gdy jako platforma streamingowa obsługujesz kilkuset użytkowników, a kilka milionów. W pierwszym przypadku dobrze napisany monolit wystarczy. W drugim już niekoniecznie.

Wszystkie wspomniane firmy skalowały się i ich architektura ewoluowała wraz ze wzrostem biznesu, ponieważ widzieli które moduły/poddziedziny wymagają indywidualnego podejścia.

Dlatego zrób modularny monolit i obserwuj aplikację. Widzisz że 70% ruchu w twojej aplikacji to requesty do katalogu produktów czy modułu streamingowego, który wymaga niezależnego skalowania aby obsłużyć przychodzący ruch bez potrzeby skalowania pozostałych modułów, to wydzielasz go jako osobny serwis. Z biegiem czasu widzisz że biznes wymaga aby lepiej dopasowywać rekomendacje twoich produktów użytkownikom i wprowadzać modyfikacje do algorytmu niezależnie od pozostałych modułów/poddziedzin? Proszę bardzo, wydzielasz poddziedzinę rekomendacji do osobnego serwisu.

I tak dalej i tak dalej.


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
AN
  • Rejestracja:prawie 11 lat
  • Ostatnio:około godziny
  • Postów:973
0

@markone_dev: Imo samo skalowanie to za mało żeby stwierdzić, że potrzebny jest mikroserwis. Bo przecież jak zeskalujesz sobie monolit to on obsłuży też ten moduł a jedyny narzut to tak naprawdę większa aplikacja i te kilka/kilkaset MB rozmiaru projektu


Zdalna praca dla Senior Python Developerów --> PW
markone_dev
  • Rejestracja:około 3 lata
  • Ostatnio:3 dni
  • Postów:809
2
anonimowy napisał(a):

@markone_dev: Imo samo skalowanie to za mało żeby stwierdzić, że potrzebny jest mikroserwis. Bo przecież jak zeskalujesz sobie monolit to on obsłuży też ten moduł a jedyny narzut to tak naprawdę większa aplikacja i te kilka/kilkaset MB rozmiaru projektu

Wiadomo, że skalowanie to nie jedyny driver do wydzielania modułu aplikacji jako osobnej usługi. Ale w kontekście tego skalowania to trzeba sobie odpowiedzieć czy chcemy i jest sens skalować całą aplikację, czy tylko jakiś jej moduł, np odpowiedzialny za streaming czy konwersję dużych dokumentów, który może się wywalać i/albo wydajnościowo wpływać na inne moduły.

Generalnie chodzi mi o to, że najlepiej zacząć od monolith first i stopniowo migrować w stronę mikroserwisów jeśli jest taka potrzeba w miarę jak poznajemy domenę biznesową, wymagania użytkowników, zachowanie aplikacji w rzeczywistym środowisku, itd.


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:ponad 14 lat
  • Ostatnio:36 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10032
0
Nofenak napisał(a):

Takie 2 głównie problemy jakie widzę, to raz, żeby nie skończyć z rozproszonymi monolitem czyli sytuacją kiedy każdy moduł/mikroserwis ściśle zależy od całej reszty i muszą być wdrażane jednocześnie, a 2 żeby też nie zrobić za dużych modułów/mikroserwisów, które ciężko ogarnąć i rozwijać. Jak to wyważyć?

Zapoznaj się z Dependency Inversion oraz Open/Close, to będzie dobre miejsce startowe.

Kilka rules of thumb:

  • Jeśli jakieś elementy zmieniają się razem: powinny być w jednym module, jeśli zmieniasz jakiś element A, ale nie musisz zmienić B, to to jest sygnał że A i B mogą być w osobnych modułach
  • Jeśli dwa kawałki kodu odpowiadają za różne elementy (np persystencję i widok), to mogą być w osobnych modułach
  • Jeśli kawałek kodu korzysta z dużej biblioteki, a inny nie, to sygnał że te dwa kody mogą (ale nie muszą) być w innych modułach.
Nofenak napisał(a):

W ogóle czy jeden moduł/mikroserwis powinien ciągnąć dane z drugiego?

Tak, to jest naturalne.

Dane mogą (i nawet powinny) płynąć z jednego modułu do drugiego, ważne jest tylko żeby ograniczyć coupling-tych modułów.

Nofenak napisał(a):

Czy komunikacja synchroniczna nie powinna być opcjonalna i komponenty nie powinny się komunikować tylko eventami czy czymś podobnym?

Nie koniecznie, nie jest to wymóg.

Co do samych mikroserwisów, to je zostawiłbym na sam koniec: Decyzja o mikroserwisach powinna być podjęta na samym końcu. Jeśli chcesz zrobić krok w stronę dobrej modularyzacji, to powinieneś zrobić tak:

  • Najpierw rozdziel swój kod na sensowne moduły
  • Jeśli to nie wystarczy, rozdziel swój kod na osobne projekty które korzystają z siebie nawzajem
  • Jeśli znowu to nie wystarczy, to uruchom swoją aplikacje w różnych procesach
  • Dopiero jeśli każde z tych metod zawiedzie, spróbuj przerobić je na mikroserwisy.

Spoko filmik, polecam: youtube.com/watch?v=zzMLg3Ys5vI.

edytowany 2x, ostatnio: Riddle
AN
  • Rejestracja:prawie 11 lat
  • Ostatnio:około godziny
  • Postów:973
0

@Riddle: Przecież autor właśnie o to pyta.

Q: Jak sensownie rozbić projekt na moduły?
A: Najpierw rozdziel swój kod na sensowne moduły

Gorzej jak Chat-GPT :P


Zdalna praca dla Senior Python Developerów --> PW
SL
  • Rejestracja:około 7 lat
  • Ostatnio:około 19 godzin
  • Postów:857
0

Dobra modułowość to w gruncie rzeczy minimalizowane zależności pomiędzy różnymi kawałkami kodu. Jak masz dobrą modułowość to:

  • dużo kodu jest pochowana np. za interfejsem. Im mniej kodu widocznego na zewnątrz tym mniejsza szana, że ktoś go użyje. Dobrym kontrprzykładem jest popularny antypattern package by layer, gdzie robisz pakiety model/service/controller. W takim podejściu wszystko gada ze wszystkim, prawidłowym podejściem jest package by feature np. order/ticketing
  • powiązania pomiędzy modułami są słabe. Np. przekazujemy id jakiegoś obiektu z innego modułu zamiast całego obiektu
  • liczba powiązań jest mała, widać klastry.

Dobrym przykładem jest też usuwalność/przenaszalność kodu tj. jeśli trzeba usunąć dany feature to jak prosto da się zrobić? W idealnym przypadku będzie to rm -rf moduł i usunięcie wywołań. Jeśli trzeba przeorać cały kod to jest słabo

Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:36 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10032
0
slsy napisał(a):
  • powiązania pomiędzy modułami są słabe. Np. przekazujemy id jakiegoś obiektu z innego modułu zamiast całego obiektu

To akurat nie o dobrej modularności, bo ten id to nadal jest zależność.

SL
  • Rejestracja:około 7 lat
  • Ostatnio:około 19 godzin
  • Postów:857
0

Mówię o sytuacji gdy przekazujemy id zamiast całego obiektu. Masz pomysł jak można to zrobić lepiej?

Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:36 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10032
0
slsy napisał(a):

Mówię o sytuacji gdy przekazujemy id zamiast całego obiektu.

A ja Ci mówię że przekazanie jednego id to również jest zależność i powiązanie między modułami. Nie ma znaczenia czy przekażesz cały obiekt czy sam id - masz taki sam coupling w obu case'ach.

Właściwie to id jest gorszy, bo taki obiekt przynajmniej ma namespace i widać explicitly coś coś jest "nie halo", a taki id (int czy long) to prymityw, i nie widać że jest to powiązanie.

slsy napisał(a):

Masz pomysł jak można to zrobić lepiej?

No tak, zniwelować tą zależność stosując odpowiednią enkapsulację.

edytowany 2x, ostatnio: Riddle
IK
  • Rejestracja:ponad 7 lat
  • Ostatnio:prawie 2 lata
0
Riddle napisał(a):
slsy napisał(a):

Masz pomysł jak można to zrobić lepiej?

No tak, zniwelować tą zależność stosując odpowiednią enkapsulację.

Jakie są sposoby na to? Jak napisać mikroserwis do dodawania i wyświetlania komentarzy pod wpisem na blogu w taki sposób, by ten mikroserwis nie wiedział o ID wpisu?
https://khorikov.org/posts/2021-02-03-should-you-reuse-ids-between-mss/ to dobrze oddaje jakie ja mam podejście do tego tematu.

Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:36 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10032
0
iksde napisał(a):
Riddle napisał(a):
slsy napisał(a):

Masz pomysł jak można to zrobić lepiej?

No tak, zniwelować tą zależność stosując odpowiednią enkapsulację.

Jakie są sposoby na to? Jak napisać mikroserwis do dodawania i wyświetlania komentarzy pod wpisem na blogu w taki sposób, by ten mikroserwis nie wiedział o ID wpisu?

Jeśli nie wiesz jak poprawnie enkapsulować moduły i mikroserwisy od siebie, to ten id to jest Twój najmniejszy problem.

Żeby coś można było nazwać "mikroserwisem", to musi to być niezależny i autonomiczny element - jeśli to coś wystawia id do innych aplikacji (które można błędnie nazwać "mikroserwisem"), to to coś nie jest i nie może być mikroserwisem - mikroserwisy mają być niezależne od siebie, powinieneś zawsze móc go usunąć i napisać nowy, tak żeby inne się nie zepsuły.

Powiem to prosto z mostu:

Jeśli masz dwie aplikacje które gadają po HTTP/REST, i wymieniają miedzy sobą id, to te dwie aplikacje nie są mikroserwisami. Są po prostu jedną aplikacją podzielonymi na dwa procesy z interfejsem HTTP pomiędzy nimi.

Brutalna prawda:

Jeśli nie do końca rozumiesz Dependency Inversion, to obawiam się że nie masz zbytnich szans na zaprojektowanie dobrego mikroserwisu.

iksde napisał(a):

https://khorikov.org/posts/2021-02-03-should-you-reuse-ids-between-mss/ to dobrze oddaje jakie ja mam podejście do tego tematu.

No, i tutaj jest dokładnie opisane to co powiedziałem. Artykuł który podlinkowałeś jest wręcz tutorialem, który równie dobrze mógłby się nazywać: "Jak złamać enkapsulację w mikroserwisach?".

Jest tam napisane, żeby - jeśli przetwarzasz informacje o cusomterach w dwóch mikroserwisach - to one powinny posługiwać się jednym id (nie ma tam wyjaśnione czemu, jest tylko napisane żeby tak robić). Domyślam się że ma to być "pragmatyczne", czyli ktoś uwidacznia szczegóły implementacyjne jednego mikroserwisu, żeby lepiej kontrolować co się dzieje - ale niestety tym samym łamie enkapsulację, tym samym sprawiając że te dwie aplikacje nie są niezależne od siebie, ergo nie są mikroserwisem.

edytowany 4x, ostatnio: Riddle
AN
  • Rejestracja:prawie 11 lat
  • Ostatnio:około godziny
  • Postów:973
1

@Riddle: W takim rozumowaniu 95% firm, które mają mikroserwisy tak naprawdę ich nie mają i autor niczego się nie nauczy. Domyślam się, że jednym z celów autora jest lepsze obracanie się w takiej architekurze, którą wykorzystują realne firmy a nie Ty w jednym projekcie... Allegro w takim razie też nie ma mikroserwisów XD Olx to samo.


Zdalna praca dla Senior Python Developerów --> PW
Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:36 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10032
2
anonimowy napisał(a):

@Riddle: W takim rozumowaniu 95% firm, które mają mikroserwisy tak naprawdę ich nie mają i autor niczego się nie nauczy. Domyślam się, że jednym z celów autora jest lepsze obracanie się w takiej architekurze, którą wykorzystują realne firmy a nie Ty w jednym projekcie... Allegro w takim razie też nie ma mikroserwisów XD Olx to samo.

No, właściwie tak. Podobnie jak 95% firm myśli że jest Agile a nie jest, myśli że ma MVC a nie ma, albo że mając testy stosuje TDD. Rynek IT bardzo lubi takie modne słówka właśnie jak microserwis, sprint, etc. ale nie wystarczy sobie nazwać czegoś microserwisem żeby nim był. "Realne firmy" mają taką architekturę jaką są w stanie wytworzyć ich najlepsi programiści, a Ci często nie znają różnicy między dependency injection i dependency inversion. Ameryki nie odkryłeś.

Mikroserwisy są tworzone przez programistów którzy mają bardzo dobrą zdolność do oceny informacji i projektowania systemów, również dlatego tak dobrze się skalują. Kiedy ten koncept jest adoptowany przez ludzi którzy nie do końca wiedzą co robią, wtedy wychodzi... coż. dwie niepotrzebne apki które gadają po HTTP.

Żeby podejść do modularyzacji należy być ekspertem w Dependency Inversion oraz enkapsulacji, bez tego aplikacja jest raczej mikroserwisem tylko z nazwy.

edytowany 3x, ostatnio: Riddle
AN
  • Rejestracja:prawie 11 lat
  • Ostatnio:około godziny
  • Postów:973
1

Nie zapędzaj się. Myślę, że większość wie co to TDD jak i MVC. To, że Ty masz swoją definicję mikroserwisów nie znaczy, że tacy giganci jak Amazon, Google, Microsoft się myli płacąc swoim ekspertom czasem więcej niż 10 krotność naszych wypłat. Tak jest i należy to przyjąć za definicję a nie walczyć z wiatrakami i przekonywać innych, że nikt nie korzysta z mikroserwisów bo robią to inaczej niż Ty


Zdalna praca dla Senior Python Developerów --> PW
Miang
MVC nie wiedzą
Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:36 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10032
0
anonimowy napisał(a):

Nie zapędzaj się. Myślę, że większość wie co to TDD jak i MVC.

Każdy kto pisze testy myśli że zna TDD, ale mało kto faktycznie to zna.

anonimowy napisał(a):

To, że Ty masz swoją definicję mikroserwisów nie znaczy, że tacy giganci jak Amazon, Google, Microsoft się myli płacąc swoim ekspertom czasem więcej niż 10 krotność naszych wypłat. Tak jest i należy to przyjąć za definicję a nie walczyć z wiatrakami i przekonywać innych, że nikt nie korzysta z mikroserwisów bo robią to inaczej niż Ty

No akurat Netflix i Google ma mikroserwisy z prawdziwego zdarzenia: oddzielnie deployowalne, niezależne od siebie, autonomiczne, bardzo luźno powiązane, ze swoim bounded context, jest ich dużo i są małe. Takie mikroserwisy, to są prawdziwe mikroserwisy. Tylko niestety to co robi Netflix i Google, w porównaniu do tego co się robi w innych firmach to niebo a ziemia.

anonimowy napisał(a):

Nie zapędzaj się. Myślę, że większość wie co to TDD jak i MVC. To, że Ty masz swoją definicję mikroserwisów nie znaczy, że tacy giganci jak Amazon, Google, Microsoft się myli płacąc swoim ekspertom czasem więcej niż 10 krotność naszych wypłat. Tak jest i należy to przyjąć za definicję a nie walczyć z wiatrakami i przekonywać innych, że nikt nie korzysta z mikroserwisów bo robią to inaczej niż Ty

Nie odbierz mnie źle - mikroserwisy to jest bardzo dobry pomysł - ale pod warunkiem że tworzą go ludzie którzy wiedzą co robią. Nie wystarczy sobie wziąć aplikacji, przekroić ją na pół, dodać do nich komunikacje po REST żeby mieć mikroserwis ;| Dwie apki które gadają po REST to jeszcze nie mikroserwis.

edytowany 5x, ostatnio: Riddle
AN
  • Rejestracja:prawie 11 lat
  • Ostatnio:około godziny
  • Postów:973
0

Dlaczego oceniasz wszystko na podstawie słabych firm, w których pracowałeś? Ja nie spotkałem się jeszcze z kimś kto nie rozumie TDD.

Jeśli pracowałeś w Netflixie I Google w działach, w których mieli idealne mikroserwisy to spoko ale ja mówię o całej firmie a nie tylko udanych mikroserwisach


Zdalna praca dla Senior Python Developerów --> PW
DA
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 2 miesiące
  • Postów:176
2

@Riddle

Jest tam napisane, żeby - jeśli przetwarzasz informacje o cusomterach w dwóch mikroserwisach - to one powinny posługiwać się jednym id (nie ma tam wyjaśnione czemu, jest tylko napisane żeby tak robić). Domyślam się że ma to być "pragmatyczne", czyli ktoś uwidacznia szczegóły implementacyjne jednego mikroserwisu, żeby lepiej kontrolować co się dzieje - ale niestety tym samym łamie enkapsulację, tym samym sprawiając że te dwie aplikacje nie są niezależne od siebie, ergo nie są mikroserwisem.

O ile z większością się zgadzam, tego zupełnie nie rozumiem. W jaki sposób dzielenie się id jest łamaniem enkapsulacji? W jaki inny sposób chciałbyś to zaimplementować? Jak chciałbyś wiedzieć, o którego customera dokładnie chodzi? To tak jakbyś stwierdził, że mikroserwisy dzielące się np. PESELem pacjenta, czyli unikalnym i jednoznacznie reprezentującym dany obiekt łamią enkapsulację, bo wypuszczają swoje szczegóły implementacyjne.

Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:36 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10032
0
dargenn napisał(a):

O ile z większością się zgadzam, tego zupełnie nie rozumiem. W jaki sposób dzielenie się id jest łamaniem enkapsulacji?
W jaki inny sposób chciałbyś to zaimplementować? Jak chciałbyś wiedzieć, o którego customera dokładnie chodzi?

W taki sposób żebyś mógł dokonać dowolnej zmiany w jednym mikroserwisie, tak żeby drugi mikroserwis nie wymagał zmian. Klasyczna enkapsulacja.

To że ktoś z was nie rozumie jak to poprawnie zaimplementować, nie jest argumentem za tym że to nie jest łamanie enkapsulacji. Bo jest.

dargenn napisał(a):

To tak jakbyś stwierdził, że mikroserwisy dzielące się np. PESELem pacjenta, czyli unikalnym i jednoznacznie reprezentującym dany obiekt łamią enkapsulację, bo wypuszczają swoje szczegóły implementacyjne.

To zależy do czego używasz tego PESEL'a. Jeśli to jest wartość biznesowa, element funkcjonalności faktycznie wymagany przez użytkowników, to to jest dana - i musisz ją przekazać. Wtedy nie istnieje sposób żeby to pominąć, więc musisz przekazać wszędzie PESEL. Jeśli natomiast używasz tego PESEL'a jako identyfikator w Twojej implementacji, to wtedy to jest szczegół i jak on Ci "wycieknie" z Twojego interfejsu to łamiesz enkapsulacje.

Twoje pytanie jest trochę zbyt niskopoziomowe, to tak jakbyś spytał czy "zwrócenie jakiegoś timestampa jest łamaniem enkapsulacji?". Cała odpowiedź brzmi: to zależy jakiego timestampa, czy ten timestamp jest elementem Twojej implementacji czy faktycznie daną biznesową.

W sercu enkapsulacji leży umiejętność rozdzielenia rzeczy które są istotne od tych które nie są - to nie jest czarno-białe, musisz rozumieć sens aplikacji którą piszesz i wiedzieć dokładnie co ona robi i po co jest napisana. Innymi słowy musisz wiedzieć które dane są istotne, a które nie. idki bardzo często nie są - są szczegółem implementacyjnym.

Zadaj sobie pytanie, czy jakbym zmienił te id z liczb na stringi, na UUID albo cokolwiek innego, to czy aplikacja nadal by działała poprawnie? No pewnie że tak. Czy gdybym zmienił każdy id dodając teraz +1000 do każdego wszędzie, czy cokolwiek by się zepsuło? No pewnie nie. A więc to szczegół implementacyjny. Czy jeśli zmieniłbyś PESEL na inną liczbę albo dodał do jakiegoś pesela + 1000, czy aplikacja wtedy by działała poprawnie? No pewnie nie. A więc to nie jest szczegół implementacyjny.

anonimowy napisał(a):

Dlaczego oceniasz wszystko na podstawie słabych firm, w których pracowałeś?

To w większości nie były słabe firmy, ale niemniej niektóre antypatterny są bardzo zakorzenione w wielu miejscach.

anonimowy napisał(a):

Ja nie spotkałem się jeszcze z kimś kto nie rozumie TDD.

Bardzo ciężko mi w to uwierzyć. Tak bardzo, że zaczynam podejrzewać że Ty sam tego nie rozumiesz. Taka umiejętność zajmuje lata żeby ją nabyć. Większość ludzi myśli że TDD to po prostu posiadanie testów.

edytowany 6x, ostatnio: Riddle
AN
  • Rejestracja:prawie 11 lat
  • Ostatnio:około godziny
  • Postów:973
1

Czyli w skrócie, według Ciebie @Riddle mikroserwisy nie mogą się ze sobą komunikować w żaden sposób (bo jeśli wyłączymy jeden to drugi ma działać identycznie jak działał)?


Zdalna praca dla Senior Python Developerów --> PW
Riddle
@anonimowy: Tylko ja widzę, że ta odpowiedź to absurd? Oczywiście że muszą się komunikować, ale to nie znaczy że muszą mieć zależność na siebie. Dependency Inversion, ktoś coś?
KR
Dependency inversion to nadal zależność. Tyle że w drugą stronę :P
IK
  • Rejestracja:ponad 7 lat
  • Ostatnio:prawie 2 lata
3
anonimowy napisał(a):

Czyli w skrócie, według Ciebie @Riddle mikroserwisy nie mogą się ze sobą komunikować w żaden sposób (bo jeśli wyłączymy jeden to drugi ma działać identycznie jak działał)?

Nie no, chodzi o to, że działanie jednego mikroserwisu nie może zależeć od drugiego. Jak mikroserwis A uderza no. poprzez RPC do mikroserwisu B, to jeśli B leży, A nie może z tego powodu rzucić błędu. Np. Netfliksowi jak padnie serwis do spersonalizowanych rekomendacji filmów, mogą pokazać najczęściej oglądane lub najlepiej oceniane. Nie będzie to idealne, bo być może user woli komedie a najczęściej oglądane są horrory, ale będzie jakoś działać.

AN
  • Rejestracja:prawie 11 lat
  • Ostatnio:około godziny
  • Postów:973
0

No i jak to się ma do przekazywania ID? Netflix przekazuje filmy za pomocą ID właśnie więc nie jest to według @Riddle mikroserwis więc proszę o inny przykład "prawdziwego" mikroserwisu


Zdalna praca dla Senior Python Developerów --> PW
Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:36 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10032
0
anonimowy napisał(a):

No i jak to się ma do przekazywania ID? Netflix przekazuje filmy za pomocą ID właśnie więc nie jest to według @Riddle mikroserwis więc proszę o inny przykład "prawdziwego" mikroserwisu

Popełniasz dwa błędy:

  • Po pierwsze, to że Ty jako użytkownik widzisz id filmu, nie znaczy że mikroserwisy między sobą używają tego id
  • Po drugie, to że ID filmu jest przekazywane np z frontu do backendu, to nie znaczy jeszcze że ten id jest zależnością tego mikroserwisu

Widzę, że po prostu nie kumasz o co chodzi z enkapsulacją. Aplikacja może używać/przetwarzać jakąś daną, ale w taki sposób żeby od niej nie zależała.

EOT

Dobra, już mi się nie chcę tłumaczyć tego samego po piąty raz.

Do wszystkich którzy myślą że mikroserwisy mogą od siebie zależeć: tematy do powtórzenia: 1. enkapsulacja 2. dependency inversion 3. loose-coupling.

edytowany 3x, ostatnio: Riddle
AN
  • Rejestracja:prawie 11 lat
  • Ostatnio:około godziny
  • Postów:973
0

No to sam sobie zaprzeczasz. Nie da się dyskutować w takim wypadku. To, że aplikacja używa ID nie znaczy, że od niej zależy czy znaczy, że zależy? Bo wcześniej twierdziłeś, że zależy.

Przecież architektura Netflixa jest dostępna (jest wiele artykułów i filmów od pracowników) i używają właśnie m.in ID


Zdalna praca dla Senior Python Developerów --> PW
Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:36 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10032
0
anonimowy napisał(a):

To, że aplikacja używa ID nie znaczy, że od niej zależy czy znaczy, że zależy?

@anonimowy: Zapoznaj się z tematem "Dependency Inversion" i wtedy pogadamy.

Zobacz pozostałe 5 komentarzy
ZN
znowutosamo
Albo co zrobić jeśli masz repo które robi zróżnicowane zapytania (bo tabelki możesz łączyć ad hoc), a kolekcje z mongo, jak z resztą w nosql lepiej odgórnie przygotować do zapytań. Jedno czy dwa zapytania ugrasz, ale masz pewien limit i jest on stanowczo ograniczony względem sql.
ZN
znowutosamo
To są drobne niuanse, jest ich znacznie więcej i w takich przypadkach myślę, że ten DI trochę wali się i traci swój sens/cel. Dla mnie baza wówczas przestaje być szczegółem, ale to moje zdanie i chciałbym dowiedzieć się co sądzą na ten temat osoby, które widzą w tym podejściu same potencjalne korzyści.
Riddle
@znowutosamo: To nie są "same" potencjalne korzyści, to jest tez duży wysiłek i koszt, nie stosuję tego wszędzie gdzie się da. Ale jeśli chcesz mieć mikroserwis, to musisz mieć też DI.
Riddle
@znowutosamo: No dwóch baz na raz raczej nie zrobisz. Pewnie musiałbyć mieć albo 100% Postgres albo 100% mongo. DI nie jest wystarczające do tego żeby korzystać z dwóch baz danych - musiałbyś dodatkowo sam taką integrację obkodzić.
ZN
znowutosamo
Po co mi DI jeśli mam całą bazę wymienić w systemie? Wychodzę z założenia, że wstępnie mam 100% w postgresql, ale docelowo część danych chcę mieć mongo (np. 40%). Dane oddzielam od siebie w tym sensie, że to co jest postgresql nie będzie zależne od tego co będzie w mongodb.
AN
  • Rejestracja:prawie 11 lat
  • Ostatnio:około godziny
  • Postów:973
0

No to chyba Ty właśnie nie znasz skoro twierdzisz, że przekazanie ID łamie tę zasadę


Zdalna praca dla Senior Python Developerów --> PW
ZN
ZN
  • Rejestracja:około 2 lata
  • Ostatnio:prawie 2 lata
  • Postów:65
3

Aby podzielić program na moduły czy serwisy to patrz głównie na dane i na związki między nimi.

Jeśli moduł ma zbyt mało danych, aby zrealizować zadanie to jest bardziej zależy od innych modułów. Wtedy potrzeba więcej komunikacji, interfejsów, pośrednich typów, a najgorsze, że to wszystko jest specyficzne dla biznesu i będzie się zmieniać w czasie.

Zostawiam dwa ciągle aktualne cytaty w temacie:

Bad programmers worry about the code.
Good programmers worry about data structures and their relationships.
---- Linus Torvalds

Data dominates. If you’ve chosen the right data structures and organized things well,
the algorithms will almost always be self-evident.
Data structures, not algorithms, are central to programming.
---- Rob Pike

edytowany 1x, ostatnio: znowutosamo
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:około godziny
  • Postów:3277
2
Nofenak napisał(a):

W jaki sposób dzielić aplikację na moduły (modularny monolit) lub mikroserwisy w optymalny sposób?

Zależy jakie kryteria tej optymalności sobie przyjmiesz i w jakim celu rozbijasz całość na mikroserwisy. Żeby sensownie zrobić system na mikrousługach, musisz sporo zainwestować w devops, bo serio, nie chcesz tego ręcznie składać do kupy na VM'kach. To taka oderwana uwaga, ale widywałem próby robienia systemów na mikrousługach i brak umiejętności pracy z infrastrukturą szybko weryfikował te pomysły.
To czym możesz się kierować, to podobnie jak w przypadku modułów aplikacji poziom splątania z innymi. Im bardziej "zwarte" interface'y możesz wystawić, tym prawdopodobnie lepiej. Po ludzku - mniej metod w serwisie X, które są potrzebne serwisowi Y. Są też wymagania biznesowe/domena. Jeżeli masz system do fakturowania, to prawdopodobnie słownik klientów może być zarządzany przez inną usługę niż repozytorium faktur, bo można dość prosto zdefiniować API. Jeżeli system ma się komunikować z systemem księgowym, to prawdopodobnie warto również usługę za to odpowiedzialną zrobić osobno, bo znowu - masz jasne API tej usługi, a jeżeli firma podejmie decyzję o zmienie tego systemu, ty będziesz zmuszony dokonać zmian (albo napisać od zera) tylko jeden klocek systemu.

Takie 2 głównie problemy jakie widzę, to raz, żeby nie skończyć z rozproszonymi monolitem czyli sytuacją kiedy każdy moduł/mikroserwis ściśle zależy od całej reszty i muszą być wdrażane jednocześnie, a 2 żeby też nie zrobić za dużych modułów/mikroserwisów, które ciężko ogarnąć i rozwijać. Jak to wyważyć?

Są jakieś wskaźniki, których sposobu liczenia nie pamiętam :) Natomiast pytania jakie warto sobie zadać, to "za co odpowiada ta usługa", "co się stanie jeżeli usługa ulegnie awarii", "co może wymusić konieczność zmiany tej usługi"

W ogóle czy jeden moduł/mikroserwis powinien ciągnąć dane z drugiego?

Zwykle trochę musi. Pytanie jak często i co się stanie jak nie będzie mógł tego zrobić. Jeżeli masz ten przykład wyżej, to usługa fakturowania, będzie musiała pobrać dane kontrahenta z innej usługi podczas tworzenia nowej faktury. Ale jeżeli faktura zostanie zapisana jako kompletny dokument, to nie będzie takiej potrzeby podczas odczytu faktury. Nie będzie również takiej potrzeby, jeżeli wyślesz całą fakturę do klocka odpowiedzialnego za eksport danych do księgowości, to on również nie będzie potrzebował odpytywać usługi "klienci" o dane. Zdecydowanie warto się pozbyć myślenia o mikroserwisach jako CRUDach odpowiedzialnych za konkretne typy obiektów.

Czy komunikacja synchroniczna nie powinna być opcjonalna i komponenty nie powinny się komunikować tylko eventami czy czymś podobnym?

Zależy. Nie da się zwykle zrobić wszystkiego asynchronicznie (albo jest to bardzo kosztowne). Jeżeli masz OPA, to bardzo ciężko będzie w sposób nieuciążliwy dla użytkownika zamienić całą komunikację na asynchroniczną. Natomiast, wciąż bardzo dobrym pomysłem jest np. przyjęcie intencji wystawienia faktury, zwrócenie informacji, że "faktura zostanie wystawiona i wysłana", a cała reszta procesu może się odbywać asynchronicznie. Natomiast domyślnie komunikacja asynchroniczna ma przewagę i powinna być punktem wyjścia.

KR
Moderator
  • Rejestracja:prawie 21 lat
  • Ostatnio:2 miesiące
  • Postów:2964
5
anonimowy napisał(a):

Czyli w skrócie, według Ciebie @Riddle mikroserwisy nie mogą się ze sobą komunikować w żaden sposób (bo jeśli wyłączymy jeden to drugi ma działać identycznie jak działał)?

Myślę, że patrzycie na to w zbyt czarno-biały sposób. Zależność zależności nierówna. Jeżeli zachodzi jakakolwiek komunikacja to oczywiście zależność istnieje. Bo gdyby nie było zależności to faktycznie oznaczałoby to że serwis A musiałby działać identycznie niezależnie od działania / niedziałania serwisu B a zatem B byłby w ogóle niepotrzebny.

W mikroserwisach (i w ogóle wszelkich modułach) chodzi o to aby ta zależność dotyczyła możliwie małego obszaru modułu - czyli ma być możliwie proste API ale duża swoboda w kształtowaniu implementacji. Ważne jest aby API projektować świadomie a nie na zasadzie że wystawiamy wszystko co mamy i moduły grzebią sobie nawzajem w bebechach. Jeżeli świadomie uczynimy z id użytkownika część API to jest to ok. Oczywiście jest to jakaś zależność ale jednak słabsza zależność niż zależność od np. całej struktury opisującej użytkownika. Bo serwis/moduł zarządzający użytkownikami nadal ma swobodę w tym jak np. przechowuje profile i co w nich trzyma i wystawienie id w niczym nie przeszkadza. Wtedy jednak dobrze udokumentować zachowania związane z id - np. czy identyfikatory mogą być powtórnie używane, jaki jest ich zakres itp.

Teraz kwestia czy używać mikroserwisów czy nie, to trochę inny problem. Dość sceptycznie podchodzę do kwestii skalowania - monolityczna aplikacja może się dobrze skalować tak samo jak mikroserwis - serio nieużywanego kodu po prostu można nie ładować do pamięci, a naprawdę kilka, kilkadziesiąt MB więcej kodu na dysku to obecnie nie jest problem. Bardziej patrzyłbym przez pryzmat wygody konfiguracji, zwłaszcza jeśli mamy pewne elementy bezstanowe. Elementy bezstanowe będzie skalować łatwiej, więc może warto je oddzielić od tych stanowych.

Mikroserwisy warto rozważać jeśli:

  • moduły są tak mocno niezależne że chcemy je rozwijać różnymi zespołami, o różnych kompetencjach, i zespoły te mogą pracować przez większość czasu samodzielnie, tj. nie muszą robić codziennie 2h spotkania aby się dogadać
  • moduły chcemy napisać w różnych technologiach lub przynajmniej zostawić sobie taką furtkę na przyszłość
  • moduły nie korzystają ze wspólnych danych, a do tego dane własne modułów powinny być modelowane w inny sposób - np. nie ma sensu używać RDBMSa do przechowywania plików, albo NoSQL tam gdzie potrzebujemy ACID
  • moduły będą uruchamiane w różnych miejscach - np. chcemy je rozdzielić geograficznie ze względu na opóźnienia - klasyczny przykład: wszelkie rodzaje cache, które muszą być blisko użytkownika
  • moduły będą aktualizowane niezależnie od siebie, mają różnej długości cykl wydawniczy
  • moduły mają inne wymagania dotyczące bezpieczeństwa - np. chcemy zminimalizować obszar systemu który ma dostęp do wrażliwych danych - np. raczej nie chcemy aby moduł odpowiedzialny za reklamy miał możliwość grzebania w profilach użytkowników... choć może jak jesteśmy Googlen albo FB to właśnie chcemy xD
  • moduły mają mocno różne wymagania wydajnościowe - dobrym przykładem jest streaming, gdzie obszar aplikacji odpowiedzialny za składowanie i dostarczanie filmów ma drastycznie inne zapotrzebowanie na przestrzeń dyskową oraz użycie sieci niż obszar aplikacji zarządzający profilami

Bardziej myślałbym o mikroserwisach jak o częściach w samochodzie. Każda część może być dostarczona przez innego dostawcę, części mają często proste interfejsy a skomplikowaną logikę w środku, mogą być z różnych materiałów, implementacja może być mocno zmieniana tak długo jak spełnione są wymogi zewnętrzne. Jednak te części ze sobą współpracują i nie musi być wcale tak że jak jedna część przestaje działać to całość będzie działać poprawnie.

edytowany 5x, ostatnio: Krolik
Zobacz pozostały 1 komentarz
Riddle
@anonimowy: Akurat to co opisał @Krolik bardzo mocno wygląda jak mikroserwis. Jeśli są rozwijane przez różne zespoły w różnych technologiach, to spełniają kryteria mikroseriwsów. Także do tego co pisze @Krolik daje +1.
Riddle
Widać, że to o czym pisze @Krolik to jest zastosowanie faktycznego mikroserwisu do jakiegoś celu; a nie "chęć posiadania czegoś modnego" a więc wrzucimy coś co nie jest mikroserwisem do projektu.
AN
@Riddle: tylko zaprzecza Twoim zasadom
Riddle
@anonimowy: Nie zaprzecza, to co @Krolik opisał to jest mniej więcej to samo co ja opisywałem. @anonimowy Widzę że masz ogromny problem z tym żeby rózróżnić od siebie słowa "interakcja" i "zależność". Coś (np. mikroserwis, klasa, funkcja, plik, program) może wejść w interakcję z czymś tak żeby na tym zależeć; albo może wejść w interakcję z nim tak żeby na nim nie zależeć. Mikroserwis to z definicji serwis który wchodzi z interakcję z innymi tak żeby na nich nie zależeć.
AN
No to po co pisałeś wcześniej, że jak ktoś używa ID to już nie jest mikroserwisem XD
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)