Modyfikatory dostepu i moduly- az tak zle w Javie?

Modyfikatory dostepu i moduly- az tak zle w Javie?
Aventus
  • Rejestracja:około 9 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:UK
  • Postów:2235
2

Witam,

Na wstepnie zaznacze ze z Java i JVM mialem doczynienia na uczelni gdy uczylem sie podstaw programowania a nastepnie liznalem troche Scali w wolnym czasie. Ogladalem wlasnie prezetancje z WJUG'a pod tytulem Modularity and hexagonal architecture in real life: Jakub Nabrdalik i jestem w szoku ze przez pierwsze prawie 20 minut autor wychwala sens pakowania wszystkiego i wystawiania jedynie publicznych "interfejsow" (nie w sensie doslownym). Czy w Javie i w ogole ekosystemie JVM jest z tym az tak zle ze trzeba uswiadamiac i zachecac ludzi? Jesli tak to jak to wyglada na codzien- ladujecie wszystko do jednego worka i wystawiacie jako publiczne?

Zawsze wydawalo mi sie ze rzeczy takie jak projekty i namespace'y i ich nie-dotnetowe odpowiedniki to standard we wspolczesnych jezykach. Mylilem sie?

Z gory dzieki i zachecam do dyskusji :)


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
edytowany 1x, ostatnio: Aventus
Zobacz pozostały 1 komentarz
Aventus
Racja, poplatalo mi się. Pisałem na kolanie :)
Burdzi0
@Aventus: Masz jakąś obcojęzyczną klawiaturę? Aż w oczy boli xd
Aventus
@Burdzi0 w sensie posty gdzie brak polskich znakow czy posty z wymieszanymi znakami? Na komputerze pracuje na brytyjskim ukladzie klawiszy, natomiast na telefonie mam autokorekte a ze dziala jak dziala to inna sprawa... Jak pisze w czasie kiedy kod sie kompiluje to nie mam czasu na poprawianie :) Ale zdaje sobie sprawe ze ciezej sie to czyta, mea culpa!
Burdzi0
@Aventus: Spoko, daję radę :P Po prostu byłem ciekawy przyczyny braku polskich znaków (interpunkcja wzorowa, więc na pewno nie niechlujstwo) :D
Aventus
@Burdzi0: Hah, fajnie wiedziec co do interpunkcji biorac pod uwage ze wyjechalem z Polski majac 12 lat :) Kiedys zmienialem sobie ustawienia klawiatury na kompie za kazdym razem jak pisalem po polsku, ale Windows chcac byc madry przelaczal mi to kiedy tylko chcial (np. po odwiedzeniu polskiej strony). Wiec kiedy pisalem kod i nagle nie moglem wstukac jakichs znakow pod standardowymi klawiszami (@, ; itp.) to sobie odpuscilem.
Michał Sikora
Michał Sikora
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 4 lata
  • Lokalizacja:Kraków
  • Postów:834
3

Hmmm, z mojego doświadczenia wynika, że przeciętny programista Javy "zna" tylko public i private. Oczywiście private jest używane dla pól, które mają publiczne gettery i settery. Ku chwale enkapsulacji.

Jeżeli chodzi o ekosystem, to nie. Jest multum dobrych bibliotek, które dbają o enkapsulację i robią to z sensem.

package private to też takie trochę oszukańcze bezpieczeństwo, bo jak zechcę to i bez magii refleksji dobiję się do klas. Dopiero Java 9 wprowdziła moduły, których i tak pewnie 99% projektów nie zaadapotowała. W Javie brakuje moim zdaniem przede wszystkim modifykatora internal.

edytowany 1x, ostatnio: Michał Sikora
danek
Używanie refleksji do takich rzeczy to trochę proszenie się o problemy
Michał Sikora
Michał Sikora
Refleksja też po coś istnieje. Ostatnio musiałem włączać hotspota na telefonie z poziomu kodu. Bez refleksji bym tego nie zrobił. I nigdzie nie sugerowałem, żeby używać refleksji do dostawania się do klas (ale czasem niestety trzeba).
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:21 minut
0

C# nie ma package private, więc nie da się użyć paczek jako kontroli dostępu. W Javie package private jest używane głównie przez biblioteki czy frameworki.

Java 9 wprowadziła moduły, które są alternatywą dla modyfikatora dostępu internal, ale ma krótki okres wsparcia. Podobnie Java 10 - można to zobaczyć np na https://en.wikipedia.org/wiki/Java_version_history . Dopiero Java 11 będzie LTSem, czyli wersją o przedłużonym wsparciu i prawdopodobnie po wyjściu Javy 11 programiści Javy się na nią liczniej przeniosą i zaczną wykorzystywać jej funkcjonalności.

Modne są teraz mikroserwisy wystawiające końcówki RESTowe. W takiej sytuacji publiczne API mikroserwisu to jedynie ścieżki RESTowe oraz DTOsy. To dość mocna hermetyzacja, zwłaszcza biorąc pod uwagę to, że nie da się użyć refleksji do dostania się do nieupublicznionych funkcjonalności mikroserwisu (refleksja nie działa po RESTu na zdalne procesy :] ).


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 1x, ostatnio: Wibowit
Aventus
  • Rejestracja:około 9 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:UK
  • Postów:2235
0
Wibowit napisał(a):

C# nie ma package private, więc nie da się użyć paczek jako kontroli dostępu(...)

Mozesz rozwinac o co Ci chodzi? Szczerze mowiac nie rozumiem do czego sie odnosisz. Ja mowiac o paczkach, modulach itp. mam na mysli jakikolwiek mechanizm- czyli np. wlasnie projekty/biblioteki w .Net. Nie pytam czy C# ma paczki (logicznie mozna powiedziec ma, ale nie technicznie).

