🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.objects
Article #12303

Re: O, to ta grupa jeszcze istnieje?...

#12303
From: Sektor van Skijlen
Date: Sat, 22 Oct 2005 22:09
396 lines
18980 bytes
Dnia Sat, 22 Oct 2005 21:55:27 +0200, jarekr skrobie:
> > Sun zawłaszczył Javę po to, żeby się częściowo zabezpieczyć przed konkurencją,
> > przecież to jasne. Nawet kiedy Rational próbował zrobić implementację Javy na
> > .NET, to Sun wytoczył mu proces.

> TO czemu GNU, IBMowi i BEI nie zabronił - nie kumam.

Bo ustawili się karnie w szeregu i złożyli uroczystą przysięgę, z ręką na
Biblii, że nigdy, ale to nigdy nie dodadzą żadnego rozszerzenia.

> A moze jednak java na .NET to może nie być do końca Java ?  (Ja to nazwałbym
> nauczyli sie na przykładzie ms javy )

Nie wiem, możliwe. I tak zresztą chyba (jak pamiętam) powstało J#, do czego
pewnie Sun nie mógł się przyczepić, bo nie nazywało się Java.

> >>Dzięki temu nie mam w kodzie ton makr, 
> >>które muszą naprawiać niekompatybilności i inne takie.
> > 
> > 
> > Po prostu, zwyczajny język katedralny. Nie, sory, mnie te makra w najmniejszym
> Idź sie naprawde umyj. TO jest naprawde ciekawe, że w tej chwili jeden z
>    najczęsciej przemysłowo stosowanych jezyków jest katedralny :-)

A co ma przepraszam jedno do drugiego? Kiedyś wszystkie produkty softwarowe
były katedralne.

> >>mam taki (java):
> >>{
> >>        dbManager.execute ( new DBMethod()  {
> >>                        public void run(final DBContext context)
> >>                        {
> >>                                DBConnection db =                               context.createConnection("bla");
> >>                                [kod koprzystający z db]
> >>                        }
> >>                } );
> >>}
> > 
> > 
> >>po prostu o ile w C++ kluczowe zarządzanie zasobami mam w konstruktorze 
> >>i destruktorze to w Javie wywalam do odpowiedniego menadżera.
> > 
> > 
> > O jaciekrence...
> > 
> > A czegoś takiego, żeby można tego było użyć po ludzku?

> To jest po ludzku - ja tego używam, w kodach różnych OR mapperów to
> znajdziesz itp.

Kochany, TO jest po ludzku:

{
	ifstream f( "file" );
	...
	auto_ptr<X> x = CreateX( f );
	...
	if ( costam )
		return x.release();
}

> > Bo takiego czegoś to można również użyć w C# (tyle że wyszłoby znacznie
> > prościej i krócej).

> Super. Ja też sie ciesze, że C# daje rade.

C# daje radę bez żadnych szurniętych opakowań. A i z tymi opakowaniami wygląda
to znacznie prościej:

{
        dbManager.execute( delegate( const DBContext context ) {
                        DBConnection db = context.createConnection("...");
                        ...
        } );
}

> >>Dla programisty końcowego efekt jest podobny. Może sobie tworzyć ile 
> >>chce  - po wylezieniu z funkcji (klamry) - wszystko jest zamykane. (bo 
> >>metoda execute w menadżerze ma finally :-) .)
> > 
> > 
> > Ale dla programisty początkowego różnica jest diametralna.
> > 
> > A może użyjesz generyków, żeby móc to zastosować do różnych typów?
> > 
> > Wiemy przecież, że nie użyjesz, bo te generyki są zbyt jujowe, żeby się tak
> > dało.

> Szczerze mówiąc - używam w tym celu :-)

I do plików też masz odpowiednią implementację createConnection?

> >>gcc version 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125)
> > 
> > 
> > Ta, jasne. I sądzisz, że będzie ci to działało na każdej platformie i każdej
> > wersji każdego kompilatora z każdym zestawem opcji? Oj ty młody i naiwny ;)

