Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

circular dependencies tussen classes

Pagina: 1
Acties:
  • 269 views sinds 30-01-2008
  • Reageer

  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 19-11 07:22
Class A include class B, en class B include class A...

En circular dependencies zijn geboren.
met de problemen die daarbij horen...

Als ik hierop zoek, dan vind ik Wikipedia: http://en.wikipedia.org/wiki/Circular_dependency
Daarin staat dat met forward declaration dit te implementeren is.

Maar er staat ook
occurrences of circular dependencies should normally be limited, since they make the resulting object-models unclear and unstructured, and are hence considered a bad programming habit.
Maar als Class A een communicatie manager is die wil zenden en ontvangen...
en class B een socket class bijvoorbeeld, dan kan het toch niet anders?
of zijn er nog nette manieren voor?

Klus page: http://klusthuis.blogspot.com


  • whoami
  • Registratie: December 2000
  • Laatst online: 29-11 22:54
Een circulaire dependency tussen classes, daar is volgens mij niets mis mee. Sterker zelfs, dat wordt veel toegepast.
Bv, het alomtegenwoordige Order / Klant voorbeeld:
code:
1
2
3
4
5
6
7
8
9
class Customer
{
    private List<Order> _orders;
}

class Order
{
    private Customer _customerToWhichThisOrderBelongsTo;
}


Wat dan wel weer vies is, is circulaire afhankelijkheden tussen assemblies / dll's.

https://fgheysels.github.io/


  • EfBe
  • Registratie: Januari 2000
  • Niet online
liquid_ice schreef op woensdag 07 november 2007 @ 10:16:
Maar als Class A een communicatie manager is die wil zenden en ontvangen...
en class B een socket class bijvoorbeeld, dan kan het toch niet anders?
of zijn er nog nette manieren voor?
Altijd goed onthouden: de groep van over-engineerende OO-fetisjisten die zelfs voor value types nog een 3-lagige class stack willen maken is groter dan je denkt.

Het benoemen van een cyclic reference tussen classes als 'slecht' is dom, het voegt nl. niets toe: het alternatief is niet per definitie 'beter' daar het meer classes inhoudt en uitleg vereist waarom het zo gedaan is.

Een 'back reference' is helemaal geen rariteit, maar een algemeen gebruikt iets. Waar men op wil wijzen is dat back references net zoveel onderhoud nodig hebben als forward references. Maar goed, dat is iets wat ik beschouw als parate kennis voor een professional, dus iets afschieten daarom zou dus inhouden dat professionals niet weten wat ze doen.

Ik vind dat wikipedia artikel echt tenenkrommend slecht: het geeft totaal niet antwoord op de vraag waarom het dan een bad practise is en waarom het dan "unclear and unstructured" wordt. Ook het argument dat ref-counter gebruikende GC's het niet aan zouden kunnen is geen argument: ten eerste is dat al jaren geleden opgelost en ten tweede is dat het probleem van een GC, niet van de developer: software schrijven gebeurt op een bepaald abstractie-niveau. Als het abstractie-niveau vereist dat je kennis nodig hebt en rekening moet houden met details van een abstractieniveau eronder, dan is het abstactie-niveau 'lek' en kun je het weggooien. Je moet dan niet gillen dat OMDAT het een leaky abstraction is je rekening moet houden met het feit dat het een leaky abstraction is, je moet dan aangeven dat je abstraction leaky is en die het raam uit kan.

Gelukkig is bv een java of een .net GC prima in staat om cyclic references op te ruimen. (COM ref counters dacht ik ook)

[ Voor 32% gewijzigd door EfBe op 07-11-2007 11:17 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

Ik sluit me aan bij whoami:
Ik zie ook geen probleem met circulaire dependencies tussen klassen, mits die klassen in hetzelfde package zitten. Dat noemen ze cohesie en daar is niets mis mee.

Door klassen in verschillende packages te zetten, geef je in feite al aan dat ze verschillen qua domein, verantwoordelijkheid, stabiliteit, etc. Dat statement maak je dan in feite ongedaan door ze sterk aan elkaar te koppelen en een circulaire dependency werkt dan als superlijm.

Dus geen circulaire dependencies tussen verschillende packages of (sub)systemen.

Fat Pizza's pizza, they are big and they are cheezy


  • EfBe
  • Registratie: Januari 2000
  • Niet online
JKVA schreef op woensdag 07 november 2007 @ 13:50:
Ik sluit me aan bij whoami:
Ik zie ook geen probleem met circulaire dependencies tussen klassen, mits die klassen in hetzelfde package zitten. Dat noemen ze cohesie en daar is niets mis mee.

Door klassen in verschillende packages te zetten, geef je in feite al aan dat ze verschillen qua domein, verantwoordelijkheid, stabiliteit, etc. Dat statement maak je dan in feite ongedaan door ze sterk aan elkaar te koppelen en een circulaire dependency werkt dan als superlijm.

Dus geen circulaire dependencies tussen verschillende packages of (sub)systemen.
Mee eens, mijn gereutel hierboven is dan ook puur gericht op cyclic dependencies IN een assembly

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

EfBe schreef op woensdag 07 november 2007 @ 11:11:
Gelukkig is bv een java of een .net GC prima in staat om cyclic references op te ruimen. (COM ref counters dacht ik ook)
COM ref counters nou juist net niet geloof ik, het zijn immers maar simpele refcounts :).

