Is het slechte oefening om terugkeer in een void-methode te gebruiken?

Stel je voor dat de volgende code:

void DoThis()
{
    if (!isValid) return;
    DoThat();
}
void DoThat() {
    Console.WriteLine("DoThat()");
}

Is het goed om een ​​retour in een void-methode te gebruiken? Heeft het een uitvoeringstraf? Of het zou beter zijn om een ​​code als volgt te schrijven:

void DoThis()
{
    if (isValid)
    {
        DoThat();
    }
}

Antwoord 1, Autoriteit 100%

Een rendement in een void-methode is niet slecht, is een gangbare praktijk voor omkeren ifVerklaringen om het nesten te verminderen .

En minder nestelen op uw methoden verbetert de codeleesheid en onderhoudbaarheid.

Eigenlijk als u een void-methode hebt zonder enige retourverklaring, zal de compiler altijd een RET-instructie aan het einde ervan.


Antwoord 2, Autoriteit 18%

Er is nog een geweldige reden voor het gebruik van bewakers (in tegenstelling tot geneste code): als een andere programmeur code toevoegt aan uw functie, werken ze in een veiligere omgeving.

Overweeg:

void MyFunc(object obj)
{
    if (obj != null)
    {
        obj.DoSomething();
    }
}

versus:

void MyFunc(object obj)
{
    if (obj == null)
        return;
    obj.DoSomething();
}

Stel je nu voor, een andere programmeur voegt de lijn toe: obj.dosomethingelse ();

void MyFunc(object obj)
{
    if (obj != null)
    {
        obj.DoSomething();
    }
    obj.DoSomethingElse();
}
void MyFunc(object obj)
{
    if (obj == null)
        return;
    obj.DoSomething();
    obj.DoSomethingElse();
}

Kennelijk is dit een simplistische behuizing, maar de programmeur heeft een crash toegevoegd aan het programma in de eerste (geneste code) -instantie. In het tweede voorbeeld (vroege uitgang met bewakers), zodra u voorbij de Guard bent, is uw code veilig tegen onbedoeld gebruik van een null-referentie.

Natuurlijk, een geweldige programmeur maakt geen fouten als deze (vaak). Maar preventie is beter dan genezen – we kunnen de code schrijven op een manier die deze potentiële bron van fouten volledig elimineert. Nesting voegt complexiteit toe, dus de best practices raden het refactoringcode aan om het nesten te verminderen.


Antwoord 3, Autoriteit 10%

Bad Practice ??? Echt niet. In feite is het altijd beter om de validaties aan te pakken door op zijn vroegst van de methode terug te keren als validaties falen. Anders zou het resulteren in een enorme hoeveelheid geneste IFS & AMP; elses. Het beëindigen van vroege verbetert de leesbaarheid van de code.

Controleer ook de antwoorden op een soortgelijke vraag: Moet ik de retour / voortdurende verklaring gebruiken in plaats van IF-anders?


Antwoord 4, Autoriteit 4%

Het is geen slechte praktijk (om alle reeds vermelde redenen). Hoe meer rendement u in een methode heeft, hoe groter de kans dat het in kleinere logische methoden moet worden opgesplitst.


Antwoord 5, Autoriteit 4%

Het eerste voorbeeld gebruikt een bewakingsverklaring. Van wikipedia :

In computerprogrammering is een bewaker een
Booleaanse uitdrukking die moet evalueren
naar TRUE als de uitvoering van het programma is
Ga door in de tak in kwestie.

Ik denk dat het hebben van een bos van bewakers aan de bovenkant van een methode een perfect begrijpelijke manier is om te programmeren. Het zegt eigenlijk “Voer deze methode niet uit als een van deze true is”.

Dus in het algemeen zou het dit leuk vinden:

void DoThis()
{
  if (guard1) return;
  if (guard2) return;
  ...
  if (guardN) return;
  DoThat();
}

Ik denk dat dat dan een stuk leesbaarder is:

void DoThis()
{
  if (guard1 && guard2 && guard3)
  {
    DoThat();
  }
}

Antwoord 6, autoriteit 2%