Modne są teraz mikroserwisy wystawiające końcówki RESTowe. W takiej sytuacji publiczne API mikroserwisu to jedynie ścieżki RESTowe oraz DTOsy. To dość mocna hermetyzacja, zwłaszcza biorąc pod uwagę to, że nie da się użyć refleksji do dostania się do nieupublicznionych funkcjonalności mikroserwisu (refleksja nie działa po RESTu na zdalne procesy :] ).

No tak ale pytam raczej o typowe aplikacje monolitowe, w tym pozytywnym znaczeniu tego slowa- modularne i/lub odpowiednio powarstwowane. Przeciez mikroserwisow w Javie nie robi sie po to zeby osiagnac to co w .Net osiaga sie projektami :)

A jeszcze dodam- refleksja rowniez za bardzo nie ma tutaj znaczenia gdyz pytam glownie o ograniczanie dostepu w kodzie jednej aplikacji (ktory moze byc rozbity po kilku repozytoriach). A wiec kod do ktorego jeden programista moze dowolnie zajrzec i gdyby bardzo chcial to moglby zmienic akcesory.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
edytowany 1x, ostatnio: Aventus
hcubyc
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 2 lata
2
Aventus napisał(a):

Czy w Javie i w ogole ekosystemie JVM jest z tym az tak zle ze trzeba uswiadamiac i zachecac ludzi? Jesli tak to jak to wyglada na codzien- ladujecie wszystko do jednego worka i wystawiacie jako publiczne?

Niestety tak. Tzn, nie my, tylko cała reszta tych złych i niedouczonych programistów :) Generalnie problem wynika głównie stąd, że jeżeli czytasz ogłoszenia o javę to większość z nich (przynajmniej kiedys, chociaz podejrzewam że aż tak wiele się nie zmieniło) zawiera słowa kluczowe spring i hibernate. Teraz wyobraź sobie, że jesteś studentem więc chcesz trafić w zapotrzebowanie na rynku, bo przeciez sprawdziłeś czego wymagają i tego sie uczysz. IMHO często dużo ludzi woli uczyć się Springa niż programowania jako tako. Szukasz tutoriali i w tutorialu dotyczącym np. wykorzystaniu frameworku spring mvc masz wszystko publiczne i w kilku pakietach bez górnolotnej architektury. No i wtedy widzisz, że ktoś tak napisał, więc też tak piszesz i stąd tak jak kolega pisał wyżej, public, private i protected. Można pisać w kotlinie, który ma internal, ale chcąc budowac moduły w jednym projekcie nie ogranicza on dostepu do klas pomiędzy modułami, co wg. mnie nie jest idealnym rozwiązaniem, bo na poziomie kompilacji nie wychwycisz, że ktoś wykorzystał klasę z modułu A w module B, która nie była publiczna. Do tego w kotlinie domyslnym modyfikatorem dostępu jest public, tak samo jak w groovym i o ile w groovym jestem w stanie to zrozumieć, bo to język rzadko stosowany do logiki biznesowej.

A tak à propos domyslnym modyfikatorem dostepu w intellij i eclipsie też jest public ;) dlatego nie dziwie się, że ktoś chce otworzyc oczy co po niektórym, że da się inaczej


Limitations are limitless > ##### Ola Nordmann napisał(a)
> Moim językiem ojczystym jest C++ i proszę uszanować to, że piszę po polsku.
edytowany 3x, ostatnio: hcubyc
DA
  • Rejestracja:ponad 10 lat
  • Ostatnio:2 miesiące
  • Postów:176
2

Oglądałem tą prezentację, i od tamtego momentu usunąłem public z defaultowego template tworzenia klasy w IntelliJ. Nabrdalik miał rację - wtedy faktycznie trzeba pomyśleć, kiedy dać klasę publiczną (zazwyczaj fasada i dtosy). Jak dla mnie package private jest dobrym defaultowym modyfikatorem dostępu - gdyby jeszcze programiści o tym pamiętali, i nie dawali wszędzie "na pałę" public...

AI
Jak zmieniłeś na package-private? Też porobowalem i jedyne co znalazłem, to możliwość zmiany modyfikatora ale tylko dla metod. Dla klas, nawet po zmianie, wciąż domyślnie było public.
DA
@Aisekai: Settings -> Editor -> File and Code Templates -> Class. Usuń public.
mad_penguin
mad_penguin
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Rzeszów
0

@Aventus: czy w C# robisz dla każdego aggregate roota osobny projekt? Bo chyba tak by to trzeba było robić, żeby odtworzyć pokazane przez Jakuba rozwiązanie z Javy. Nigdy się z tym nie spotkałem i wydaje mi się to dziwne :) Ewentualnie można ukrywać wszystko w zagnieżdżonych klasach w fasadzie.

edytowany 2x, ostatnio: mad_penguin
Aventus
Oczywiscie ze nie, bardziej chodzi ogolnie o logiczny podzial odpowiedzialnosci/funkcjonalnosci i wystawianie publicznego API. Cala reszta ktora nie musi byc uzywana przez klientow powinna zostac widoczna tylko w tej paczce/module (jak zwal tak zwal).
Wibowit
Czyli Jakub mówi o dużo bardziej szczegółowej segregacji dostępu aniżeli internal w praktyce :]
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:21 minut
0

Mozesz rozwinac o co Ci chodzi? Szczerze mowiac nie rozumiem do czego sie odnosisz. Ja mowiac o paczkach, modulach itp. mam na mysli jakikolwiek mechanizm- czyli np. wlasnie projekty/biblioteki w .Net. Nie pytam czy C# ma paczki (logicznie mozna powiedziec ma, ale nie technicznie).

