Interfejsy nad implementacje

Odpowiedz Nowy wątek
2017-12-17 20:16
Krwawy Kaczor
1

Czytam o dobrych praktykach i serio tak programujecie w firmach, ze np w parametrach jako typ podajecie interfejs a nie konkretna klase? Wiem ze to pozwala na latwiejsze rozwijanie programu, ale tez jest zasada YAGNI, ktora mowi zeby nie projektowac tak, zeby myslec o przyszlosci tylko o teraz. Druga sprawa to jak mamy jako typ podana konkretna klase to latwo mozemy do niej przejsc w IDE, a przy interfejsie trzeba duzo szukac.

Pozostało 580 znaków

2018-01-02 16:08
0

Natomiast .net core pod względem wydajności już przegonił javke:
https://benchmarksgame.alioth.debian.org/u64q/csharp.html

Czy to jest ok że ten benchmarki nie dają się rozgrzać JITowi ? nie ma tam żadnego warmupu.

EDIT

ok - by design XD https://benchmarksgame.alioth[...]eople-just-make-up-stuff.html


small data and high latency
edytowany 1x, ostatnio: rubaszny_karp, 2018-01-02 17:32

Pozostało 580 znaków

2018-01-02 18:21
4
Wibowit napisał(a):

Przeczytałem sobie wywiad z Andersem Hejlsbergiem nt tego czemu w C# jest w ogóle wymóg stosowania słowa virtual jeśli chcemy mieć metodę wirtualną: http://www.artima.com/intv/nonvirtual.html
Są dwa argumenty.

Pierwszy to wydajność i jego rozumiem. .NET ma słabego JITa i nie radzi sobie z metodami wirtualnymi. JVM natomiast nie ma problemu i nawet wirtualne gettery, settery, hashcode'y, equalsy itd nie powodują spadku wydajności.

To nie tak, że .NET ma słabego JITa - po prostu ponieważ mało metod jest wirtualnych, to dewirtualizacja nie była nigdy istotnym problemem. Gdyby JVM nie miał dewirtualizacji to by strasznie ssał wydajnościowo, więc musiano to zaimplementować. A Hejlsberg w przeciwieństwie do Ciebie widział Javę w czasach, gdy brak dewirtualizacji powodował problemy wydajnościowe.

Hejlsberg popełnił też błąd przy opisywaniu Javy: We can observe that as people write code in Java, they forget to mark their methods final. Therefore, those methods are virtual.. final wcale nie wyklucza wirtualności metody

Nie popełnił błędu, po prostu nie znasz Javy. To się nie skompiluje:

class C extends B {
  @Override
   void m() {
    System.out.println("C");
  }
}

Final kończy możliwości nadpisywania metody: You use the final keyword in a method declaration to indicate that the method cannot be overridden by subclasses. I o to mu chodziło, metoda jest wirtualna dopóki jej jawnie nie sfinalizujesz. A nadmiar wirtualnych metod to problem dla maszyny wirtualnej.

Drugi argument to jakieś bajeczki o wersjonowaniu i tym, że konflikty nazw w Javie powodują problemy przy aktualizacji wersji Javy. Tu się gość grubo pomylił, bo problemy z aktualizacją Javy wynikają z intensywnego użycia refleksji i wzbogacania bajtkodu. Jeżeli narzędzie analizujące bajtkod jest przystosowane do Javy X, a Java X+1 ma dodatkowe konstrukcje w bajtkodzie to to narzędzie się sypnie.

Tak, to on się pomylił, mimo że widział Javę wcześniej niż Ty, a języki programowania projektował kiedy jeszcze Ciebie na świecie nie było. :-)

Jak dla mnie to zabawa z override, new itd to próba ratowania syfiastego kodu (nadużywającego dziedziczenia) zamiast naprawiania go (poprzez kompozycję, czyli trzymanie się zasady SRP).

Tyle, że jak już wiemy kod nadużywający dziedziczenia łatwiej napisać w Javie, bo trzeba włożyć większy wysiłek, żeby dziedziczenia zabronić.

