Privacy in statische talen

Hoewel ik de waarde van implementatie/interface-onderscheid begrijp, begrijp ik niet waarom de meeste OO-systemen fouten veroorzaken bij de toegang tot privé-leden.

Ik zou inderdaad geen toegang willen krijgen tot privé-leden in mijn hoofdprogramma.
Maar ik zou die toegang graag willen hebben voor testen en debuggen.

Is er een goede reden om fouten te maken en geen waarschuwingen? Zoals ik het zie, ben ik genoodzaakt om code te schrijven die ik kan testen, maar dat maakt geen gebruik van taalondersteuning voor interfaces, of gebruik de taalondersteuning, maar heb moeite met testen.

Bewerken

Voor degenen die suggereerden om openbare interfaces te gebruiken. Dat kan, maar het is minder convinent.
Op een conceptueel niveau vind ik privacy die niet geeft om wie of wanneer behoorlijk grof.
Vriendklassen lijken een redelijke oplossing. Een andere kan een 'alle openbare' compilerschakelaar zijn.

2
De oplossing is om geen tests te schrijven die rechtstreeks toegang geven tot privé-leden van het te testen object. Uw tests moeten op de openbare interface werken.
toegevoegd de auteur Oliver Charlesworth, de bron
Moeten particuliere leden volgens het ontwerp niet over andere (openbare) methoden beschikken om ze al te bellen? Het idee van private methoden is om de interne werking van een klasse te segmenteren zonder de openbare interface te compliceren. Waarom zou je een privémethode schrijven zonder een doel (dwz een openbare methode die het gebruikt)?
toegevoegd de auteur Stecman, de bron

5 antwoord

Zoals ik het zie, ben ik genoodzaakt om code te schrijven die ik kan testen, maar dat maakt geen gebruik van taalondersteuning voor interfaces, of gebruik de taalondersteuning, maar heb moeite met het testen.

Waarom moet u de variabelen en functies van private openen? Ofwel worden ze op een bepaald moment (maar indirect) door public -functies genoemd, of het zijn gewoon ontoegankelijke stukjes code die er helemaal niet zouden moeten zijn omdat er geen manier is om ze aan te roepen. Denk er eens over na, als de private methode volledig onmogelijk is om van buiten de klas op welke manier dan ook aan te roepen, zal het dan ooit worden uitgevoerd?

If you really want to test a private method anyway, you can pull it into its own class. Plus, if its so complex that it really needs to best tested individually, there's a chance that it deserves to have its a chance in the first place. The other option is to just make it public whenever you need/want to test it, but not actually change the 'real' code (leaving it private). As others have said, some languages also have features that help you test these methods by exposing them slightly more, such as friend in C++, internal in C#, and package-private in Java. Occasionally the IDE's themselves even help out.

Is er een goede reden om fouten te maken en geen waarschuwingen?

Een belangrijke reden is niet dat je ze niet kunt bellen, het is zo dat andere mensen ze niet kunnen bellen. Stel je dit voor, je schrijft een bibliotheek die door een substantieel aantal klanten zal worden gebruikt. U hebt alles gemarkeerd wat niet nodig is om privé te bellen, en alle functionaliteit die ze nodig hebben is openbaar. Programmeurs gaan door en gebruiken uw bibliotheek, schrijven er een heleboel code mee en produceren tevreden klanten zowel uit zichzelf als uit hun eigen klanten.

Een paar maanden later besluit je om je enorm succesvolle bibliotheek op te peppen en te ontdekken dat je een beetje moet refactoren. Vandaar dat u een aantal van uw private -methoden [hernoemt, toevoegt/verwijdert], maar let erop dat alle interfaces van uw openbare methode exact hetzelfde blijven om een ​​probleemloos proces te upgraden. MAAR in deze universe produceren compilers alleen waarschuwingen en geen fouten wanneer u een private -variabele opent, en verschillende van uw clientprogrammeurs hebben code geschreven die roept die private methoden. Wanneer ze nu proberen te upgraden naar uw nieuwe versie van uw bibliotheek, krijgen ze een aantal echte fouten omdat ze die private methoden niet meer kunnen aanroepen. Nu moeten ze ofwel tijd besteden om erachter te komen wat er mis is gegaan met de code en potentieel grote delen ervan herschrijven waar ze zich niets van herinneren (had ik al gezegd dat dit twee jaar in de toekomst is?). Daarom moeten ze volledig opnieuw leren hoe ze uw bibliotheek moeten gebruiken en hun clientcode moeten herschrijven, wat voor niemand leuk is. Nu zijn ze nogal ontstemd dat je zo onattent was dat ze letterlijk al hun code doorbraken met je upgrade en hun leven veel moeilijker maakten.