Ale napisałeś, że jesteś zdziwiony że widziałeś gościa który wychwala konkretnie package private, a nie żaden inny mechanizm. Dlatego wspomniałem iż C# package private nie posiada, więc wprost się sytuacji nie porówna. Organizowanie kodu za pomocą paczek to zupełnie co innego niż organizowanie kodu za pomocą modułów/ projektów/ solucji (WTF?)/ zwał jak zwał.

No tak ale pytam raczej o typowe aplikacje monolitowe, w tym pozytywnym znaczeniu tego slowa- modularne i/lub odpowiednio powarstwowane. Przeciez mikroserwisow w Javie nie robi sie po to zeby osiagnac to co w .Net osiaga sie projektami :)

Słusznie. Mikroserwisy różnią się od monolitów wieloma rzeczami, nie tylko dostępem do klas. Mikroserwisy można na przykład stawiać na różnych maszynach, ale nie o tym mowa w tym wątku. Widoczność klas między modułami można ustalić za pomocą wprowadzonego w Javie 9 mechanizmu modułów (Jigsaw), jak tu już zresztą zostało ze dwa razy napisane. Jigsaw nie służy tylko do określania widoczności klas, ale także np do zarządzania zależnościami. W module-info.java możesz określić co dany moduł eksportuje, których modułów wymaga, do czego pozwala na dostęp refleksją, jakich usług dostarcza, itd https://www.oracle.com/corporate/features/understanding-java-9-modules.html

Wracając jednak do mikroserwisów moim zdaniem jednak sprawdzają się znacznie lepiej niż hierarchie modułów. Mikroserwisy mają to do siebie, że nie ma w nich hierarchii, każdy mikroserwis może gadać i zależeć od dowolnego innego. Nie ma problemu z tym, by serwis A wołał serwis B kiedy trzeba i jednocześnie serwis B wołał serwis A kiedy mu potrzeba. Dowolny graf zależności jest prosty do zaimplementowania. Jednak mikroserwisy i tak wymuszają sporą dozę dyscypliny, bo wystawianie funkcjonalności RESTem wymaga pewnego planu i jest zdecydowanie bardziej czasochłonne niż przestawienie modyfikatora dostępu z protected/ package private/ internal/ etc na np public.

W przypadku hierarchii modułów też się da zrobić tak, by moduł Parent wołał moduł Child kiedy chce (moduł Child zależy od modułu Parent), ale trzeba się nieco nagimnastykować. Moduł Parent definiuje ChildInterface (zawierający to co Parent chce od Childa), moduł Child definiuje klasę ChildImplementation rozszerzającą ChildInterface i podrzuca instancję modułowi Parent. Trochę gimnastyki, ale pozwala to na wołanie zarówno Childa z poziomu Parenta jak i naturalnie Parenta z poziomu Childa.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
Aventus
  • Rejestracja:około 9 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:UK
  • Postów:2235
1
Wibowit napisał(a):

Ale napisałeś, że jesteś zdziwiony że widziałeś gościa który wychwala konkretnie package private, a nie żaden inny mechanizm. Dlatego wspomniałem iż C# package private nie posiada, więc wprost się sytuacji nie porówna. Organizowanie kodu za pomocą paczek to zupełnie co innego niż organizowanie kodu za pomocą modułów/ projektów/ solucji (WTF?)/ zwał jak zwał.

Tak jak napisalem wyzej, chodzilo mi o ogolne "pakowanie" funkcjonalnosci i wystawianie publicznego API. Chyba najbardziej uniwersalnym sformulowaniem bedzie modul.

Wracając jednak do mikroserwisów moim zdaniem jednak sprawdzają się znacznie lepiej niż hierarchie modułów(...)

Musze sie tutaj nie zgodzic- rozumiem do czego zmierzasz, ale w ogole nie mieszalbym mikroserwisow do dyskusji. To ze mikroserwisy w naturalny sposob zapewniaja ograniczony dostep to tylko i wylaczanie skutek, nie przyczyna uzycia takiej architektury. Ktos czytajacy co piszesz moglby pomyslec ze jesli chce lepiej porozdzielac odpowiedzialnosci w swojej aplikacji to "wystarczy" walnac system oparty o mikroserwisy. To jak mikroserwisy w skutek swojej architektury zapewniaja ograniczony dostep mozna osiagnac bez nich uzywajac wlasnie modulow i jasno defniujac puliczne API w tychze. Zreszta np. Martin Folwer jest zwolennikiem podejscia monolith-first o czym zapewne wiesz. Jesli ktos nie potrafi dobrze zaprojektowac monolitu to tym bardziej nie poradzi sobie z mikroserwisami.

Kwestie konfliktow zaleznosci (np. NuGet w .Net) mozna rozwiazac na kilka sposobow. A jesli zaleznosci jest tak wiele ze rozwiazywanie konfliktow staje sie koszmarem to jest to jasny znak ze mamy problem z architektura ogolnie, bo mamy spaghetti na najwyzszym poziomie architektonicznym. A jesli z jakiegos powodu system musi byc oparty o tyle zaleznosci to powinno sie pomyslec nad zmiana architektury (komunikacja oparta o Message Bus i/lub mikroserwisy) jednak bynajmniej nie z tylko z powodu zaleznosci (czyli referencji) per se a z tego ze na takim etapie ciezko mi uwierzyc ze system nie ma innych problemow (skalowanie wertykalne itp.).


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
edytowany 1x, ostatnio: Aventus
hcubyc
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 2 lata
0

