Jako początkujący programista mam wybór architektury do nowego projektu.

Jako początkujący programista mam wybór architektury do nowego projektu.
DKN
  • Rejestracja:ponad 4 lata
  • Ostatnio:7 miesięcy
  • Postów:128
1

Mam pewien problem.
Opisze lakonicznie swoją sytuacje projektowa.

Wiecie jak to jest w firmach. Ludzie odchodzą, projekty zostają.
Jestem na poziomie junior/mid (w pracy dostałem mida, chociaż te przedrostki tez często nic nie znaczą)
Dowiedziałem się, ze będę głównym odpowiedzialnym za nowy projekt, wraz z jego architektura. Apka restowa.

U nas zawsze robiło się dość słaba architekturę, czasem miałem nawet wrażenie, ze jej nie ma, w starszych projektach klasy po kilkaset linii, brak testow i inne rzeczy dające się często usłyszeć na prelekcjach o złym kodzie.

Ostatnio ze starszym kolega staraliśmy się to wszystko zmieniać, wdrażając jakieś dobre praktyki, czysty kod, małe funkcje, dobre nazewnictwo i testy, a nie pisząc coś by tylko działało.

Po jego odejściu jestem ja i dwójka młodych świeżo po studiach. Nie mam żadnego doświadczenia w kwestiach wyboru architektury.

Chciałbym przygotować ta aplikacje na dalszy jej rozwój, tak by nie tylko urodzić dziecko a jeszcze żeby urosło fajnie, czy jakoś tak.

Aplikacja komunikacja się z bazą lub bazami, wystawiająca restpointy na zewnątrz. Nic nadzwyczajnego, miliony takich powstało.

Chce uciec od anemicznego podejścia, ale również chce zrobic to po to by nie wpaść w błoto i nie wybrać czegoś co mnie zje. Czytałem i słuchałem o podejściu cqrs, wiem ze jest jego wiele wariantów.
Za chwile będę robił POCa z jakimś wariantem cqrs.

Moje pytania to:

  1. Jak bardzo cqrswa apka może być na pierwszy raz. Tzn, od którego momentu zacząć podział. Chciałbym by została jedna baza, ale również chciałbym cos więcej niż tylko podział restow.

  2. Na czym się skupić najbardziej, czy sa jakieś mocno newralgiczne miejsca w tej architekturze?

  3. Czy ma ktos albo wie gdzie szukać jakiś większy fajny projekt z Javy oparty o cqrs?


Z każdym dniem czuje się głupszym programista.
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
5

Ja bym zaczął od tego żeby zrobić dobrą separacje warstw, w przypadku javy np. podzielić aplikacje od razu na odseparowane moduły (np. maven modules). Taki najbardziej podstawowy podział to odcięcie API od logiki domenowej i np. repozytoriów danych. Komunikacja między tymi klockami za pomocą interfejsów tak, że np. zmiana repozytorium z SQLa na cokolwiek innego nie powoduje żadnej zmiany w innych miejscach, bo np. domena polega tylko na jakimś XYZRepository i nie ma znaczenia jak to jest zaimplementowane pod spodem.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
Zobacz pozostałe 4 komentarze
Shalom
Żeby było jasne: nie mówie tu o idiotycznej sytuacji gdzie ktoś ma wszystko w jednym worku i obok siebie leży interfejs i jedyna klasa która go implementuje :D Jasne że takie coś nie ma absolutnie żadnego sensu. Zobacz na https://github.com/Pharisaeus/almost-s3 akurat cel tego repo jest inny, ale ma też taką separacje (zobacz że np. domain nie ma zależności do repository, podobnie repository w zasadzie nie zależy od niczego oprócz samych interfejsów)
SK
Thx;) Czasami spotykam się z kodem gdzie każda klasa implementuje jakiś interfejs i w zasadzie cała aplikacja tak wygląda. Jeżeli dobrze rozumiem to bardzo dobrą praktyką jest wydzielenie sobie interfejsów dla danego modułu tak jak np domain, repo, cokolwiek i inny moduł korzysta właśnie z interfejsu a nie konkretnej implementacji. Mogę w każdej chwili wyrzucić cały kod z modułu repo ale z punktu widzenia modułów które z niego korzystają nie ma to znaczenia póki repo interfejs nie został zmieniony. Nowe klasy z repo go implementują więc kontrakt został zachowany.
SK
A jeżeli chodzi już o wewnętrzną implementację danego modułu, czy można sobie wtedy podarować robienie interfejsów jeżeli z góry widzę ze tak naprawdę istnieje tylko jedna klasa która by go implementowała i jest wykorzystywana tylko wewnątrz tego modułu? Chciałbym tu rozróżnić jakiś mały moduł od jakiegoś większego gdzie użycie interfejsu faktycznie może mieć sens jak stosuje jakiś Design Pattern jak strategia czy coś. Pozdrawiam.
Shalom
W takiej sytuacji interfejs zawsze można sobie później wyciągnąć jak będzie ci potrzebny ;) W sytuacji o której pisałem ma to zupełnie inne znaczenie, bo pozwala na całkowity brak zalezności między modułami. Jeśli taką zależność masz (np. domain wie o repository) to bardzo szybko robią się mocno związane (bo gdzieśtam użyjesz klasy z drugiego modułu) i potem juz wszystko jest zabetonowane.
PK
PK
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 3 lata
  • Postów:245