Overigens, gezien dat wikipedia artikel, gaat dit gewoon om circulair compiler dependencies in C++. Dingen die sowieso al niet moeten bestaan, want dat betekent simpelweg dat je gewoon teveel files include die niet nodig zijn (als je alleen een pointer naar een class nodig hebt dan hoef je de header van die class niet te includen, punt). Een uitzondering hierop is als je dependencies nested classes zijn, maar dat is op te lossen door de nested classes hun eigen header te geven zodat je beide parent classes kunt includen voor de definitie van de nested classes. Of als je VC++ gebruikt met de standaard compile opties en pointer-to-memberfunctions, want dan wil je ook de hele class definitie hebben anders gaat ie raar doen (de grootte van een pointer-to-memberfunction is afhankelijk van het soort class, maar bij een forward declared class weet ie het soort niet dus is dat automatisch 16 bytes).

Overigens eens met EfBe, dat artikel gaat nergens over.
.edit: ik heb maar even een comment toegevoegd aan de talk page.

[ Voor 68% gewijzigd door .oisyn op 07-11-2007 16:05 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Een referentie naar dezelfde klasse is ook een circulaire referentie, en dat is zelfs verdomde handig. Bijvoorbeeld een Entry van een linked list implementatie.
code:
1
2
3
class Entry {
  Entry next;
}

  • YopY
  • Registratie: September 2003
  • Laatst online: 06-11 13:47
offtopic / @wikipedia, als je het er niet mee eens bent, kun je het simpelweg aanpassen.

Nu is het alleen wel zo dat er mensen zijn (die dat stukkie eerst geschreven hebben) die het gelijk weer terugdraaien, maar ja. Als je je eigen mening kunt ondersteunen met goeie onderbouwing (in tegenstelling wat er (blijkbaar) nu staat), dan zouden ze er op zich niets tegen kunnen doen.

En links / referenties geven, anders beginnen ze daar weer over te zeuren.

  • EfBe
  • Registratie: Januari 2000
  • Niet online
YopY schreef op donderdag 08 november 2007 @ 08:57:
offtopic / @wikipedia, als je het er niet mee eens bent, kun je het simpelweg aanpassen.

Nu is het alleen wel zo dat er mensen zijn (die dat stukkie eerst geschreven hebben) die het gelijk weer terugdraaien, maar ja. Als je je eigen mening kunt ondersteunen met goeie onderbouwing (in tegenstelling wat er (blijkbaar) nu staat), dan zouden ze er op zich niets tegen kunnen doen.

En links / referenties geven, anders beginnen ze daar weer over te zeuren.
Als ik me moet bezighouden met het corrigeren van onzin op het internet heb ik een dagtaak! ;) Het artikel heeft niet echt een bestaansrecht wanneer het gaat over classes en niet over dll / library references, dus om daar nou over te gaan bakkelijen met de oorspronkelijke schrijver... oisyn heeft goed verwoord waarom het onzin is in zn remark op de discussiepage daar, ik denk dat de originele 'specialist' daar wel wat mee kan ;)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

YopY schreef op donderdag 08 november 2007 @ 08:57:
offtopic / @wikipedia, als je het er niet mee eens bent, kun je het simpelweg aanpassen.
De enige zinnige aanpassing is het verwijderen van het hele artikel, aangezien het enige zinnige wat erin staat de codevoorbeelden zijn, en die hebben op zichzelf geen bestaansrecht. En iets zegt me dat meneer Frederik Orderud het daar niet mee eens gaat zijn.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • EfBe
  • Registratie: Januari 2000
  • Niet online
.oisyn schreef op donderdag 08 november 2007 @ 11:45:
De enige zinnige aanpassing is het verwijderen van het hele artikel, aangezien het enige zinnige wat erin staat de codevoorbeelden zijn, en die hebben op zichzelf geen bestaansrecht. En iets zegt me dat meneer Frederik Orderud het daar niet mee eens gaat zijn.
Dat is inderdaad een nadeel van wikipedia en hun groep specialisten. Veel zijn erg goed, maar sommigen vinden zichzelf wel erg veel beter dan de rest. Neem het artikel over Relational Algebra. Het voorbeeld dat gebruikt wordt bevat een cycle. Bad practise 101 in relational model land. Maar de specialist vindt het niet 'relevant' dat er een cycle in zit. EN OF dat relevant is... Maar winnen doe je zo'n discussie echt niet, dus verloren moeite. De beste man weet best wel waar hij over praat maar is niet in staat te begrijpen dat om de echte kennis over te brengen, je wel relevante 'dragers' voor die kennis moet kiezen anders verzandt het gebodene in geleuter. Dat hij zo'n slecht voorbeeld gekozen heeft is IMHO tekenend en gelijk aan dit cyclic dependencies verhaal: iemand wil iets overbrengen, maar kiest totaal het verkeerde voorbeeld.