> A ty piszesz kod, który działa na każdej platformie, z każdym zestawem
> opcji ? (to bedzie ciekawe - biorąc pod uwagę, ze każdy release
> kompilatorów C++ uzupełnia kolejne braki (pamietam jak długo czekałem na
> "export template")

Może cię to zaskoczy, ale tak. Tak właśnie dokładnie piszę. To nic, że każdy
release kompilatorów uzupełnia się o kolejne braki. Jak czegoś się nie da
zrobić, to po prostu nie używam, trudno.

Na export template ja wcale nie czekałem i czekać nie będę. Ten ficzer jest
cokolwiek szurnięty, a jego przydatność jest znikoma. Btw. skoro czekałeś, to
się pewnie doczekałeś; mogę wiedzieć w jakiej implementacji?

> > Użyłeś tutaj niegwarangowanej właściwości: że referencja będzie
> > zaimplementowana tak, jak wskaźnik, oraz, że możesz swobodnie dokonać
> > "rzutowania przez unię" referencji na wskaźnik. Nie ma takiej gwarancji
> > niestety w standardzie; kompilator mógł cię oszukać. Nawet na tym samym
> > kompilatorze w tej samej wersji może ci to działać lub nie w zależności od
> > opcji kompilacji.
> Swoją drogą zamierzałem użyc jeszcze bardziej niegwarantowanej własności
> (unia).

Bez różnicy. Unia jest formą rzutowania.

> > Zatem to już jest pierwszy minus.
> > 
> > Drugi minus: Popatrz, ile musiałeś się namęczyć i natworzyć własnych typów
> > danych i narzutować po kilka razy, żeby uzyskać void* będący i tak jedynie
> > hipotetycznym adresem tego obiektu w pamięci (jak wspomniałem, jest to
> > nie gwarantowane przez standard, podobnie np. jak to że dla dwóch kolejno
> > zadeklarowanych zmiennych lokalnych x i y tego samego typu nie musi być
> > prawdą, że &x+1 == &y).

> Działa...

I co z tego, że tobie akurat działa?

> nie jest to takie wielkie namęczenie.

No nie wiem - dwa dodatkowe typy danych i trzy zakręcone rzutowania. Opisałeś
się tego badziewia znacznie więcej, niż ja. Muszę przyznać, że jestem z siebie
dumny ;)

> Zauważ, że kod napisałem
> dość czytelnie.

Na tyle, na ile czytelnie w ogóle można coś takiego napisać.

> > Przykro mi, niezaliczone. Zgłosi się pan za tydzień.
> taa minusy wsadź sobie w...
> ja uważam, że wisisz mi połówkę.

O tym możemy jeszcze podyskutować.

> działa - możesz sprawdzić.

Kochany, możesz mi wierzyć albo nie, ale jakiś czas temu gościu podesłał na
pl.comp.lang.c kod, który jakoby miałby robić w języku C listy bez użycia
malloc(). Moment... to było chyba to:

#include <stdio.h>

struct point
{
    int x;
    struct point *nast;
};

int main ()
{
    int a;
    struct point *poprz, *biezacy, *start;
    start = biezacy;
    while (a != 0)
    {
        scanf("%d",&a);
        biezacy->x=a;
        poprz = biezacy;
        poprz->nast=++biezacy;
    }
    biezacy=start;
    while (biezacy->x != 0)
    {
        printf("%d\n",biezacy->x);
        biezacy=biezacy->nast;
    }

    return 0;
}

I był z tym wszystkim jeden drobny problem: na gcc 2.95 ten program NAPRAWDĘ
DZIAŁA i wcale się nie sypie, co można by wnioskować z kodu.

I co, cwaniaczku? Program działa to program jest poprawny?

> Poza tym:
> 1. właśnie widzisz co oznacza brak standardu

Jaki znów brak standardu, o czym ty do mnie rozmawiasz?