14

Odnośnie CQRS, zwróć uwagę na sekcje kiedy stosować: https://martinfowler.com/bliki/CQRS.html

Jeśli nie masz z tym doświadczenia ani nikogo kto w ten sposób realizuje projekty to nie rób tego. Zrobisz w ten sposób z projektu eksperyment, który podnosi ryzyko oraz koszty utrzymania. Ty sobie odejdziesz z firmy jak coś, a inni będą musieli się z tym użerać.

Pomyśl o sobie jakbyś to Ty zlecał tego typu projekt zewnętrznej ekipie. Czy chciałbyś w prostym kodzie oglądać ddd, wzorce/techniki o jakich mówi się na konferencjach? One są sexy przy złożonych problemach, ale przy banałach to przez te techniki jedynie wpompujesz złożoność do prostego projektu, tak podkręca się koszty i to jest słabe.

Jeśli projekt jest trywialny to w komercyjnym projekcie dbałym wyłącznie o:

  • poznaj wymagania, spróbuj je zrozumieć, uprościć przed pisaniem kodu
  • pokrycie testami rzeczy do których nie masz pewności (jak zaczniesz pisać testy poczujesz na własnej skórze co należy w kodzie zmienić)
  • utrzymanie względnego porządku, aby nie łamać dobrych zasad bez potrzeby (np. mutowanie argumentów)
  • dokumentowanie zmian w git (drobne komity, dobrze opisane)
  • utrzymywanie spójnej dokumentacji (tak aby nowa osoba mogła szybciej się wdrożyć)
  • ostrożne dokładanie zależności (mniej znaczy więcej)

i jeśli starczy Ci mocy to:

  • przywiąż większą uwagę do obsługi transakcji, bo często są źle obsługiwane
  • doprecyzuj opisy w jira tak, by Ci dwaj juniorzy lepiej się orientowali w kodzie

Chciałbym przygotować ta aplikacje na dalszy jej rozwój, tak by nie tylko urodzić dziecko a jeszcze żeby urosło fajnie, czy jakoś tak.

Zobacz jak zaczniesz dokladać techniki to juniorom skomplikujesz pracę, jeśli i oni będą małpować to co robisz to w niecały rok stworzycie potwora, ktory wszyscy kolejni programiści będą wyklinać. Także jeśli nie ma żadnego konkretnego problemu do rozwiązania, który by jednoznacznie wskazywał, że cqrs jest wyjściem to nie rób tego, zwłaszcza jesli nie znasz negatywnych skutków. Nie ma technik bez wad.

Zwykle jeżeli jesteś najmądrzejszą osobą w pokoju to znaczy, że jesteś w złym pomieszczeniu. Także jeśli chciałbyś podejmować się ciekawszych projektów np. z cqrs to powinieneś pracy szukać w ciekawszych firmach.