[ Voor 19% gewijzigd door EfBe op 08-11-2007 12:09 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • remmelt
  • Registratie: Januari 2001
  • Laatst online: 16:20
whoami schreef op woensdag 07 november 2007 @ 10:41:
Een circulaire dependency tussen classes, daar is volgens mij niets mis mee. Sterker zelfs, dat wordt veel toegepast.
Bv, het alomtegenwoordige Order / Klant voorbeeld:
code:
1
2
3
4
5
6
7
8
9
class Customer
{
    private List<Order> _orders;
}

class Order
{
    private Customer _customerToWhichThisOrderBelongsTo;
}


Wat dan wel weer vies is, is circulaire afhankelijkheden tussen assemblies / dll's.
Nou ja, je kan natuurlijk zeggen dat je hier geheugen teveel gebruikt: je hebt namelijk nu twee keer het Customer object en twee keer het Order object geinstantieerd. Dubbel geheugen! Als je taal pointers ondersteunt kan je natuurlijk met een pointer werken en bespaar je daar mee, maar als je bv PHP schrijft dan kan dat niet.

Overigens kan je er ook niet van uit gaan dat een taal zelf maar al je objecten update. In jouw voorbeeld:

Order o = new Order(); // Meteen blue monday in m'n hoofd
o->getCustomerFromDB(); // het customer object is nu geladen
Customer c = new Customer(<customer_id>); // constructor laadt ook meteen uit de DB

o->setCustomerName('Piet');
print(c->getName());

Zie je waar ik heen wil? Je hebt redundante objecten.


Overigens kun je zulk soort dingen vaak op elegante wijze oplossen, bijvoorbeeld door gebruik te maken van interfaces. Sla er eens een boek Design Patterns op na!

  • whoami
  • Registratie: December 2000
  • Laatst online: 29-11 22:54
remmelt schreef op woensdag 14 november 2007 @ 11:53:
[...]


Nou ja, je kan natuurlijk zeggen dat je hier geheugen teveel gebruikt: je hebt namelijk nu twee keer het Customer object en twee keer het Order object geinstantieerd. Dubbel geheugen!
Says who ?
Dit stukje voorbeeld-code is C#, waarbij classes reference types zijn. Die objecten (instanties van die class) verwijzen dus gewoon naar hetzelfde stuk geheugen op de heap.
Dit kan je vergelijken met het werken met pointers.
Overigens kun je zulk soort dingen vaak op elegante wijze oplossen, bijvoorbeeld door gebruik te maken
Mag je mij eens vertellen hoe interfaces je helpen bij het oplossen van het probleem van die gedupliceerde instanties ....

In jouw voorbeeld is het gewoon je repository (die je niet hebt in jouw voorbeeld) die er moet voor zorgen dat je gewoon dezelfde instantie terugkrijgt (bv dmv een Identity map)
Sla er eens een boek Design Patterns op na!
teach me ....

Trouwens, mij ging het hier allemaal niet om. Mijn code-voorbeeld was er gewoon om aan te tonen dat cyclische referenties tussen classes helemaal niet fout zijn.
Om dat aan te tonen, ga ik echt geen volledige code gaan posten die met alles rekening gaat gaan houden ofzo hoor 8)7

[ Voor 46% gewijzigd door whoami op 14-11-2007 12:20 ]

https://fgheysels.github.io/


Verwijderd

@remmelt:

PHP doet ook gewoon in pointers hoor, sterker nog, als het om objecten gaat doet ie per default pointers wat soms erg irritant is.

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Verwijderd schreef op woensdag 14 november 2007 @ 12:24:
PHP doet ook gewoon in pointers hoor, sterker nog, als het om objecten gaat doet ie per default pointers wat soms erg irritant is.
Zo hoort het IMHO ook; als je een kopie van een instantie wil hebben dan dien je maar expliciet een .Clone ofzo aan te roepen; De enige typen die als value (en dus niet al reference) gepassed dienen te worden by default zijn de simple types als integers etc.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • whoami
  • Registratie: December 2000
  • Laatst online: 29-11 22:54
RobIII schreef op woensdag 14 november 2007 @ 12:47:
[...]

De enige typen die als value (en dus niet al reference) gepassed dienen te worden by default zijn de simple types als integers etc.
Niet helemaal mee akkoord .... De types die als value moeten gepassed worden, zijn types die geen 'identiteit' hebben, ofwel: types waarbij het niet uitmaakt of je eenzelfde instantie krijgt of niet (value types dus. :P).

Stel bv dat je een struct hebt waarmee je kleuren wilt gaan voorstellen; een struct 'Color' dus (die members heeft om R, G, B voor te stellen voor dat kleur, whatever.

Als je een method hebt, die een Color als argument verwacht, dan maakt het niet uit of je nu dezelfde instantie krijgt, of een kopie ervan (als de inhoud maar hetzelfde is).


Om maar te zeggen dat dit niet altijd voor 'simpele' (primitieve) types op gaat.

https://fgheysels.github.io/


Verwijderd

Het is dan ook soms irritant, meestal is het handig ;)

