Wzorzec repozytorium. Kilka niepewności. Co zamiast

Wzorzec repozytorium. Kilka niepewności. Co zamiast
S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
0

. A "programowaniem aspektowym" zapewne też nazywasz proxy nad Twoją klasą utworzone przez kontener IoC.

Tak spring tworzy proxy. Ale aspektowe jest przez to że celem klasy którą tworzenie nie jest zarządzanie transakcjami :
https://en.wikipedia.org/wiki/Aspect-oriented_programming


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:3 dni
  • Lokalizacja:Wrocław
0
jarekr000000 napisał(a):

To nie robicie jak ludzie, ze jest po prostu jedna, dwie metody utilsowe, które jako parametr przyjmują funkcję do wykonania na DB (z argumentem w postaci sesji)?

Nie, bo ludzie tak nie robią. (Argumenty oparte na presupozycjach obalają się same.)

Jakby nie widzę zysku z tego. W kodzie swojego serwisu robię co potrzebuję na sesji i tyle, nie muszę niczego nikomu przekazywać. Lubię, jak jest prosto, te wszystkie "reużywalne" repozytoria i query objecty, szybko przestają być "reużywalne" i albo trzeba refaktoryzować, żeby było dobrze, albo dodawać ify, żeby było bardziej enterprise.

Nic nie trzeba rejestrować.

No ja też nie muszę, wszystko jest już zarejestrowane. (Taka zaleta posiadania konwencji zamiast konfigurowania IoC w XML.)

Żadnych aspektów/ procy cudów.

Z polimorfizmu jest taki cud jak z wizerunku Jezusa na toście.

Testowanie proste.

Wręcz banalne. Czy mock sesji, czy SQLite w pamięci, czy integracja - wszystko to jest proste.

scibi92 napisał(a):

Ale aspektowe jest przez to że celem klasy którą tworzenie nie jest zarządzanie transakcjami :

Nie no, masz rację... Ja po prostu nie lubię tego słowa, bo kojarzy mi się z powolnymi frameworkami, które robią cuda z wyjściowym kodem, żeby te swoje "aspekty" dodać.

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0
somekind napisał(a):

Nic nie trzeba rejestrować.

No ja też nie muszę, wszystko jest już zarejestrowane. (Taka zaleta posiadania konwencji zamiast konfigurowania IoC w XML.)

Żadnych aspektów/ procy cudów.

Z polimorfizmu jest taki cud jak z wizerunku Jezusa na toście.

No bo jak masz po prostu prosty polimorfizm - to co się rejestruje? I po co ta konwencja?
Bo jeżeli masz coś działającego na "konwencji".. to chyba nie jest to prosty polimorfizm.

Może pokaż przykład.


jeden i pół terabajta powinno wystarczyć każdemu
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:3 dni
  • Lokalizacja:Wrocław
0

Mniej więcej tak działają interceptory z IoC, że generują w locie proxy, które nadpisuje metody z klasy bazowej.
Rejestruje się klasy, żeby nie trzeba było ich tworzyć ręcznie tylko wyciągnąć sobie z kontenera.

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0

No to jednak nie jest prosty polimorfizm. To samo w Javie jest w Spring/JavaEE. Zresztą też przez konwencję. Kiedyś wydawało mi się fajne.
Napisz mi ... a jak się ta transakcja jednak nie wystartuje (metody się nie nadpiszą) to gdzie stawiasz breakpointa, żeby się dowiedzieć dlaczego?


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 1x, ostatnio: jarekr000000
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:3 dni
  • Lokalizacja:Wrocław
0

Jeśli metoda się nie nadpisze, to sprawdzę, czy jest wirtualna, czy klasa jest udekorowana atrybutem, i czy na pewno jest zarejestrowana w IoC. Ale to dość sztuczny przypadek - w sensie może się zdarzyć na początku projektu, kiedy jeszcze nie ma konfiguracji, ale nie nagle pewnego dnia. (No chyba, że ktoś nie oznaczy metody jako virtual itp., ale to są trywialne do naprawienia kwestie.)

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0

Czyli całe piękno kontenerów.... To nie jest proste!

Wczoraj np. walczyłem po raz kolejny z Webspherem (javowy kontener JavaEE)- jeden z serwisów Rest nie startował transakcji w odpowiednim momencie i działał jakby nie był skonfigurowany annotacjami ( czyli dawniej XMLem obecnie wje...nym w kod).