I w sumie po całej tej dyskusji zrozumiałem chyba narzekanie @jarekr000000 na IoC i interceptory. Faktycznie, skoro domyślnie każda metoda jest wirtualna, to nieostrożnie napisany i użyty interceptor może odstawiać w aplikacji jakąś niedebugowalną czarną magię. W C# nie ma tego problemu - od razu widać w kodzie, co potencjalnie może być wywoływane przez interceptor.

Wibowit napisał(a):

A więc według niego możliwość posiadania dwóch osobnych hierarchii metod wirtualnych (o tej samej sygnaturze) w jednej hierarchii dziedziczenia klasy to zaleta nad Javą i główny powód (bo drugi powód to kiepski JIT w .NETu) dla wprowadzenia takich kombinacji w C#. mind=blown

W ogóle nie zrozumiałeś problemu, który w ten sposób został rozwiązany:

Whenever they introduce a new method in a base class, if someone in a derived class had a method of that same name, that method is now an override—except if it has a different return type, it no longer compiles. The problem is that Java, and also C++, does not capture the intent of the programmer with respect to virtual.

W ogóle o tym rzekomym problemie z wersjonowaniem w Javie pierwszy raz przeczytałem właśnie w wywiadzie z Hejlsbergiem. Wygląda więc na to, że Hejlsberg "naprawił" problem który nie istnieje.

Tak właśnie było, sam widziałem! :-)

C# z powodu swojej alergii na metody wirtualne wybrał statyczne metody rozszerzające by dodać funkcjonalności do istniejących klas w bibliotece standardowej. Ma to tę wadę, iż konkretne klasy nie są w stanie bezpośrednio nadpisać nowej metody implementując funkcjonalność w bardziej efektywny sposób, tzn przy użyciu referencji o typie interfejsu zawsze zostanie użyta domyślna metoda statyczna (rozszerzająca).

To nie jest alergia na metody wirtualne - to pragmatyzm, w programowaniu występujący pod nazwą YAGNI, na który rzekomo też się powołujesz.
Podobnie jak pragmatyzmem jest czynienie rzeczy bezstanowych statycznymi.

Wibowit napisał(a):

Nie jestem spięty. Po prostu nie lubię jak ktoś mi wciska kit :]

No tak, o swój monopol trzeba dbać. ;)


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."
edytowany 1x, ostatnio: somekind, 2018-01-03 00:05

Pozostało 580 znaków

2018-01-03 00:17
0

Tak, to on się pomylił, mimo że widział Javę wcześniej niż Ty, a języki programowania projektował kiedy jeszcze Ciebie na świecie nie było. :-)

Bardzo rzeczowy argument. Może papieża mam teraz zacytować?

To nie tak, że .NET ma słabego JITa - po prostu ponieważ mało metod jest wirtualnych, to dewirtualizacja nie była nigdy istotnym problemem. Gdyby JVM nie miał dewirtualizacji to by strasznie ssał wydajnościowo, więc musiano to zaimplementować. A Hejlsberg w przeciwieństwie do Ciebie widział Javę w czasach, gdy brak dewirtualizacji powodował problemy wydajnościowe.

No i Microsoft zrzucił zadanie przyspieszania kodu na barki programistów C#. Pragmatyzm MS w pigułce, który pokutuje już kilkanaście lat. Prawdziwy pragmatyzm to skupienie się na logice biznesowej, a nie zastanawianiu się w jaki sposób pomóc słabemu kompilatorowi.

Poza tym, masz jakiś dowód, że w 2002 roku (rok wydania .NET Framework 1.0) dewirtualizacja w JVMie od Suna nie istniała? Ja nie jestem w stanie się doszukać.

No i najbardziej istotna kwestia: gdzie te przykłady pokazujące jakie te metody wirtualne są straszne? Chętnie bym takie zobaczył, a jedyne co widzę to tylko ideologie czy inne fanatyzmy.