> i dlaczego tyle jest makr w bibliotekach standardowych

Wiesz chociaż, do czego one służą, ty młody i naiwny?

> 2. naprawdę myślisz że znajdziesz kompilator w którym sobie nie poradze
> ? (czy może szybko taki machniesz)

W zupełności wystarczy, żeby kompilator implementował pola typu referencyjnego
np. na dwóch bajtach jako delta od czegoś-tam. Albo nawet może być na czterech
bajtach. Albo może być to na 8 bajtach (gdzie wskaźnik ma 4), a pierwsze 4 nie
zawierają wcale wartości wskaźnika do obiektu. Na dobrą sprawę zresztą w ogóle
wystarczy, żeby w tych nawet tej samej ilości bajtów pamięci co sizeof
wskaźnika była zapisana wartość, która jak najbardziej jest odniesieniem do
obiektu, ale te cztery bajty razem wcale nie są wskaźnikiem do tego samego
obiektu. I leżysz.

Standard pozwala na takie rzeczy. Nie wiem, czy są kompilatory, które z tego
korzystają. Jest niewykluczone (nie analizowałem tego, więc nie wiem), że
kompilator może nawet w ramach optymalizacji takiego pola NIE UTWORZYĆ W
OGÓLE (mógłby, jeśli np. klasa jest zdefiniowana lokalnie w funkcji i wiadomo,
że nikt jej na zewnątrz nie używa).

Standard C++ wyraźnie mówi, na przykład, że ustalony jest jedynie rozmiar
typów char, signed char i unsigned char i że wynosi on 1. Rozmiary pozostałych
typów są implementation-defined. A sizeof pobrany z typu referencyjnego zwraca
rozmiar typu referowanego.

> >>(nie przykładałem sie do nazw i kodu - tak z palca strzeliłem za drobną 
> >>poprawką - przyznam, sie ze pierwszy pomysł nie działał (referencje nie 
> >>mogą być częścią uni ) )
> > 
> > 
> > Ten pomysł też tak naprawdę nie działa.
> > 
> > Rzutowanie dowolnego wskaźnika na void* działa i będzie działać. Można go też
> > zrzutować spowrotem i też będzie działać. To standard gwarantuje.
> > 
> > To, co ty wyczyniłeś, nie gwarantuje, bo nigdzie nie jest napisane, że pola
> > typów referencyjnych mają taką samą reprezentację, jak wskaźniki do tych
> > typów.

> Działa - działa. :-)
> Mam to na ekranie - możesz sam sobie sprawdzić.

Dobrze. To skompiluj mi takie coś:

char t[] = { 2, 0, 0, 0 };
int x [] = { 10, 20, 30 };
cout << x[*(int*)t] << endl;

Ja na swoim prywatnym też mogę odpalić i stwierdzić, że działa.

Kochany, empirycznie to sobie możesz szukać punktu G u kobiety.

Jeśli mamy rozmawiać o tym, co w języku MOŻNA zrobić, to trzymajmy się tego,
co napisał standard. Albo piszesz program, który jest poprawny zgodnie ze
standardem języka, albo piszesz program, który przypadkiem działa, bo akurat w
pamięci trafiły ci się przypadkiem takie dane, jakie ci są potrzebne.

> > Cóż, faktem jest, że doświadczenia w tych językach się nie krzyżują. Ale, jak
> > wspomniałem, bardzo chętnie się dowiem, jakież to techniki bazowane na C++ są
> > niefortunnie stosowane w Javie. Jakieś przykłady, chętnie ze źródłami.

> (odpisałem w innym msg) ale tak dla dodatku ( troche mi sie przypomniało)
>   number 1 - double checked locking... który, zeby było zabawniej w C++
> też nie ma gwarancji działania :-)

Czyli skucha. Nie pytałem cię o złe nawyki już w C++ przeniesione do Javy,
tylko o nawyki, które są dobre w C++, a okazują się złe w Javie.

