Over engineering lvl ultimate.

Over engineering lvl ultimate.
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:minuta
  • Postów:3277
11

Tak trochę się żalę, trochę śmieję przez łzy. Trafiłem do nowego projektu, bo jak zwykle coś tam trzeba na kiedyś tam zrobić, bo klient chce, czeka i coś tam a projekt niby w Java. Aplikacja to typowy CRUD. Ile może trwać zadanie typu "obsłuż request, weź dane z bazy, zapakuj w zwrotkę i odeślij"? Zwykle chwila moment. Ale tutaj wchodzi do gry wybitna wręcz architektura tego cuda, na widok której barokowi mistrzowie architektury chlipaliby jak przedszkolaki w kątach zaprojektowanych przez siebie katedr.
Wygląda to tak:

  • Jest warstwa w Javie. Nie robi prawie nic, poza tym, że istnieje, sprawdza jakieś tam uprawnienia i podobne pierdoły i oczywiście wystawia endpointy.
  • Przyjętego requesta jakoś tam lekko modyfikuje i wywołuje synchronicznie serwis w Pythonie (P1)
  • P1 pakuje to co dostał w wiadomość i umieszcza w kolejce
  • Wiadomość z kolejki odbiera kolejny serwis z logiką biznesową, wywołuje sobie metodę wskazaną wprost w wiadomości
  • Pakuje to co dostanie z monolitycznej bazy danych w kolejną wiadomość i wrzuca na kolejkę.
  • Z kolejki wiadomość czekający na nią z utęsknieniem P1, szuka wiszącego requesta i likwiduje asynchroniczność
  • Java dostaje response z P1 i nic z nim nie robiąc odsyła do klienta.

Żeby było śmieszniej, to Java (która nie robi nie...) jest napisana w technologii ogłoszonej 15 lat temu jako retired. Z jakiegoś nieznanego mi powodu baza danych jest "własnym silnikiem". No i żeby pozwolić na customizację tego cuda, na jakimś etapie stworzenia dołączono do tego jeszcze DSL'a do customizacji.

Miang
résumé driven development
RequiredNickname
Ubezpieczalnia w stolicy??
piotrpo
@RequiredNickname: Nie, chyba w każdej firmie z historią są takie historie.
Miang
np. w jednym z naszych ministerstw, co śmieszniejsze wersja 1.0 działała, takie pomysły sie pojawiły w wersji ulepszonej
Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:minuta
  • Lokalizacja:Laska, z Polski
  • Postów:10031
2

Niech zgadnę. Ludzie pracujący w tym projekcie uważają że "jest dobrze" i "nie ma co zmieniać"? 😄

piotrpo
Jak byś tam był.
LukeJL
  • Rejestracja:około 11 lat
  • Ostatnio:2 minuty
  • Postów:8397
7

To nie wygląda mi jako świadomy overengineering, tylko bardziej jak nieukończona budowla. Były ambitne plany zbudowania np. wiaduktu, a postawione zostały tylko słupy. Ew. też dużo entropii i właśnie brak planu niż jakaś świadoma inżynieria. Może kilka programistów robiło i jeden znał Javę, drugi Pythona, a trzeci trochę tego, trochę tamtego i razem próbowali zrobić coś ambitnego, ale nie dogadali się i coś nie pykło.

Oczywiście gdybam, ale nie zdziwiłbym się, gdyby opisany w twoim poście flow był robiony bez żadnego planu, przez kilku ludzi w różnym czasie, którzy próbowali dodać swoją cząstkę do istniejącego burdelu. Ktoś zrobił serwis w Pythonie, bo nie znał Javy. Inny znał kolejki, to zrobił na kolejkach. Trzeci trafił do pracy przez przypadek, więc próbował nieudolnie to połączyć itp.


edytowany 3x, ostatnio: LukeJL
lambdadziara
no tak, ale po co robic wlasna baze dla wymagania typu obsluzenie requestu? Chyba ze wymagania byly z poczatku znacznie bardziej ambitne a z czasem okrojone do obsluzenia requesta? Moze taka architektura to konsekwencja nieudolnego waterfalla?
SL
  • Rejestracja:około 7 lat
  • Ostatnio:około 9 godzin
  • Postów:857
6

Ja byłem w projekcie, gdzie rozwiązaniem problemu jeden z serwisów nie wyrabia (faktycznie dużo processingu związanego z parsowaniem dużych i częstych eventów z zewnątrz) było dodanie kolejnego serwisu, który podmienia zwykłą synchroniczne wywołanie na message/czekanie na message przez MOM (czyli funkcjonalnie to samo). Nie wiem w jaki sposób miało to rozwiązać rzeczywisty problem, ale takie rzeczy się dzieją jak ktoś oderwany od ziemi wymyśla architekturę