No i moduły w obrębie jednego projektu są na tym samym poziomie tj. nie ma relacji parent-child. Mając dobrze zmodularyzowany monolit nie ma większego problemu żeby przejść na architekturę mikroserwisów czy też po prostu podzielić monolit na dwa inne. Tak samo moduły w javie 9 nie udostępniają jawnie hierarchizowania modułów.


Limitations are limitless > ##### Ola Nordmann napisał(a)
> Moim językiem ojczystym jest C++ i proszę uszanować to, że piszę po polsku.
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:21 minut
0

ZTCW to nie da się zrobić cyklicznej zależności modułów w Mavenie, np: https://stackoverflow.com/q/16468525 Nie da się też tego zrobić w Scalowym SBT.

Mikroserwis składa się z dwóch modułów: API i implementacji. Mikroserwis A może zależeć od API mikroserwisu B, a mikroserwis B może zależeć od API mikroserwisu A i nie ma tutaj cyklu. Tą architekturę można przenieść na moduły monolitu. Wtedy np moduł-A-API jest używany przez każdego chętnego, a moduł-A-impl jest używany tylko przez moduł spinający aplikację w całość. Taka płaska hierarchia modułów byłaby dla mnie zdecydowanie bardziej przekonująca niż typowa hierarchia modułów, gdzie nie ma osobnych modułów z publicznym API.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 2x, ostatnio: Wibowit
KR
  • Rejestracja:ponad 8 lat
  • Ostatnio:dzień
  • Postów:166
0
dargenn napisał(a):

Oglądałem tą prezentację, i od tamtego momentu usunąłem public z defaultowego template tworzenia klasy w IntelliJ. Nabrdalik miał rację - wtedy faktycznie trzeba pomyśleć, kiedy dać klasę publiczną (zazwyczaj fasada i dtosy). Jak dla mnie package private jest dobrym defaultowym modyfikatorem dostępu - gdyby jeszcze programiści o tym pamiętali, i nie dawali wszędzie "na pałę" public...

No ja wolę jak pisze się na pałę public niż pisanie na pałę private.
Programowanie obiektowe to też tworzenie złożonych zachowań poprzez kompozycję prostych klas. Pisanie wszędzie private to uniemożliwienie tworzenia nowych zachowań w oparciu o istniejące klasy. Pozostaje tylko złożona logika podzielona na wiele plików.
Zdaję sobie sprawę, że są klasy, fragmenty kodu, które nie mają sensu w innym kontekście niż niż użyte i jak najbardziej powinny być private.

danek
właśnie po to pomiędzy private a public jest jeszcze pakietowy
danek
  • Rejestracja:ponad 10 lat
  • Ostatnio:6 miesięcy
  • Lokalizacja:Poznań
  • Postów:797
1

Pakiety można traktować jako takie Duże obiekty czyli coś jak obiekt tylko na wyższym poziomie abstrakcji. Wtedy jak ktoś chce ktoś wykorzystać z modułu to wchodzi tylko w publiczne klasy i nie musi przeglądać całości. (Jako moduł można tu traktować jakąś autonomiczną część aplikacji, może mieć swoje endpointy, swoją baze danych itp)


Spring? Ja tam wole mieć kontrole nad kodem ᕙ(ꔢ)ᕗ
Haste - mała biblioteka do testów z czasem.
hcubyc
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 2 lata
0
Wibowit napisał(a):

Mikroserwis składa się z dwóch modułów: API i implementacji. Mikroserwis A może zależeć od API mikroserwisu B, a mikroserwis B może zależeć od API mikroserwisu A i nie ma tutaj cyklu.

Możesz wytłumaczyć? Nie bardzo rozumiem, bo jeżeli mikroserwis A zależy od mikroserwisu B i na odwrót to każdym razem gdy robisz zmianę w jednym z nich (mam na myśli zmiany łamiące obecny kontrakt) to musisz też zrobić zmiany w drugim. To brzmi właśnie jak cykl, bo gdy będziesz musiał coś zmienić w jednym, to musisz zmienić w drugim i wtedy musisz też równolegle je wdrażać albo wprowadzić zmianę w jednym z nich w taki sposób, żeby drugi mógł nadal działać czyli wydłużyć ogólny czas, który potrzebujesz na daną funkcjonalność.


Limitations are limitless > ##### Ola Nordmann napisał(a)
> Moim językiem ojczystym jest C++ i proszę uszanować to, że piszę po polsku.
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:21 minut
2

Jeśli zrobię zmianę łamiącą kontrakt to tak czy siak muszę zmienić kod po obu stronach - zarówno ten wystawiający API według kontraktu jak i ten korzystający z API. Niespecjalnie widzę jak cykl ma tu coś zmieniać.

Może rozpiszę co mam na myśli pisząc o typowej dla monolitów hierarchii modułów i hierarchii typowej dla mikroserwisów. Najpierw trzeba jeszcze podać założenie, że nie może być wprost cykli w zależnościach, tzn jeśli moduł A zależy od B, to moduł B nie może zależeć od A.

W hierarchii monolitowej nie ma rozdziału na moduł z API i moduł implementujący to API. Stąd nie da się zrobić cykli w ogóle. Ponadto hierarchia często jest dość głęboka. Dla przykładu możemy mieć:

  • moduł common niezależący od niczego
  • moduł core zależący od modułu common
  • moduł orders zależący od modułu core
  • moduł trading zależący od modułu orders
  • itd

Zależności są przechodnie, więc moduł trading tak naprawdę zależy nie tylko od modułu orders ale także common i core, więc ma dostęp do klas z tych modułów. Taka architektura skutkuje pchaniem funkcjonalności do modułów najwyżej w hierarchii, tam gdzie będą najszerzej dostępne (to ułatwia sprawy na krótką metę, tzn jest to chodzenie po linii najmniejszego oporu). Stąd w monolicie będą dominować moduły common i core.