Co się okazało - klasa implementująca nie deklarowała implementacji interfejsu bezpośrednio, tylko za pośrednictwem jakiejś klasy bazowej. Z punktu widzenia Javy to samo (jak dziedziczysz z klasy która implementuje interfejs to jest to przechodnie). Z punktu widzenia kontenera - pogubił się w skanowaniu klas i nie znalazł interfejsu (debil :-)) , a w nim były adnotacje konfigurujące. Kilka godzin w plecy, bo kto by na to wpadł.

Dlatego uważam , że dorośli programiści nie powinni się w to bawić. Jednak podejście z JOOQ - czyli ogólnie High order functions jest niezawodne. Żaden kontener się nie miesza i wszystko jest jasne w momencie kompilacji. Nie ma żadnych konwencji and konfiguracji.

W ogólności to takie rzeczy jak transakcje, security, monitoring itp. można by załatwiać przez Free Monad .. ale IMO w Javie nie może Free działać (mimo że jest taki projekt na githubie :-).


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 3x, ostatnio: jarekr000000
EP
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad 6 lat
  • Postów:122
0
somekind napisał(a):

@scibi92: no ja nie mam Springa, więc po prostu rejestruję w kontenerze SessionFactory jako singletona, a Session per lifetime scope. Do tego mam zarejestrowany interceptor, który opakowuje wskazane (atrybutem) metody/klasy, i podczas ich wykonywania otwiera transakcje, wykonuje kod metody, potem zatwierdza transakcję (albo wycofuje jeśli poleciał wyjątek). Wewnątrz metody operuję po prostu na obiekcie session (Get/Load/Save/Delete/QueryOver), nie mam żadnych commitów, rollbacków, ani nawet try-catch.

@somekind: pokazałbyś jakiś przykład? Ponieważ jestem wspomnianym programistą który w każdej metodzie otwiera nową sesję ORMa i ma try-catch. Niemniej jednak nie płacą mi za linijki (ba, w ogóle nie płacą).


Wenn ist das Nunstück git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!
Zobacz pozostały 1 komentarz
EP
O, dokładnie o to mi chodziło, dzięki :)
somekind
Nie ma sprawy. :)
jarekr000000
Ech... czyli to samo co w javowym mainstreamie -> DynamicProxy. Ojcowie pisali te kompilatory, sprawdzania typów etc., a tu każda łajza może zwrócić invocation.returnValue = 42 i co zrobisz :-) . Normalnie powrót BASICa.
somekind
No niby może, tylko się testy wysypią i łajzę się wyśle do piekła. Serio chciałbym mieć takie problemy.
jarekr000000
To masz fajnie, że Ci się testy wysypią. 90% projektów Javowych robi testy na mockach bez kontenera i takie kwiatki nie wychodzą. To był oczywiście z d..y przykład. Faktyczne problemy sa jak masz w interceptorach tzw. ThreadLocale -a system używa wątków, do tego cała klasa problemów z okolic return this, kolejnością interceptorów, beanami zainicjalizowanymi na dziko (bez kontenera).
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:3 dni
  • Lokalizacja:Wrocław
3
jarekr000000 napisał(a):

Czyli całe piękno kontenerów.... To nie jest proste!

Wczoraj np. walczyłem po raz kolejny z Webspherem (javowy kontener JavaEE)- jeden z serwisów Rest nie startował transakcji w odpowiednim momencie i działał jakby nie był skonfigurowany annotacjami ( czyli dawniej XMLem obecnie wje...nym w kod).

Co się okazało - klasa implementująca nie deklarowała implementacji interfejsu bezpośrednio, tylko za pośrednictwem jakiejś klasy bazowej. Z punktu widzenia Javy to samo (jak dziedziczysz z klasy która implementuje interfejs to jest to przechodnie). Z punktu widzenia kontenera - pogubił się w skanowaniu klas i nie znalazł interfejsu (debil :-)) , a w nim były adnotacje konfigurujące. Kilka godzin w plecy, bo kto by na to wpadł.

Ja nie mam Websphera, JavyEE ani upośledzonych kontenerów. Mam sprawdzone narzędzia, których używam w prosty sposób.