DM
  • Rejestracja:ponad 4 lata
  • Ostatnio:około 6 godzin
  • Postów:220
2

Z ciekawosci - jaka to kolejka i jak mapuje oczekujace requesty w P1 z partycjami (albo czyms innym w zalenosci od uzytej kolejki) z wiadmoscia z serwisu z logika biznesowa?

edytowany 3x, ostatnio: dmw
piotrpo
ActiveMQ. Do "jak" jeszcze nie dotarłem.
KE
  • Rejestracja:około 6 lat
  • Ostatnio:około 13 godzin
  • Postów:658
5

Jest warstwa w Javie. Nie robi prawie nic, poza tym, że istnieje, sprawdza jakieś tam uprawnienia i podobne pierdoły i oczywiście wystawia endpointy.

Wygląda jak napoczęty i nigdy niedokończony strangler pattern. Jak stary jest kod Javy?

edytowany 1x, ostatnio: kelog
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:minuta
  • Postów:3277
6

@LukeJL @kelog Tak, to wygląda na strangle pattern, tylko w wykonaniu anemicznego dusiciela. Owinąć ofiarę mu się udało, ale żeby coś udusić to już nie bardzo. Oczywiście, to że wygląda, nie oznacza, że faktycznie taki był zamysł. Mogło tak być, a być może jedynie próbujemy nadać temu sens i cel, których tam nigdy nie było.
Kawałek w Java jest aktywnie utrzymywany, czyli ktoś, kiedyś z jakiegoś nieznanego mi powodu podbił to całkiem świeżej wersji Java, Nie wiem po co i dlaczego przy okazji nie zrobiono tego nieco głębiej, bo to wciąż średniowieczne protokoły komunikacyjne na starożytnych fundamentach. Całość do zaorania i odtworzenia w tydzień.

Z drugiej strony, jak łatwo się domyślić, to nie jest oprogramowanie tworzone pod chmurę, multitenancy SaaS itd. Tylko instalowane na bare metal, no może VM. Tutaj też jest jakieś pudrowanie trupa i widać próby pakowania tego wszystkiego w kontenery. No i skoro to lata u iluś tam klientów, czyli realnie nie wiadomo kto gdzie i w jaki sposób z tego korzysta, jakie haki są zastosowane do integracji z resztą lokalnego otoczenia systemu, to zrobienie jakiejś grubszej zmiany jest ultra ryzykowne. Opis z pierwszego posta dotyczy jakiegoś tam wycinka systemu, którego reszta jest duża, zintegrowana na poziomie monolitycznej bazy danych.

marian pazdzioch
  • Rejestracja:ponad 6 lat
  • Ostatnio:2 dni
  • Postów:707
1

Czy działa? Przynosi dochody? I jakie jest w sumie Twoje zadanie?

edytowany 1x, ostatnio: marian pazdzioch
Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:minuta
  • Lokalizacja:Laska, z Polski
  • Postów:10031
0
marian pazdzioch napisał(a):

Czy działa? Przynosi dochody? I jakie jest w sumie Twoje zadanie?

Czy wprowadzenie koniecznych zmian jest drogie? Czy dodawanie małego feature zajmuje dni zamiast minut/godzin? Czy błędy są kosztowne i trudne do naprawienia?

marian pazdzioch
Czy kogoś to obchodzi? Jeśli zysk jest odpowiednio duży, to raczej nie.
RequiredNickname
Firmy lubią w optymalizację więc to nie kwestia czy obchodzi tylko pewnie nie wiedzą
Miang
yten kto to zrobił pewnie myślał ze dla niego wprowadzenie zmian bedzie łatwe a dla każdego innego będzie niemożliwe, wiec go nie wywalą
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:minuta
  • Postów:3277
2
marian pazdzioch napisał(a):

Czy działa? Przynosi dochody? I jakie jest w sumie Twoje zadanie?