edytowany 3x, ostatnio: pan_krewetek
LM
Zalogowałem się tylko po to, żeby polubić ten komentarz :) Bardzo trafny.
PK
pan_krewetek
Dzięki :-)
AK
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 2 godziny
  • Postów:3561
2

@pan_krewetek:

Uprzedziłeś mnie, przy czym napisałeś super, o wiele lepiej niż bym marzył.

Chciałem napisać, żeby nie kierować się modą, np nie żenić mikoserwisów "bo się o tym mówi" a nie ma ku temu uzasadnienia.


Bo C to najlepszy język, każdy uczeń ci to powie
PK
pan_krewetek
Dzięki ;-)
DKN
  • Rejestracja:ponad 4 lata
  • Ostatnio:7 miesięcy
  • Postów:128
0

Dzięki za odpowiedź.

@pan_krewetek:

Zwykle jeżeli jesteś najmądrzejszą osobą w pokoju to znaczy, że jesteś w złym pomieszczeniu. Także jeśli chciałbyś podejmować się ciekawszych projektów np. z cqrs to powinieneś pracy szukać w ciekawszych firmach.

Zgadzam się.** Chyba, że** pokój ten umożliwia tobie zyskanie doświadczenia, którego nie zyskałbyś w firmie, gdzie byłoby więcej mądrzejszych. Nie chce się zasiedzieć, ale doświadczyć jak najwięcej się da a pozniej wyjść.

Ogólnie poruszyłeś sedno problemu. Tzn. szukam balansu między bardziej zaawansowanym podejściem do tworzenia apki a biznesem. CQRS jakby nie patrzeć polega na oddzieleniu query od command, pytanie w którym miejscu ten tort można pokroić bezpiecznie.
Czuje, że nie ma uniwersalnej odpowiedzi, wręcz przeciwnie, łatwo przejść w zależyzm.
Zakładam, że aplikacja musi być skalowana, ale projekt również nie bedzie bardzo bardzo złożony, więc chyba zdecyduje się na upośledzony cqrs.

Napisałeś:

utrzymywanie spójnej dokumentacji (tak aby nowa osoba mogła szybciej się wdrożyć)

Dobrze by kod testowy był wystarczający, ale nie myśląc życzeniowo. Wprowadziłem:

Diagram komponentowy obejmuje całą architekturę Czyli co z jakiej bazy gdzie i po co.
Każdy nowy fjuczer jest dopisywany do diagramu funkcjonalnośći wymagań, które są odseparowane na domeny biznesowe, jakoś je lubie, szczególnie gdy mam nową apkę i widze w niej blackboxa, to diagram funkcj wymagan, pozwala bardzo szybko dowiedzieć sie co ona robi.
Do corowych funkcji dopisze diagram sekwencji (sick, nienawidzę go robić).

utrzymanie względnego porządku, aby nie łamać dobrych zasad bez potrzeby (np. mutowanie argumentów)

Chodziło ci o to, że przekazywana referencja ma być wzorem z którego możemy jedynie czerpać, a nie możemy jej zmieniać, ponieważ istnieje prawdopodobieństwo, że jest wykorzystywana przez inne rzeczy?

Dodatkowo zastanawiałem się żeby wrzucić jakiś system metryk, by inrzynierysjko w liczbach widzieć ile dany commit pogorszył. Ktoś zna jakiś system godny polecenia?


Z każdym dniem czuje się głupszym programista.
edytowany 5x, ostatnio: DKN
PK
PK
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 3 lata
  • Postów:245
1

Zgadzam się. Chyba, że pokój ten umożliwia tobie zyskanie doświadczenia, którego nie zyskałbyś w firmie, gdzie byłoby więcej mądrzejszych. Nie chce się zasiedzieć, ale doświadczyć jak najwięcej się da a pozniej wyjść.

A post wcześniej piszesz:

Chciałbym przygotować ta aplikacje na dalszy jej rozwój, tak by nie tylko urodzić dziecko a jeszcze żeby urosło fajnie, czy jakoś tak.

Nie wiem jak inni forumowicze to widzą, ale projekty w których ludzie składali podobne deklaracje kończyły się śmierdzącą kupą i tak się dzieje, gdy ludzie są zapatrzeni w siebie, a nie cele które są przed nimi stawiane.