"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 10x, ostatnio: Wibowit, 2018-01-03 01:22
Szukałem o dewirtualizacji i znalazłem taki artykuł z roku 2000: http://citeseerx.ist.psu.edu/[...]484&rep=rep1&type=pdf . To nie dowodzi, że w 2002 takowej nie było, ale może sugerować, że gdy MS rozpoczął prace nad dotnetem, to mogło jeszcze nie być sensownych mechanizmów, szczególnie, że rozwój zaczął się w latach dziewięćdziesiątych, a pierwsze bety były w 2001 (za wiki). - Afish 2018-01-03 03:18
Też to widziałem. Wydaje mi się jednak iż dewirtualizacja powinna mieć dłuższą historię. - Wibowit 2018-01-03 03:34
Czy ja wiem? A gdzie miała szansę się rozwinąć wcześniej? - Afish 2018-01-03 03:36

Pozostało 580 znaków

2018-01-03 09:35
0

Mojej pamięci bardzo nie ufam... ale w 2000 roku java 1.3 miała optymalizację wywołań polimorficznych. Ba! normalnie HotSpot je nawet inlinował jak się dało.
Kojarzę, bo to (miedzy innymi) mnie przekonało do wyjścia z grajdołka C++.


Bardzo lubie Singletony, dlatego robię po kilka instancji każdego.
edytowany 2x, ostatnio: jarekr000000, 2018-01-03 09:47

Pozostało 580 znaków

2018-01-11 03:55
0
Wibowit napisał(a):

Bardzo rzeczowy argument. Może papieża mam teraz zacytować?

Jeśli dla kogoś papież jest autorytetem w IT, to współczuje kolegom z zespołu. Musi być im ciężko, gdy mimo modlitw kolegi, build się po raz kolejny wysypał.

Zarzucasz bezpodstawnie gościowi, który ma spore doświadczenie w tej branży, że "rozwiązywał nieistniejące problemy", nie jest to zbyt poważne.

No i Microsoft zrzucił zadanie przyspieszania kodu na barki programistów C#.

Niczego nie zrzucił, bo dużego problemu z tym nigdy nie było. Teraz mają czas na zabawy, to to optymalizują.

Prawdziwy pragmatyzm to skupienie się na logice biznesowej

No i np. po to wprowadzono lambdy i LINQ... Tak bardzo wyśmiewane przez Javowców przez 8 lat jako całkowicie zbędny cukier składniowy. Aż nadeszła Java 8 i zaczęła się nowa epoka hipokryzji w dziejach cywilizacji.

Poza tym, masz jakiś dowód, że w 2002 roku (rok wydania .NET Framework 1.0) dewirtualizacja w JVMie od Suna nie istniała? Ja nie jestem w stanie się doszukać.

Nie mam dowodu, ale wiem, że C# był projektowany wcześniej.

No i najbardziej istotna kwestia: gdzie te przykłady pokazujące jakie te metody wirtualne są straszne? Chętnie bym takie zobaczył, a jedyne co widzę to tylko ideologie czy inne fanatyzmy.

Nie chodzi o zło metod wirtualnych, ale nie otwieranie na dziedziczenie klas, które nie powinny być dziedziczone. O to, czemu nadmierne dziedziczenie jest złe, możesz spytać Seligi.


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2018-01-12 21:41
0

Jeśli dla kogoś papież jest autorytetem w IT, to współczuje kolegom z zespołu. Musi być im ciężko, gdy mimo modlitw kolegi, build się po raz kolejny wysypał.
Zarzucasz bezpodstawnie gościowi, który ma spore doświadczenie w tej branży, że "rozwiązywał nieistniejące problemy", nie jest to zbyt poważne.

Rozwój Javy przeczy jego obawom. Zamiast wierzyć, ufać i wielbić nieomylnego kolesia można skonfrontować jego teorie z faktami. Co prawda wysnuł swoje teorie dobre kilkanaście lat temu, a po czasie to każdy mądry, ale mimo wszystko obecna sytuacja w Javie przeczy jego założeniom.

Niczego nie zrzucił, bo dużego problemu z tym nigdy nie było. Teraz mają czas na zabawy, to to optymalizują.

Javowcy nie muszą się zastanawiać czy użyć metody wirtualnej czy nie. W Javce nie ma takiego dylematu. A wybór między metodą wirtualną, a niewirtualną jest moim zdaniem dalece bardziej trudny niż wybór między intem, a Integerem (tutaj wybór jest banalny - używamy inta tam gdzie się da, a gdzie się nie da używamy Integera).

