Vraag Zijn de gedeeltelijke klassen van C # slecht ontwerp?


Ik vraag me af waarom het 'partial class'-concept zelfs bestaat in C # / VB.NET. Ik werk aan een applicatie en we lezen een (eigenlijk heel goed) boek dat relevant is voor het ontwikkelingsplatform dat we op het werk implementeren. In het boek biedt de auteur een grote codebase / wrapper rond de API van het platform en legt uit hoe hij deze heeft ontwikkeld, aangezien hij verschillende onderwerpen leert over de platformontwikkeling.

Hoe dan ook, lang verhaal kort - hij gebruikt gedeeltelijke klassen, overal ter wereld, als een manier om meerdere overerving in C # (IMO) te vervalsen. Waarom hij niet alleen de lessen in meerdere heeft gesplitst en compositie gebruikt, gaat mij te boven. Hij zal 3 'partial class'-bestanden hebben om zijn basisklasse op te maken, elke w / 3-500 regels code ... En dit meerdere malen in zijn API.

Vindt u dit gerechtvaardigd? Als ik het was, zou ik de S.R.P. en creëerde meerdere klassen om verschillende vereiste gedragingen af ​​te handelen, en maakte vervolgens een basisklasse die exemplaren van deze klassen als leden heeft (bijvoorbeeld samenstelling). Waarom heeft MS zelfs een gedeeltelijke klasse in het kader geplaatst? Ze verwijderden de mogelijkheid om alle code op elk scoopniveau in C # uit te vouwen / samen te vouwen (dit was toegestaan ​​in C ++) omdat het natuurlijk gewoon slechte gewoonten toestond - gedeeltelijke klasse is, IMO, hetzelfde. Ik denk dat mijn vraag is: kun je me uitleggen wanneer er een legitieme reden zou zijn om ooit een gedeeltelijke les te gebruiken? 

EDIT: Ik ben me ervan bewust dat er voor Web / WinForms geen andere keuze is. Maar daarbuiten? Waarom heeft MS niet gewoon een ander sleutelwoord geplaatst om klassen met code-genn'ed samen te lijmen? Of is er echt een legitiem ontwerpscenario dat het verdient?

Ik bedoel dit niet als een rant / war thread. Ik ben eerlijk om hier iets te leren. Wanneer moeten deelklassen worden gebruikt bij het ontwerpen van codes? Eenvoudige vraag, niet nodig om te sluiten

Bedankt


67
2018-03-19 14:01


oorsprong


antwoorden:


Kun je me uitleggen wanneer er een legitieme reden zou zijn om ooit een gedeeltelijke les te gebruiken?

Een van de meest legitieme en nuttige redenen is om de scheiding aan te moedigen van automatisch gegenereerde code en uw eigen aangepaste extensies. Het is bijvoorbeeld gebruikelijk om een ​​automatisch gegenereerde formuliercode van een of andere ontwerper te hebben, maar u wilt gewoonlijk uw eigen specifieke gedrag eraan toevoegen. Op deze manier raakt u, als u het automatische codegedeelte regenereert, het deel met uw specifieke extensies niet aan.

Dat gezegd hebbende, is het goed mogelijk om te veel van het goede te hebben. Een aantal tips:

  • Maak je lessen niet partial omwille van zijn partial.

  • Plaats geen deelklassen ergens behalve behalve elkaar. Als je naar een volledig onafhankelijk deel van het project moet springen om de andere helft van de klas te zien, doe je het waarschijnlijk verkeerd.

  • Niet gebruiken partial als een techniek om de grootte van de klas te verbergen. Als je je klassen uitbreekt met partial omdat ze te groot zijn, moet je de Single Responsibility Principle.

  • Als je drie of meer hebt partial fragmenten voor dezelfde klas, het is bijna een garantie dat je gedeeltelijk misbruikt. Twee is de typische bovengrens van de redelijkheid, en het wordt over het algemeen gebruikt om automatisch gegenereerde code te segmenteren uit handgeschreven code.