Działa (pojęcie względne), przynosi dochody, bo to nie jest tania rzecz, konkurencja nikła, a "gdzieś tam" za tymi wszystkimi warstwami, które opisuję jest kawałek dość unikalnej algorytmiki. Oczywiście mogłoby działać lepiej, w znaczeniu być szybsze, tańsze we wdrożeniu, wygodniejsze dla użytkowników końcowych, tańsze w rozwoju.
Moje zadanie - w sumie to ciężko powiedzieć. Niby mam tam dorobić parę prostych ficzerów (crud) i "przenieść to do chmury", co jest już zadaniem dość karkołomnym. Tak czy inaczej - zrobię swoje, pchać palców między drzwi nie zamierzam
Podejrzewam, że główny strumień przychodów to w tej chwili utrzymanie tego ulepa, bo architektura + liczba instancji powodują, że to zwyczajnie musi się walić jak króliki na wiosnę.
W mojej ocenie, w tej formie oprogramowanie jest prawie niesprzedawalne. Nie mam na myśli tego jak ono jest skonstruowane, tylko co jakie koszty obsługi generuje po stronie klienta.

Ja mam dużo wyrozumiałości dla technicznych niedostatków, wiem, że software ma dostarczać wartość użytkownikowi, a nie być pięknie napisany. Ale z drugiej strony, po co pisać coś źle, jeżeli można napisać dobrze? Po co zarabiać mało, skoro można dużo?

marian pazdzioch
Po co pisać źle? Znam wiele powodów, jednym z nich jest "trzeba pracować tak żeby praca była". Oraz - cruda wygeneruje każdy llm, przenieść do chmury ulepa llm nie potrafi więc, należy się jednak cieszyć że mamy w szufladach nie skończony materiał do pracy.
loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 18 godzin
  • Postów:1574
0

Życie rzadko wynajduje rewolucyjne rozwiązania albo zmienia wszystko od podstaw. W większości wypadków adaptuje to co jest - jak np. nerw błędny albo bierze coś co już działa (-> mitochondrium, chloroplasty). Póki co jeszcze nikt nie przebił tego w długowieczności.

Więc o co ci chodzi? Że rzeczywistość działa inaczej niż w szkole uczą? To powinno się już uświadomiać w wieku nastu lat.


Przetrzyma wszystko
Miang
Tobie chyba teksty pisze jakiś LLM ;)
superdurszlak
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 13 godzin
  • Lokalizacja:Kraków
  • Postów:1999
2

Znam tego typu projekty. Autorzy najczęściej są przekonani o słuszności raz obranego podejścia i będą je powielać - IMO tutaj nie ma co ratować.

Jak spróbujesz to poprawiać - nie wiem, namawiać zespół by to uprościć, usunąć zbędne elementy - to w najlepszym razie pojawi się 100 niekoniecznie merytorycznych argumentów, dlaczego tak musi być, a w najgorszym Cię spałują, zbutują i przerobią na wycieraczkę.

Jedyna szansa, to że znajdzie się więcej ludzi, którym to nie pasuje, i będziecie mieć dość siły przebicia by na to wpłynąć.


piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:minuta
  • Postów:3277
3

@superdurszlak Niestety jestem już dostatecznie stary, żeby nie odczuwać potrzeby zmieniania niezmienialnego. W dodatku jestem w tym projekcie od machania łopatą, a nie martwienia się o jego stan, mam robić swoje, wiem do kiedy, szkoda mi czasu i nerwów na puste dyskusje nie prowadzące do niczego. Gdybym miał większą odpowiedzialność i zakres decyzyjny, to bym szukał sposobu na poprawienie tego projektu, ale że nie mam i nawet nie specjalnie się do tego rwę, a nawet nie wiem jakie były powody takich decyzji...

Miang
jakiś dyrektorek tam pewnie się zaszył
Mbappe_koksik
  • Rejestracja:2 miesiące
  • Ostatnio:42 minuty
  • Postów:63
4
Kopiuj
+--------------------+       +------------------+       +-------------------+
|   Klient (API)    | ----> |  Java (Gateway)  | ----> | Python Service P1 |
+--------------------+       +------------------+       +-------------------+
                                      |                           |
                                      |                           v
                                      |                 +-------------------+
                                      |                 |  Kolejka (MQ)     |
                                      |                 +-------------------+
                                      |                           |
                                      |                           v
                                      |                 +-------------------+
                                      |                 |  Python Service   |
                                      |                 | (Logika Biznesowa)|
                                      |                 +-------------------+
                                      |                           |
                                      |                           v
                                      |                 +-------------------+
                                      |                 |  Baza Danych       |
                                      |                 | (Custom Engine)    |
                                      |                 +-------------------+
                                      |                           |
                                      |                           v
                                      |                 +-------------------+
                                      |                 |  Kolejka (MQ)     |
                                      |                 +-------------------+
                                      |                           |
                                      |                           v
                                      |                 +-------------------+
                                      |                 |  Python Service P1 |
                                      |                 +-------------------+
                                      |                           |
                                      v                           v
                               +------------------+       +--------------------+
                               |  Java (Gateway)  | <---- |   Klient (API)    |
                               +------------------+       +--------------------+