W hierarchii mikroserwisowej każdy serwis składa się z dwóch modułów - moduł-api i moduł-impl. moduł-api nie zależy od żadnego innego modułu, a moduł-impl zależy od dowolnej ilości modułów API. Dzięki temu nie ma cyklów w hierarchii modułów, a sama hierarchia modułów jest płaska. Nie ma centralnego modułu ze współdzielonymi funkcjonalnościami, więc nie ma rozpychania centralnego modułu. Przykładowa hierarchia może wyglądać tak:

  • moduł orders-api bez zależności
  • moduł trading-api bez zależności
  • moduł accounts-api bez zależności
  • moduł orders-impl zależący od orders-api i np accounts-api
  • moduł trading-impl zależący od trading-api i np accounts-api
  • moduł accounts-impl zależący od accounts-api i np orders-api

Jak widać jest faktyczny cykl między accounts i orders, ale dzięki rozbiciu na moduły API i impl nie ma tego cyklu w hierarchii modułów. Na koniec trzeba dorzucić moduł który spina całą resztę do kupy. Nazwijmy go wiring. Moduł ten zależy od wszystkich innych. Uruchamia wszystkie moduły typu impl, wyciąga z nich obiekty implementujące API i przekazuje te obiekty do modułów zależnych od tych API. Czyli w naszym przypadku moduł wiring:

  • stawia orders-impl, trading-impl i accounts-impl i wyciąga z nich obiekty implementujące odpowiednio orders-api, trading-api i accounts-api
  • obiekt implementujący orders-api jest podrzucany do modułu accounts-impl
  • obiekt implementujący accounts-api jest podrzucany do modułów orders-impl i trading-impl

Mikroserwisowa hierarchia modułów trochę podobnych wad i zalet co prawdziwe mikroserwisy. Zaletą jest jak już wspomniałem możliwość bezproblemowego robienia cyklicznych zależności oraz brak tendencji upychania funkcjonalności do wspólnego modułu (gdyż takiego nie ma). Wadą jest to, że np moduły muszą być odporne na chwilowy brak zależności. Np przy starcie moduły typu impl nie widzą innych modułów, dopiero po wystartowaniu moduł wiring podrzuca implementacje API do konkretnych modułów korzystających z nich. Jest to taka sama sytuacja jak w rzeczywistych mikroserwisach. Rzeczywiste mikroserwisy startują w dowolnej kolejności, więc jeśli mikroserwis A zależy od mikroserwisu B, ale mikroserwis A wystartował przed mikroserwisem B, to mikroserwis A musi trochę poczekać zanim zacznie korzystać z mikroserwisu B. Wadą mikroserwisowej hierarchii modułów jest też to, że wygląda dość sztucznie, nietypowo, a ja nie widziałem takiej w praktyce w monolicie.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 1x, ostatnio: Wibowit
danek
Jak w praktyce u Ciebie wygląda ta zależność?
Wibowit
U mnie czyli gdzie? :) W firmie mamy rzeczywiste mikroserwisy, więc nawet nie trzeba się zastanawiać nad emulowaniem architektury mikroserwisowej w monolicie. Natomiast hobbystycznie mam projekt np https://github.com/tarsa/SortAlgoBox gdzie zastosowałem typową hierarchię monolitową bez rozdziału na moduły API i moduły impl. No ale akurat ten projekt zacząłem kilka lat temu, jeszcze przed wejściem w tematykę mikroserwisów.
Aventus
Tu nie chodzi o emulowanie architektury mikroserwisowej w monolicie. Jesli juz to ewolucja idzie w druga strone. Obecnie tez pracuje przy systemie opartym o mikroserwisy i jak najbardziej sie sprawdza, natomiast probowanie rozwiazac kazdy problem gdzie chcemy rozdzielic odpowiedzialnosci za pomoca mikroserwisow jest conajmniej nierozsadne. Mikroserwisy to przede wszystkim podejscie do rozwiazania calej gamy problemow, a podzielenie odpowiedzialnosci jest tego skutkiem ubocznym (aczkolwiek porzadanym), o czym pisalem wyzej.
hcubyc
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 2 lata
1

Jeśli zrobię zmianę łamiącą kontrakt to tak czy siak muszę zmienić kod po obu stronach - zarówno ten wystawiający API według kontraktu jak i ten korzystający z API. Niespecjalnie widzę jak cykl ma tu coś zmieniać.

Tak to prawda, ale nie mając cyklu to działa tylko dla jednego z przypadków, gdy A zależy od B i zmieniasz B to zmieniasz obydwa, gdy zmieniasz A to zmieniasz jeden.

Teraz rozumiem o co ci chodzi, ale to to samo co moduły, które mają API publiczne (fasada/interfejs, dtosy, wyjątki), a całą resztę ukrytą wewnątrz modułu. Problem jest taki, że mimo wszystko wciąz tam jest cykl i jeżeli byś chciał testować moduły orders i accounts to i tak musisz je postawić razem albo całą aplikację, chyba że dla testów postawisz orders z stubem/mockiem accounts i na odwrót, co moim zdaniem mija się z celem. Tak samo gdybyś z tego monolitu chciał wyciągnąć orders jako faktyczny mikroserwis to wciąż zmieniasz dwa moduły, wiec IMHO pytanie czy to nie powinien być jeden moduł skoro są od siebie zależne lub czy np. nie dałoby się złamać tego cyklu wprowadzając komunikację eventami.


Limitations are limitless > ##### Ola Nordmann napisał(a)
> Moim językiem ojczystym jest C++ i proszę uszanować to, że piszę po polsku.
edytowany 1x, ostatnio: hcubyc
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:21 minut
0