Dlatego uważam , że dorośli programiści nie powinni się w to bawić. Jednak podejście z JOOQ - czyli ogólnie High order functions jest niezawodne. Żaden kontener się nie miesza i wszystko jest jasne w momencie kompilacji. Nie ma żadnych konwencji and konfiguracji.

Nie mam JOOQ, ale też nie mam problemu ze swoim działającym rozwiązaniem. Nie mam copy-paste, w całym kodzie mam tylko jedno miejsce, w którym muszę podpiąć debugger, aby dowiedzieć się, czemu transakcja sie nie udała, a do tego ta sama transakcja jest użyta we wszystkich metodach używanych w danym UoW (co prawda nie przydaje się to często, ale skoro już mam to za darmo, to po co sobie upośledzać rozwiązanie).

Kontener IoC mam i tak, bo jestem zbyt leniwy, żeby go nie mieć, więc dodanie do niego paru dodatkowych ficzerów to dla mnie żaden wysiłek, a zyski są ogromne.
Moja "magia" działa. Setki linii kodu nawalone przez proceduralnych programistów, którzy chcą mieć wszystko jawnie napisane bez żadnej delegacji ani generycznych rozwiązań, zazwyczaj generują sporo błędów.

edytowany 1x, ostatnio: somekind
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0

No ale dlaczego zamiast jakimś kontenerem i magią nie zrobić tego prosto?

Kopiuj
//przykład uproszczony w składni javowej
TxManager{
  public <T> T  doInTx( Function1<DBSession, RESULT> dbCommand ) {
        DBSession session = openSession();
        try {
              session.beginTransaction();
              dbCommand.apply(session);
              session.getTransaction().commit();
        }
        catch (...) {
             session.getTransaction().rollback();
        }
    } 

}

i wtedy gdzie chcesz to siejesz:

Kopiuj
TxManager.doInTx ( sess-> {
 sess.query("BL BLA JAKIS SQL");
... itd
}

jeden i pół terabajta powinno wystarczyć każdemu
edytowany 1x, ostatnio: jarekr000000
S9
Pomyliło mi się, myślałem że chodzi o kontener w sensie serwera ;)
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:3 dni
  • Lokalizacja:Wrocław
1

@jarekr000000: bo jestem leniwy i nie chcę pisać w setkach miejsc TxManager.doInTx. W projekcie bez kontenera (albo z upośledzonym kontenerem, którego nie da się łatwo i stabilnie rozszerzać), to bym takiego helpera użył. Ale jak kontener mam, to korzystam z jego możliwości.

jarekr000000
Jak masz same doInTx to to naprawdę nie jest problem - kodu nie wychodzi więcej. Problem się robi jak masz doInSecure + doWithMonitoring + doWithLogs + doWithErrorHandling + doInTx - wtedy niestety albo kończy się bardzo słabym "doItAllForMe" ... albo Scalą.
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0

(to odnosi się do usuniętego postu @scibi92)

Co jest skomplikowanego w wywołaniu funkcji... kiedy cały kod twojego systemu jest podany explicit?
Naprawdę runtime magia na threadlocalach, proxy i nadpisywaniu bajtkodu jest prostsza? No bez żartów...


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 3x, ostatnio: jarekr000000
S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
0

poza tym tak jest o wiele łatwiej. Jak będziesz łatwo współdzieli transakcje między obiektami biznesowymi itd?

EDIT:
A jak będziesz przenosić transakcje między obiektami logiki biznesowej


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
edytowany 1x, ostatnio: scibi92
Zobacz pozostałe 29 komentarzy
jarekr000000
Mój kod przykładowy jakiś czas temu podawałem. Możesz spróbować zobaczyć co byś tam kontenerem poprawił. Np. w testach.
jarekr000000
Jak się nie nauczy pisać w javie to trzeba podmieniać.
S9
Nie chce mi się szukać :)
SP
PostConstruct używa się bo JavaEE często serializuje i deserializuje beany i przy tej okazji wywoływany jest konstruktor. I może się zdarzyć, że konstruktor zostanie wywołany wiele razy chociaż nie powinien, bo zasięg beana jest np. @ViewScoped. PostConstruct gwarantuje że ta metoda zostanie wywołana tylko raz dla danego beana
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:3 dni
  • Lokalizacja:Wrocław
