Optional - często go używacie?

Optional - często go używacie?
PI
  • Rejestracja:ponad 9 lat
  • Ostatnio:3 miesiące
  • Postów:2787
2

Siema. Interesuje mnie, czy zawsze, w każdym możliwym przypadku NPE używacie Optionala? Czy jednak nie? Jeśli mamy linijkę np

Kopiuj
object.getA().getB().getC();

to tych potencjalnych NPE jest sporo, ale użycie Optionala tutaj doda kolejny narzut kodu. Wiadomo, lepiej mieć kilka linijek więcej i mieć gwarancję że akurat NPE nam nie wy3.14eprzy działania programu.

Co też myślicie o następującej sytuacji - mamy sobie publiczną metodę X, która jako argument przyjmuje jakiś skomplikowany obiekt i wewnątrz tej metody jest taki łańcuch getów jak wyżej. Natomiast wiemy doskonale, że tej metody użyliśmy jedynie w 2 -3 miejscach i tam mamy pewność, że obiekt te wszystkie swoje pola i podpola ma. Czy fakt, że do danej metody ma się dostęp w obrębie całej aplikacji, powoduje konieczność "handlowania" potencjalnymi nullami (już pomińmy inne przypadki brzegowe)? Czy też przenosimy odpowiedzialność na użytkownika - wpakował nulla, to dostaje NPE na twarz i elo.

Zachęcam do wypowiadania się @Shalom @jarekr000000 @Koziołek @scibi92 @Krolik @katelx

Burdzi0
Również mnie to ciekawi, +1
NoZi
  • Rejestracja:około 16 lat
  • Ostatnio:około 17 godzin
5

Przykład który podałeś łamie Law of Demeter ;)


Hate the sin, love the sinner
PI
Prawda. Niemniej jednak, trudno jest w 100% w całej aplikacji tego prawa przestrzegać, przynajmniej według mnie :D
LitwinWileński
niekoniecznie, gdyż ten object to może być struktura bez logiki
Riddle
@LitwinWileński: +1 @Pinek Można, jak się wie co robi. Prawo demeter to tak na prawdę szczególny przypadek enkapsulacji - jak przestrzegasz enkapsulacji w całej aplikacji to prawo demeter masz jakby "automatycznie".
PI
Po 5 latach już nawet mnie nie interesuje czy łamię Prawo Demeter czy nie :D
LitwinWileński
wniosek: trzeba zatrudniać programistów z mniejszym dośw. niż 5 lat ech
katelx
  • Rejestracja:prawie 10 lat
  • Ostatnio:4 miesiące
  • Lokalizacja:Hong Kong
0

preferuje uzywanie null object pattern w wiekszosci miejsc gdzie optional moglby byc jakims rozwiazaniem.
btw, imo zwykle robienie czegos takiego jak object.getA().getB().getC() w metodzie swiadczy o innych zlych praktykach np. czemu nie przekazac do metody tego co zwraca getC() zamiast robic taki lancuch wywolan (poza uzywaniem fluent interface, no ale wtedy to raczej ciezko o NPE ;))

PI
Co do przykładu - załóżmy, że w danej metodzie wykorzystujemy też object.getD() ;) wtedy okej moglibyśmy przekazywać samo "D", ale z "A" nadal łańcuch by szedł, no chyba że byśmy dali dwa parametry - "D" i "C"
katelx
w sumie jak by tu sie jeszcze babrac z optionalami to juz rzeczywiscie lepiej po prostu try / catch walnac i zapomniec ;)
PI
try catch z NPE? ;) Nie no chyba jak już to sprawdzenie ifem czy różne od null
katelx
zezarcie wyjatku to jednak szybszy sposob na zapomnienie o problemie ;) a tak serio - zalezy co masz po drodze, jesli rzeczywiscie kazdy obiekt w lancuszku moze byc nullem to zarowno uzywanie if null jak i optionali bedzie tak samo uciazliwe
katelx
  • Rejestracja:prawie 10 lat
  • Ostatnio:4 miesiące
  • Lokalizacja:Hong Kong
3

@Pinek odpowiadajac na pytanei z komentarza, chodzi mi o to ze lepiej wyglada powiedzmy:

Kopiuj
class Country {
    private Age adultAge;
    boolean isAdult(Age age) {
        return age.value() >= adultAge.value();
    }
}

niz

Kopiuj
boolean isAdult(StaticDataEntry data) {
    return data.getPerson().getAge().value() > data.getPerson().getCountryOfResidence().getAdultAge().value();
}

oczywiscie zamodelowanie aplikacji tak zeby mozliwe bylo uzycie isAdult z przykladu 1) wymaga wiecej wysiku ale zwraca sie wlasnie przy obsludze bledow

Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
2

@Pinek nigdy nie masz pewności że ktoś tam kiedyś da nulla, a jeśli tak postanowi to powinien wtedy automatycznie zmienić sugnaturę metody na Optional i obsłużyć w kodzie przypadek kiedy nie ma wartości. Nie należy wszystkiego opakować Optionalem, bo to bez sensu. Należy dać Optional wtedy kiedy widzimy że możemy / chcemy zwracać "pustą" wartość.
Poza taka wiązanka get.get.get to tragedia i klasyczne przeciekające warstwy/gwałt na enkapsulacji. Jeśli coś takiego występuje to rób delegacje tak żeby finalnie mieć tylko x.get() a reszta ukryta pod spodem.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
1

Tutaj nie NPE jest problemem tylko to że nie masz informacji co może być nullem a co nie.

W podejściu:

Kopiuj
object.getA().getB().getC();

rozumiem że każdy z tych elementów to po prostu uniwersalny getter wykorzystywany różnie w wielu miejscach i kontekstach.

W podejściu:

Kopiuj
object.getCOfBInA(); 

masz w miarę dokładny cel wywołania A i B, w związku z tym możesz określić czy chcesz w tej sytuacji się wywalić "NoDataFound!" czy zwrócić po prostu null (i opisać to w JavaDoc lub zastosować Optional).

edytowany 1x, ostatnio: vpiotr
PI
  • Rejestracja:ponad 9 lat
  • Ostatnio:3 miesiące
  • Postów:2787
0

@vpiotr:

Okej, wszystko co napisałeś jest fajne i zgodne ze sztuką. Ale w praktyce siadasz do projektu w pracy i np masz model z 15 polami, więc już samych getterów/setterów jest 30. A te pola to nie zwykłe prymitywy, tylko kolejne obiekty modelowe. Dołożenie tylu kombinacji spowodowałoby 70-100 metod getterowych w klasie modelu :( I cóż wtedy zaradzić?

edytowany 1x, ostatnio: flowCRANE
PI
Dzięki, na pewno przeczytam cały cykl
katelx
  • Rejestracja:prawie 10 lat
  • Ostatnio:4 miesiące
  • Lokalizacja:Hong Kong
0

@Pinek nowy kod pisac juz dobrze, stary powoli zmieniac przy okazji :)

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

Pomijając uwagi jak powyżej to piszem tak:

Kopiuj
object.getA().flatMap(a -> a.getB()).flatMap(b ->b.getC()).forEach( c ->  zrobCosTam(c));

i jakoś idzie z tymi optionalami.

A co do nulli - ja tam lubie ludzi częstować NPE jeśli zasłużyli. Dajesz nulla do moje metody to witaj się z NPE.
Jakbym napisał, że przyjmuje nulla to móglbyś dawać (ale przecież bym nie napisał tylko powiedzieł, że argument jest Optional).
Generalnie wszelkiego rodzaju asserty, predykaty sprawdzające czy coś jest nullem akceptuje, czasem robię.
Fajne jest np. Objects.requireNonNull()
Ale najczęściej nie wrzucam nawet takich asercji . (Zależy w jakim kodzie). Bo to z pewnością ułatwia znalezienie błędu, ale z drugiej strony jest to szum informacyjny - potem metoda ma 2 linijki sensownego kodu plus dodatkowe 5 z assertami. Nie warto wszędzie śmiecić.

Wszelkiego rodzaju if( x != null) w logice to już zalążek zła.
No a najgorsze zło, które często spotykam w kodzie różnych firm i "konsultantów" to to:

Kopiuj
public T method1(Type arg1)  {
   if ( arg1 != null ) { 
   .... bla bla bla that's just code
  } else {
   return null;
  }
}

Powinien być specjalny krąg piekiełka programistycznego dla tych co tak piszą.


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 1x, ostatnio: jarekr000000
Shalom
Piszą tak pewnie z czystej złośliwości :D Ja musiałem robić ify z dupy żeby sprawdzać czy nie dostałem nulla?! To niech inni tez muszą! ;) BTW IntelliJ mówi mi że ponoć przekazywanie Optionala jako argumentu funkcji jest w złym stylu ;]
jarekr000000
Co do Optional z Java 8 to jest to zjebana koncepcja Briana Goetza. Bez komentarza - chcesz go wkurzyć to spytaj czemu Optional jest np. nieserializowalny (ja to zrobiłem - dobrze, że było dużo ludzi w pobliżu :-) ). Dla ustalenia uwagi używam Option z JavaSlanga i kakam na te ich głupotki.
PI
jarekr000000
@Pinek no jasne. Fakt, że słyszy to pytanie na każdej konferencji po 3 razy... (słusznie :-) )
PO
  • Rejestracja:prawie 10 lat
  • Ostatnio:4 dni
  • Postów:153
9

U mnie w firmie był szał na Optionale i niestety wyglądało to tak, że były wypchane wszędzie. Na przykład można było się spotkać z takim czymś:

Kopiuj
jakisOptional.orElse(null)

Generalnie trzeba używać tego z głową, ale to chyba jak wszystkiego :)

Shalom
aaaa, to musiał zrobić jakiś geniusz :D
KA
W sumie to geniusz. Zamiast refaktorować pół systemu połączył nowe podejście ze starym NPE. Też bym tak zrobiła i nieraz tak robiłam zamiast refaktorować cały system
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4706
7

Piękne


jeden i pół terabajta powinno wystarczyć każdemu
Koziołek
Moderator
  • Rejestracja:prawie 18 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:Stacktrace
  • Postów:6821
5

object.getA().getB().getC();

The Getter Train has no breaks

77342405.jpg

Kopiuj

Optional.nullable(myObject).map(myObject::getA).map(A::getB).map(B::getC);

I teraz pozostaje problem wartości w orElse. Można spróbować z null, ale tylko wtedy, gdy wypluwasz wszystko do GUI i masz tam jakieś regułki obsługi null/pusty String. W przeciwnym wypadku kulturalnie jakiś błąd jeżeli nie masz wartości domyślnej :) W ostateczności można zignorować, ale wtedy warto mieć uzasadnienie.


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
edytowany 1x, ostatnio: Koziołek
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
1
Pinek napisał(a):

Okej, wszystko co napisałeś jest fajne i zgodne ze sztuką. Ale w praktyce siadasz do projektu w pracy i np masz model z 15 polami, więc już samych getterów/setterów jest 30. A te pola to nie zwykłe prymitywy, tylko kolejne obiekty modelowe. Dołożenie tylu kombinacji spowodowałoby 70-100 metod getterowych w klasie modelu :( I cóż wtedy zaradzić?

To co opisałeś to nie obiekty tylko struktury danych (czyli wszystkie/większość pól dostępna na zewnątrz).
Osobiście nie mam nic przeciwko programowaniu strukturalnemu, ale trzeba mieć świadomość że się je uprawia.
I wtedy można zrobić coś takiego:

Kopiuj
public class MyTest {
  public ClassC getC() {
     ClassA objA = getA();
     return getC(objA);
  }

  private ClassA getA() {
     return new ClassA(); // zrodlo dowolne
  }

  private ClassC getC(ClassA obj) {
     return obj != null ? obj.getB() != null ? obj.getB().getC() : null : null; // wyrazenie dowolnie
  }
}

// i na koncu
object.getC(); 

I teraz najważniejsze: ten kod powyżej jest rozwlekły i wydaje się nadmiarowy - i taki ma być.

Bo masz takie ścieżki wyboru:
a) albo Twój (kolejkowy) kod dowolnie permutuje sobie wywołania struktur danych w programie i nie panujesz nad tym (faktura wyciąga sobie dane o płci ze struktury HR-owej z CV-ki)
b) albo wiesz co robisz i jesteś pewien że możesz zrobić właśnie tak getC() i będzie to rozwiązanie stabilne.
c) albo robisz CQRS / fasadę które na potrzeby zebrania potrzebnych danych odpalają odpowiednie zapytanie które mieli po bazie

Rozwiązanie (a) wydaje się najwygodniejsze, ale oznacza brak architektury przepływu danych.
Rozwiązanie (b) ukrywa ale i usztywnia dostęp do danych. Zwiększa pracochłonność rozwiązania. Stosowane głównie w starszych architekturach.
Rozwiązanie (c) jest płynne - gdy zmienia się źródło danych zmieniasz zapytanie i po sprawie. Zapytanie łatwo przekierujesz na inną tabelę czy powiązanie. Jeśli wynik (Proxy, Mapa, DTO itp) się nie zmienia to klienci klasy nie muszą być przebudowywani.

A Optionala na razie nie używam - w pracy Java 7. Pewnie do jakichś prostych wywołań, jednostopniowych bym użył. Ale nie do takiej kolejki.

edytowany 2x, ostatnio: vpiotr
S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
1

Opcjonal jest wtedy dobry jak wiemy że jakiś parametr jest ... opcjonalny czy to metody czy zwracany. Wedlug mnie na przykład może być ok jeśli zwracamy mamy DAO i zwracamy wynik wyszukiwania po unikatowej kolumnie, np.

Kopiuj
   Optional<Book> findBookByISBN(String ISBN);


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
azalut
  • Rejestracja:około 12 lat
  • Ostatnio:ponad rok
  • Postów:1129
1

optionali uzywam jak wiem ze jakies pole lub wynik metody jest opcjonalny + ten optional bedzie "użyteczny" tzn za chwile nie zostanie zamieniony na nulla "bo trzeba"

edytowany 3x, ostatnio: azalut
1

W ogóle nie rozumiem jaka jest korzyść z tego Optional. Jak dla mnie to utrudnianie sobie życia, sztuka dla sztuki.

No bo powiedzcie mi w czym taki kod:

Kopiuj
import java.util.Optional;

public class adhoc {
	public static void main(String[] args) {

		Integer x = null;
		Optional optionalX = Optional.ofNullable(x);
		int xx = (int) optionalX.orElse(0);
		
		System.out.println(2 * xx);
	}
}

jest lepszy od takiego:

Kopiuj
public class adhoc {
	public static void main(String[] args) {

		Integer x = null;
		int xx = x == null ? 0 : x;
		System.out.println(2 * xx);
	}
}

W R też we wszystkich pakietach widze, że piszą na początku funkcji sprawdzania w stylu

Kopiuj
if(is.na(x){
  x <- 0
}
Julian_
ewentualnie: x <- ifelse(is.na(x), 0, x)
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
2

@Pijany Kot w takim kodzie w ogóle nie ma to sensu bo masz tylko 1 poziom. Ale jak pobierasz wartość która przylatuje z jakiegoś obiektu 10 poziomów wyżej, jeszcze poprzez kilka hierarchii klas to wcale nie tak łatwo stwierdzić czy to może być null czy też nie. Możesz oczywiście cały kod opakować null checkami, ale to szaleństwo i sprawdzi się co najwyżej w g**no-skrypcie w R na kilka linijek. W projekcie na setki tysięcy linii to możesz o tym zapomnieć. Optional automatycznie wymusza obsłużenie wartości "pustej" i nie da sie tego nijak przeoczyć.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 1x, ostatnio: Shalom
Julian_
A to o tym czy zmienna może być nullowa nie mówi jej typ? np. boolean / Boolean?
Shalom
@Julian_: o_O no jeśli jedyne typy z których korzystasz to prymitywy, to kto wie... Ale normalni ludzie mają jednak cała masę własnych klas i wrapperów na inne typy i tam juz takiej możliwosci nie ma. Ba, zalecam nigdy nie uzywać w kodzie bezpośrednio z typów standardowych, bo kończy się to boleśnie kiedy okazuje sie że potrzebujesz dorzucić jakieś dane i nagle wymaga to refaktorowania połowy systemu zamiast dodania jednego pola do klasy.
Julian_
nie pisz do mnie w taki sposób.
Koziołek
Moderator
  • Rejestracja:prawie 18 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:Stacktrace
  • Postów:6821
1

@Pijany Kot, widzisz nie rozumiesz co robisz w Javie i przykład nie za bardzo ci wchodzi.

Kopiuj
public class adhoc {
    public static void main(String[] args) {
 
        Integer x = null;
        Optional optionalX = Optional.ofNullable(x);
        optionalX.ifPresentOrElse(
		xx-> System.out.println(2 * (int)xx),
		() -> System.out.println(0)
	);
    }
}

i nie trzeba nic kombinować z jakimś Ifem, z jakimś orElse czy przepisywaniem zmiennych. Optional zamyka ci wartość w kontenerze i daje możliwość manipulowania tą wartością z uwzględnieniem potencjalnego nulla.


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
edytowany 1x, ostatnio: Koziołek
Julian_
kompiluje Ci się to co napisałeś?
Koziołek
Jutro wieczorem się już skompiluje.
Julian_
Masz błąd. To się nie kompiluje. Exception in thread "main" java.lang.Error: Unresolved compilation problems: Syntax error, insert ")" to complete Expression Syntax error, insert ")" to complete MethodInvocation Syntax error, insert "AssignmentOperator Expression" to complete Assignment Syntax error, insert ";" to complete Statement
Prędki_Lopez
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 4 lata
  • Postów:248
2

Tak dodatkowo zarzucę tutaj tematem ze stacka gdzie Brian Goetz mówi dla jakich przypadków stworzyli optionale: https://stackoverflow.com/questions/26327957/should-java-8-getters-return-optional-type/26328555#26328555

vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
1

TL;DR / i stary ten wątek chyba trochę?
Nie wiem czy było, ale chyba powinno się zacząć od linku ze SO:
http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html

KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:6 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
0
podroznik napisał(a):

U mnie w firmie był szał na Optionale i niestety wyglądało to tak, że były wypchane wszędzie. Na przykład można było się spotkać z takim czymś:

Kopiuj
jakisOptional.orElse(null)

Generalnie trzeba używać tego z głową, ale to chyba jak wszystkiego :)