Ogólnie poruszyłeś sedno problemu. Tzn. szukam balansu między bardziej zaawansowanym podejściem do tworzenia apki a biznesem. CQRS jakby nie patrzeć polega na oddzieleniu query od command, > pytanie w którym miejscu ten tort można pokroić bezpiecznie.
Czuje, że nie ma uniwersalnej odpowiedzi, wręcz przeciwnie, łatwo przejść w zależyzm.

Jak masz mniej expa to pisz na miarę potrzeb i nie wyprzedzaj przyszłości. Pisanie na miarę potrzeb pozwoli Ci później łatwiej wprowadzić zmiany do problemów o których jeszcze mało wiesz. Jeśli natomiast wyprzedzisz projekt, będziesz próbował projekt uelastycznić tam gdzie Ci się to wydaje to taka improwizacja podkręci tylko złożoność projektu. Później gdy zrozumiesz realne wymagania oraz stawiane przed Tobą problemy to zrozumiesz, że czas się wycofować z tych "inrzynieryjnych" pomysłów. Nie będzie to proste, stąd nastaw się na szukanie nowej rozwojowej pracy albo na nadgodziny, bo jedno z nich niebawem Cię spotka.

edytowany 1x, ostatnio: pan_krewetek
DKN
2 pierwsze cytaty moim zdaniem się uzupełniają. Nie chce zabrnąć za daleko z samym planowaniem dlatego, ze leży na mnie gdzieś odpowiedzialność, stąd jakaś pokora. Z twojej wypowiedzi zrozumiałem, że lepszy bardzo dobry crud niż jakiś słaby cqrs, podoba mi się to myślenie w sumie.
AK
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 2 godziny
  • Postów:3561
0
DKN napisał(a):

Zakładam, że aplikacja musi być skalowana, ale projekt również nie bedzie bardzo bardzo złożony, więc chyba zdecyduje się na upośledzony cqrs.

rysunek

O ile w pełni rozumiem CQRS gdy w obu pionach użyte są odmienne technologie (kolejki, bazy NOSQL, append logi, whatever), i zwraca nam się przez np większą responsywność / wydajność / spłaszczenie szczytów obciążenia systemu - tak tutaj, gdy chodzi o obciążenie tej samej bazy SQL, mi się wydaje wyłącznie komplikacją, tzn zysków nie widzę
Ale zaznaczę się nie znam, nie posadziliśmy nigdy CQRS na produkcji.


Bo C to najlepszy język, każdy uczeń ci to powie
DKN
Hmm.. Jestem lekko zaskoczony, myslalem, ze cqrs jest prawie wszędzie, zapytam z ciekawości, z jakich architektur głównie korzystałeś?
Charles_Ray
Co to znaczy ze CQRS jest prawie wszędzie?
DKN
@ Charles_Ray Metafora może nietrafiona, bardziej powininem powiedzieć, gdzie jest separacja. Np: 1. Separate Models Commands and Queries, 2. Separate Storage Engines, daje link do artykułu. https://altkomsoftware.pl/en/blog/cqrs-event-sourcing/ tu link, ale bez wchodzenia
LukeJL
  • Rejestracja:około 11 lat
  • Ostatnio:8 minut
  • Postów:8398
7
DKN napisał(a):

Po jego odejściu jestem ja i dwójka młodych świeżo po studiach. Nie mam żadnego doświadczenia w kwestiach wyboru architektury.

No to będziesz robił słabą architekturę. Coś w tym złego?

Wiele programistów oczekuje zbytniej perfekcji, a prawda jest taka, że możesz zrobić tylko taką architekturę, na ile ci pozwala twoje doświadczenie. Więc jeśli jest niewielkie, to architektura będzie słaba. Przy czym trzymanie się zdrowego rozsądku (np. zasad SOLID, enkapsulacji) czy stosowanie norm estetycznych np. "małe pliki, czytelne nazwy, prostota" itp. itd.) pozwala jakoś uniknąć zbytniego burdelu.

