Chaqiriq Hiyerarşisi bilan muammo

Funktsional usulni kaskad uslubida chaqiradigan vaziyat bor. Tasvirlash va savol uchun quyidagi misolga qarang. Men bu vaziyatga oid ba'zi texnik so'zlarni bilishni istardim. Odamlar nimani nazarda tutayotganimni tushunish osonroq bo'ladi.

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;
    }

Agar bola uslubi muvaffaqiyatli ishlayotgan bo'lsa, avvalgi chaqiruv usuliga/funksiyasiga qaytib borish jarayonidan qanday qochaman?

Masalan, login usuli checkForSomething ("johndoe") deb chaqiradi. Agar checkForSomething ("johndoe") kiritilsa, u DoOpenDashboard-ni chaqirib, Dashboard oynasini ochadi. Shu nuqtada mening jarayonim checkforsoemthing uchun qaytib ketmasligi kerak va keyin tizimga kirish kerak. Umid qilamanki, bu mantiqan.

1
Agar siz so'ragan narsa (osonlik bilan) bajarilishi mumkin bo'lsa ham, siz uni necha marta chaqirishingizdan qat'i nazar, boshqacha tarzda ishlaydigan usulni qo'llayapsiz. Bu, albatta, tizimni saqlab qolish uchun qiyin bo'ladi.
qo'shib qo'ydi muallif R0MANARMY, manba
Sizning savolingiz tushunish juda qiyin. Siz o'zingizning foydalanuvchi allaqachon kirganmi yoki yo'qligini ko'rsatish uchun sinfga statik o'zgaruvchi yoki namunaviy a'zolik qo'sha olmaysizmi va bu booleanning qiymati noto'g'ri bo'lsa, faqat Login() () deb nomlanasiz?
qo'shib qo'ydi muallif Kiley Naro, manba
Sizda o'z ichiga olgan sinfning bir xil nomiga ega bo'lgan usul bo'lishi mumkin emas.
qo'shib qo'ydi muallif Miguel Angelo, manba
Iltimos, savolni kod blokidan tashqariga olib chiqing ... hozirgi kabi uni o'qib bo'lmaydi.
qo'shib qo'ydi muallif Miguel Angelo, manba

2 javoblar

Bu erda nima so'rayotganingizni aniq bilmasangiz. Sizning pseudocode sinfingizning konstruktorida Login() usulini chaqiradi. Agar bu sizning kodingiz qanday ishlayotgan bo'lsa, unda yana kirishni qayta tiklashni oldini olish uchun ushbu klassning yangi namunalarini yaratishdan qochishingiz kerak.

Ammo, men, albatta, siz Ok qarshi naqsh haqida so'rayapsiz deb o'ylayman:

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

EDIT -ni tanlang

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

(shuni ham aytib o'tish joizki, boshqa usullar ham mavjud, ammo menimcha, bu birinchi narsa hozircha etarli bo'ladi)

Shunday qilib, har bir qo'shimcha tekshiruv boshqa ichki o'rnatilgan bo'lsa, hech qanday tekshiruvga olib kelmaydi. Bundan tashqari, button1_Click tugmalarini bosib, bool (muvaffaqiyat uchun haqiqiy, noto'g'ri uchun noto'g'ri) funksiyasini chaqirib, va darhol noto'g'ri holatga qaytib kelgan holda, istisno qilmasdan ham amalga oshirilishi mumkin:

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
qo'shib qo'ydi
Bu aniq yoki boshqasi emas. Shubhasiz, bu kodni kompilyatsiya qilmaydi va siz taxminan qaytib qiymat xato yoki yo'qmi, yoki usul nomi xatolikmi, men kabi yaxshi.
qo'shib qo'ydi muallif sq33G, manba
Bu konstruktor emas, bu faqat sinf nomi bilan bir usul (uning qaytish turiga ega ekanligini unutmang).
qo'shib qo'ydi muallif R0MANARMY, manba
Mumkin bo'lgan joyda "Flattening Arrow Code" da ko'rsatilgan konteyner tekshiruvidan foydalanaman. Menejment mantig'ini kod vb6 kodidan chiqaraman. Men ishbilarmonlik mantig'ini ochib, tushuna oladigan bo'lsam, dahshatli vaziyatga tushaman.
qo'shib qo'ydi muallif Shai, manba

Sizning usullaringiz faqat bir marta tekshiriladimi? Ehtimol, siz bir necha marta so'raladigan ba'zi bir xususiyatlarga muhtojsiz, lekin faqat bir marta sinovdan o'tgan.

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
qo'shib qo'ydi