Wat denk je, toen ze de code aan het repareren waren, hebben ze je nieuwe private methoden onderzocht en genoemd, dus als je ooit besluit hun interface te wijzigen wanneer je een upgrade uitvoert, begint de hele cyclus opnieuw. Wat was iets handiger voor u, u kreeg gewoon een hoop ongelukkige klanten.

Wacht, waren ze niet idioten voor het aanroepen van mijn privémethoden? Waarom keken ze niet naar de waarschuwingen? Dit is hun schuld, niet de mijne!

Wel, ja, het is hun schuld en ze hadden het probleem kunnen voorkomen door ervoor te zorgen dat ze op deze waarschuwingen letten. Maar niet iedereen is een fan van code-kwaliteit die waarschuwingen wil corrigeren en begrijpen, en een aanzienlijk aantal mensen negeert ze gewoon. Het probleem is dat u het geheel zelf had kunnen voorkomen als compilers fouten hadden gemaakt om toegang te krijgen tot private variabelen en methoden in plaats van waarschuwingen, omdat anders het trefwoord private net zo goed kon helemaal niet bestaan. Je hebt misschien wat tijd verloren omdat die methoden moeilijker te testen zijn, maar je hebt de kracht gekregen om minder intelligente mensen ervan te weerhouden je code te misbruiken en ze de schuld te geven voor problemen die ze onderweg veroorzaken.

Een van mijn favoriete eigenschappen van softwareontwikkeling (en productontwerp in het algemeen) is dat dingen eenvoudig en correct of moeilijk of niet goed te gebruiken moeten zijn. Echte privé-leden zijn de belichaming van dit advies omdat ze je code letterlijk onmogelijk correct kunnen gebruiken.

[hypothetische reactie:] Nou, de mensen die mijn code gebruiken, moeten slim genoeg zijn om erachter te komen. Het enige dat ik van hen verwacht, is gewoon een beetje extra tijd spenderen om de code correct te gebruiken.

Dus u weigert bewust de tijd te besteden die nodig is om de kwaliteit van uw code te verbeteren en het gemakkelijker te gebruiken maken? Dan wil ik niets te maken hebben met wat je code is. Uiteraard is uw tijd belangrijker dan die van uw klanten, dus ik neem de 2,5 seconden die nodig zijn om de webpagina voor uw project te sluiten en klik op het volgende Google-resultaat. Er zijn veel meer private leden van de bibliotheken die u gebruikt dan u zou denken, en het glorieuze is dat u zelfs geen milliseconde van uw tijd hoeft te besteden aan zorgen maken over hen omdat ze volledig verborgen voor u en zou alleen maar afleiden van de gemakkelijkere en betere manier om dingen te doen die in de publieke -interface worden geboden. Als alles openbaar was of een privé-melding met een slechte waarschuwing, zou je een groter aantal functies moeten doorzoeken voordat je echt hebt gevonden wat je wilde.

Telkens wanneer u privé invoert vóór een ledenfunctie, hebt u zichzelf de kracht gegeven om deze op elk gewenst moment in de toekomst te wijzigen, omdat niemand anders dan u het kan aanraken. De tweede die iemand anders probeert toegang te krijgen, krijgt een show-stopping fout omdat de compiler je rug heeft en zal niet toestaan ​​dat ze iets stoms doen met je code als je al alles wat ze nodig hebben in een veel bruikbare vorm hebt geleverd in uw publieke -interface.

