Probleem met de oproephiërarchie

Ik heb een situatie waarin ik de functie/methode in een trapsgewijze stijl aanroep. Zie het volgende voorbeeld voor illustratie en vraag. Ik wou dat ik een technisch woord kende voor deze situatie. Het zou gemakkelijker zijn voor mensen om te begrijpen waar ik het over heb.

public static class test
{
    private void button1_Click(object sender, RoutedEventArgs e)
    {
        if (Login("johndoe","password")) 
        {
            if(checkForSomething("johndoe"))
            {
                DoOpenDashboard();

               //Now it opens dashboard, it has several buttons. 
               //Each button does several different things
               //On this example I am just giving you two level of hierarchy
               //but in my actual program, there are 7 levels.
            }
        }
    }

    public static bool Login(string userid, string password)
    {
        //valid user
        return true;
    }

    public static bool checkForSomething(string userid) 
    {
        return true;
    }

Hoe voorkom ik dat het proces teruggaat naar de vorige aanroepmethode/-functie als de onderliggende methode met succes wordt uitgevoerd?

Inlogmethode is bijvoorbeeld het aanroepen van checkForSomething ("johndoe") . Als checkForSomething ("johndoe") wordt doorgegeven, opent het Dashboard-venster door DoOpenDashboard aan te roepen. Op dit punt zou mijn proces niet terug moeten gaan naar het controlevoorwaarde en dan inloggen. Ik hoop dat het logisch is.

1
Zelfs als wat u vraagt ​​(gemakkelijk) kan worden gedaan, schendt u nog steeds het principe van de enkele verantwoordelijkheid door een methode te hebben die zich anders gedraagt ​​op basis van hoe vaak u het noemt. Het zal zeker resulteren in een moeilijk te onderhouden systeem.
toegevoegd de auteur R0MANARMY, de bron
Je vraag is heel moeilijk te begrijpen. Kun je niet zomaar een statische variabele of instantie toevoegen aan je klas om aan te geven of je gebruiker al is ingelogd en gebruik je alleen Login() als de waarde van die booleaanse waarde false is?
toegevoegd de auteur Kiley Naro, de bron
U kunt geen methode hebben met dezelfde naam als de klasse waarin deze is opgenomen.
toegevoegd de auteur Miguel Angelo, de bron
Verplaats alsjeblieft de vraag buiten het codeblok ... het is onmogelijk om het te lezen zoals het nu is.
toegevoegd de auteur Miguel Angelo, de bron

2 antwoord

Niet echt duidelijk over wat je hier vraagt. Uw pseudocode toont de methode Login() die wordt aangeroepen door de constructor van uw klasse. Als dit echt de werking van uw code is, moet u voorkomen dat nieuwe instanties van deze klasse worden gemaakt om te voorkomen dat u opnieuw aanmeldt.

Ik denk echter dat je echt vraagt ​​naar het Arrow anti-patroon:

http://codinghorror.com/blog/2006/01/flattening-arrow -code.html

Bewerken

I was trying to avoid copy & paste, but since the original post seems not to have been clear enough, here's a selection from Coding Horror as linked above:

Where appropriate, I flatten that arrow code by doing the following:

  1. Replace conditions with guard clauses. This code..

    if (SomeNecessaryCondition) { //function body code }

    .. works better as a guard clause:

    if (!SomeNecessaryCondition) { throw new RequiredConditionMissingException; } //function body code

(merk op dat er ook andere technieken worden vermeld, maar ik denk dat deze eerste voorlopig volstaat)

Op deze manier leidt elke extra controle niet tot een andere genest als - als een controle mislukt, de methode aanroep mislukt. Dit kan ook worden gedaan zonder een uitzondering te werpen door button1_Click een functie te laten gebruiken die een bool teruggeeft (true voor succes, false voor fout) en onmiddellijk false retourneert bij een mislukte voorwaarde:

private void button1_Click(object sender, RoutedEventArgs e)
{
    if (AllSystemsGo())
    {
        DoOpenDashboard();
    }
}

private bool AllSystemsGo()
{
    if (!Login("johndoe","password"))
        return false;

    if (checkForSomethingEvil("johndoe"))
        return false;

    if (!checkForSomethingImportant())
        return false;

    return true;
}
0
toegevoegd
Het is niet duidelijk de een of de ander. Het is duidelijk dat dit geen code is, en je gok is net zo goed als de mijne, of de geretourneerde waarde een vergissing is of de naam van de methode een vergissing is.
toegevoegd de auteur sq33G, de bron
Het is geen constructor, het is gewoon een methode met dezelfde naam als de klasse (merk op dat het een retourneringstype heeft).
toegevoegd de auteur R0MANARMY, de bron
Ik gebruik contion-controle zoals vermeld in "Flattening Arrow Code" waar dit mogelijk is. Ik haal bedrijfslogica uit de code vb6 code. Omdat ik de bedrijfslogica uittreksel en begrijp, kom ik in een gruwelijke situatie terecht.
toegevoegd de auteur Shai, de bron

Probeer je ervoor te zorgen dat je methoden maar één keer worden gecontroleerd? Misschien moet u enkele eigenschappen meerdere keren opvragen, maar slechts één keer testen.

private bool? canLogin;
private bool? somethingOk;

private bool CanLogin
{
    get
    {
        if (canLogin == null)
            canLogin = Login("johndoe","password");
        return canLogin.Value;
    }
}

private bool SomethingOk
{
    get
    {
        if (somethingOk == null)
            somethingOk = checkForSomething("johndoe");
        return somethingOk .Value;
    }
}

private void button1_Click(object sender, RoutedEventArgs e)
{
    if (this.CanLogin && this.SomethingOk &&//other checks) 
    {
        DoOpenDashboard();            
    }
}
0
toegevoegd