Próby pisania kodu "lepiej niż umiemy w danym momencie" kończą się przeinżynierowanymi potworkami czy cargo cultem, gdzie próbujesz wbić się w jakiś schemat (choćby to CQRS), ale nie umiesz tego dobrze zaimplementować, dostosowując do potrzeb projektu, więc nic ci to nie daje, przez perfekcjonizm wtłaczasz tylko kolejne porcje przeinżynierowanego spaghetti do projektu.

Lepiej nabierać powoli doświadczenie, iterować. Im więcej widziałeś/robiłeś projektów, tym lepiej możesz przewidzieć "co pójdzie nie tak" i lepiej zaprojektować architekturę.

Żeby szybciej iterować (=szybciej zdobywać doświadczenie), możesz robić swoje projekty po pracy, wtedy sam sobie wypróbujesz różne podejścia. Możesz też popatrzeć na różne projekty open source i się inspirować albo (co równie ważne) uczyć na błędach (np. jeśli ktoś zakłada issue na GH z prostym feature requestem, a maintainer mu odpowiada, że przy obecnej architekturze projektu to jest niemożliwe do zaimplementowania - to masz już wskazówkę, że coś poszło nie tak).

Ogólnie nie napiszesz dobrego kodu z powietrza, nie mając wcześniejszego doświadczenia.

wyboru architektury.

Architektury się nie "wybiera" tylko ją tworzy i modyfikuje w trakcie rozwoju projektu.

Ew. jeśli jesteś w stanie, to możesz ją zaprojektować już na samym początku, podjąć pewne kluczowe założenia (ale znowu - jeśli masz małe doświadczenie, to kiepsko to zaprojektujesz, więc i tak w trakcie rozwoju projektu będziesz musiał zmienić wiele założeń, bo okaże się, że o wielu rzeczach nie pomyślałeś).


edytowany 1x, ostatnio: LukeJL
katakrowa
Zgodnie z powiedzeniem: rób najlepiej jak umiesz ale nie lepiej :-)
LukeJL
no dokładnie, po angielsku jest takie powiedzenie "trying too hard". Po polsku można powiedzieć, że wiele projektów jest pisanych w stylu to takie "wyżej sra niż dupę ma". Z drugiej strony dla eksperymentów warto próbować różnych rzeczy, uczyć się nowych wzorców, bo tak się człowiek uczy i rozwija, z drugiej strony nie należy oczekiwać cudów. Zaimplementowanie modnego wzorca nie sprawi, że projekt będzie lepszy.
AK
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 2 godziny
  • Postów:3561
0

... zapytam z ciekawości, z jakich architektur głównie korzystałeś? — DKN 2020-12-18 16:29

z architektury bez specjalnej nazwy 1). Warstwy, dobre odpowiedzialności i nazwy klas. Przemyślane pakiety. Kilka rzemieślniczych reguł.
Warstwa danych (zwał jak zwał: repozytoria, DAO, whatever), usługi, warstwa wyższa kontrolerów/widoków (gdy uprawiam Apache Wicket, jemu najbliżej do MVVM)

Brak CQRS nie jest brakiem architektury ... im więcej myślę, wg mnie CQRS nie jest nawet architekturą, a pewnego rodzaju (implementacyjnym?) wzorcem inżynierskim.
Tzn można mieć CQRS a projekt mieć w stanie zwyczajowo łączonym z opisem "bez architektury" czyli wolnoamerykanka, burdel.

  1. urobiłem to zdanie na kolanie, trochę nawiązując do "chrześcijan bez osobliwego wyznania"

Bo C to najlepszy język, każdy uczeń ci to powie
edytowany 1x, ostatnio: AnyKtokolwiek
Charles_Ray
  • Rejestracja:prawie 17 lat
  • Ostatnio:około 16 godzin
  • Postów:1873
1

Z racji małego doświadczenia możesz nie do końca rozumieć uzasadnienie niektórych konceptów, niemniej polecam Ci na szybko ogarnąć książeczki Clean Architecture i Fundamentals of Software Architecture.