Teraz rozumiem o co ci chodzi, ale to to samo co moduły, które mają API publiczne (fasada/interfejs, dtosy, wyjątki), a całą resztę ukrytą wewnątrz modułu.

Nie to samo, bo bez podziału na -api i -impl nie jesteś w stanie zrobić cyklu w zależnościach.

Problem jest taki, że mimo wszystko wciąz tam jest cykl i to jest problem, bo jeżeli byś chciał testować moduły orders i accounts to i tak musisz je postawić razem albo całą aplikację, chyba że dla testów postawisz orders z stubem/mockiem accounts i na odwrót, co moim zdaniem mija się z celem.

A bez cyklu nie muszę stawiać ich razem?

Tak samo gdybyś z tego monolitu chciał wyciągnąć orders jako faktyczny mikroserwis to wciąż zmieniasz dwa moduły

Gdzie i co mam zmienić? Jeśli wyciągnę moduł orders-impl jako faktyczny mikroserwis to zależność od orders-api pozostaje taka sama, ale teraz moduły np accounts-impl muszą komunikować się z orders-impl przez RESTa, a nie przez np Javowy interfejs.

wiec IMHO pytanie czy to nie powinien być jeden moduł skoro są od siebie zależne lub czy np. nie dałoby się złamać tego cyklu wprowadzając komunikację eventami.

Zależności między mikroserwisami nie muszą tworzyć grafu acyklicznego, więc po co się ograniczać? I tak musisz obsłużyć sytuację, w które mikroserwisy są stawiane w różnej kolejności i w różnej kolejności np restartowane. Natomiast czasami taka zależność w obie strony się przydaje. Np serwis R zajmuje się parsowaniem raportów, a serwis G wrzucaniem ich do swojego cache, łączeniem ich z innymi danymi i pokazywaniem. Serwig G po restarcie dobija się do serwisu R, by zaktualizować własny cache. Ale z drugiej strony, jeśli przyjdą nowe raporty to serwis R wrzuca nowe raporty do serwisu G. Jak widać mamy komunikację dwustronną dlatego, że cache jest w innym serwisie niż parser, ale czy to powód by zmieniać lokalizację cache i sposób powiadamiania o zmianach?


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
hcubyc
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 2 lata
0

Nie to samo, bo bez podziału na -api i -impl nie jesteś w stanie zrobić cyklu w zależnościach.

Czemu nie? Jedyne czego potrzebujesz to fasady innego modułu.

A bez cyklu nie muszę stawiać ich razem?

W sumie celna uwaga, majac zależność w jednym kierunku mockuje/stubbuje, dziwnie by to wyglądało gdyby były dwa moduły z dwoma mockami, ale to tylko moje poczucie gustu, więc faktycznie argument bez sensu.

Jeśli wyciągnę moduł orders-impl jako faktyczny mikroserwis to zależność od orders-api pozostaje taka sama, ale teraz moduły np accounts-impl muszą komunikować się z orders-impl przez RESTa, a nie przez np Javowy interfejs.

To prawda, to nie wiele do zmiany, ale podchodząc do tematu czysto ideologicznie to wciąż zostaje problem, że cokolwiek trzeba dłubnąć, z praktycznego punktu widzenia nie ma to znaczenia.

Zależności między mikroserwisami nie muszą tworzyć grafu acyklicznego, więc po co się ograniczać?

Traktuję tu mikroserwisy jako biznesowe komponenty/moduły systemu i wg mnie powinny tworzyć graf acykliczny, Przykład, który podałeś nie opisuje silnej zależności biznesowej logiki, więc w takim przypadku nie widzę w tym nic złego, tak samo w przypadkach gdy mikroserwis rozwiązuje inny problem technologiczny tym bardziej, jeżeli jest to na zasadzie napisz, zapomnij, najbliższa zmiana będzie za pół roku


Limitations are limitless > ##### Ola Nordmann napisał(a)
> Moim językiem ojczystym jest C++ i proszę uszanować to, że piszę po polsku.
edytowany 1x, ostatnio: hcubyc
AI
Pytanie odnośnie mikroserwisów javowych (tzn w obrębie jednego "projektu", bardziej bym powiedział Fasad), jeżeli mikroserwis A potrzebuje komunikować się z mikroserwisem B, a mikroserwis B z mikroserwisem A (mamy cykl) to czy rozwiązanie na zasadzie stworzenia klasy będącej "łącznikiem" wszystkich mikroserwisów (czy Fasad) nie byłoby złe? Coś na kształt topologii gwiazdy. Zdaję sobie sprawę, że zrzuca to duza odpowiedzialność na tą klasę.
Aventus
  • Rejestracja:około 9 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:UK
  • Postów:2235
1