Hoe dan ook, lang verhaal kort - hij gebruikt gedeeltelijke klassen, overal ter wereld, als een manier om meerdere overerving in C # (IMO) te vervalsen. Waarom hij niet gewoon de klassen opsplitste in meerdere en de compositie gebruikt is mij een raadsel. Hij zal 3 'partial class'-bestanden hebben om zijn basisklasse op te maken, elke w / 3-500 regels code ... En dit meerdere malen in zijn API.

Ja, dat is zeker een duidelijk misbruik van partial!


95
2018-03-19 14:02



Er zijn twee redenen dat ik deelklassen zou (en zou doen).

  1. Om automatisch gegenereerde delen van de code te scheiden (zoals WinForms designercode of T4-uitvoer).
  2. Om geneste typen hun eigen bestand toe te staan ​​terwijl nog steeds de inkapseling wordt bereikt die door uw ontwerp is vereist.

Bijwerken
Ik kan zien dat sommigen niet overtuigd zijn van mijn tweede punt, dus laat ik een voorbeeld geven; de ListViewItemCollection in het kader. Het is terecht genest onder ListView omdat het alleen voor gebruik door is ListView, maar om het onderhoud veel gemakkelijker te maken, zou ik het een eigen bestand geven door deelklassen te gebruiken. Ik zie dit niet als een slecht ontwerp of een verkeerd gebruik van de partial trefwoord.

Voor meer discussie, bekijk de vraag die deze kopieert: Gedeeltelijke klassen in C #


12
2018-03-19 14:11



Een ander legitiem gebruik van deelklassen is het verminderen van de "monolithische webservice" -ruis in WCF. U wilt het opsplitsen in logische groepen van functionaliteit, maar u wilt geen reeks afzonderlijke service-instanties / eindpunten maken (vermoedelijk omdat ze de status, bronnen, enzovoort delen).

De oplossing? Laat de service meerdere interfaces implementeren en implementeer elke interface in zijn eigen deelklasse. Breng vervolgens verschillende eindpunten in de configuratie in kaart met dezelfde fysieke implementatie. Het maakt het project veel onderhoudbaarder, maar je hebt nog steeds maar één fysiek eindpunt.

In sommige gevallen zou ik dit soort aanpak als een slechte praktijk noemen vanwege de SRP, maar als je met WCF-services of webservices in het algemeen werkt, is het niet zo eenvoudig. Je moet interne ontwerpvereisten in evenwicht brengen met externe verbruikseisen.


10
2018-03-19 14:12



Een minder vaak voorkomend gebruik zou kunnen zijn om een ​​enorme klasse op te splitsen in afzonderlijke fysieke bestanden om het leven gemakkelijker te maken vanuit het oogpunt van bronbeheer. Ik heb zojuist meegewerkt aan een project met enorm opgeblazen webserviceklassen die lopen naar duizenden regels code en met methoden die verband houden met verschillende zakelijke functies.

Het samenvoegen van verschillende functietakken is een nachtmerrie doordat verschillende teams gelijktijdig niet-gerelateerde wijzigingen aanbrengen in hetzelfde bestand. Ik kan de webservice niet opsplitsen zonder enkele wijzigingen serieus te breken, maar door de klas op te splitsen in deelklassen wordt het gedrag exact behouden en worden een heleboel samenvoegproblemen verwijderd.

Ik moedig het bovenstaande zeker niet aan als een ontwerpkeuze, maar het was een mooie snelle overwinning voor ons en het laat zien dat partials niet slecht zijn alle de tijd...


7
2018-03-19 14:52



Ik heb in het verleden op verschillende manieren gedeeltelijke lessen gebruikt. Naarmate ik meer te weten kom over programmeren en met name het concept van "voorkeur voor de compositie ten opzichte van overerving", zie ik gemakkelijk de noodzaak afnemen voor zowel verticale overerving als overmatig gebruik van deelklassen.

Anders dan automatisch gegenereerde code, kan ik geen goed gebruik van deelklassen bedenken. Zelfs als u EF gebruikt en andere metadata nodig hebt, raden ze zelfs niet aan partities voor metadata te gebruiken. Als je in een ander deel objecten probeert te dupliceren (alleen om metadata toe te voegen), krijg je een compileerfout.