Het irritante vooral eraan is dat dat gedrag een keer geswitched is, dat zorgt dan voor verwarring enzo.

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
whoami schreef op woensdag 14 november 2007 @ 12:52:
Stel bv dat je een struct hebt waarmee je kleuren wilt gaan voorstellen; een struct 'Color' dus (die members heeft om R, G, B voor te stellen voor dat kleur, whatever.
Ik had wat duidelijker moeten zijn. Inderdaad hoort een struct daar ook bij; ik wou de term value-types (en reference types) niet gebruiken omdat daarmee nog niet duidelijk is wat dan wel een value type en wat niet is. Maar uiteraard sluit ik me hierbij aan.

Wat beterderder uitgelegd:
Variable that are based on value types directly contain a values. Assigning one value type variable to another copies the contained value. This differs from the assignment of reference type variables, which copies a reference to the object but not the object itself.

[ Voor 40% gewijzigd door RobIII op 14-11-2007 13:05 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

RobIII schreef op woensdag 14 november 2007 @ 12:47:
[...]

Zo hoort het IMHO ook; als je een kopie van een instantie wil hebben dan dien je maar expliciet een .Clone ofzo aan te roepen; De enige typen die als value (en dus niet al reference) gepassed dienen te worden by default zijn de simple types als integers etc.
Zo "hoort" het? Waarom? Waarom de gebruiker niet gewoon zelf laten kiezen wat hij wilt zodat uit de syntax duidelijk is wat er exact gebeurt zonder het type te kennen? Ik ben het er dus niet mee eens, ook niet na je nuancering. Niet dat het erg is dat mensen daarover over meningen verschillen, maar je brengt het alsof er maar 1 correcte manier is oid :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
.oisyn schreef op woensdag 14 november 2007 @ 23:14:
[...]

Zo "hoort" het? Waarom? Waarom de gebruiker niet gewoon zelf laten kiezen wat hij wilt zodat uit de syntax duidelijk is wat er exact gebeurt zonder het type te kennen? Ik ben het er dus niet mee eens, ook niet na je nuancering. Niet dat het erg is dat mensen daarover over meningen verschillen, maar je brengt het alsof er maar 1 correcte manier is oid :)
Laat ik mezelf dan nog eens nuanceren (mierenneukers :P ): Het "hoort" IMHO zo als je niet expliciet (al dan niet verplicht) aangeeft wat je bedoelt (by val/ref). Heeft een taal de mogelijkheid (al dan niet verplicht) om aan te geven of je by value of by reference wil gebruiken dan is dat inderdaad nog mooier. Dus als het impliciet is (om welke reden dan ook) dan is het zoals ik beschreef (en bedoelde) volgens mij het best; is het expliciet (mogelijk) dan heeft dat inderdaad de voorkeur met als 'default' (dus als je niets aangeeft) de beschreven manier.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dus eigenlijk zeg je dat het ruk is als een taal geen mogelijkheid heeft om referenties te hebben naar objecten? Well no shit sherlock :P

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Is er echt zo'n taal? :X

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

(Quick)Basic ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Hmmm kon die objecten dan?

Daar had je in ieder geval wel bij parameters de optie byval of byref.

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Een object 'by value' passen is eigenlijk onzin. Je passed de pointer. By ref passen van een object is een pointer naar de pointer passen. Beide keren blijft het object waar het was.

C/C++ is dus duidelijk, Basic is dat dus niet, maar goed het hele pointerverhaal is altijd lastig, dus praat men over by value ipv over een pointer ;)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Verwijderd

Er kunnen best wel voordelen zitten aan het byval kunnen passen van een object hoor.

In principe is het krom als een taal alles byval kan passen behalve objecten toch?

Het kan inderdaad wel vaag zijn of een taal een pointer passed of een pointer van een pointer, of juist een kopie van het object (wat IMHO hoort als je een object byval passed).

Even opgezocht:

Q(uick)Basic kon inderdaad geen objecten aan.

[ Voor 42% gewijzigd door Verwijderd op 15-11-2007 12:21 ]


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Verwijderd schreef op donderdag 15 november 2007 @ 12:11:
Er kunnen best wel voordelen zitten aan het byval kunnen passen van een object hoor.

In principe is het krom als een taal alles byval kan passen behalve objecten toch?

Het kan inderdaad wel vaag zijn of een taal een pointer passed of een pointer van een pointer, of juist een kopie van het object (wat IMHO hoort als je een object byval passed).
Dat is dus precies de verwarrende crap: byval maakt GEEN copy, het passed het object in zo'n vorm dat je het object niet kunt vervangen door een andere (dat kan wel, maar dat heeft geen effect voor de caller).

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Verwijderd

Voor zo ver ik weet maakt PHP bijvoorbeeld wel een kopie van het object als je deze byval passed (voor zo ver je een versie gebruikt waarbij dat mogelijk is).

Zo zijn er wel meer talen lijkt me, anders zou het byval passen van een object zoals je zegt compleet nutteloos zijn.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Records :)
Daar had je in ieder geval wel bij parameters de optie byval of byref.
Als parameters ja, maar je kon niet midden in code een referentie naar een ander "object" hebben. Dan zat je dus te kloten met arrays waar die dingen in stonden en de indices die pointers representeerden.
EfBe schreef op donderdag 15 november 2007 @ 12:08:
Een object 'by value' passen is eigenlijk onzin. Je passed de pointer. By ref passen van een object is een pointer naar de pointer passen. Beide keren blijft het object waar het was.
Dat hangt van je definitie van een object af. Ik zie een int of een Vector3 iig ook als een object. En die passen toch echt by value dmv een kopie op de stack (of in een CPU register), net als een MyClass waarvan ik eigenlijk helemaal geen kopie wil maken. Ik denk dat de definitie van een object sterk gekoppeld is aan de taal waarin je werkt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Dricus
  • Registratie: Februari 2002
  • Laatst online: 07:44