@piotrpo dobrze to zrozumiałem czy inaczej, popraw mnie jak coś

tefu
Czyli cała prawa strona w sumie jest po nic.
ZI
Dobry diagram lepszy niz milion slow <3
YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:2 minuty
  • Postów:2363
3

W projektach transformacyjnych często dorzuca się pośrednie architektury, które mają ułatwić tranzycję do architektury docelowej. Interesująca byłaby historia, która doprowadziła do takiej sytuacji i jaki problem rozwiązywała. Który komponent jest najstarszy? Który najmłodszy?

piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:minuta
  • Postów:3277
0

@Mbappe_koksik Dobrze zrozumiałeś. Jakieś tam uwagi do diagramu można mieć, ale z grubsza to tak wygląda.
@yarel Jakieś powody pewnie były. Czy są jeszcze jakcyś weterani, którzy wiedzą jakie one były - wiątpię.

marian pazdzioch
Ale to nawet lepiej. Masz albo dużo pola do poprawiania (dużo pracy, pieniądze sypią się jak wióry) albo podkładkę do ciągłego narzekania "łohoho tak wolno pracuję bo ten system to kupa". Tak czy siak, twoje na wierzchu.
piotrpo
Na razie robię jakąś tam prostą funkcjonalność, trochę wiem co piszę, trochę nie wiem. Nie narzekam, jak zacznę trochę bardziej ogarniać jak to chodzi, to pewnie wezmę się za proste poprawki.
AS
  • Rejestracja:prawie 4 lata
  • Ostatnio:około 15 godzin
  • Postów:344
1

Custom DB engine?! To musiała być ciekawa historia, jak ktoś na to pozwolił 15 lat temu. OracleDB było za drogie? Postgres nie był cool?

edytowany 1x, ostatnio: ArchitektSpaghetti
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:minuta
  • Postów:3277
2
ArchitektSpaghetti napisał(a):

Custom DB engine?! To musiała być ciekawa historia, jak ktoś na to pozwolił 15 lat temu. OracleDB było za drogie? Postgres nie był cool?

Ja tam nie jestem ciekawy takich historii. To trochę tak, jak kiedy widzisz parę bardzo grubych ludzi, którzy mają małe dziecko i z tyłu głowy pojawia się myśl, że to raczej nie było in-vitro.

FR
  • Rejestracja:około 11 lat
  • Ostatnio:10 minut
  • Postów:921
0

Co Was dziwi custom db engine?
W firmach, ktore mają stare systemy i najczęściej też firmach produktowych logika na procedurach to klasyk, z którym nawet da się żyć bo masz jawnie informacje co się dzieje. Gorzej jak są jakieś inne cuda typu triggery poustawiane. Albo coś się gdzieś indziej samo wykonuje a nie z backendu.

Wręcz jestem zdania, że im gorzej napisane procedury (od góry do dołu) są lepsze niż te które ktoś próbował pisać w stylu clean code'a, bo łatwiej się to przepisuje i większa szansa, że nie wywalisz czegoś w kosmos.

edytowany 1x, ostatnio: froziu
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:minuta
  • Postów:3277
0

@froziu Tu nie chodzi o jakiegoś PSQL, który coś robi w Oracle, tylko napisanie własnego Oracle.

FR
<ohui_meme />
jarekr000000
Używałem baz oracle kilkanaście lat - uważam, że napisanie własnego db engine jest przeważnie mniejszym złem.
superdurszlak
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 13 godzin
  • Lokalizacja:Kraków
  • Postów:1999
0
froziu napisał(a):

Wręcz jestem zdania, że im gorzej napisane procedury (od góry do dołu) są lepsze niż te które ktoś próbował pisać w stylu clean code'a, bo łatwiej się to przepisuje i większa szansa, że nie wywalisz czegoś w kosmos.

No tak, kiedyś znaleźliśmy 3 procedury robiące dokładnie to samo, ale każda trochę inaczej. W efekcie mieliśmy niezły cyrk w BD, a ustalanie co jest grane w systemie pełnym magicznych numerków zamiast informacji, a ludzie którzy znali system w większości zostali zwolnieni - to jest dopiero jazda.


marian pazdzioch
Pewnie byli z tych co myśleli że jak naklepią g**no kodu to nich ich nie zwolni a tu cyk.
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)