Er is geen prestatieverlies, maar het tweede stuk code is beter leesbaar en dus gemakkelijker te onderhouden.


Antwoord 7

In dit geval is je tweede voorbeeld betere code, maar dat heeft niets te maken met het terugkeren van een void-functie, het is simpelweg omdat de tweede code directer is. Maar terugkeren van een ongeldige functie is prima.


Antwoord 8

Het is prima in orde en geen ‘prestatiestraf’, maar schrijf nooit een ‘als’-statement zonder haakjes.

Altijd

if( foo ){
    return;
}

Het is veel leesbaarder; en je zult nooit per ongeluk aannemen dat sommige delen van de code binnen die verklaring vallen, terwijl dat niet het geval is.


Antwoord 9

Ik ben het in deze niet eens met alle jonge whippersnappers.

Het gebruik van return in het midden van een methode, ongeldig of anderszins, is een zeer slechte gewoonte, om redenen die bijna veertig jaar geleden heel duidelijk werden verwoord door wijlen Edsger W. Dijkstra, beginnend in de bekende “GOTO Verklaring als schadelijk beschouwd”, en wordt vervolgd in “Structured Programming”, door Dahl, Dijkstra en Hoare.

De basisregel is dat elke besturingsstructuur en elke module precies één ingang en één uitgang moet hebben. Een expliciete terugkeer in het midden van de module breekt die regel en maakt het veel moeilijker om te redeneren over de status van het programma, wat het op zijn beurt veel moeilijker maakt om te zeggen of het programma correct is of niet (wat een veel sterkere eigenschap is dan “of het nu lijkt te werken of niet”).

‘GOTO-verklaring als schadelijk beschouwd’ en ‘gestructureerd programmeren’ waren het begin van de revolutie van ‘gestructureerd programmeren’ in de jaren zeventig. Die twee stukken zijn de redenen waarom we tegenwoordig if-then-else, while-do en andere expliciete controleconstructies hebben, en waarom GOTO-statements in hogere talen op de lijst met bedreigde diersoorten staan. (Mijn persoonlijke mening is dat ze op de lijst met uitgestorven soorten moeten staan.)

Het is vermeldenswaard dat de Message Flow Modulator, het eerste stuk militaire software dat OOIT de acceptatietest bij de eerste poging heeft doorstaan, zonder afwijkingen, ontheffingen of “ja, maar” woordenstroom, is geschreven in een taal die dat wel deed niet eens een GOTO-statement hebben.

Het is ook vermeldenswaard dat Nicklaus Wirth de semantiek van de RETURN-instructie in Oberon-07, de nieuwste versie van de Oberon-programmeertaal, heeft gewijzigd, waardoor het een achterliggend stuk is van de verklaring van een getypte procedure (dwz functie), in plaats van een uitvoerbare instructie in de hoofdtekst van de functie. Zijn uitleg van de wijziging zei dat hij het precies deed omdat de vorige vorm WASeen schending van het één-uitgangsprincipe van gestructureerd programmeren.


Antwoord 10

Als je bewakers gebruikt, zorg er dan voor dat je bepaalde richtlijnen volgt om lezers niet in verwarring te brengen.

  • de functie doet één ding
  • bewakers worden alleen geïntroduceerd als de eerstelogica in de functie
  • het niet-genestegedeelte bevat de kernintentie van de functie

Voorbeeld

// guards point you to the core intent
void Remove(RayCastResult rayHit){
  if(rayHit== RayCastResult.Empty)
    return
    ;
  rayHit.Collider.Parent.Remove();
}
// no guards needed: function split into multiple cases
int WonOrLostMoney(int flaw)=>
  flaw==0 ? 100 :
  flaw<10 ? 30 :
  flaw<20 ? 0 :
  -20
;

Antwoord 11

Gooi uitzondering in plaats van niets terug te geven wanneer object nul is, enz.

Uw methode verwacht dat het object niet null is en dat is niet het geval, dus u moet een exception genereren en de beller dat laten afhandelen.

Maar een vroege terugkeer is anders geen slechte gewoonte.

Other episodes