@hcubyc: Ja bym sie wycofal z dyskusji bo moim zdaniem jest bez sensu- mikroserwisy to nie jest rozwiazanie problemow ktorych dotyczy temat. Owsze, jako skutek zmian moga po czesci przysluzyc sie rozwiazaniu problemu w temacie, ale jest to okraszone cena w postaci wad jakie architektura oparta o mikroserwisy ze soba niesie. Nie wiem czemu wibowit sie tak uwzial tych mikroserwisow. No chyba ze to jeden z tych ktorzy na kazdy problem maja jedno sluszne rozwiazanie :)


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
Zobacz pozostałe 33 komentarze
Wibowit
Scala już wiele lat temu zrobiła wspólny alias (Int) na opakowanego i nieopakowanego inta, ale oprócz wygodniejszej składni nie dało to żadnego zysku wydajnościowego bądź pamięciowego. Zysk wydajnościowy i pamięciowy zależy od wsparcia VMki do różnego rozkładu danych w pamięci, a nie od hierarchii typów na etapie kompilacji do bajtkodu. Zastanawia mnie czy kiedykolwiek dotrze do ciebie, że generyki to zupełnie inna sprawa niż hierarchia typów. Valhalla nie zmienia hierarchii typów, ale zmienia generyki - dla ciebie to prawdopodobnie zbyt skomplikowane.
somekind
Ale mnie nie obchodzi Valhalla w ogóle. Spójny system typów + jedna implementacja generyków, nie trzeba niczego zmieniać, hackować ani kombinować przez wiele lat. I nie ma znaczenia zysk wydajnościowy czy pamięciowy, bo tu chodzi o wygodę pisania kodu.
Wibowit
Czyli cały niby dramat ma polegać na tym, że trzeba napisać List<Integer> zamiast List<int>? No to faktycznie kolosalny problem. Ale Valhalla akurat to poprawi.
somekind
Problem nie polega na pisaniu deklaracji tylko na tym, że jest dychotomia i trzeba jedne obiekty konwertować na drugie, zamiast po prostu używać wszędzie jednego typu. Jeśli to nie jest problem, to po co ta Valhalla powstaje?
Wibowit
Konwertowanie to tyle co: int a = 5; Integer b = a; int c = b; itd, więc to jest pryszcz. Generalnie się tego konwertowania nawet nie widzi. Valhalla powstaje właśnie dla optymalizacji pamięciowych i wydajnościowych.
danek
  • Rejestracja:ponad 10 lat
  • Ostatnio:6 miesięcy
  • Lokalizacja:Poznań
  • Postów:797
2

Wydaje mi się, że wątek pierwotnie miał dotyczyć nadużywania public w kodzie, z czym się zgadzam. Po kij klasa która jest użyta (i powinna być używa tylko tam) w jednym miejscu i robi tylko jedną rzecz ma być widoczna w całym projekcie? Prędzej czy później ktoś jej użyje w jakimś dziwnym kontekście i potem będzie bida (plus zaśmieca podpowiadanie składni). Wydaję mi się, że lepszym rozwiązaniem jest przeniesienie idei obiektów (hermetyzacji itp) na poziom abstrakcji wyżej.
Przykład:
mamy generowanie raportów: załóżmy, że proces składa się z kilku kroków, obsługiwanych przez kolejne obiekty. Po co teraz cały projekt ma wiedzieć, że istnieją kolejne kroki, skoro z perspektywy systemu ważne jest tylko to, że dla jakichś tam parametrów otrzyma się taki raport. Czyli zrobić jedną klasę publiczną z metodą generate (czy tam cokolwiek) i cała logika siedziałaby klasach z dostępem pakietowym wsadzonych w jednym pakiecie.
Można też iść o krok dalej i testować tylko metody publiczne w pakietach, bo one definiują API (zachowanie) całego pakietu.


Spring? Ja tam wole mieć kontrole nad kodem ᕙ(ꔢ)ᕗ
Haste - mała biblioteka do testów z czasem.
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:dzień
  • Lokalizacja:Wrocław
1
Aventus napisał(a):

Czy w Javie i w ogole ekosystemie JVM jest z tym az tak zle ze trzeba uswiadamiac i zachecac ludzi? Jesli tak to jak to wyglada na codzien- ladujecie wszystko do jednego worka i wystawiacie jako publiczne?

A w C# jest lepiej? Większość bezmyślnie oznacza wszystko jako public.

krsp napisał(a):

No ja wolę jak pisze się na pałę public niż pisanie na pałę private.
Programowanie obiektowe to też tworzenie złożonych zachowań poprzez kompozycję prostych klas. Pisanie wszędzie private to uniemożliwienie tworzenia nowych zachowań w oparciu o istniejące klasy.

Racja, wyciek abstrakcji znacząco ułatwia dopisywanie nowych fragmentów kodu w losowo wybranej warstwie aplikacji. To ma szczególne znaczenie, jeśli chcemy aby projekt powstawał zgodnie ze wzorcem big ball of mud.

Wibowit napisał(a):

Mikroserwis składa się z dwóch modułów: API i implementacji.

Ale to jest jakaś uchwała gminy, norma ISO czy tak było w książce od JEE?

Moduł brzmi dla mnie jak jednostka logiczno-architektoniczno-deploymentowa. Jeśli implementacja znajduje się w jednym module, to znaczy, że w 2018 roku ciągle trzaskacie jednowarstwowy kod. No można i tak, wszak to też ułatwia implementację big ball of mud.

Zobacz pozostałe 8 komentarzy
Wibowit
Poza tym trudno zaemulować internala za pomocą package-private (hmm, w ogóle czy się da?). Za to łatwo zaemulować internala rozbijając moduł na dwa: moduł-api i moduł-impl (czy jak kto woli: moduł-public i moduł-internal).
Aventus
"A w C# jest lepiej? Większość bezmyślnie oznacza wszystko jako public." To prawda, i nad tym ubolewam.
Wibowit
To może przyda się wam jakiś Jakub Nabrdalik, tyle że od C#.
jarekr000000
@Wibowit problem jest z tym, że choćby przyszło 1000 Nabrdalików, Venkatów, Uncle Bobów i tak dalej to większość kodu piszą goście, którzy nawet o nich nie słyszeli. Bo ci, którzy słuchają, jeżdżą na konferencje, czytają fora, książki, blogi itp. ze względów oczywistych nie mają już czasu napie...lać.
somekind
@Wibowit: problemy w C# i Javie na poziomie designu, architektury czy dobrych praktyk są z grubsza te same. Nie trzeba nowych prelegentów do C#, całe życie można pasożytować na Szulcu, Pałce czy Ratajskim.
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
0