Ja, het zal het in het nu iets moeilijker maken om te testen, maar het heeft er ook voor gezorgd dat je je er in de toekomst geen zorgen over hoeft te maken als je een refactor maakt en je code een lot gemakkelijker maakt voor andere mensen om te gebruiken. Ga je gang en maak het tijdelijk openbaar (ik vind je 'al-public compiler switch idea :) leuk, maar vergeet niet om het terug te zetten als je klaar bent. Jij en je klanten kunnen allemaal plezier beleven aan het werken met eenvoudiger en meer aanpasbare code. : D

1
toegevoegd
@sabof Hij heeft misschien een goede kans om het toch goed te doen, maar waarom niet gewoon zijn pistool afpakken zodat hij zichzelf niet in de voet kan schieten? :)
toegevoegd de auteur Gordon Gustafson, de bron
Goh, Goh Gee Willikers, wat een groot antwoord, +1.
toegevoegd de auteur Camilo Martin, de bron
Persoonlijk geloof ik dat een gebruiker die geen toegang heeft tot een 'risicovolle' functie evenveel kans heeft 'het juiste te doen' als hij een nieuwe ingenieuze manier bedenkt om de verschillende gebouwen in het blok samen te vouwen terwijl hij zelf de voet schiet . Mijn verantwoordelijkheid is hen te vertellen welke functies riskant zijn, maar de toegang niet afdwingen.
toegevoegd de auteur sabof, de bron
Wat ik niet leuk vind aan strikte inkapseling, is dat ik niet zoveel manieren krijg om mijn programma te verkennen. In talen met goede hulpmiddelen is dit misschien geen probleem.
toegevoegd de auteur sabof, de bron
Wat ik bedoel is dat de gebruiker een slechtere oplossing kan bedenken dan toegang tot privé/evalue/gotoing. Een ander aspect is dat ik het 'verkeerde' zou kunnen doen, kijken of het werkt en het vervolgens correct implementeren of het idee helemaal afwijzen. Een minder flexibele omgeving heeft niet zoveel bruggen naar verschillende oplossingen.
toegevoegd de auteur sabof, de bron

Er zijn verschillende voordelen aan het hebben van volledige inkapseling:

  • Beveiliging . Sterk getypeerde OOP-talen met sterke inkapseling kunnen bepaalde garanties hebben over de beveiliging van de gegevens in het programma. De Java-taal is ontworpen met het oog op veiligheid en beveiliging, dus voor bepaalde bibliotheekklassen (bijvoorbeeld String of SecurityManager ) kunnen de velden niet worden geopend. Hiermee wordt voorkomen dat schadelijke code slechte dingen met deze objecten doet en kan de code aannemen dat de objecten veilig zijn.

  • Maintainability . Een van de belangrijkste redenen om private velden en methoden privé te behouden, is om de implementatie naadloos te laten veranderen; zolang er geen updates in de openbare interface worden gemaakt, kan code die de bijgewerkte klasse gebruikt zonder wijzigingen werken. Als u toegang tot private velden toestaat en vervolgens de implementatie wijzigt, loopt u het risico een onbegrensde hoeveelheid code te verbreken.

  • Stabiliteit/Verifieerbaarheid/testbaarheid . Klassen leggen meestal invarianten op hun velden - een implementatie van een dynamische array kan bijvoorbeeld vereisen dat een veld dat bijhoudt hoeveel ruimte wordt gebruikt, overeenkomt met het totale aantal elementen. Mensen toestaan ​​om willekeurig toegang te krijgen tot private velden, zelfs met een waarschuwing, maakt het mogelijk om deze invarianten te doorbreken. Zonder het vermogen om op de invarianten te rekenen, wordt het moeilijk of onmogelijk om te redeneren over de juistheid van de code. Als u bovendien ergens in de code een invariant breekt, zou u waarschijnlijk elk stuk code in het programma moeten bekijken dat toegang heeft tot het object, aangezien een van hen mogelijk de private veld. Met sterke inkapseling kunnen deze invarianten niet breken, en met semiencapsulation via friend s of package-private mechanismen, wordt de hoeveelheid te bekijken code begrensd.