> number 2 - metody wirtualne w konstruktorze - nie ma chyba programisty
> C++, który by po przejsciu na javę się na tym nie wyłożył

Przede wszystkim w C++ nikt _nie woła_ metod wirtualnych spod konstruktora.

Osobny problem, however, polega na tym, że metody spod konstruktora są wołane
W OGÓLE. A taką metodę można przypadkiem sobie gdzieś w klasie potomnej
przedefiniować.

Pewnie bym się na tym wyłożył, to fakt. Na zasadzie, że bym nie przewidział. A
po takim doświadczeniu opakował modyfikatorem final KAŻDĄ metodę w klasie,
która jest wołana spod konstruktora. Niewykluczone nawet, że po pewnym czasie
każdą metodę bym odruchowo robił final, odblokowując ją dopiero wtedy, gdy coś
nie działa.

Pozostawianie metod domyślnie z zezwoleniem na przedefiniowanie to naprawdę
szurnięty pomysł. Nie obchodzi mnie to, że w Smalltalku też tak jest (przy
okazji: ciekawe, dlaczego Opera nie wymawia Smalltalk 'smOltOk', tylko coś w
rodzaju 'smelltick' ;). Metoda powinna mieć JAWNIE zaznaczone, że ma
zezwolenie na przedefiniowanie w klasie pochodnej. W tym sensie, uważam że
podejście C# jest najlepsze z możliwych (tak, uważam że lepsze, niż w C++):
musisz zarówno jawnie nadać metodzie prawa do przedefiniowania w klasie
pochodnej, jak i jawnie zaznaczyć, że przedefiniowujesz metodę (a nie tworzysz
nową). Dzięki takiemu podejściu rzeczywiście wiesz, co robisz.

W Javie nie wiesz. Możesz stworzyć sobie metodę w klasie pochodnej, której
nazwa i lista argumentów przypadkiem pokryje ci się z metodą istniejącą w
klasie bazowej. Możesz sobie wywołać jakąś swoją metodę, myśląc że ona coś-tam
ciekawego robi, co sam zdefiniowałeś - a tu myk! użytkownik przedefiniował
metodę w klasie pochodnej i ta metoda robi zupełnie co innego.

Nieważne zresztą. To nie ja się upieram przy twierdzeniu, że Java jest
bezpiecznym językiem.

Tutaj zresztą również skucha. To jest tylko i wyłącznie kwestia zapomnienia o
różnicach techniczno-językowych pomiędzy C++ a Javą, a takich można by
wymienić jeszcze bardzo wiele: nie stawiamy średnika po definicji klasy, klasę
bazową określamy słowem super, po this dajemy kropkę, a nie strzałkę itd. itd.

Prosiłem o pokazanie _technik programowania_ stosowanych w C++ i będących
niewłaściwymi w Javie.

> number 3 - jest dużo koncepcji typu
>         object = null; } //     ludzie wierzą, że to przypisanie działa jak delete
> (chyba zapełniają pustkę po delect object; )   -ale to fakt
> jest nie od ludzi mądrych - tyle, że nie mogłem pominąć - bo to jest
> wręcz wyznacznik kodu pisanego przez konwertytę

Słyszałem od tzw. niektórych (ci niektórzy czytają tą grupę i więdzą, że o
nich mówię), że to właściwie jedyny sposób na to, żeby się jawnie pozbyć
obiektu. Być może obiekt nie zniknie fizycznie, bo jeszcze się przez jakiś
czas pobełta w śmietniku, ale można już założyć, że obiektu nie ma. Jest to w
Javie jedyny sposób na - też nie takie niezawodne, ale w pewnych granicach tak
- usunięcie obiektu.

Przykładowo, jeśli chcemy usunąć obiekt, który jest trzymany przez inny obiekt
(i może być tam akurat null), to żeby ten obiekt usunąć, należy zapisać
referencję nullem. I mieć nadzieję, że nikt sobie nigdzie tej referencji nie
zapamiętał.