Dricus

ils sont fous, ces tweakers

.oisyn schreef op donderdag 15 november 2007 @ 12:52:
Dat hangt van je definitie van een object af.
[...]
Ik denk dat de definitie van een object sterk gekoppeld is aan de taal waarin je werkt.
Het hang volgens mij van je definitie van 'by value' af. Het is natuurlijk hopeloos onduidelijk als 'by value' de ene keer betekent dat je een waarde op de stack gaat kopiëren en de andere keer dat je een reference naar de waarde op de stack gaat zetten. Deze definitie verschilt per programmeertaal, niet de definitie van wat een object is. C++ is wat dat betreft inderdaad consequent.

De kreet 'object' valt onder het OO paradigma. Een object is in dat paradigma een instance van een class. Het OO paradigma schrijft (bij mijn weten) niet expliciet voor wat 'by value' en 'by reference' inhoudt.

offtopic:
In C++ is het dan wel weer zo dat je zowel gebruik kunt maken van een pointer als van een reference. De uiteindelijke werking is hetzelfde, alleen de syntax is anders. Dit vind ik dan weer minder consequent. Maarja, je kunt niet alles hebben toch? :P

Stel niet uit tot morgen wat je vandaag nog tot morgen kunt uitstellen...


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

MrHuge schreef op donderdag 15 november 2007 @ 13:39:
[...]

Het hang volgens mij van je definitie van 'by value' af. Het is natuurlijk hopeloos onduidelijk als 'by value' de ene keer betekent dat je een waarde op de stack gaat kopiëren en de andere keer dat je een reference naar de waarde op de stack gaat zetten. Deze definitie verschilt per programmeertaal, niet de definitie van wat een object is.
Noem dan eens een taal waarin de definitie anders is dan bijv. in C++? Zoals ik het zie werk je in talen als C# met referenties naar objecten, en dat zijn de dingen die je by value doorgeeft. Als je een referentie aanpast dan ziet de caller dat idd niet nee. Tenzij je een referentie by ref meegeeft, dan ziet de caller dat wel.

Dat de aanpassingen aan het object altijd zichtbaar zijn is omdat beide referenties (in het geval van by value) naar hetzelfde object wijzen. Maar het is gewoon een kwestie van bewoording - je geeft het object by reference mee, maar tegelijkertijd geef je de daadwerkelijke reference by value mee. Wat er niet duidelijk aan is is waar die by ref en by value precies op slaat, niet zozeer de betekenis van die termen zelf - dat is in alle talen hetzelfde.
De kreet 'object' valt onder het OO paradigma. Een object is in dat paradigma een instance van een class.
[flauw] Dus een int is geen object, want het is immers geen instance van een class? [/flauw]
Maar ik had het over de term "object" in EfBe's bewoording, niet objecten in het algemeen. EfBe zegt dat by value doorgeven van "objecten" onzin is, wat het natuurlijk niet is. Maar hij doelt hier specifiek op ref types en juist niet op value types (in .Net dus). En dat is gangbaar taalgebruik in Java en C#, waar een object echt een instantie van (een (ref-type) subclass van) het type Object is. Een int in Java is geen object. In C++ is alles een object.
In C++ is het dan wel weer zo dat je zowel gebruik kunt maken van een pointer als van een reference. De uiteindelijke werking is hetzelfde, alleen de syntax is anders. Dit vind ik dan weer minder consequent. Maarja, je kunt niet alles hebben toch? :P
Als je C++ een beetje kent dan snap je helemaal waarom er een verschil bestaat tussen pointers en references, en dat het gemis hiervan juist in andere talen tot inconsequenties leidt bij bijv. operator overloading :)

[ Voor 8% gewijzigd door .oisyn op 15-11-2007 14:01 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Dricus
  • Registratie: Februari 2002
  • Laatst online: 07:44

Dricus

ils sont fous, ces tweakers

Dat de aanpassingen aan het object altijd zichtbaar zijn is omdat beide referenties (in het geval van by value) naar hetzelfde object wijzen. Maar het is gewoon een kwestie van bewoording - je geeft het object by reference mee, maar tegelijkertijd geef je de daadwerkelijke reference by value mee. Wat er niet duidelijk aan is is waar die by ref en by value precies op slaat, niet zozeer de betekenis van die termen zelf - dat is in alle talen hetzelfde.
Goed punt. De verwarring zit hem ook in het al dan niet bestaan van het verschil tussen value-types en reference-types. In C++ geef je altijd expliciet aan of je het over een reference (of pointer) hebt of over een value. In bijv. Java zijn de built-in types (zoals int en char) value-types, classes zijn reference-types.
[flauw] Dus een int is geen object, want het is immers geen instance van een class?[/flauw]
Is niet flauw, is gewoon waar :). Binnen het OO paradigma is een object een instance van een class. OO talen (zoals C++ en Java) waarin je types als int of char als built-in types hebt, zijn dus geen zuivere OO talen. Wat dat betreft komt bijvoorbeeld Ruby meer in de buurt.
en dat het gemis hiervan juist in andere talen tot inconsequenties leidt bij bijv. operator overloading :)
Hmm, IMHO is het bestaan van operator overloading hier het probleem (dat maakt een programmeertaal IMHO nodeloos ingewikkeld), niet het niet bestaan van een onderscheid tussen pointers en references, maar nu beginnen we wel erg van het topic af te dwalen (ik begon, I know ;)).

Stel niet uit tot morgen wat je vandaag nog tot morgen kunt uitstellen...


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

MrHuge schreef op donderdag 15 november 2007 @ 14:38:
Is niet flauw, is gewoon waar :). Binnen het OO paradigma is een object een instance van een class. OO talen (zoals C++ en Java) waarin je types als int of char als built-in types hebt, zijn dus geen zuivere OO talen.
Omdat het geen class is? Het kan natuurlijk net zo goed wel een class zijn, maar dan een onovererfbare (final) class zonder members. Zie bijvoorbeeld het .Net type System.Int32, waar 'int' in principe gewoon een alias voor is (in C# en C++/CLI), en dus een veel minder built-in uiterlijk heeft.

In C++ (en C++/CLI) kun je een int gewoon benaderen als alle andere objecten. Ik vind het dan ook onzin om een int geen object te noemen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

liquid_ice schreef op woensdag 07 november 2007 @ 10:16:
Maar als Class A een communicatie manager is die wil zenden en ontvangen...
en class B een socket class bijvoorbeeld, dan kan het toch niet anders?
of zijn er nog nette manieren voor?
Als A en B moeten kunnen communiceren, zal er per definitie een pad van includes moeten bestaan. Hoeveel klassen je er ook tussenhangt: de lijn is altijd te trekken. Daarin zit ook meteen de tekortkoming van het wikipedia artikel: circulaire referenties zijn geen probleem als ze een gedegenereerde cirkel (oftewel: een lijn) vormen. Alleen als ze daadwerkelijk een cirkel door je classes heen trekken zou er weleens iets mis kunnen zijn.

Wie trösten wir uns, die Mörder aller Mörder?


  • Dricus
  • Registratie: Februari 2002
  • Laatst online: 07:44

Dricus

ils sont fous, ces tweakers

.oisyn schreef op donderdag 15 november 2007 @ 14:56:
Omdat het geen class is? Het kan natuurlijk net zo goed wel een class zijn, maar dan een onovererfbare (final) class zonder members. Zie bijvoorbeeld het .Net type System.Int32, waar 'int' in principe gewoon een alias voor is (in C# en C++/CLI), en dus een veel minder built-in uiterlijk heeft.

In C++ (en C++/CLI) kun je een int gewoon benaderen als alle andere objecten. Ik vind het dan ook onzin om een int geen object te noemen.
Okee, met built-in bedoel ik dus de situatie dat int niet gedefiniëerd is als class, maar gewoon puur als datatype. Volgens het OO paradigma is een int dan dus geen object, want er ligt geen class aan ten grondslag.
Tuurlijk kun je het begrip object gemakkelijk breder trekken, bijv als zijnde een instance van type (met een class definiëer je een type inclusief de operaties die je erop kunt uitvoeren, int is een type). Ik vind het begrip object dan persoonlijk wel vager worden, aangezien je dan niet meer exclusief in OO termen praat.

Stel niet uit tot morgen wat je vandaag nog tot morgen kunt uitstellen...


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

MrHuge schreef op donderdag 15 november 2007 @ 15:53:
Volgens het OO paradigma is een int dan dus geen object, want er ligt geen class aan ten grondslag.
Ik denk dat je het te letterlijk benadert. Wat is dan daadwerkelijk het probleem van het feit dat er geen class is, zodat het niet meer aan het OO paradigima voldoet? Of een type nou voorgedefiniëerd is of niet, en met of zonder class, het doet er allemaal niet toe - het type bestaat nou eenmaal, en op hetzelfde niveau als andere types. Het is een type waar je een instantie van kunt maken en waar je operaties op los kunt laten. Zo'n instantie is dus een object. Wat is nou exact het probleem als het type niet gedefiniëerd is middels een class? Dat je 'm niet kunt overerven? Maar dan passen alle final classes dus niet in het OO paradigima? Dat vind ik een beetje ver gaan.

[ Voor 6% gewijzigd door .oisyn op 15-11-2007 16:13 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • JeromeB
  • Registratie: September 2003
  • Laatst online: 15-11 14:27

JeromeB

woei

Mr Huge, naast class-based OOP zijn er nog andere manieren om OO te programmeren. Prototype-based programmeren (in JavaScript) is een voorbeeld.

PC load letter? What the fuck does that mean?


  • Dricus
  • Registratie: Februari 2002
  • Laatst online: 07:44

Dricus

ils sont fous, ces tweakers

.oisyn schreef op donderdag 15 november 2007 @ 16:12:
Ik denk dat je het te letterlijk benadert. Wat is dan daadwerkelijk het probleem van het feit dat er geen class is, zodat het niet meer aan het OO paradigima voldoet? Of een type nou voorgedefiniëerd is of niet, en met of zonder class, het doet er allemaal niet toe - het type bestaat nou eenmaal, en op hetzelfde niveau als andere types. Het is een type waar je een instantie van kunt maken en waar je operaties op los kunt laten. Zo'n instantie is dus een object. Wat is nou exact het probleem als het type niet gedefiniëerd is middels een class? Dat je 'm niet kunt overerven? Maar dan passen alle final classes dus niet in het OO paradigima? Dat vind ik een beetje ver gaan.
Er is geen sprake van een probleem. Ook niet van te letterlijk benaderen. Er is sprake van een discussie over een definitie. Jouw definitie van wat een object is is breder dan die van mij.
Wat ik probeer te benadrukken is dat er zoiets is als een OO paradigma, waarin bepaalde basisprincipes en definities gelden. De basis van dit paradigma is dat een computer programma wordt gezien als een verzameling samenwerkende objecten. Elk object kan messages ontvangen van andere objecten of versturen naar andere objecten. De eigenschappen, de interface en het gedrag van deze object worden gedefiniëerd met behulp van een class.

In mijn optiek zijn C++ en Java geen zuivere implementaties van dit paradigma, aangezien niet alle beschikbare types gedefiniëerd zijn middels een class (ik vraag me af of er überhaupt een zuivere implementatie van OO bestaat). In Java wordt er een expliciet onderscheid gemaakt tussen built-in types (of Primitive Types, waar int er één van is) en classes (of Reference Types, waar een class type er één van is). Een object wordt gedefiniëerd als een class instance of een array.

Het lastige van het OO paradigma is dat er geen officiële definitie van bestaat en dat er de nodige discussie over is (zoals ook deze). Er is dus ook geen sprake van gelijk hebben of krijgen in dit soort discussies. Het is volgens mij wel zo dat mijn definitie van een object meer gehanteerd wordt dan de jouwe (zie ook hier).
JeromeB schreef op donderdag 15 november 2007 @ 19:22:
Mr Huge, naast class-based OOP zijn er nog andere manieren om OO te programmeren. Prototype-based programmeren (in JavaScript) is een voorbeeld.
Volgens mij kun je een prototype definitie in JavaScript zien als een soort class. Ik zeg niet dat een class in een OO programmeertaal ook expliciet een class genoemd moet worden. Wat is je punt precies?

Stel niet uit tot morgen wat je vandaag nog tot morgen kunt uitstellen...


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

MrHuge schreef op donderdag 15 november 2007 @ 20:22:
[...]

Er is geen sprake van een probleem. Ook niet van te letterlijk benaderen. Er is sprake van een discussie over een definitie. Jouw definitie van wat een object is is breder dan die van mij.
Wat ik probeer te benadrukken is dat er zoiets is als een OO paradigma, waarin bepaalde basisprincipes en definities gelden. De basis van dit paradigma is dat een computer programma wordt gezien als een verzameling samenwerkende objecten. Elk object kan messages ontvangen van andere objecten of versturen naar andere objecten. De eigenschappen, de interface en het gedrag van deze object worden gedefiniëerd met behulp van een class.
Dat snap ik allemaal, en mijn vraag aan jou is: waarom voldoen ints en floats niet aan die eigenschappen, behalve dan de letterlijke stelling dat ze geen class zijn, want dat is het enige dat ze laat verschillen met andere types. Dus óf blijkbaar vindt je de eis dat het een class moet zijn zo belangrijk dat ze daarom niet in het OO paradigima passen, óf er zijn andere eigenschappen waar value types niet aan voldoen waar algemene classes wél aan voldoen die je tot nu toe nog niet hebt weten te benoemen. En waarom is een array dan ineens wel object? Omdat hij overerft van Object (doet een System.Int32 in .Net ook), of omdat je er members op aan kunt roepen (In C++ heeft een int ook gewoon een constructor, destructor en operators)? Goed, je kunt er niet van overerven, maar als dat de issue is dan is een java.lang.String ook geen object. Een int encapsuleert ook data. Je kunt er een message naartoe sturen, bijvoorbeeld om een nieuwe waarde te assignen.

Het is trouwens grappig dat je de documentatie van Java aanhaalt, want dat brengt ons weer helemaal terug naar waar deze discussie mee gestart is (geheel in de stijl van "circular dependencies" :P), namelijk mijn opmerking dat een definitie van "object" vaak afhangt van de taal waarin je werkt. In Java is dat een class instance of een array, in C++ is dat elk type dat geïnstantieerd is:
1.8 The C+ + object model [intro.object]
1 The constructs in a C + + program create, destroy, refer to, access, and manipulate objects. An object is a region of storage. [Note: A function is not an object, regardless of whether or not it occupies storage in the way that objects do. ] An object is created by a definition (3.1), by a new-expression (5.3.4) or by the implementation (12.2) when needed. The properties of an object are determined when the object is created. An object can have a name (clause 3). An object has a storage duration (3.7) which influences its lifetime (3.8). An object has a type (3.9). The term object type refers to the type with which the object is created. Some objects are polymorphic (10.3); the implementation generates information associated with each such object that makes it possible to determine that object’s type during program execution. For other objects, the interpretation of the values found therein is determined by the type of the expressions (clause 5) used to access them.
Bron: ISO/IEC 14882:2003
Volgens mij kun je een prototype definitie in JavaScript zien als een soort class.
Nee, prototyping is geen subset van classing. Het zijn siblings, ze leven naast elkaar als vormen van OOP. De een is niet een vorm van de ander.

[ Voor 41% gewijzigd door .oisyn op 15-11-2007 22:17 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Dricus
  • Registratie: Februari 2002
  • Laatst online: 07:44

Dricus

ils sont fous, ces tweakers

@.oisyn:
Even voor de duidelijkheid: De discussie draait er dus niet zozeer om of een int een object is, maar of het type int als een class gezien kan worden. Als het type int als class gezien kan worden, dan is een instance van het type int dus een object (vanuit het OO paradigma beschouwd). Zo niet, dan niet :).

Nu rijst meteen de vervolgvraag: waarom is het type int dan geen class (en dan bedoel ik niet dat het geen class genoemd wordt, maar dat het type niet de kenmerken vertoont van wat een class is, volgens het OO paradigma)?

Deze vraag is mijns inziens niet algemeen te beantwoorden.
Zoals je zelf al zegt is het type System.Int32 in C# afgeleid van Object. Het is welliswaar gedefiniëerd als een struct, maar aangezien een struct in C# gedefiniëerd is als een beperkte vorm van een class, vertoont System.Int32 wel kenmerken van een class (self-contained unit, encapsuleert het 'gedrag' van een integer). Dat maakt een instance van System.Int32 dus min of meer een object.

Aan de andere kant zijn er talen waar int gedefiniëerd is als primitive type (Java) of fundamental type (C++). Een primitive type of fundamental type wordt geen class genoemd, en vertoont ook geen kenmerken van wat een class is (geen self-contained unit, encapsuleert geen 'gedrag', je kunt er geen messages naartoe sturen). Dat maakt dat instances van een primitive type of fundamental type mijns inziens geen objecten genoemd kunnen worden als je de definities van het OO paradigma hanteert.

Stel niet uit tot morgen wat je vandaag nog tot morgen kunt uitstellen...


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

MrHuge schreef op vrijdag 16 november 2007 @ 14:27:
Aan de andere kant zijn er talen waar int gedefiniëerd is als primitive type (Java) of fundamental type (C++). Een primitive type of fundamental type wordt geen class genoemd, en vertoont ook geen kenmerken van wat een class is (geen self-contained unit, encapsuleert geen 'gedrag', je kunt er geen messages naartoe sturen).
Aha, en nu komen we eindelijk op de discrepantie, want op al deze punten ben ik het dus niet eens :). Het encapsuleert wel gedrag (namelijk het gedrag dat je van een int verwacht - het is hierin niet anders dan een std::complex<float> oid), je kunt er wel messages naartoe sturen (assignment), en het is natuurlijk al helemaal self-contained.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Ik ben het er mee eens dat de wikipedia pagina wel wat duidelijker mag zijn en nogal warrige voorbeelden bevat. Met hun conclusie ben ik het echter wel eens: circular dependencies zijn vaak een slecht teken. (In sommige omgevingen, zoals COM of JavaScript kun je ook in de messen lopen met circular references, wat weer heel wat anders is.)

Het voorbeeld van de TS bijvoorbeeld:
liquid_ice schreef op woensdag 07 november 2007 @ 10:16:
Class A include class B, en class B include class A...

Maar als Class A een communicatie manager is die wil zenden en ontvangen...
en class B een socket class bijvoorbeeld, dan kan het toch niet anders?
of zijn er nog nette manieren voor?
In dit voorbeeld zie ik dus niet waarom B afhankelijk moet zijn van A.
code:
1
2
3
4
5
6
class A {
  public String send(String sendText) {
      B socket = new B();
      return socket.send(sendText);
  }
}

B is hiermee niet afhankelijk van A. Voordelen: B kan hergebruikt worden op andere plekken dan A, als A aangepast wordt dan hoeft B niet te worden gecontroleerd, B kan onafhankelijk van A worden getest, en het is duidelijker.

Ik ben het ermee eens dat circular references soms onderdeel kunnen zijn van je probleemdomein en ze altijd vermijden is wellicht contraproductief. Ik vind dan wel dat de circular references altijd zo direct mogelijk moeten zijn, dus niet A -> B -> ... F -> A, en moeten blijven binnen een bepaalde package/assembly.

De meeste andere circular references die ik zie ontstaan door code die op de verkeerde plek staat of het gebrek aan een tussenobject. Over het algemeen zeer gemakkelijk op te lossen, met alle voordelen voor hergebruik, testbaarheid en onderhoudbaarheid.

  • citegrene
  • Registratie: Februari 2006
  • Laatst online: 02-11 03:00
circular dependencies zijn per definitie niet altijd goed omdat het veel voor komt,

Een linkedlist is bijvoorbeeld niet te vergelijken met het het customer / order voorbeeld. Entry van linkedlist mag namelijk null zijn. Als customer van order null is, zorgt dit voor complexiteit op veel andere plekken.

Daarnaast is Entry ook een private inner class van linkedlist, waardoor toevoegen en verwijderen van de entries altijd gecontrolleerd verloopt via linkedlist class.

Zeggen dat circular dependecy slecht is , is kort door de bocht, maar ik denk wel dat er in veel gevallen het op een foute manier wordt toegepast.

[ Voor 3% gewijzigd door citegrene op 30-11-2007 23:09 ]

Pagina: 1