No i np. po to wprowadzono lambdy i LINQ... Tak bardzo wyśmiewane przez Javowców przez 8 lat jako całkowicie zbędny cukier składniowy. Aż nadeszła Java 8 i zaczęła się nowa epoka hipokryzji w dziejach cywilizacji.

Nie wiem kto wyśmiewał, ale przymiarki do wprowadzenia lambd były już od wielu lat. Po drodze była sprzedaż Suna, poślizgi z Javą 7, wybranie planu B (czyli przesunięcia części bajerów z Javy 7 do Javy 8) i dlatego lambdy w Javce weszły późno. A zanim weszły to lukier składniowy oferował np IntelliJ, który sam zwijał SAMy w edytorze.

Ja za to czekam, aż C# pozbędzie się zbędnej zabawy ze słówkiem kluczowym virtual. Kiedy to może nastąpić?

Nie chodzi o zło metod wirtualnych, ale nie otwieranie na dziedziczenie klas, które nie powinny być dziedziczone. O to, czemu nadmierne dziedziczenie jest złe, możesz spytać Seligi.

Podaj link do jakichś konkretnych wypowiedzi Seligi. Nie jest moim autorytetem, więc oczekuję konkretów, a nie napinki (a on lubi się napinać).

Jak się okazuje Java ma od zarania dziejów narzędzie do organizacji kodu. Nazywa się to private package scope. Szczegóły tutaj: Toruń JUG #28 - "Keep IT clean, or how to hide your shit" Jakub Nabrdalik
Do tego w Javce 9 doszedł Jigsaw, więc można jeszcze inaczej ograniczać widoczność klas między modułami czy bibliotekami. C# pewnie też ma coś podobnego.


"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, 2018-01-12 21:42

Pozostało 580 znaków

2018-01-13 04:06
1
Wibowit napisał(a):

Rozwój Javy przeczy jego obawom. Zamiast wierzyć, ufać i wielbić nieomylnego kolesia można skonfrontować jego teorie z faktami. Co prawda wysnuł swoje teorie dobre kilkanaście lat temu, a po czasie to każdy mądry, ale mimo wszystko obecna sytuacja w Javie przeczy jego założeniom.

Ale on nie bazował na obecnej sytuacji tylko na tym, co widział w latach dziewięćdziesiątych.

Nie wiem kto wyśmiewał, ale przymiarki do wprowadzenia lambd były już od wielu lat.

Wszyscy ci, którzy twierdzili, że C# w porównaniu z Javą ma tylko zbędny cukier składniowy. Na czele z Tobą.

Ja za to czekam, aż C# pozbędzie się zbędnej zabawy ze słówkiem kluczowym virtual. Kiedy to może nastąpić?

Nigdy - to po pierwsze byłoby ogromne breaking change, po drugie byłoby sprzeczne z ideą języka, po trzecie nikomu do niczego nie jest potrzebne i nikt nie jest szalony aby taki krok wstecz postulować.
Równie dobrze mógłbyś czekać aż Java pozbędzie się zbędnej zabawy z typami danych.

Podaj link do jakichś konkretnych wypowiedzi Seligi. Nie jest moim autorytetem, więc oczekuję konkretów, a nie napinki (a on lubi się napinać).

W którejś ze swoich słynnych prezentacji o tym mówił. Na tłumaczenie czemu nadużywanie dziedziczenia jest złe i należy preferować kompozycję nie mam czasu, to zbyt podstawowa wiedza.


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2018-01-13 12:13
0

Ale on nie bazował na obecnej sytuacji tylko na tym, co widział w latach dziewięćdziesiątych.

A konsekwencje jego decyzji są do dziś.

Wszyscy ci, którzy twierdzili, że C# w porównaniu z Javą ma tylko zbędny cukier składniowy. Na czele z Tobą.

A zacytuj :) Gdzie napisałem, że lambdy są zbędne?

Nigdy - to po pierwsze byłoby ogromne breaking change, po drugie byłoby sprzeczne z ideą języka, po trzecie nikomu do niczego nie jest potrzebne i nikt nie jest szalony aby taki krok wstecz postulować.
Równie dobrze mógłbyś czekać aż Java pozbędzie się zbędnej zabawy z typami danych.