Wat betreft uw vraag over testen - in veel talen kan inkapseling in bepaalde gevallen worden verbroken; C ++ heeft friend , Java heeft package-private, etc., zodat de klas kan zeggen "normaal kun je deze niet aanraken, maar er kunnen uitzonderingen gemaakt worden." U kunt vervolgens uw testcode een vriend of in hetzelfde pakket als de hoofdklasse maken om deze grondiger te testen.

Ik hoop dat dit helpt!

0
toegevoegd
@ OliCharlesworth- Dat is waar, maar C ++ -klassen waren niet ontworpen voor beveiliging, terwijl Java dat wel was. De beveiligingsmanager in Java is zodanig ontworpen dat sleutelklassen niet kunnen worden weergegeven in (bijvoorbeeld tekenreeks, systeem, enzovoort) en kan worden aangepast zodat u toegang tot belangrijke klassen van uw keuze kunt voorkomen. Ik zou zeggen dat het niet vaak op deze manier wordt gebruikt, maar Java biedt deze beveiliging wel.
toegevoegd de auteur templatetypedef, de bron
Ik ben nooit overtuigd door een argument dat inkapseling -> beveiliging (althans niet in de OO-zin). C ++ heeft onbewerkte wijzers, Java heeft reflectie, etc.
toegevoegd de auteur Oliver Charlesworth, de bron

De voor de hand liggende reden zou zijn dat te veel mensen veel (al?) Waarschuwingen lijken te negeren. In sommige talen (bijv. Python) is het vrijwel zoals je hebt gezegd - iets dat "privé" is, is in principe advies tegen externe code door het rechtstreeks te gebruiken, maar de compiler dwingt dat niet af.

Wat betreft de zin die ik voel, ik vermoed dat het varieert tussen talen - in iets als C ++, de houding ten opzichte van hen ("bescherm tegen Murphy, niet Machiavelli") kan gezien worden als een rechtvaardiging voor het feit dat het een waarschuwing in plaats van een fout.

Ik denk dat het veilig is om te zeggen dat in Ada, dat op zijn zachtst gezegd een veel koelere ontvangst zou ontvangen (en dat wil niet zeggen dat ik denk dat het ook warm ontvangen zou worden door C ++ programmeurs, alleen dat ze zullen het idee misschien niet zo haten als de meeste Ada-programmeurs dat wel zouden doen).

Aan de andere kant moet ik me afvragen wat het ontwerp is van een klasse die niet (redelijk redelijk) kan worden getest via de externe interface. Op de zeldzame (hoe dan ook zeldzaam, in elk geval) gelegenheid die je niet kunt, denk ik dat het redelijk gemakkelijk te rechtvaardigen is om van de testklasse een vriend te maken (in C ++ -taalgebruik, hoewel vele anderen vergelijkbare concepten hebben).

0
toegevoegd
Ik zie hoe Ada-programmeurs het idee misschien niet leuk vinden. Iets in de lijn van instelbare striktheid zou iedereen kunnen plezieren - dynamische ontwikkeling met statische garanties.
toegevoegd de auteur sabof, de bron

Ik stond op het punt om te posten, "Sterke handhaving van inkapseling zorgt ervoor dat je baas niet op je privéleden stapt." totdat ik me realiseerde hoe dat verkeerd zou kunnen klinken, maar bij nader inzien is het waarschijnlijk ongeveer gelijk.

0
toegevoegd

De manier waarop ik het zie, is dat je de toegang tot iets in een object moet vergeten, tenzij je een manier hebt om dat in de interface van dat object te doen. Ik denk dat een correct OO-systeem fouten (en geen waarschuwingen) moet geven als u probeert toegang te krijgen tot specifieke leden van de implementatie. Ik heb onlangs een goed gesprek bijgewoond door Kevlin Henney over dit onderwerp en ik vond het zeer nuttig, een kopie kan hier worden bekeken: http://www.infoq.com/presentations/It-Is-Possible-to-Do-OOP-in-Java (merk op dat het gaat voornamelijk over Java, maar bevat ook vergelijkingen met andere OO-systemen)

Voor het testen van de meeste tijd vind ik dat het grootste deel van de te testen code wordt bestreken door openbare interface-oproepen. Het is slechts in zeldzame gevallen dat ik iets als runtime-reflectie moet gebruiken om 100% dekking te krijgen.

0
toegevoegd