Nb. jakbyś pytał, dlaczego moim zdaniem odśmiecacz ukrywa błędy projektowe, to
to jest właśnie ten przypadek:

Problem: polega na tym, że ktoś sobie zapamiętał odniesienie do obiektu i
zamierza go używać, podczas gdy powinien używać tylko w pojedynczym kontekście
i za każdym razem pobierać to odniesienie za pomocą odpowiedniej metody (bo
być może za każdym wywołaniem metody będzie to inne odniesienie, a odniesienie
uzyskane poprzednio może wskazywać na już nieistniejący obiekt).

W środowisku z odśmiecaczem: problem jest niewidoczny, przynajmniej pozornie.
Obiekt nie zostanie usunięty, zapisanie odniesienia nową wartością nic tego
obiektu nie wzrusza, cwaniaczek nadal używa sobie starego obiektu.

W środowisku bez odśmiecacza: problem objawia się próbą odniesienia do
zwolnionego obiektu - rzadko się zdarza, żeby program się w ten sposób nie
posypał, bo w tym momencie jeździ po pamięci jak chce.

Na czym polega problem ze środowiskiem z odśmiecaczem? Na tym właśnie, że tego
błędu nie widać. Obiekt bowiem powinien być usunięty, a na jego miejsce
utworzony nowy. Stary powinien zniknąć, bo reprezentuje coś, co już dawno nie
powinno istnieć. Ponieważ jakiś szurnięty programista postąpił niezgodnie z
protokołem i zapamiętał sobie odniesienie do obiektu, więc w ten sposób
program dalej działa i nawet produkuje wyniki, tylko "coś jest nie tak".

Oczywiście, że teoretycznie w programie bez odśmiecacza jest znacznie gorzej.
Ale to tylko pozór. Program się sypie, bo MA SIĘ SYPAĆ. W programie jest
ewidentny błąd i program ten NIE powinien działać. To co jest w takim razie
gorsze: to, że program się sypie, czy to, że program działa nie do końca
dobrze? W którym z nich łatwiej jest znaleść taki błąd, co więcej, w którym z
nich łatwiej sobie z niego w ogóle zdać sprawę?

Oczywiście, że to bardzo źle, że sobie można pojeździć po pamięci, ale ja
wcale nie mówiłem o języku, który ma bezpośredni dostęp do pamięci, tylko o
języku bez odśmiecacza, co nie jest tożsame. Spokojnie wyobrażam sobie język,
w którym nie ma odśmiecacza, ale każdy obiekt i wszelkie odwołania do nich są
skrzętnie notowane i dba się o to, żeby w miarę możliwości "nie reużywać
adresów" przydzielanej pamięci. A najlepiej to w ogóle mieć po prostu unikalne
idenfikatory dla każdego obiektu, które są niepowtarzalne. W takiej sytuacji
program po prostu rzuciłby wyjątkiem odwołania się do niepoprawnego
odniesienia do obiektu. Czyli wysypałby się tak właśnie, jak się miał wysypać.

Właśnie dlatego też zresztą stało się w Javie konieczne dodanie słabych
odniesień.

> number 4 - nieużywanie tablic - w javie są normalne i porządne tablice
>         ale doświadczony programista C++ nawet na nie nie patrzy tylko
>         używa ślepo wszędzie List<> itp. - to jest np. mój problem :-)  

No dobra. Powiedzmy, że wreszcie podałeś punkt wart dyskusji.

Normalne i porządne to znaczy jakie? Czy są skracalne/rozszerzalne? Czy
posiadają taką funkcjonalność jak std::vector?

> number 5 - brak zrozumienia  dla koncepcji
>         niestatycznych klas wewnętrznych ogólnie        
>         - te w javie dodają jednak troche lukru syntaktycznego  i       
>         rozwiązują mnóstwo pozornych braków Javy