TL;DR
W Javie jest super-rozwiązanie package-private ale nikt z niego nie korzysta, ponieważ masz przeinżynierowanie i zamiast tego robi się pakiety typu:

Kopiuj
com.januszsoft.dao.*
com.januszsoft.services.*
com.januszsoft.utils.*

Była o tym prezentacja, nawet chyba wspomniana przez OP.
Nie wiem czemu tak jest - albo za mała wiedza wśród ludzi do czego służy package private, albo może ten poziom dostępu nie jest zbyt wygodny.
To drugie może wynikać np. z tego że klasy
z: com.januszsoft.dao.*
nie mają dostępu do klas package-private
z: com.januszsoft.dao.users.*

edytowany 1x, ostatnio: vpiotr
Wibowit
A w Scali już taka widoczność jest :]
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 18 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
3

Jest źle. Są zespoły gdzie jest ok, ale to raczej chlubne wyjątki.

Moim zdaniem największe skurczysyństwo to odwaliły JavaBeany - czyli robimy getera i setera i mamy enkapsulacjem.

Rok temu jeden junior/stazysta nie mógł zrozumieć, że nie robię getterów i setterów, a do tego, o zgrozo, czasem robię publiczne pola (finalne...).

Po dłuższej ewangelizacji podsumował:

  • ja to podejście nawet rozumiem, ale u mnie na studiach nie zaliczyłbyś nawet pierwszego semestru...

jeden i pół terabajta powinno wystarczyć każdemu
edytowany 1x, ostatnio: jarekr000000
Aryman1983
Aryman1983
@jarekr000000: wracaj do szkoły nieuku :-)
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:21 minut
0
Aventus napisał(a):

@hcubyc: Ja bym sie wycofal z dyskusji bo moim zdaniem jest bez sensu- mikroserwisy to nie jest rozwiazanie problemow ktorych dotyczy temat. Owsze, jako skutek zmian moga po czesci przysluzyc sie rozwiazaniu problemu w temacie, ale jest to okraszone cena w postaci wad jakie architektura oparta o mikroserwisy ze soba niesie. Nie wiem czemu wibowit sie tak uwzial tych mikroserwisow. No chyba ze to jeden z tych ktorzy na kazdy problem maja jedno sluszne rozwiazanie :)

Jak ci bardzo przeszkadza nazwa "mikroserwis" to możesz ją zamienić np na "krzesełko" i wyjdzie na to samo. Moim zdaniem po prostu jeśli rozdzielę moduły na część publiczną modułX-api i prywatną modułX-impl gdzie konkretny modułX-impl może zależeć tylko od modułY-api (dla dowolnego Y) to otrzymam lepszą hierarchię zależności modułów niż w typowym monolicie. Powody już opisałem kilka razy, więc może nie będę się powtarzał.

Aktualizacja:
Niektórzy może nie zaczaili analogii api do internal, więc może lekka zmiana nazw pomoże. moduł-api to to samo co moduł-public, a moduł-impl to to samo co moduł-internal. Teraz jest jasne?


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 1x, ostatnio: Wibowit
Zobacz pozostałe 3 komentarze
Wibowit
moduł to moduł, a nie paczka
danek
zależy, u mnie moduł to paczka
Wibowit
Temat jest w dziale Java, więc trzymajmy się terminologii Javowej :]
danek
i tak i nie, własnie chodzi o to, że tu chodzi o coś innego niż taki klasyczny moduł np z mavena
Wibowit
komu chodzi i czemu tak?
FE
  • Rejestracja:ponad 11 lat
  • Ostatnio:prawie 3 lata
0
vpiotr napisał(a):

Nie wiem czemu tak jest - albo za mała wiedza wśród ludzi do czego służy package private, albo może ten poziom dostępu nie jest zbyt wygodny.
To drugie może wynikać np. z tego że klasy
z: com.januszsoft.dao.*
nie mają dostępu do klas package-private
z: com.januszsoft.dao.users.*

To nie jest 'niezbyt wygodne', to jest po prostu mocno słabe. To powoduje, że w prędzej czy później trzeba podjąć decyzję - czy wrzucamy milion klas w jeden płaski pakiet czy łamiemy package-private i jednak tworzymy pod-pakiety żeby to miało sens. A szkoda, bo przy małych pakietach świetnie się sprawdza.


danek
  • Rejestracja:ponad 10 lat
  • Ostatnio:6 miesięcy
  • Lokalizacja:Poznań
  • Postów:797
0

Ale to nie jest teraz tak, że wszystko ma być private. Nadal część klas jest public ale tylko te, o których powinien wiedzieć świat


Spring? Ja tam wole mieć kontrole nad kodem ᕙ(ꔢ)ᕗ
Haste - mała biblioteka do testów z czasem.
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:21 minut
0

@danek: Najpierw dowiedz się czym jest package-private. To jest coś innego niż public, private, protected czy internal.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 1x, ostatnio: Wibowit
jarekczek
Prawie to samo, co internal. Tylko w javie nie ma mocno wyodrębnionego pojęcia "biblioteki", bo wiemy, że ludzie lubią sobie przepakować. Ale ideowo jest to to samo, co internal. Oznacza do użycia tylko przez autora.
Wibowit
Widoczność na cały moduł, a widoczność na jedną paczkę to kolosalna różnica. Tak samo jak różnica między pakowaniem stu klas do jednej paczki, a pakowaniem stu klas do jednego modułu.
danek
Nadal, zależy jak zdefiniujesz moduł ;) I nie, nie ma jednej uniwersalnej definicji
Wibowit
A jest gdzieś modyfikator dostępu do modułu wg twojej definicji?
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)