CQRS na całą aplikację to prawie na pewno przeinżynierowanie i proszenie się o problemy - podziel całość domenowo i zaaplikuj CQRS tam, gdzie to ma sens - na przykład ktoś inny wprowadza dane, a ktoś inny je czyta (sprzedający i kupujący, piszący i czytający, adminki i wyszukiwarki etc). Kierowałbym się kwestiami skalowalności i spójności danych (ewentualna konsystencja*). Realizacja techniczna może być na różnym poziomie złożoności - od jednej tabelki po dedykowane usługi.

(*) - tak to żart, chodzi o eventual consistency ;)


”Engineering is easy. People are hard.” Bill Coughran
edytowany 8x, ostatnio: Charles_Ray
TurkucPodjadek
TurkucPodjadek
  • Rejestracja:około 8 lat
  • Ostatnio:około 4 lata
  • Postów:607
2

Zacząłbym naprawdę od najprostszych rzeczy (listuję od mniej do bardziej skomplikowanych):

  1. Najpierw rozdzielasz funkcjonalności (np. funkcje) na pliki, czyli jak mowa o bazie danych to pliki z nazwami (przykładowo) insert, select itp - by coś odwzierciedlały
    Skupiasz się na tym, by w pliku insert, który przykładowo odpowiada za logikę wpisu do bazy danych, nie fruwały jakieś funkcjonalności pasujące do select
    Na tym etapie skupiasz się, aby działało.

  2. Jak pliki się zbytnio namnażają, to wtedy stosujesz katalogi grupujące te pliki z funkcjami

  3. Tworząc funkcje, staraj się tworzyć proste funkcje, które przyjmują i zwracają absolutnie generyczne typy danych w Twoim języku programowania.
    Przykład: funkcja zwracająca wyniki zapytania, niech zwraca "generyczny" typ danych w Twoim języku (z wynikami zapytania), a nie jakiś skomplikowany kursor/uchwyt czy coś do drivera bazy, który gdzieś tam później migruje między warstwami i niemal każda funkcja może się go potem "spodziewać", czyli musi wiedzieć coś o jakimś skomplikowanym typie danych "z zewnątrz". Później ten skomplikowany typ danych będzie sprawiał problemy w testach (nierzadko potrzeba czegoś ekstra "na zewnątrz", by działał)

  4. Tworząc specyficzną funkcję (nie taką, która jest "współdzielona" w obrębie całej apki) sprawdzaj w dobrym IDE, czy jak testowo taką funkcję usuniesz/zakomentujesz, to zaświeci Ci się na czerwono tylko miejsce jej użycia (optymalnie) lub zaświeci się również w innych funkcjach (zazwyczaj źle).
    Przykład: masz funkcję, która zapisuje dane do pliku. Gdy ją usuniesz IDE powinno Ci wskazać błąd w tych ogólnych miejscach, w który była ona wołana do zapisu, jak Ci wyskakują odwołania w funkcjach typu odczytDanych, to znaczy, że w poprzednich punktach coś pomieszano.

    Kod, który pozwala w miarę bezboleśnie usuwać swoje kawałki/funkcje, jest już raczej dobrze rozplanowany.

  5. Jak funkcje mające podobny zakres odpowiedzialności lub "dziedzinę", również ostro namnażają w katalogach - rozważ stosowanie interfejsów czy tam klas (lub ekwiwalentu w danym języku programowania), aby je podzielić pod tym względem.

Jak jesteś na etapie po punkcie 5) - winszuje gratulacje, świat stoi otworem, masz teraz znacznie ułatwione zadanie. Teraz dopiero możesz się zastanowić czy potrzebujesz DDD, CQRSów, ESów, mikroserwisów czy innych konceptów, bo dopiero teraz będzie widać, czy ich zastosowanie ma jakiś sens w Twojej aplikacji. Jeśli zdecydujesz się pójść którąś z takich dróg, wówczas odpowiednio przestrzegając punktów 1-5 będzie Ci znacznie łatwiej.

edytowany 2x, ostatnio: TurkucPodjadek
S9
  • Rejestracja:ponad 4 lata
  • Ostatnio:około 2 lata
  • Lokalizacja:Warszawa
  • Postów:1092
6

@DKN:
Polecam również prezentacje

Dodatkowo zalecam stosowanie niemutowalnych obiektów i zastąpienie java.util.collection Vavrem


edytowany 2x, ostatnio: scibi_92
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)