Powtórzę: pytałem o stosowane w kodzie "teoretycznie działające" konstrukcje,
stosowane w porządnym pisaniu w C++, ale dające złe efekty w Javie. Doczekam
się ich kiedyś?


-- 
//  _    ___         Michal "Sektor" Malecki <sektor(whirl)kis.p.lodz.pl>
\\ L_ |/ `|  /^\ ,()                         <ethourhs(O)wp.pl>
// \_ |\  \/ \_/ /\ C++ bez cholesterolu: http://www.intercon.pl/~sektor/cbx
"I am allergic to Java because programming in Java reminds me casting spells"
Technical Details
Message-ID: <djedbc$1mq$1@kujawiak.man.lodz.pl>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!mat.uni.torun.pl!news.man.torun.pl!newsfeed.pionier.net.pl!news.man.lodz.pl!not-for-mail
References: <nfhjk1hl02upbbv345glfvo4kc2fun0nfm@4ax.com> <03d8l1pfp4nnodpg9a6cseej1rk5obc6pp@4ax.com> <dj38jh$ot4$1@nemesis.news.tpi.pl> <65bal15agggp87dn5i76d97ahr0gbtpi5u@4ax.com> <dj3frf$q3u$1@atlantis.news.tpi.pl> <dj3tvl$e7f$1@kujawiak.man.lodz.pl> <jgdfl1dvsjnrqh8lh25f9koj7b2tb47619@4ax.com> <djb0o0$mhp$1@kujawiak.man.lodz.pl> <djb4u5$2k9$1@news.dialog.net.pl> <djbt6l$q78$1@kujawiak.man.lodz.pl> <djdiub$q0$1@news.dialog.net.pl> <dje1rj$91g$1@kujawiak.man.lodz.pl> <dje5f2$g1k$1@news.dialog.net.pl>

Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!mat.uni.torun.pl!news.man.torun.pl!newsfeed.pionier.net.pl!news.man.lodz.pl!not-for-mail
From: Sektor van Skijlen <ethouris@pl.wp.spamu.lubie.nie.invalid>
Newsgroups: pl.comp.objects
Subject: Re: O, to ta grupa jeszcze istnieje?...
Date: Sat, 22 Oct 2005 22:09:48 +0000 (UTC)
Organization: LODMAN - Metropolitan Area Network in LODZ, Poland
Lines: 396
Sender: Michal Malecki <sektor@zly.kis.p.lodz.pl>
Message-ID: <djedbc$1mq$1@kujawiak.man.lodz.pl>
References: <nfhjk1hl02upbbv345glfvo4kc2fun0nfm@4ax.com>   <03d8l1pfp4nnodpg9a6cseej1rk5obc6pp@4ax.com> <dj38jh$ot4$1@nemesis.news.tpi.pl> <65bal15agggp87dn5i76d97ahr0gbtpi5u@4ax.com> <dj3frf$q3u$1@atlantis.news.tpi.pl> <dj3tvl$e7f$1@kujawiak.man.lodz.pl> <jgdfl1dvsjnrqh8lh25f9koj7b2tb47619@4ax.com> <djb0o0$mhp$1@kujawiak.man.lodz.pl> <djb4u5$2k9$1@news.dialog.net.pl> <djbt6l$q78$1@kujawiak.man.lodz.pl> <djdiub$q0$1@news.dialog.net.pl> <dje1rj$91g$1@kujawiak.man.lodz.pl> <dje5f2$g1k$1@news.dialog.net.pl>
NNTP-Posting-Host: zly.kis.p.lodz.pl
Mime-Version: 1.0
X-Trace: kujawiak.man.lodz.pl 1130018988 1754 212.191.89.2 (22 Oct 2005 22:09:48 GMT)
X-Complaints-To: abuse@man.lodz.pl
NNTP-Posting-Date: Sat, 22 Oct 2005 22:09:48 +0000 (UTC)
User-Agent: tin/1.6.2-20030910 ("Pabbay") (UNIX) (SunOS/5.9 (sun4u))
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit