Reflection ondergewaardeerd of misfeature?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
Afbeeldingslocatie: http://library.creativecow.net/articles/okerstrom_jon/reflections/OddReflection1.jpg
Intro
In het topic Vergroot OO programmeren de schaalbaarheid van software? plaatste ik een reply over reflection.

Persoonlijk vind ik dat reflection een ondergewaardeerde feature is, SmallTalk-80 bevatte al ondersteuning voor reflection evenals moderne talen zoals .NET (C#/VB) en JAVA.

Naar mijn mening zien veel programmeurs reflection als 'iets moeilijks dat zij niet nodig hebben'. Zelf dacht ik dit ook, totdat ik er een tijd geleden mee aan de slag ging. Maar nu denk ik dat reflection een erg krachtige feature is, en dat het zonde is dat deze feature (volgens mij) niet vaak genoeg gebruikt wordt.

In het zelfde topic reageerde ook Soultaker, die het volgende zij over reflection:
quote: Soultaker
Ik vind persoonlijk reflectie een misfeature. Essentieel voor bepaalde toepassingen (RMI of serialisatie bijvoorbeeld) maar als bouwsteen voor OOP eerder schadelijk dan behulpzaam. Geen enkel gangbaar design pattern gebruikt reflectie (of noem een paar tegenvoorbeelden?)
Hij heeft dus een heel andere mening over reflection (die ik overigens niet deel).

Doel van dit topic
In dit topic wilde ik discussiëren over het nut van reflectie, waar je het zelf (niet) voor gebruikt en of je net als mij de mening deelt dat reflection wat meer in de schijnwerpers zou moeten worden gebracht.

Leesvoer
Introductie
Wikipedia: Reflection (computer science)
http://msdn.microsoft.com/en-us/library/ms173183(VS.80).aspx
http://java.sun.com/devel...lArticles/ALT/Reflection/
Design patterns:
http://msdn.microsoft.com/en-us/magazine/cc164170.aspx
http://www.vbdotnetheaven...ernUsingReflectionVB.aspx
Wikipedia: Visitor pattern (zie halverwege de details sectie)

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Haan
  • Registratie: Februari 2004
  • Laatst online: 19:28

Haan

dotnetter

Ik gebruik in mijn (.NET/C#) code Reflection eigenlijk alleen voor logging doeleinden.
- De huidige class opvragen: MethodBase.GetCurrentMethod().DeclaringType
- De huidige method opvragen: MethodBase.GetCurrentMethod().Name
- ToString() van een class overriden om de properties en hun waardes terug te geven:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public override string ToString()
{
    Type type = this.GetType();
    PropertyInfo[] properties = type.GetProperties();
    StringBuilder sb = new StringBuilder();
    sb.AppendFormat("Class: {0}", type.Name);
    sb.AppendLine();
    sb.AppendLine("Properties / values:");

    foreach (PropertyInfo pi in properties)
    {
        sb.AppendFormat("{0}: {1}", pi.Name, pi.GetValue(this, null));
        sb.AppendLine();
    }

    return sb.ToString();
}

Dit is eventueel ook nog uit te breiden met fields dmv GetFields, of door ook nog onderscheid te maken in public / private / etc. modifiers op de properties / fields.

Voordat ik wist hoe reflection werkte kostte bovenstaande altijd een hoop gedoe met hard-coded strings in de code :P

Een collega gebruikte altijd deze regel om de locatie te vinden van waar een programma is gestart:
C#:
1
Assembly.GetExecutingAssembly().Location.Replace(Assembly.GetExecutingAssembly().ManifestModule.Name, "")

Maar ik heb het idee dat dat een goed voorbeeld is van hoe je het niet moet gebruiken..

Ik ben ook wel benieuwd naar andere handige toepassingen :)

[ Voor 14% gewijzigd door Haan op 27-09-2010 14:29 ]

Kater? Eerst water, de rest komt later


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 18:57
Tja, ik gebruik het atm voor verschillende doeleinden:

- at runtime laden van assemblies & instantieren van objecten (plugins)
- late binding van COM dll's binnen een .NET project (ik zou graag gebruik kunnen maken van het dynamic keyword, maar onze projecten draainen nog onder 3.5, wegens issues in .NET 4.0).

Reflection is geen misfeature; het mag gewoon niet misbruikt worden.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
Een ORM framework van php, Doctrine, maakt gebruik van phpdoc annotaties voor het managen van de mappings. Ik ben niet bekend met C(++/#) of Java, maar zie docblock annotations voor functionaliteiten wel als reflectie. En de manier waarop het wordt gebruikt is zeer fijn.

Dus ja: ik sta er wel positief tegenover :)

Verder wilde ik ook een cache mechanisme schrijven voor Zend_Cache, waar het serializen van de objecten te tunen was met dezelfde docblock annotaties. En ik zie nog wel meer mogelijkheden voor dergelijke "augmented" lagen bovenop je normale modellen.

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

roy-t schreef op maandag 27 september 2010 @ 13:51:
Naar mijn mening zien veel programmeurs reflection als 'iets moeilijks dat zij niet nodig hebben'. Zelf dacht ik dit ook, totdat ik er een tijd geleden mee aan de slag ging.
Ik zie het niet als moeilijk. Ik zie het meer als ranzige hack met een beperkt toepassingsgebied. In dat opzicht ben ik het met Soultaker eens. Het is, net als eval(), iets wat je pas toe zou moeten passen wanneer er geen andere redelijke mogelijkheid is.
Maar nu denk ik dat reflection een erg krachtige feature is, en dat het zonde is dat deze feature (volgens mij) niet vaak genoeg gebruikt wordt.
Het is vooral krachtig in het onderuit halen van de zekerheden die een compiler je normaal geeft.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • DaRKie
  • Registratie: December 2001
  • Laatst online: 02-09 19:08
Reflection is indd een krachtig iets en kan je leven soms gemakkelijker maken bij het bouwen van generieke ondersteunende structuren ... maar hou het aub ver weg van je business code.
Het lijkt op het eerste zicht allemaal ok tot je moet beginnen debuggen.

Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
Ik snap niet waarom het de compiler onderuit zou halen, en waarom het lastig te debuggen zou zijn. Zie het als een XML bestand lezen, je weet nooit zeker er in het XML bestand staat, maar je kunt toch prima code schrijven om XML bestanden te lezen. De reflection code zelf wordt netjes door de compiler gechecked, alleen de binnenkomende class kan verschillende eigeschappen hebben.

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Greyfox
  • Registratie: Januari 2001
  • Laatst online: 11-09 13:40

Greyfox

MSX rulez

Als performance belangrijk is bij het loggen, zou ik geen reflection gebruiken. Het is namelijk nogal een belastende operatie.

MSX 2 rulez more


Acties:
  • 0 Henk 'm!

  • DaRKie
  • Registratie: December 2001
  • Laatst online: 02-09 19:08
De compiler onderuit halen:
Wil je bv een methode/variabele via reflection ophalen zal je de naam ervan als string moeten opgeven. Staat er per ongeluk een foutje in deze string -> merk je pas @runtime.
Geen fout typen ... ok, alles werkt, later past iemand de methode naam aan maar vergeet dat deze ook ergens via reflection opgeroepen wordt -> merk je pas @runtime

Het debuggen van reflection is niet altijd lastig, maar als je project er vol mee zit dan is het bij momenten toch wel moeilijk orienteren.
Greyfox schreef op maandag 27 september 2010 @ 14:53:
Als performance belangrijk is bij het loggen, zou ik geen reflection gebruiken. Het is namelijk nogal een belastende operatie.
Wat ik weet van Java: vroeger (< 1.4) was het verschil zeer groot, tegenwoordig is het verwaarloosbaar.

[ Voor 25% gewijzigd door DaRKie op 27-09-2010 14:55 ]


Acties:
  • 0 Henk 'm!

  • Greyfox
  • Registratie: Januari 2001
  • Laatst online: 11-09 13:40

Greyfox

MSX rulez

Wat ik weet van Java: vroeger (< 1.4) was het verschil zeer groot, tegenwoordig is het verwaarloosbaar.
Dat is niet de ervaring die ik heb.
Verwaarloosbaar is relatief, zeker als je heel veel moet loggen.

MSX 2 rulez more


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Ik ken het eigenlijk vooral van Qt. Signals en slots vallen neem ik aan ook onder (een vorm van) reflection? Daar is het wel handig om runtime dynamisch componenten aan elkaar te linken. Ik ben in ieder geval behoorlijk gecharmeerd van de manier waarop Qt werkt.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 18:57
roy-t schreef op maandag 27 september 2010 @ 14:48:
Ik snap niet waarom het de compiler onderuit zou halen
Omdat de compiler niet in staat is, om, at compile time ( duh ) te gaan checken of een bepaalde member wel bestaat, of, als een bepaalde property 'settable' is, etc...
(pseudocode)
code:
1
2
MethodInfo bliep = someType.GetMethod ("Melk");
bliep.Invoke()


Wie zegt bv dat het type een method 'Melk' heeft, en wie checkt at-compile time of dat die method wel geen parameters heeft ?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 10:03

Creepy

Tactical Espionage Splatterer

Zoijar: bedoel je niet RTTI i.p.v reflection?

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

roy-t schreef op maandag 27 september 2010 @ 14:48:
Ik snap niet waarom het de compiler onderuit zou halen, en waarom het lastig te debuggen zou zijn. Zie het als een XML bestand lezen, je weet nooit zeker er in het XML bestand staat, maar je kunt toch prima code schrijven om XML bestanden te lezen. De reflection code zelf wordt netjes door de compiler gechecked, alleen de binnenkomende class kan verschillende eigeschappen hebben.
XML is goed te valideren middels een xsd. Daarnaast kun je keurige foutafhandeling schrijven. Het 'probleem' bij XML is dat het uit een ander domein komt dus zul je sowieso wat om moeten zetten. Bij reflection zit je echter in hetzelfde domein. Wanneer je weet hoe de methode heet dan heb je al helemaal geen reflection meer nodig. Daarvoor heb je namelijk een interface. Wanneer je de methode niet kent dan vraag ik me überhaupt af of je er wel wat mee kunt.

Het enige dat ik me voor kan stellen is data je wat dingen met properties kunt doen. Het doorsturen naar een GUI zonder dat je de daadwerkelijke implementatie kunt weten @compile time.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

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

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zoijar schreef op maandag 27 september 2010 @ 15:02:
Ik ken het eigenlijk vooral van Qt. Signals en slots vallen neem ik aan ook onder (een vorm van) reflection?
Hoe dan? Ik heb zelf nooit echt met Qt gewerkt, maar ik ken het idee een beetje. Maar het is dus ook zo dat je @ runtime alle signals en slots bij naam kunt opvragen?

Overigens denk ik dat de meeste gebruiken van reflection eigenlijk over introspection gaan. Oftewel het inzien, en niet zozeer het aanpassen.

[ Voor 15% gewijzigd door .oisyn op 27-09-2010 15:26 ]

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.


Acties:
  • 0 Henk 'm!

  • DaRKie
  • Registratie: December 2001
  • Laatst online: 02-09 19:08
Greyfox schreef op maandag 27 september 2010 @ 15:01:
[...]


Dat is niet de ervaring die ik heb.
Verwaarloosbaar is relatief, zeker als je heel veel moet loggen.
Het is niet omdat het verwaarloosbaar is dat het niet onperformant kan worden bij overdreven gebruik. Maar als je zegt dat je veel logt, lijkt me eerder het wegschrijven van de logs de bottleneck.

Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Wij gebruiken het hier voor dependency injection (configureerbare connectoren e.d.), en om een virtual path provider wat assemblies te laten scannen voor bestanden. Als onze programmeurs zomaar voor de gein reflection gaan lopen gebruiken krijgen ze van mij echt wel een bitchslap.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Reflectie (in elk geval in Java) heeft in mijn optiek een aantal nadelen:
  • breekt information hiding (je hoeft je niks meer aan te trekken van public/protected/private)
  • runtime i.p.v. compile-time checking
  • verminderd de leesbaarheid, minder makkelijk te doorzien (ook weer vanwege het runtime-karakter)
  • omslachtige syntax
Het heeft wat mij betreft ook een aantal voordelen:
  • je kunt er generieke tooling/libraries mee maken, die op een andere manier eigenlijk niet te maken zijn
  • je kunt velden initialiseren zonder dat er een setter (of constructor argument) op je publieke interface komt. Dit levert naar de rest van de applicatie juist weer betere information hiding op (zie hieronder m.b.t. IoC).
  • je kunt lifecycle-methoden toevoegen zonder een specfieke interface te hoeven implementeren/extenden
Deze voordelen komen met name van pas in een Inversion of Control (IoC) container, waarbij je IoC kunt laten plaatsvinden zonder een specifieke interface te moeten implementeren, of zelfs zonder expliciet aan te hoeven geven welke velden je via IoC gepopuleerd wilt krijgen1. Ik kan me voorstellen dat iets dergelijks ook in een persistence framework zou kunnen werken.

In het algemeen geldt - zoals zovaak - dat het een krachtig mechanisme is, waarmee je jezelf ook krachtig in de voet kunt schieten :) Ik zou het niet gebruiken als het voordeel niet zeer duidelijk aanwezig is.

Maar wat vindt de TS zelf eigenlijk het mooie aan reflection?

[1] Apache Felix Dependency Manager

[ Voor 6% gewijzigd door Herko_ter_Horst op 27-09-2010 15:38 ]

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

WPF en Silverlight maken gretig gebruik van Reflection, een voorbeeld ervan is bij PropertyChanged.

Daar moet je dan een string meegeven zodat de runtime dat kan oppikken en dan je geupdate property ophalen. Maar daarvoor gebruik ik dan liever 'static reflection', wat er ongeveer zo uitziet:

C#:
1
2
3
4
5
6
7
8
9
        protected void RaisePropertyChanged<TValue>(Expression<Func<TValue>> propertySelector)
        {
            MemberExpression memberExpression = (propertySelector.Body as MemberExpression);

            if (null != memberExpression && null!= this.PropertyChanged)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(memberExpression.Member.Name));
            }
        }


En dan in je property:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Test: INotifyPropertyChanged
{
   private string _name;
   public string Name 
   {
        get 
        {
             return this._name;
        }
        set
        {
             if(this._name != value)
             {
                   this._name = value;
                   this.RaisePropertyChanged(() => this.Name);
                   // ipv this.PropertyChanged(this, new PropertyChangedEventArgs("Name"));
             }
        }
    }
}


Voordeel: Compile time checking, refactoring werkt goed. Met Resharper kan je ook strings doorzoeken maar met dit heb je net iets meer controle.
Nadelen: ja, het is trager :P

Ik heb er een dubbel gevoel bij, ik gebruik het alleen in uiterste nood. In tijden van C++ waarin het niet bestond miste men het ook niet he...

[ Voor 5% gewijzigd door Snake op 27-09-2010 16:00 . Reden: Sorry, uit de losse hand getypt :) ]

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09 23:18

djc

Janoz schreef op maandag 27 september 2010 @ 14:42:
Het is vooral krachtig in het onderuit halen van de zekerheden die een compiler je normaal geeft.
En dan hebben we het nog niet eens over de zekerheden van je argeloze opvolger of collega...

Rustacean


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Snake schreef op maandag 27 september 2010 @ 15:50:
Voordeel: Compile time checking, refactoring werkt goed. Met Resharper kan je ook strings doorzoeken maar met dit heb je net iets meer controle.
Met PostSharp kun je dit nog mooier oplossen met slechts één extra attribuut, en kun je gewoon auto-implemented properties gebruiken.
Nadelen: ja, het is trager :P
Groter nadeel: het is niet-standaard. Als je de naam wijzigt, lijkt me die ene string wijzigen niet zo'n probleem omdat het er vlak onder staat en met copy-paste voorkom je typfouten. ;) Daarnaast vind ik null!= ook minder leesbaar dan !=null trouwens. :p
roy-t schreef op maandag 27 september 2010 @ 14:48:
De reflection code zelf wordt netjes door de compiler gechecked, alleen de binnenkomende class kan verschillende eigenschappen hebben.
Wat heb je vervolgens aan een class waarvan je niet weet of die voldoet en die je weer met reflection moet gaan uitlezen? Of mis ik iets :?
Herko_ter_Horst schreef op maandag 27 september 2010 @ 15:34:
Maar wat vindt de TS zelf eigenlijk het mooie aan reflection?
^^^, en waar gebruikt men het "niet vaak genoeg"?


Toch even een extra voorbeeldje van imo correct gebruik: enum value descriptions.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
Janoz schreef op maandag 27 september 2010 @ 15:11:
[...]

XML is goed te valideren middels een xsd. Daarnaast kun je keurige foutafhandeling schrijven. Het 'probleem' bij XML is dat het uit een ander domein komt dus zul je sowieso wat om moeten zetten. Bij reflection zit je echter in hetzelfde domein. Wanneer je weet hoe de methode heet dan heb je al helemaal geen reflection meer nodig. Daarvoor heb je namelijk een interface. Wanneer je de methode niet kent dan vraag ik me überhaupt af of je er wel wat mee kunt.

Het enige dat ik me voor kan stellen is data je wat dingen met properties kunt doen. Het doorsturen naar een GUI zonder dat je de daadwerkelijke implementatie kunt weten @compile time.
Ok voor XML heb je iig nog XSD's, maar stel dat het een ini bestand is of een ander soort bestand dat je moet uitlezen, daar ga je ook niet zomaar myInt = Int32.Parse(lines[0]); op loslaten, en ook kun je bij het inlezen van een bestand niet precies weten wat je gaat krijgen. Ik zie reflection (deels) net zo, je leest code in. Code die je via reflection krijgt behandel ik ook anders dan 'interne' code, juist om de redenen die jij noemt. Toch vind ik niet dat dit code slecht leesbaar maakt.

Als je er echt niet meer uit komt kun je er altijd nog doorheen stappen :).

@Pedorus,

Je hebt geen interface nodig, je kunt bijvoorbeeld door alle properties heen itereren en kijken of deze gedecoreerd zijn met een (custom) attribute, zoja doe je hier iets mee. (Zo werkt serialisation bijvoorbeeld).

Edit: ik lees net dat JAVA geen attributes heeft :/

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

roy-t schreef op maandag 27 september 2010 @ 17:51:
Ok voor XML heb je iig nog XSD's, maar stel dat het een ini bestand is of een ander soort bestand dat je moet uitlezen, daar ga je ook niet zomaar myInt = Int32.Parse(lines\[0]); op loslaten, en ook kun je bij het inlezen van een bestand niet precies weten wat je gaat krijgen.
Als je ook geen integer verwacht dan is er ook helemaal geen reden om het anders te interpreteren als een String. Verwacht je wel een integer (omdat je er later mee gaat rekenen bv) dan zul je deze wel om moeten zetten. Het punt is juist dat je van tevoren weet wat je met je gegevens gaat doen. Wanneer het uit een ander domein komt (xml en ini) dan heb je geen keuze om het te converteren. Blijf je in hetzelfde domein dan is er helemaal geen reden om middels een string een specifieke property uit te gaan lezen aangezien je ook gewoon netjes de getter aan kunt roepen.
Ik zie reflection (deels) net zo, je leest code in. Code die je via reflection krijgt behandel ik ook anders dan 'interne' code, juist om de redenen die jij noemt. Toch vind ik niet dat dit code slecht leesbaar maakt.

Als je er echt niet meer uit komt kun je er altijd nog doorheen stappen :).
Maar ik zie eigenlijk echt nog niet in waarom je reflection 'uit vrije wil' toe zou willen passen. Meestal is alles wel middels interfaces of eventueel AOP op te lossen. Eigenlijk zie ik alleen nut bij properties icm ioc of de copyProperties in commons.beanutils.

De enige andere situaties waarin ik het toegepast heb moeten hebben is bij unittests om wat dingen in de class te kunnen injecteren waar je normaal niet bij zou mogen.
@Pedorus,

Je hebt geen interface nodig, je kunt bijvoorbeeld door alle properties heen itereren en kijken of deze gedecoreerd zijn met een (custom) attribute, zoja doe je hier iets mee. (Zo werkt serialisation bijvoorbeeld).

Edit: ik lees net dat JAVA geen attributes heeft :/
Een interface is veel cleaner en duidelijker. Daarnaast heeft Java geen attributes, maar waarschijnlijk kun je hetzelfde wel middels annotations bereiken.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Wolfboy
  • Registratie: Januari 2001
  • Niet online

Wolfboy

ubi dubium ibi libertas

.oisyn schreef op maandag 27 september 2010 @ 15:23:
[...]

Hoe dan? Ik heb zelf nooit echt met Qt gewerkt, maar ik ken het idee een beetje. Maar het is dus ook zo dat je @ runtime alle signals en slots bij naam kunt opvragen?
Yes, al gebruiken de signals/slots in de praktijk eigenlijk voornamelijk een lading macro's en komt er meestal niet veel reflection bij kijken.

Docs: http://doc.trolltech.com/4.7/signalsandslots.html

Blog [Stackoverflow] [LinkedIn]


Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 11-09 13:55
Enige goede toepassing van Reflection die ik ooit heb kunnen verzinnen is het genereren van documentatie.
Nu zie ik hier nog wel wat goede voorbeelden genoemd, maar het sturen van je ORM middels comments (docblocks) valt daar niet onder :F

Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

pedorus schreef op maandag 27 september 2010 @ 16:40:
[...]

Groter nadeel: het is niet-standaard. Als je de naam wijzigt, lijkt me die ene string wijzigen niet zo'n probleem omdat het er vlak onder staat en met copy-paste voorkom je typfouten. ;) Daarnaast vind ik null!= ook minder leesbaar dan !=null trouwens. :p
[...]
Define niet standaard? :P Dat kan ik niet vinden in die link?

En inderdaad, zoveel werk is het niet om die property te wijzigen MAAR toch, wat ik compiletime kan doen doe ik compiletime. Period. Minder problemen naderhand.

Over die null != :

Ik zet ALTIJD de constante voorop, weer een beetje compile time checking. Nu geeft csc.exe wel een error als je
C#:
1
if(car = null) 

doet ipv
C#:
1
if(car == null)
maar een hele resum aan talen geven dit niet. En dus doe ik
C#:
1
if(null == car)
, dat geeft in iedere taal een error. (in PHP weet ik het niet. maar dat is ook geen taal, dat is een samenraapsel van 234234 standaarden.)

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • bomberboy
  • Registratie: Mei 2007
  • Laatst online: 02:47

bomberboy

BOEM!

Reflection is handig voor het automagisch genereren van invoerschermen in GUIs.

Je kan bijvoorbeeld heel eenvoudig een GUI genereren op basis van de publieke getters en setters van een klasse. Ik denk dan bijvoorbeeld aan schermen/panels waar je allerlei configuratieparameters van een applicatie ingeeft.

Van zodra er een optie bijkomt in je klasse, is deze ook onmiddellijk beschikbaar in de GUI zonder dat je daarvoor iets extra aan programmeerwerk moet doen. Hetzelfde kan uiteraard ook voor het werken met config-files. Overloop alle items in de configfile. Als er een setter bestaat met dezelfde naam als de parameter in de config-file, zet die dan. Eigenlijk analoog aan Java Properties. Met als voordeel dat eventuele input-checks automatisch kunnen gebeuren bij het inlezen van de data.

Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
bomberboy schreef op maandag 27 september 2010 @ 22:03:
Reflection is handig voor het automagisch genereren van invoerschermen in GUIs.

Je kan bijvoorbeeld heel eenvoudig een GUI genereren op basis van de publieke getters en setters van een klasse. Ik denk dan bijvoorbeeld aan schermen/panels waar je allerlei configuratieparameters van een applicatie ingeeft.

Van zodra er een optie bijkomt in je klasse, is deze ook onmiddellijk beschikbaar in de GUI zonder dat je daarvoor iets extra aan programmeerwerk moet doen. Hetzelfde kan uiteraard ook voor het werken met config-files. Overloop alle items in de configfile. Als er een setter bestaat met dezelfde naam als de parameter in de config-file, zet die dan. Eigenlijk analoog aan Java Properties. Met als voordeel dat eventuele input-checks automatisch kunnen gebeuren bij het inlezen van de data.
@Janoz,

Ik wilde eigenlijk net hetzelfde typen als bomberboy, dit ga je nooit met een interface kunnen doen, en scheelt ontzettend veel werk.

Ik heb vroeger wel eens voor een zut classes een UI-helper-class moeten schrijven om ervoor te zorgen dat je goede invoerschermen kreeg, geen pretje, erg dom werk, en tightly-bound dus alles ging snel stuk.

Ik krijg van jou (mogelijk onterecht) echt de vibe alsof je bang bent voor reflection. Het is maar een tool natuurlijk, eentje die zowel goed als fout gebruikt kan worden.

[ Voor 6% gewijzigd door roy-t op 27-09-2010 22:52 ]

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Snake schreef op maandag 27 september 2010 @ 21:40:
Define niet standaard? :P Dat kan ik niet vinden in die link?
Ik bedoelde dat een willekeurige programmeur de manier zoals die in het voorbeeld daar staat sneller zal snappen, omdat dat een stuk vaker voorkomt.
En inderdaad, zoveel werk is het niet om die property te wijzigen MAAR toch, wat ik compiletime kan doen doe ik compiletime. Period. Minder problemen naderhand.
PostSharp is nog veel minder werk :p
maar een hele resum aan talen geven dit niet. En dus doe ik
C#:
1
if(null == car)
, dat geeft in iedere taal een error.
offtopic:
Daarom doe ik in c# ook altijd een '@' voor mijn variabelenamen. In principe zullen er in c# geen andere keywords bij komen, maar in andere talen zoals sql gebeurd dit wel. Dat het wat minder leesbaar is neem ik maar op de koop toe.. :+ Overigens prefereer ik ook in zeg c++ leesbaarheid boven het mogelijk maken van een foutje dat er bij testen zo uitkomt.
roy-t schreef op maandag 27 september 2010 @ 17:51:
@Pedorus,

Je hebt geen interface nodig, je kunt bijvoorbeeld door alle properties heen itereren en kijken of deze gedecoreerd zijn met een (custom) attribute, zoja doe je hier iets mee. (Zo werkt serialisation bijvoorbeeld).
Hier zie ik niet wat er tegen een interface zou zijn, behalve dat me dat beter lijkt werken (bijv. vanwege de @compile time check). Als je het hebt over iets als een DataGrid waarin willekeurige objecten kunnen worden weergegeven, dan is het logisch dat daar Reflection wordt gebruikt. Maar dat soort controls zijn er al, dus die hoef je veelal niet zelf te maken.

Ik denk dat het punt is dat je het belangrijkere stukje nog niet hebt beantwoord (wat is het mooie aan reflection en wanneer moeten programmeurs het vaker gebruiken). ;)
Dit is echt een top-artikel. :+ Er wordt in het voorbeeld een hoop extra code gemaakt om een dependency op te lossen, maar magisch gezien zijn alle mogelijkheden wel in een enum beschikbaar (enmInvParts wat ook nog niet aan de standaard naming convention voldoet). Deze consultant praat een probleem+oplossing aan waarbij het mij onduidelijk is welk daadwerkelijk probleem op het einde is opgelost.
Wikipedia: Visitor pattern (zie halverwege de details sectie)
Dit voorbeeld is mooier, maar voor alle (daar 3) classes even wat uitschrijven lijkt me ook niet zo erg en daarnaast sneller.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

Even inhakend op het argument van Reflection gebruiken om plug-ins en componenten run-time in te laden:
In C#/VB.Net 4.0 is het Managed Extensibility Framework geintroduceerd wat in ieder geval alle Reflection die wordt uitgevoerd verbergt.

Overigens over dat INotifyPropertyChanged dingetje, ik doe meestal dit:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
class Test {
    public const string Foo_Property = "Foo";

    public int Foo {
        get { return foo; }
        set {
            if(foo != value) {
                foo = value;
                OnPropertyChanged(Foo_Property);
            }
        }
    }
}

En databinding dan als volgt:
C#:
1
textBoxFoo.DataBindings.Add("Text", testInstantie, Test.Foo_Property);

Nu met Land Rover Series 3 en Defender 90


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 18:57
Ook geen (N)Hibernate zonder reflection, dacht ik zo. :P

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

roy-t schreef op maandag 27 september 2010 @ 22:51:
Ik wilde eigenlijk net hetzelfde typen als bomberboy, dit ga je nooit met een interface kunnen doen, en scheelt ontzettend veel werk.

Ik heb vroeger wel eens voor een zut classes een UI-helper-class moeten schrijven om ervoor te zorgen dat je goede invoerschermen kreeg, geen pretje, erg dom werk, en tightly-bound dus alles ging snel stuk.
Ik zal ook zeker niet willen beweren dat reflection zo snel mogelijk uit het platform verwijderd moet worden. Het heeft zo zijn toepassingen. Het eerder aangehaalde IoC configuratie, en ook deze áutomatisch settings genererende GUI kan handig zijn. Al zou ik met de laatste terughoudend zijn en me beperken tot configuratie en beheer schermen.
Ik krijg van jou (mogelijk onterecht) echt de vibe alsof je bang bent voor reflection. Het is maar een tool natuurlijk, eentje die zowel goed als fout gebruikt kan worden.
Ik ben niet bang voor reflection, ik ben bang voor de gevolgen. In mijn werk probeer ik zo defensief mogelijk te ontwikkelen. Runtime code generatie met afhandeling is dan iets dat je voornamelijk wilt vermijden. Natuurlijk zijn er plekken waar je er eigenlijk niet omheen kunt. Het verbaast mij dan ook waarom jij het kunt zien als de 1 van de pijlers die OO ontwikkeling makkelijker maakt. Misschien sneller, maar persoonlijk vind ik onderhoudbaarheid en stabiliteit een stuk belangrijker. Reflection zie ik als een lichte variant van eval in javascript. Die zou je ook zo min mogelijk moeten gebruiken, maar zonder die eval hadden we geen JSON.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

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

.oisyn

Moderator Devschuur®

Demotivational Speaker

pedorus schreef op maandag 27 september 2010 @ 22:54:
Dit voorbeeld is mooier, maar voor alle (daar 3) classes even wat uitschrijven lijkt me ook niet zo erg en daarnaast sneller.
Tot je een visitor gebruikt voor een AST met 40+ classes, dan is het bijhouden van de visitors monnikenwerk. Voor m'n parser geimplementeerd in C++ heb ik eerst een DSL gemaakt zodat ik die class hierarchies makkelijk kan specificeren, waaruit vervolgens de benodigde code wordt gegenereerd (ik heb dus een parser geschreven om een parser te kunnen schrijven 8)7). Ik had liever reflection gebruikt.
Janoz schreef op dinsdag 28 september 2010 @ 09:38:
In mijn werk probeer ik zo defensief mogelijk te ontwikkelen. Runtime code generatie met afhandeling is dan iets dat je voornamelijk wilt vermijden.
Mijn vorige post in deze draad werd straal genegeerd maar bevat imho een hele belangrijke opmerking. Je hebt reflection en je hebt introspection. In talen als Java en C# wordt het op een hoop gegooid, maar gebruik maken van reflection impliceert niet meteen dat je ook dingen aan het genereren bent. Maar dat laatste is wel waar jullie angst vandaan komt, waardoor heel reflection maar meteen als evil wordt weggezet. Imho onterecht.

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.


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
Ja ik moet ook toegeven dat ik eigenlijk exclusief introspection gebruik. Hoewel voor plugin systemen je natuurlijk een hoop functionaliteit kan bedenken met runtime code generatie.

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

.oisyn schreef op dinsdag 28 september 2010 @ 11:13:
Mijn vorige post in deze draad werd straal genegeerd maar bevat imho een hele belangrijke opmerking. Je hebt reflection en je hebt introspection. In talen als Java en C# wordt het op een hoop gegooid, maar gebruik maken van reflection impliceert niet meteen dat je ook dingen aan het genereren bent. Maar dat laatste is wel waar jullie angst vandaan komt, waardoor heel reflection maar meteen als evil wordt weggezet. Imho onterecht.
Ik heb even lopen googlen naar introspection om te kijken wat er exact mee bedoeld wordt, maar op wikipedia kom ik niet verder dan dat het enkel om 'instance of' (en de non java equivalenten) gaat en dat vind ik zelf niet eens echt onderdeel van reflection. Ik vermoed echter dat de definitie toch iets breder ligt. Zou je kunnen vertellen wat jij onder introspectie verstaat?

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

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

.oisyn

Moderator Devschuur®

Demotivational Speaker

Die wikipedia-pagina gaat nergens over, wat ook wel duidelijk is aangezien er geen bronvermelding onder staat. Je komt wat dat betreft wat verder met de filosofische definitie van het woord. Introspection is het kunnen inzien van de definities in de code (dus types en hun members, dingen in de global scope, etc.). Reflection betekent het kunnen aanpassen van die definities.

http://eimers.blogspot.co...ion-vs-introspection.html legt het wel aardig uit.

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.


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

Ah, ok. In java termen is introspectie dan meer het deel dat in Class en Method geimplementeerd is, terwijl reflection meer de bytecode enhancement is.

In dat geval blijft het meeste van mijn beweringen staan, al zou ik de "runtime code generatie" wat moeten nuanceren. Ook methode aanroepen gebaseerd op onbetrouwbare input of niet met refactor acties mee veranderende string constanten zie ik als iets dat voornamelijk vermeden moet worden.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • alwinuzz
  • Registratie: April 2008
  • Laatst online: 21:14
Zelf maak ik onderscheid tussen infrastructuur en 'features'-code.
De code voor de features moet zo simpel en vanzelfsprekend mogelijk zijn, reflection maakt code minder vanzelfsprekend en heb ik daar dus liever niet.

Maar bij de infrastructuur (IoC, ORM, mappen van UI<-->properties enz.) gebruik ik graag reflection. Dankzij reflection kan de infrastructuur op conventies gebaseerde dingen aan elkaar knopen, zodat dat niet handmatig (en foutgevoelig) hoeft.

En reflection kan meer type-safe zijn dan je denkt, zelf gebruik ik een variant op dit: http://www.clariusconsult...7/06/TypedReflection.aspx
Een beetje wat Snake zegt over static reflection.
Geen 'magic strings' nodig :)
pedorus schreef op maandag 27 september 2010 @ 22:54:
[...]
offtopic:
Daarom doe ik in c# ook altijd een '@' voor mijn variabelenamen. In principe zullen er in c# geen andere keywords bij komen, maar in andere talen zoals sql gebeurd dit wel. [...]

[...]
offtopic:
Dit meen je toch niet serieus? :P

[ Voor 20% gewijzigd door alwinuzz op 29-09-2010 12:20 ]


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

Als ik al reflection gebruik dan is dat in unittests (daar gebruik ik het toch wel regelmatig, maar dat is dan ook geen runtime code, maar code die alleen @ compiletime draait) of weggestopt in libraries (spring en hibernate bv).

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
In het geval van Java heb je reflection ook 'nodig' omdat je geen function pointers hebt. Ik heb o.a. een helper class geschreven die aan de hand van een soort column ID, een tableresult, een doelobject en een doelproperty het resultaat uit die column in dat business object propt. Een beetje ORM achtig dus (en nee, gangbare ORM's zijn niet te gebruiken, anders had ik er zelf niet een geschreven). Het is ideaal dat je in plaats van 5 regels code per property er nog maar een hoeft te schrijven, die ook nog eens een stuk leesbaarder is, iets in de trant van:

Helper.set(Row source, String column, Object dest, String propery);

Pro's:
- Sneller te devven (hebben het over objecten met zo 20+ properties)
- Leesbaarder
- Minder foutgevoelig

Con's:
- Kleine performanceimpact van reflection

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

Is dat veel leesbaarder dan

dest.setProperty(source.getColumn());

?

je bent daarnaast nog wat Cons vergeten:

- Bij refactoren veranderen de hier gebruikte property names niet mee.
- Bij zoeken naar Usage komt deze code niet naar voren.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Janoz schreef op maandag 04 oktober 2010 @ 15:30:
Is dat veel leesbaarder dan

dest.setProperty(source.getColumn());
Die properties zijn dus getters en setters van de bean. Als je als property "Name" meegeeft roept 'ie de "setName" setter aan.

Daarnaast zit er casting logica in, kijken of iets null is, etc. Als source en target dates zijn worden die netjes gecast bijvoorbeeld. Als ik zeg dat je anders per property 5 regels code nodig hebt kun je er ook vanuit gaan dat ik dat meen.
?

je bent daarnaast nog wat Cons vergeten:

- Bij refactoren veranderen de hier gebruikte property names niet mee.
- Bij zoeken naar Usage komt deze code niet naar voren.
Die vind ik redelijk minor eerlijk gezegd. Als method names niet kloppen krijg je gewoon een KennieVindenException, en de code is duidelijk genoeg verder. Ik zeg ook niet dat je reflection te pas en te onpas moet gebruiken, maar 't heeft z'n uses en kan gewoon development tijd schelen. Zo wordt 't enorm vaak gebruikt om in een config aan te geven welke connector of logger classes gebruikt moeten worden bijvoorbeeld.

https://niels.nu


Acties:
  • 0 Henk 'm!

  • DaRKie
  • Registratie: December 2001
  • Laatst online: 02-09 19:08
Hydra schreef op maandag 04 oktober 2010 @ 15:37:
- Bij refactoren veranderen de hier gebruikte property names niet mee.
>>Die vind ik redelijk minor eerlijk gezegd. Als method names niet kloppen krijg je gewoon een KennieVindenException
Tuurlijk zal je een exception krijgen als je string een foutieve naam bevat. Het is alleen de vraag wanneer je dit gaat merken aangezien je dit pas @runtime kunt krijgen. En zolang het tijdens de testen eruit komt, is het ook nog niet zo een probleem ... maar er is gewoon geen garantie dat een dergelijk foutje er toch doorsijpelt en zich pas manifesteerd als de applicatie op productie draait en dan is je minor probleempje ineens a major one :)

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

Hydra schreef op maandag 04 oktober 2010 @ 15:37:
[...]


Die properties zijn dus getters en setters van de bean. Als je als property "Name" meegeeft roept 'ie de "setName" setter aan.
dat bedoel ik ook met mijn 'property'. Ik had even de argument namen over genomen.
Dit voorbeeld zou dan
dest.setName(row.getNameColumn()) of row.getColumn("name") wanneer het een map is.
Daarnaast zit er casting logica in, kijken of iets null is, etc. Als source en target dates zijn worden die netjes gecast bijvoorbeeld. Als ik zeg dat je anders per property 5 regels code nodig hebt kun je er ook vanuit gaan dat ik dat meen.
Is er niet een tussenoplossing mogelijk? Een (static) helpermethod die een object neemt en daar de 5 regels doet?

code:
1
2
3
4
5
Helper.asDate(Object dateProperty) {
  Date result;
  //je vijf regels incl cast
  return result;
}


Dan krijg je (even aangenomen dat de helper methoden middels static import erin zitten)
code:
1
dest.setSomeDateProperty(asDate(src.getColumn("aDateProperty")));
Die vind ik redelijk minor eerlijk gezegd. Als method names niet kloppen krijg je gewoon een KennieVindenException, en de code is duidelijk genoeg verder. Ik zeg ook niet dat je reflection te pas en te onpas moet gebruiken, maar 't heeft z'n uses en kan gewoon development tijd schelen. Zo wordt 't enorm vaak gebruikt om in een config aan te geven welke connector of logger classes gebruikt moeten worden bijvoorbeeld.
Dat vind ik inderdaad ook wel legitieme toepassingen (Spring, evt uitgebreide Log4j config). Het grote verschil is dat je hier van het ene type (xml configuratie) naar het andere type (java code) gaat.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Janoz schreef op maandag 04 oktober 2010 @ 15:48:
Is er niet een tussenoplossing mogelijk?
De versie daarvoor was een tussenoplossing. Ik heb dat met reflection opgelost om te zorgen dat je niet voor alle combinaties van datumobjecten (er moet o.a. geconverteerd (niet gecast) worden tussen een intern en een Java date) e.d. aparte helperclasses hoeft te maken. Vergeet ook niet dat je in alle objecten moet checken of een object null is, of geen waarde heeft (twee aparte gevallen). De methode voor een date zag er ongeveer zo uit:

Java:
1
2
3
4
5
6
7
8
9
public Date Helper.getAsDate(RowItem item)
{
   if(item == null)
     return null;
   else if(item.values().size() == 0)
    return null;
   else
    return ((MyDate)item.values().get(0)).toDate();
}


En dat goldt dan voor alle mogelijke types. Dit terwijl je van item weet wat het type is, en dus als je weet in welke property je 'em moet zetten het prima af kan.

Dus dan wordt het in plaats van:
o.setName(Helper.getAsString(row.findItem("name"));
o.setAge(Helper.getAsInteger(row.findItem("age"));
o.setDob(Helper.getAsDate(row.findItem("dob"));
...

Gewoon:
Helper.set(row, "name", o, "Name");
Helper.set(row, "age", o, "Age");
Helper.set(row, "dob", o, "Dob");

Minder typewerk, en bovendien omdat het echt VEEL properties zijn is de kans dat je door copy-pastefouten errors krijgt ook minder. Die set-functie geeft een error als niet gecast kan worden. En als er een String in een integer gepropt moet worden, wordt die gewoon geparsed.

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

Copy paste fouten zul je in beide gevallen hebben lijkt me. Daarnaast scheelt het qua typewerk ook niet veel aangezien de bovenste variant bijna allemaal ge-'ctrl-spatie'-t kan worden. Daarnaast is de (static) implementatie van die getAsSomeType niet anders dan hetgeen je nu in de huidige Helper class geimplementeerd hebt.

Ik begrijp dat je het zo gedaan hebt, maar ik zou het zo niet doen denk ik.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Janoz schreef op maandag 04 oktober 2010 @ 16:10:
Copy paste fouten zul je in beide gevallen hebben lijkt me.
Nouja, in mijn oplossing kon je niet in een copy-paste actie de verkeerde getAs method laten staan, omdat je er nog maar 1 had. Natuurlijk kon je 'em nog in de verkeerde property prakken maar dat had je daarvoor ook.
Daarnaast scheelt het qua typewerk ook niet veel aangezien de bovenste variant bijna allemaal ge-'ctrl-spatie'-t kan worden.
De setters wel, dat is ook niet zozeer het probleem. De "findItem" sowieso niet.
Daarnaast is de (static) implementatie van die getAsSomeType niet anders dan hetgeen je nu in de huidige Helper class geimplementeerd hebt.
Nee, maar je hebt niet meer ongeveer 6 getAs<Type> methods die allemaal moeten controleren of iets null is of leeg is, en dan nog eventueel moeten casten of parsen. Dat zit nu in 1 (m.i. overzichtelijke) method.
Ik begrijp dat je het zo gedaan hebt, maar ik zou het zo niet doen denk ik.
Een collega van me dacht er net zo over als jij :)

Ik zeg ook niet dat het de beste manier is hoor, maar ik ben er zelf wel content mee. In de oude versie van de code had je per property ook 2 regels nodig (itt mijn voorbeeld, maar ik ben ff kwijt waarom, heb die code hier niet). Het was gewoon irritant om te onderhouden en dat is nu net iets simpeler.

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

Hydra schreef op maandag 04 oktober 2010 @ 16:19:
De setters wel, dat is ook niet zozeer het probleem. De "findItem" sowieso niet.
Kan in beide gevallen niet. Bij de reflection variant is ook de setter een zelf te tikken naam.
Nee, maar je hebt niet meer ongeveer 6 getAs<Type> methods die allemaal moeten controleren of iets null is of leeg is, en dan nog eventueel moeten casten of parsen. Dat zit nu in 1 (m.i. overzichtelijke) method.
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static Date getAsDate(RowItem item) 
{ 
   if(isNullable(item)) 
     return null; 
   else 
    return ((MyDate)item.values().get(0)).toDate(); 
}

/*
.. vijf andere...
*/

private static boolean isNullable(RowItem item)
{
   return (item == null) || (item.values().size() == 0)
}

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 19:59

RayNbow

Kirika <3

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


Acties:
  • 0 Henk 'm!

  • bomberboy
  • Registratie: Mei 2007
  • Laatst online: 02:47

bomberboy

BOEM!

DaRKie schreef op maandag 04 oktober 2010 @ 15:44:
[...]
Tuurlijk zal je een exception krijgen als je string een foutieve naam bevat. Het is alleen de vraag wanneer je dit gaat merken aangezien je dit pas @runtime kunt krijgen. En zolang het tijdens de testen eruit komt, is het ook nog niet zo een probleem ... maar er is gewoon geen garantie dat een dergelijk foutje er toch doorsijpelt en zich pas manifesteerd als de applicatie op productie draait en dan is je minor probleempje ineens a major one :)
In heel veel gevallen (en in ik denk ook in het voorbeeld dat aangehaald wordt) heb je die garantie gewoon wel mits wat eenvoudige unit-tests.

De "tegenstanders" van reflection in dit topic lijken steeds in een soort van panic-mode te gaan. Heel vaak zijn de namen gebruikt bij reflection gewoon strict vastgelegd en komt daar in de verste verte geen user-input aan te pas. Dat wil zeggen dat je een vast-gedifineerde set van mogelijke waarden hebt die je perfect volautomatisch kan (en moet) testen. Hiermee bedoel ik ook dat je perfect kan testen dat de code die die namen gebruikt ook enkel de juiste waarden gebruikt.

Op die manier heb je net zo goed de garantie dat alles werkt zoals hoort en er geen onvoorziene input kan gegenereerd worden.

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

bomberboy schreef op maandag 04 oktober 2010 @ 16:30:
De "tegenstanders" van reflection in dit topic lijken steeds in een soort van panic-mode te gaan. Heel vaak zijn de namen gebruikt bij reflection gewoon strict vastgelegd en komt daar in de verste verte geen user-input aan te pas.
String constanten zijn ook userinput. De user is in dat geval de programmeur die op dat moment de applicatie in onderhoud heeft.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • bomberboy
  • Registratie: Mei 2007
  • Laatst online: 02:47

bomberboy

BOEM!

Maar zoals je heel goed niet gequote hebt: user-input die je heel eenvoudig kan checken in unit-tests.

En zelfs in het geval van een library die gebruikt wordt door externen blijft dat een geldig statement. Als ik bij een willekeurige methode null meegeef als parameter, krijg ik ook gewoon een NPE terug geslingerd. Bij reflection gebeurt gewoon hetzelfde (met een MethodNotFoundException of iets dergelijks).
Ik zie niet in waarom dat een probleem is.

Dat de compiler het niet voor je ontdekt is nu eenmaal zo. Daarvoor zijn die unit-tests die ik aanhaalde. Reflection is lang niet de enige feature waarbij de compiler niet alles op voorhand kan checken.

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

Ik begrijp dat je er soms niet omheen kunt, maar zoals ik laat zien kan het door Hydra gestelde voorbeeld ook zonder reflection opgelost worden. Ikzelf probeer zo defensief mogelijk te programmeren. Altijd fluistert Murphy in mijn achterhoofd mee. Blind vertrouwen op het wel aanwezig zijn van unittest en daarom een shortcut nemen de de onderhoudbaarheid van je software verkleind is niet iets wat ik zomaar zou doen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Janoz schreef op maandag 04 oktober 2010 @ 16:26:
[...]

Kan in beide gevallen niet. Bij de reflection variant is ook de setter een zelf te tikken naam.

[...]

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static Date getAsDate(RowItem item) 
{ 
   if(isNullable(item)) 
     return null; 
   else 
    return ((MyDate)item.values().get(0)).toDate(); 
}

/*
.. vijf andere...
*/

private static boolean isNullable(RowItem item)
{
   return (item == null) || (item.values().size() == 0)
}
Je hoeft mij echt niet uit te gaan leggen hoe het ook kan, dat is ongeveer de implementatie die het eerder was, met nog wat andere huishoudelijke code die ik hier niet kan posten. De mijne is gewoon een stuk leesbaarder. Als het zo simpel was als in jouw voorbeeld had ik niet de moeite genomen het te refactoren.
Janoz schreef op maandag 04 oktober 2010 @ 17:00:
Ik begrijp dat je er soms niet omheen kunt, maar zoals ik laat zien kan het door Hydra gestelde voorbeeld ook zonder reflection opgelost worden.
Ik claim nergens dat het niet 'kan'. Mijn methode MET reflection is leesbaarder. Ik kan helaas niet de code posten (dan violate ik 3 NDA's en ben ik bovendien 'herkenbaar') maar zoals ik al eerder gezegd heb, heb ik de hoeveelheid benodigde code verminderd en de zaak leesbaarder gemaakt. Klaar.

[ Voor 24% gewijzigd door Hydra op 04-10-2010 17:15 ]

https://niels.nu


Acties:
  • 0 Henk 'm!

  • bomberboy
  • Registratie: Mei 2007
  • Laatst online: 02:47

bomberboy

BOEM!

Zelf heb ik al een paar slechte ervaringen gehad met programmeurs die naar eigen zeggen "robuust" programmeren. Ik heb vermoedelijk een andere definitie van "robuust" dan sommige andere mensen en dat beïnvloedt waarschijnlijk de perceptie wat :)

Een concreet voorbeeld was het parsen van een stuk textuele data (met spec van hoe die er moest uitzien):
Mijn aanpak: indien het stukje tekst niet voldeed aan de spec: exception
de zogenaamd robuuste aanpak: ook al voldoet de tekst niet aan de spec, toch nog proberen om er iets nuttigs uit te halen. De helft van de keren werkte dit goed, de andere helft niet.

Het probleem was dan dat de schrijver van die robuuste variant zelf niet altijd wist of het nu goed of niet goed geïnterpreteerd was (hoe zou je het ook moeten weten) en er soms ook verder gewerkt werd met foute informatie waardoor alle logica erna ook met foute resultaten eindigde.

Het soort van robuust programmeren waarbij fouten eigenlijk verdoezeld worden en pas in een volgend stadium opduiken zijn in mijn mening dan ook een veel groter probleem dan runtime exceptions zoals die die je bij Reflection kan krijgen.

Maar dit dreigt een beetje off-topic te gaan op deze manier.
Misschien hebben we zelfs niet zo'n fundamenteel verschillende mening, maar de insteek is net wat anders en we benaderen het van een andere invalshoek.

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

Ik denk dat we het daarover meer eens zijn dan je denkt. Ik heb het over defensief programmeren, niet 'robuust'. Ik zou mijn veilige benadering eerder willen vergelijken met jouw 'gooi maar een exceptie zodra je ruikt dat er iets mis zou kunnen zijn'-benadering. Sowieso wil ik een applicatie die in de helft van de gevallen waarin de input verkeerd is dat niet eens detecteert niet eens genoemd zien worden in een zin met het woord robuust erin :). Waar de discussie tussen Hydra en mij een kwestie van smaak is, is het verdoezelen van fouten iets waarvoor je die collega best tegen de spreekwoordelijke muur mag zetten.

En nog een kleine dienstmededeling. Offtopic is in de devschuur geen zonde. Dat straffen we niet af, maar dat splitsen we af. Dit topic is bijvoorbeeld ontstaan uit een stukje offtopic uit een andere draad.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • _Erikje_
  • Registratie: Januari 2005
  • Laatst online: 10-09 20:55

_Erikje_

Tweaker in Spanje

het kan de code een stuk mooier maken maar een belangrijk punt voor mij om het beperkt te gebruiken:

De meeste programmeurs snappen het niet.

Dit heeft impact op de onderhoudbaarheid en in mijn ogen moet je de software zo makkelijk mogelijk ontwerpen, zodat elke newb je code meteen snapt. KISS, je weet zelf!! 8)

Daarnaast zit er natuurlijk een veiligheidsaspect aan, laat nooit de userinput onderdeel worden van de string die je gebruikt om te reflecteren. Werk altijd met final/static variabelen!!
Pagina: 1