1

Nie jest trudne tylko czasochłonne. 10 linijek konfigurujących IoC to mniej roboty niż kilkaset wywołań new.

No i new działa tylko jeśli piszesz końcową aplikacje, jeśli piszesz frameworki to podejście nie zadziała.

edytowany 1x, ostatnio: somekind
Zobacz pozostałe 13 komentarzy
jarekr000000
tylko zakładasz, że ja mam tego kodu więcej. to co u mnie jest wywołanie explicit tego managera. U ciebie jest schowane w runtimie, ale jest. Moje doświadczenie jest takie, że taki kod schowany nie poprawia debugowalności. (W takim Springu nieraz mam kilkanaście interceptorów, które potrafią całkiem wypaczyć to co się dzieje podczas niby trywialnego wywołania bean.doThisBabeForMe() ).
somekind
No, ale to już trzeba mieć pretensje do tych, którzy dodali tyle interceptorów. Osobiście nie widzę powodu, żeby mieć więcej niż jeden.
S9
No właśnie, to nie wina twórców Springa czy innego frameworka/biblioteki IoC/AoP że jest to źle używane
jarekr000000
masz security, transakcje, cache, monitoring, timouty i tak dalej. A jak nie chcesz pisać wielkich XMLi (zwanych tez annotacjami) to jedziesz przez konwencję. A konwencja jest taka, że dodają się wszędzie. I system pozamiatany.
S9
@Security na kontrolerze albo konfiguracja Javova,@Transactional na serwisach i tyle.
S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
0

Taki kod burzy podział na obiektyki odpowiedzialne za logikę i ORM


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
jarekr000000
Skąd takie mądrości?
S9
A jak będziesz przenosił transakcje między obiektami logiki?
jarekr000000
nawet nie rozumiem twojego zdania - co to znaczy przenosił transakcje ? w pudełku po pizzy? transakcję albo kontynuuje - albo commituje, albo rollbakuje
S9
A jak będziesz współdzielić instancje to tego TXManagera twojego?
jarekr000000
Nie muszę współdzielić instancji. (chociaż mam też takie przypadki). Normalnie w Javie i wielu innych językach obiektowych obiekty można przesyłać jako argumenty metod (co nawet jest całkiem wygodne).
DE
  • Rejestracja:ponad 9 lat
  • Ostatnio:10 miesięcy
  • Postów:1788
0

@somekind: a tak jeszcze wracając do tematu tego nieszczęsnego repozytorium. Załóżmy, że mam to repo zgodne z DDD, czyli jest to kolekcja obiektów domenowych. wykorzystywana podczas wykonywania jakiś operacji biznesowych.

Teraz potrzebuję wypluć na front jakieś dane ze stronicowaniem. Ponieważ samo ograniczanie wyników zapytania odbywa się w klasie, która zajmuje się tym stronicowaniem, to mam takie wyjścia:
a) Wrzucić wszystko do repozytorium, zamiast kolekcji/pojedynczego obiektu domenowego zwrócić paginator i mieć w dupie
b) Wrzucić wszystko do kontrolera i też mieć w dupie
c) Zwrócić z repozytorium zapytanie i utworzyć paginator w kontrolerze (albo nie z repozytorium tylko utworzyć jakiś QueryObject czy coś)
d) Utworzyć coś (co może ma jakąś nazwę, BlaBlaProvider?), co zwróci gotowy paginator (tak jak punkt a), tylko że nie robimy tego w repo).

Osobiście d) mi się najbardziej podoba. Czy taki obiekt, który zwraca dane tylko używane w widoku ma jakąś swoją nazwę (poza QueryCommand i QueryCommandHandler z CQRS).

edytowany 1x, ostatnio: Desu
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:3 dni
  • Lokalizacja:Wrocław
0

Ja również wybieram opcję d. CQRS bym tu nie mieszał, bo to może działać bez tego podejścia.
Czy to ma jakąś inną nazwę? Pewnie nie, bo nazwy wymyśla enterprise, a to jest zbyt mądre i rozsądne, żeby było enterprise. :P

._.
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 6 lat
  • Postów:250
0

Ale dlaczego ty chcesz zwracać "paginator" który jest częścią Prezentacji albo Web z jakiegoś provaidera?.

edytowany 1x, ostatnio: ._.
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)