W piątek przerabiałem taki kod. W Scali XD


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
Riddle
@KamilAdam: a wiesz że ten wątek jest z 2017? :D
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:6 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
1

Co to za odkop?

a wiesz że ten wątek jest z 2017?

Tak, przeglądałem sobie stare wątki i odkryłem że problem dalej występuje. A dokładniej ja muszę się z nim mierzyć w legacy. 10 linii kodu (dwa razy użyte orNull, raz case null => w switchu) zamieniłem na jedną linie _.flatMap(_._2).contains("y")


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
ZD
  • Rejestracja:około 3 lata
  • Ostatnio:ponad rok
  • Postów:2310
1

Javowski Optional byłby dużo piękniejszy, gdyby w jakiejś wersji kompilator w każdej metodzie Optional wymuszał not null (tzn "jakiegoś" optionala musisz zwrócić).

BTW koduję w głowie klasy/interfejsy Javowskie które są "hardwarowo" wbudowane w kompilator, ciągle jest zamiar podzielić się tym w jakiejś dyskusji bo mnie to zaciekawiło, ale odkłada się w czasie ...


If you put a million monkeys at a million keyboards, one of them will eventually write a Java program - the rest of them will write Perl
Zobacz pozostałe 21 komentarzy
S9
@piotrpo: to szczerze - gratuluje. Ale nie mniej - nie jest to takie łatwe. Tym bardziej że Java się zaczeła mocno do przodu iść. Dlamnie jeżeli jest fajny produkt, ciekawe wyzwania to czy to jest Java czy Kotlin ma drugorzędne znaczenie. Ja miałem faze na Kotlina, i mi przeszło, choć gdyby ktoś zaproponował że serwisy będziemy pisać w Kotlinie to bym oczywiście to poparł ;)
S9
a może być tez tak że słabo umiem przekonywac innych...
piotrpo
To nie jest kwestia "za mało umiem". Ostatecznie praktycznie każdy programista Java jest w stanie zacząć pisać w Kotlinie z marszu. Problemy to "boję się", "nie wiem czy to działa", "ostatni raz się czegoś nowego uczyłem jak weszła Java 1.4" i kwestia wspierania Kotlina przez różne narzędzia - jakieś chmurowe lambdy, debuggery, SonarQube. Jest też sensowny powód, sama zmiana języka niczego nie rozwiąże. Nie da się też powiedzieć, że w Kotlinie będziemy pisać n% szybciej.
S9
@piotrpo: oprócz samych Javovców trzeba przekazać też management ;)
jarekr000000
@scibi_92: na ogół management ma naprawdę w dupie - tylko ludzie około kodu są ważni - programiści i architekci
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)