Przy wprowadzaniu generyków w C# Microsoft zdecydował się na szalony krok stworzenia niekompatybilnego zestawu kolekcji standardowych. Dlaczego tamto wydarzenie było niewystarczająco szalone by go unikać? Czyżby dlatego, że C# 1.0 był jeszcze mało popularną niszą i można było go dowolnie zmieniać?

W którejś ze swoich słynnych prezentacji o tym mówił. Na tłumaczenie czemu nadużywanie dziedziczenia jest złe i należy preferować kompozycję nie mam czasu, to zbyt podstawowa wiedza.

Ja zaczynam sobie od dziedziczenia, a jak widzę że można mieć wymierny zysk z kompozycji to wprowadzam kompozycję. Zamiana dziedziczenia na kompozycję to zupełnie inna sprawa niż zakopywanie się z jakimiś mikro-optymalizacjami dotyczącymi słówka virtual.


"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, 2018-01-13 12:14

Pozostało 580 znaków

2018-01-13 16:50
0
Wibowit napisał(a):

A zacytuj :) Gdzie napisałem, że lambdy są zbędne?

Nie będę przekopywał wszystkich hejtów, które pod adresem C# napisałeś do tej pory, sam sobie przeszukaj. :)

Przy wprowadzaniu generyków w C# Microsoft zdecydował się na szalony krok stworzenia niekompatybilnego zestawu kolekcji standardowych. Dlaczego tamto wydarzenie było niewystarczająco szalone by go unikać? Czyżby dlatego, że C# 1.0 był jeszcze mało popularną niszą i można było go dowolnie zmieniać?

Ale stare kolekcje wciąż zostały w i są dostępne nawet dzisiaj, co więcej nie są nawet oznaczone jako obsolete. Kompilacja starego kodu dla frameworka 2.0 nie powodowała błędów kompilacji ani nie zmieniała jego sposobu działania. Uczynienie metod domyślnie wirtualnymi wymagałoby usunięcia z języka modyfikatorów virtual, new i być może override, stary kod mógłby się przestać kompilować albo zacząć działać inaczej. Nie warto tego robić dla tak bardzo nieistotnej i nikomu normalnego nieprzeszkadzającej podstawy języka.
Zwłaszcza, że już niedługo i tak będzie podobnej wielkości problem z wprowadzeniem nullable reference types w C# 8. Tylko to akurat jest znacznie ważniejsze i warte dużego zamieszania.

Ja zaczynam sobie od dziedziczenia, a jak widzę że można mieć wymierny zysk z kompozycji to wprowadzam kompozycję. Zamiana dziedziczenia na kompozycję to zupełnie inna sprawa niż zakopywanie się z jakimiś mikro-optymalizacjami dotyczącymi słówka virtual.

Dobrzy programiści najpierw się zastanawiają, czy potrzebne będzie dziedziczenie czy kompozycja, czy dziedziczenie w ogóle ma sens w danym przypadku - a ma go raczej w niewielu, a potem to implementują. W przeciwnym razie wychodzą albo kosmicznie koszmarne hierarchie dziedziczenia albo programowanie przez permutacje.


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2018-01-13 17:13
0

Dobrzy programiści najpierw się zastanawiają, czy potrzebne będzie dziedziczenie czy kompozycja, czy dziedziczenie w ogóle ma sens w danym przypadku - a ma go raczej w niewielu, a potem to implementują. W przeciwnym razie wychodzą albo kosmicznie koszmarne hierarchie dziedziczenia albo programowanie przez permutacje.

Wolę refaktorować kod który już istnieje niż ten który dopiero sobie wyobrażam. W ten sposób efekty są zwykle lepsze i przychodzą szybciej. Projektowanie daleko naprzód śmierdzi trochę waterfallem. Zamiast kombinować od początku, poprogramuję sobie tak jak mi wygodnie, a w momencie kiedy zorientuję się, że kompozycja ma sens to ją wprowadzam i gitara.


"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 4x, ostatnio: Wibowit, 2018-01-13 17:17

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0