Hoe meer we leren over refactoring en SOC (Separation of Concerns), hoe kleiner en gerichter onze klassen worden. Ze worden standaard opnieuw gebruikt, wat ze na verloop van tijd kogelvrij maakt en gemakkelijk kan worden getest. Zeg gewoon NEE tegen gigantische programma's. Henry Ford leerde dit concept in de vroege jaren 1900 dat programmeurs het 100 jaar later begonnen te leren.

Gebruik samenstelling wanneer je kunt ...


4
2017-10-07 14:28



Daar ben ik het volledig mee eens John's antwoord. Maar ik zou het een stap verder doen.

  • Maak je lessen niet partijdig.

Het enige gebruik van deelklassen dat ik kan bedenken dat ik zou overwegen "goed ontwerp" is met automatisch gegenereerde code. Elk ander gebruik is bijna zeker een onnodige splitsing van je klas. (Eigenlijk kan ik dat zien Jeff's tweede punt op geneste klassen is mogelijk een geldig gebruik)

Persoonlijk vind ik dat dit boek dat je aan het lezen bent, een slecht ontwerp is, maar bedenk wel dat hij misschien gedeeltelijke klassen gebruikt, zodat hij slechts een deel van de code beetje bij beetje kan demonstreren in plaats van alleen de hele klas in één keer te presenteren.


2
2018-03-19 14:12



Kun je me uitleggen wanneer er een legitieme reden zou zijn om ooit een gedeeltelijke les te gebruiken?

Recente versies van Visual Studio gebruiken gedeeltelijke klassen om de automatisch gegenereerde designercode te scheiden van uw eigen code ..

Een ASP.NET-voorbeeld:

  • page.aspx
  • Page.aspx.cs <- Uw code
  • Page.aspx.Designer.cs <- Een gedeeltelijke klasse die automatisch gegenereerde code bevat.

Een voorbeeld van WinForms:

  • Form1.resx
  • Form1.cs <- Uw code
  • Form1.Designer.cs <- Een gedeeltelijke klasse die automatisch gegenereerde code bevat

2
2018-03-19 14:08



Ik heb gedeeltelijke klassen gebruikt om statische gegevenstoegangsmethoden fysiek te scheiden van bedrijfsklassewoningen en -methoden in een actieve recordarchitectuur. We hadden bijvoorbeeld partiële klassen van Company en CompanyData naast elkaar. Het voordeel was dat het ene bestand de POCO was en het andere alleen gegevenstoegangsmethoden. Dit was een opstapje naar het verwijderen van gegevenstoegang tot repository-klassen in een oudere toepassing. Ik denk dat dit een legitiem gebruik was, het maakte het re-factoringproces zeker beter.


2
2018-03-19 14:19



Een ander goed gebruik voor gedeeltelijke klassen zou zijn bij het implementeren van de Abstract fabriekspatroon. Maak het root-fabrieksobject gedeeltelijk en plaats vervolgens de eigenlijke fabrieksmethoden in hetzelfde bestand als de klasse die de fabriek instelt.

BEWERK: Gedeeltelijke klassen werken ook goed voor klassen die communiceren met een configuratiebestand. Plaats de code met de configuratieparameters in de buurt van de code die de configuratieparameter daadwerkelijk gebruikt.


2
2018-03-19 15:35



Gewoon struikelde over deze draad terwijl je de voordelen van gedeeltelijke klasse googelde. Ik ben bezig met het converteren van een Java EE-applicatie naar een op silverlight gebaseerde .NET-versie. Ik kwam de volgende code tegen in de kijklaag:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.225
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

...

 public partial class Wwcusts04d : System.Windows.Controls.Page {

Welnu, als de gedeeltelijke pagina zelf automatisch wordt gegenereerd, wat is dan het nut ervan te behouden? Bovendien koppelt de code binnenin verschillende besturingselementen aan hun naam. Ik beken niet dat ik kennis heb van silverlight, maar is dit ding niet beter geschikt in xaml?


2
2017-08-05 07:51