(වෙනත් නම්) හැසිරවීමට අලංකාර ක්‍රම


165

මෙය සුළු විකාරයකි, නමුත් සෑම විටම මට මේ වගේ දෙයක් කේත කිරීමට සිදු වූ විට, පුනරාවර්තනය මට කරදර කරයි, නමුත් විසඳුම් කිසිවක් නරක නොවන බව මට විශ්වාස නැත.

if(FileExists(file))
{
    contents = OpenFile(file); // <-- prevents inclusion in if
    if(SomeTest(contents))
    {
        DoSomething(contents);
    }
    else
    {
        DefaultAction();
    }
}
else
{
    DefaultAction();
}
  • මේ ආකාරයේ තර්කනය සඳහා නමක් තිබේද?
  • මමත් ඕසීඩී ද?

කුතුහලය නිසා පමණක් නම්, මම නපුරු කේත යෝජනා සඳහා විවෘතව සිටිමි ...


8
M එම්මාඩ් කරීම්: DefaultActionඇමතුම් දෙකක්
ඩ්‍රයි

ඔබගේ පිළිතුරට ස්තූතියි, නමුත් මම සිතන්නේ උත්සාහය / ඇල්ලීම භාවිතා නොකිරීම හැර, ප්‍රති results ල ලබා නොදෙන දෝෂ ඇති විය හැකි අතර එය අතහැර දැමීමට හේතු වනු ඇත (ඔබේ ක්‍රමලේඛන භාෂාව අනුව).
NoChance

20
මම හිතන්නේ මෙහි ඇති ප්‍රධාන ගැටළුව වන්නේ ඔබ නොගැලපෙන මට්ටමේ සාරාංශවල වැඩ කිරීමයි . ඉහළ වියුක්ත මට්ටම : make sure I have valid data for DoSomething(), and then DoSomething() with it. Otherwise, take DefaultAction(). DoSomething () සඳහා දත්ත ඔබ සතුව ඇති බවට සහතික කර ගැනීමේ අමිහිරි තොරතුරු අඩු වියුක්ත මට්ටමක පවතින අතර එබැවින් වෙනත් ශ්‍රිතයක තිබිය යුතුය. මෙම ශ්‍රිතයට ඉහළ වියුක්ත මට්ටමින් නමක් ඇති අතර එය ක්‍රියාත්මක කිරීම පහත් මට්ටමක පවතී. පහත දැක්වෙන හොඳ පිළිතුරු මෙම ගැටළුව විසඳයි.
ගිලාඩ් නූර්

6
කරුණාකර භාෂාවක් සඳහන් කරන්න. හැකි විසඳුම්, සම්මත මෝඩයන් සහ දීර් standing කාලීන සංස්කෘතික සම්මතයන් විවිධ භාෂාවන්ට වෙනස් වන අතර එය ඔබේ ප්‍රශ්නයට විවිධ පිළිතුරු ලබා දෙනු ඇත.
කාලෙබ්

1
ඔබට මෙම පොත "ප්‍රතිනිර්මාණය කිරීම: පවතින කේතයේ සැලසුම වැඩිදියුණු කිරීම" ගැන සඳහන් කළ හැකිය .එසේ නම් ව්‍යුහය, සැබවින්ම ප්‍රයෝජනවත් භාවිතයන් පිළිබඳ අංශ කිහිපයක් තිබේ.
වැකර්

Answers:


98

ශ්‍රිතය (ක්‍රමය) වෙන් කිරීම සඳහා එය උපුටා ගෙන returnප්‍රකාශය භාවිතා කරන්න :

if(FileExists(file))
{
    contents = OpenFile(file); // <-- prevents inclusion in if
    if(SomeTest(contents))
    {
        DoSomething(contents);
        return;
    }
}

DefaultAction();

නැතහොත්, වඩා හොඳ, වෙනම ලබා ගැනීමේ අන්තර්ගතයන් සහ එහි සැකසුම්:

contents_t get_contents(name_t file)
{
    if(!FileExists(file))
        return null;

    contents = OpenFile(file);
    if(!SomeTest(contents)) // like IsContentsValid
        return null;

    return contents;
}

...

contents = get_contents(file)
contents ? DoSomething(contents) : DefaultAction();

යාවත්කාලීන කිරීම:

ඇයි ව්‍යතිරේක, ඇයි OpenFileIO ව්‍යතිරේකය විසි නොකරන්නේ:
IO ගොනුව පිළිබඳ ප්‍රශ්නයට වඩා එය ඇත්තෙන්ම සාමාන්‍ය ප්‍රශ්නයක් යැයි මම සිතමි. වැනි නම් FileExists, OpenFileඅවුල් කළ හැක, නමුත් ඒවා වෙනුවට නම් Foo, Barආදිය, - එය බව පැහැදිලි වනු ඇත DefaultActionබොහෝ විට හැඳින්විය හැක DoSomething, ඒ නිසා-සුවිශේෂී නොවන නඩුව විය හැක. පීටර් ටෝක් ඔහුගේ පිළිතුර අවසානයේ මේ ගැන ලිවීය

2 වන ප්‍රභේදයේ ත්‍රිමාණ කොන්දේසි සහිත ක්‍රියාකරු සිටින්නේ ඇයි:
[C ++] ටැගය තිබේ නම්, මම එහි කොන්දේසි කොටස ifප්‍රකාශයට පත් කරමින් ප්‍රකාශයක් ලිව්වෙමි contents:

if(contents_t contents = get_contents(file))
    DoSomething(contents);
else
    DefaultAction();

නමුත් වෙනත් (සී-වැනි) භාෂාවන් සඳහා, if(contents) ...; else ...;ත්‍රිමාණ කොන්දේසි සහිත ක්‍රියාකරු සමඟ ප්‍රකාශන ප්‍රකාශයට සමාන වේ, නමුත් දිගු වේ. කේතයේ ප්‍රධාන කොටස get_contentsක්‍රියාකාරී වූ නිසා, මම කෙටි අනුවාදය භාවිතා කළෙමි (එසේම අතහැර දැමූ contentsවර්ගය). කෙසේ වෙතත්, එය මෙම ප්රශ්නයෙන් ඔබ්බට ය.


93
බහුවිධ ප්‍රතිලාභ සඳහා +1 - ක්‍රම ප්‍රමාණවත් තරම් කුඩා කළ විට , මෙම ප්‍රවේශය මට වඩාත් සුදුසු විය
gnat

මම ඉඳහිට එය භාවිතා කළද, බහු ප්‍රතිලාභවල විශාල රසිකයෙක් නොවේ. සරල දෙයක් සම්බන්ධයෙන් එය තරමක් සාධාරණ ය, නමුත් එය හොඳින් පරිමාණය නොකරයි. අපගේ ප්‍රමිතිය නම් පිස්සු සරල ක්‍රම හැර අන් සියල්ලටම එය වළක්වා ගැනීමයි. මන්ද ඒවා ක්‍රම හැකිලීමට වඩා ප්‍රමාණයෙන් වැඩීමට නැඹුරු වන බැවිනි.
බ්‍රයන් නොබ්ලෝච්

3
බහුවිධ ප්‍රතිලාභ මාර්ගවලට C ++ වැඩසටහන් වල performance ණාත්මක ක්‍රියාකාරීත්ව බලපෑම් ඇති කළ හැකි අතර, RVO භාවිතා කිරීමට ප්‍රශස්තිකරුවා දරන උත්සාහයන් පරාජය කරයි (NRVO ද, එක් එක් මාර්ගය එකම වස්තුවක් ආපසු ලබා දෙන්නේ නැත්නම්).
Functastic

2 වන විසඳුම පිළිබඳ තර්කනය ආපසු හැරවීමට මම නිර්දේශ කරමි: {if (ගොනුව පවතී) content අන්තර්ගතයන් සකසන්න; if (කිසියම්) {ආපසු අන්තර්ගතය; }} ආපසු හරවන්න; } එය ප්‍රවාහය සරල කරන අතර රේඛා ගණන අඩු කරයි.
වෙජ්

1
හායි ඇබික්ස්, ඔබ මෙහි අදහස් වලින් යම් ප්‍රතිපෝෂණයක් ඇතුළත් කර ඇති බව මම දුටුවෙමි: එසේ කිරීම ගැන ස්තූතියි. ඔබගේ පිළිතුරෙන් සහ වෙනත් පිළිතුරු වලින් ආමන්ත්‍රණය කළ සියල්ල මම පිරිසිදු කර ඇත්තෙමි.

56

ඔබ භාවිතා කරන ක්‍රමලේඛන භාෂාව (0) කෙටි පරිපථ ද්විමය සැසඳීම් (එනම් අසත්‍ය SomeTestනම් FileExistsආපසු නොඑන්නේ නම් ) සහ (1) පැවරුම මඟින් වටිනාකමක් ලබා දෙයි ( ප්‍රති result OpenFileලය පවරා ඇති contentsඅතර එම අගය තර්කයක් ලෙස සම්මත වේ වෙත SomeTest), ඔබට පහත සඳහන් දෑ වැනි දෙයක් භාවිතා කළ හැකිය, නමුත් කේතය අදහස් දැක්වීමට ඔබට තවමත් උපදෙස් දෙනු =ලැබේ.

if( FileExists(file) && SomeTest(contents = OpenFile(file)) )
{
    DoSomething(contents);
}
else
{
    DefaultAction();
}

එසේ නම් එය කෙතරම් සංකෝචනය වී ඇත්ද යන්න මත පදනම්ව, ධජ විචල්‍යයක් තිබීම වඩා හොඳ විය හැකිය ( DefaultActionමෙම අවස්ථාවේ දී දෝෂය හසුරුවන කේතය සමඟ සාර්ථක / අසාර්ථක තත්වයන් පරීක්ෂා කිරීම වෙන් කරයි )


මේ මම එය කරන්නේ කෙසේද යන්නයි.
ඇන්තනි

13
ifමගේ මතය අනුව, ප්‍රකාශයක් තුළ එතරම් කේතයක් තැබීම සඳහා දළ වශයෙන් .
moteutsch

15
මම ඊට පටහැනිව, මේ ආකාරයේ "යමක් තිබේ නම් සහ මෙම කොන්දේසිය සපුරාලන්නේ නම්" වැනි ප්‍රකාශයක් වැනි ය. +1
ගොර්පික්

මමත් කරනවා! සමහර පරිශ්‍රයන් සපුරා නොමැති පුද්ගලයින් බහු ප්‍රතිලාභ භාවිතා කරන ආකාරය මම පෞද්ගලිකව අකමැතියි. ඔවුන් නම්, ඇයි ඔබ එම IFS talk තෝරාගැනුම ප්රතිලෝම කරන්න ඔබගේ කේතය ක්රියාත්මක කරන්නේ නැහැ ඇත හමු?
ක්ලාර්

"යමක් තිබේ නම් සහ මෙම කොන්දේසිය සපුරාලන්නේ නම්" හොඳයි. "යමක් පවතින්නේ නම් සහ මෙහි සම්බන්ධිත යමක් කර මෙම තත්වයට අනුකූල වන්නේ නම්", OTOH, අවුල් සහගතය. වෙනත් වචන වලින් කිවහොත්, මම කොන්දේසියක් තුළ අතුරු ආබාධවලට අකමැතියි.
පිස්ක්වර්

27

DefaultAction වෙත ඇමතුම පුනරාවර්තනය කිරීමට වඩා බරපතල වන්නේ ශෛලියම වන බැවින් කේතය විකලාංග නොවන ලෙස ලියා ඇත ( විකලාංග ලිවීමට හොඳ හේතු සඳහා මෙම පිළිතුර බලන්න ).

විකලාංග නොවන කේතය නරක වන්නේ මන්දැයි පෙන්වීමට, මුල් උදාහරණය සලකා බලන්න, ජාල තැටියක ගබඩා කර ඇත්නම් එය විවෘත නොකළ යුතු බවට නව අවශ්‍යතාවයක් හඳුන්වා දුන් විට. හොඳයි, එවිට අපට කේතය පහත පරිදි යාවත්කාලීන කළ හැකිය:

if(FileExists(file))
{
    if(! OnNetworkDisk(file))
    {
        contents = OpenFile(file); // <-- prevents inclusion in if
        if(SomeTest(contents))
        {
            DoSomething(contents);
        }
        else
        {
            DefaultAction();
        }
    }
    else
    {
        DefaultAction();
    }
}
else
{
    DefaultAction();
}

නමුත් 2Gb ට වඩා විශාල ලිපිගොනු විවෘත නොකළ යුතු බවට කොන්දේසියක් ද ඇත. හොඳයි, අපි නැවත යාවත්කාලීන කරමු:

if(FileExists(file))
{
    if(LessThan2Gb(file))
    {
        if(! OnNetworkDisk(file))
        {
            contents = OpenFile(file); // <-- prevents inclusion in if
            if(SomeTest(contents))
            {
                DoSomething(contents);
            }
            else
            {
                DefaultAction();
            }
        }
        else
        {
            DefaultAction();
        }
    else
    {
        DefaultAction();
    }
}
else
{
    DefaultAction();
}

එවැනි කේත ශෛලිය විශාල නඩත්තු වේදනාවක් වනු ඇති බව ඉතා පැහැදිලිය.

නිසියාකාරව විකලාංග ලෙස ලියා ඇති පිළිතුරු අතර ඇබික්ස්ගේ දෙවන උදාහරණය සහ ජෑන් හුඩෙක්ගේ පිළිතුර ඇත , එබැවින් මම එය නැවත නොකියමි , එම පිළිතුරු වල අවශ්‍යතා දෙක එකතු කිරීම පමණක් වනු ඇති බව පෙන්වා දෙන්න

if(! LessThan2Gb(file))
    return null;

if(OnNetworkDisk(file))
    return null;

(හෝ goto notexists;ඒ වෙනුවට return null;), එකතු කළ රේඛා හැර වෙනත් කේතයකට බලපාන්නේ නැත . උදා: විකලාංග.

පරීක්ෂා කිරීමේදී, සාමාන්‍ය රීතිය විය යුත්තේ ව්‍යතිරේක පරීක්ෂා කිරීම මිස සාමාන්‍ය අවස්ථාව නොවේ .


8
මට +1. ඊතල හිස ප්‍රති-රටාව වළක්වා ගැනීමට මුල් ප්‍රතිලාභ උපකාරී වේ. Codinghorror.com/blog/2006/01/flattening-arrow-code.html සහ lostechies.com/chrismissal/2009/05/27/ බලන්න. මෙම රටාව ගැන කියවීමට පෙර, මම සෑම විටම එක් ශ්‍රිතයකට 1 ප්‍රවේශය / පිටවීම සඳහා දායක වී සිටිමි. අවුරුදු 15 ක් හෝ ඊට පෙර මට ඉගැන්වූ දේ නිසා න්‍යාය. මට හැඟෙන්නේ මෙය කේතය කියවීමට පහසු වන අතර ඔබ සඳහන් කළ පරිදි වඩා නඩත්තු කළ හැකි බවයි.
මූස් මහතා

3
RMrMoose: ඊතල විරෝධී රටාව පිළිබඳ ඔබේ සඳහන බෙන්ජොල්ගේ පැහැදිලි ප්‍රශ්නයට පිළිතුරු සපයයි: "මේ ආකාරයේ තර්කනයකට නමක් තිබේද?" එය පිළිතුරක් ලෙස පළ කරන්න, ඔබට මගේ ඡන්දය ලැබී තිබේ.
outis

මෙය විශිෂ්ට පිළිතුරකි, ස්තූතියි. සහ rMrMoose: "ඊතල හෙඩ් විරෝධී රටාව" මගේ පළමු වෙඩි උණ්ඩයට පිළිතුරු සපයයි, එබැවින් ඔව්, එය පළ කරන්න. මම එය පිළිගන්නවා යැයි මට පොරොන්දු විය නොහැක, නමුත් එය ඡන්ද ලැබීමට සුදුසුයි!
බෙන්ජෝල්

@outis. ස්තූතියි. මම පිළිතුර එකතු කළා. ඊතල හෙඩ් විරෝධී රටාව නිසැකවම හොලොවඩල්ගේ තනතුරට අදාළ වන අතර ඔහුගේ ආරක්ෂක වගන්ති ඒවා වටා ගමන් කිරීමේදී හොඳින් ක්‍රියා කරයි. මේ සඳහා දෙවන වෙඩි උණ්ඩයට ඔබ පිළිතුරු දෙන්නේ කෙසේදැයි මම නොදනිමි. එය හඳුනා ගැනීමට මට සුදුසුකම් නැත :)
මූස් මහතා

4
+1 "පරීක්ෂණ ව්‍යතිරේක මිස සාමාන්‍ය අවස්ථාව නොවේ."
රෝයි ටින්කර්

25

නිසැකවම:

Whatever(Arguments)
{
    if(!FileExists(file))
        goto notexists;
    contents = OpenFile(file); // <-- prevents inclusion in if
    if(!SomeTest(contents))
        goto notexists;
    DoSomething(contents);
    return;
notexists:
    DefaultAction();
}

ඔබ කිව්වේ ඔබ නපුරු විසඳුම් සඳහා පවා විවෘත බවයි, එබැවින් නපුරු ගොටෝ ගණන් භාවිතා කරමින්, නැත?

ඇත්ත වශයෙන්ම සන්දර්භය මත පදනම්ව මෙම විසඳුම දෙවරක් ක්‍රියාව කිරීම හෝ නපුරු අතිරේක විචල්‍යතාවයට වඩා අඩු නපුරක් විය හැකිය. මම එය ශ්‍රිතයක් තුළට ඔතා, එය දිගු ශ්‍රිතය මධ්‍යයේ නිසැකවම නිවැරදි නොවන නිසා (අවම වශයෙන් මැදට පැමිණීම නිසා නොවේ). නමුත් දිගු ක්‍රියාකාරිත්වය හරි නැත, කාල පරිච්ඡේදය.

ඔබට ව්‍යතිරේක ඇති විට, ඒවා කියවීමට පහසු වනු ඇත, විශේෂයෙන් ඔබට OpenFile සහ DoSomething ලබා ගත හැකි නම් කොන්දේසි සෑහීමකට පත් නොවන්නේ නම් ව්‍යතිරේකය විසි කරන්න, එබැවින් ඔබට පැහැදිලි චෙක්පත් අවශ්‍ය නොවේ. C ++ හි අනෙක් අතට, ජාවා සහ සී # ව්‍යතිරේකය විසි කිරීම මන්දගාමී මෙහෙයුමකි, එබැවින් කාර්ය සාධන ලක්ෂ්‍යයේ සිට ගෝටෝ තවමත් වඩාත් යෝග්‍ය වේ.


"නපුර" පිළිබඳ සටහන: C ++ නිති අසන ප්‍රශ්න 6.15 "නපුර" ලෙස අර්ථ දක්වන්නේ:

එයින් අදහස් කරන්නේ එවැනි එවැනි ඔබ වැළකී සිටිය යුත්තේ යමක් වඩාත් කාලය, එහෙත් ඔබ වැළකී සිටිය යුත්තේ යමක් නොවේ සියලු කාලය. නිදසුනක් වශයෙන්, ඔබ මෙම "නපුරු" දේවල් "නපුරු විකල්පයන්ගේ අවම නපුර" වන සෑම අවස්ථාවකම භාවිතා කරනු ඇත.

එය gotoමෙම සන්දර්භය තුළ අදාළ වේ . ව්‍යුහාත්මක ප්‍රවාහ පාලන ඉදිකිරීම් බොහෝ විට වඩා හොඳය, නමුත් ඔබ ඔවුන්ගේම නපුරුකම් රාශියක් රැස් කර ගන්නා තත්වයට පත්වන විට, තත්වයට පැවරීම, මට්ටම් 3 කට වඩා ගැඹුරට කැදැල්ල, අනුපිටපත් කේතය හෝ දිගු කොන්දේසි වැනි දේ gotoඅවසන් විය හැකිය. අඩු නපුරක් වීම.


11
මගේ කර්සරය පිළිගැනීමේ බොත්තම මත සැරිසරයි ... සියලු පිරිසිදු කරන්නන් නොතකා. පරීක්ෂාව: ඩී
බෙන්ජෝල්

2
ඔව් ඔව්! කේතය ලිවීමට නියත වශයෙන්ම “නිවැරදි” ක්‍රමය මෙයයි. දැන් කේතයේ ව්‍යුහය වන්නේ "දෝෂයක් තිබේ නම් දෝෂය හසුරුවන්න. සාමාන්‍ය ක්‍රියාව. දෝෂයක් තිබේ නම් දෝෂය හසුරුවන්න. සාමාන්‍ය ක්‍රියාව" එය හරියටම විය යුතුය. සියලුම "සාමාන්‍ය" කේතය ලියා ඇත්තේ තනි මට්ටමේ ඉන්ඩෙන්ටේෂන් එකකින් වන අතර සියලු දෝෂ ආශ්‍රිත කේත වලට මට්ටම් දෙකක් ඇත. එබැවින් සාමාන්‍ය හා වඩාත්ම වැදගත් කේතය වඩාත් කැපී පෙනෙන දෘශ්‍ය ස්ථානයක් ලබා ගන්නා අතර අනුක්‍රමිකව පහළට පහළට ගලායාම ඉතා ඉක්මණින් හා පහසුවෙන් කියවිය හැකිය. සෑම අතින්ම මෙම පිළිතුර පිළිගන්න.
hlovdal

2
තවත් පැතිකඩක් නම් මේ ආකාරයෙන් ලියා ඇති කේතය විකලාංග වේ. උදාහරණයක් ලෙස පේළි දෙක "if (! FileExists (ගොනුව)) \ n \ tgoto notexists;" දැන් මෙම තනි දෝෂ අංගය (KISS) හැසිරවීමට පමණක් සම්බන්ධ වී ඇති අතර වඩාත්ම වැදගත් වන්නේ එය වෙනත් කිසිදු රේඛාවකට බලපාන්නේ නැත . මෙම පිළිතුර stackoverflow.com/a/3272062/23118 කේත විකලාංග තබා ගැනීමට හොඳ හේතු කිහිපයක් ලැයිස්තුගත කරයි.
hlovdal

5
නපුරු විසඳුම් ගැන කතා කිරීම: මට ඔබේ විසඳුම for(;;) { if(!FileExists(file)) break; contents = OpenFile(file); if(!SomeTest(contents)) break; DoSomething(contents); return; } /* broken out */ DefaultAction();
ගොටෝ

4
@ හර්බි: ඔබේ විසඳුම වඩා නපුරු ය goto, මන්ද ඔබ breakකිසිවෙකු අපයෝජනයට ලක් නොකරන බැවින් එය අනිසි ලෙස භාවිතා කරනු ඇත, එබැවින් කේතය කියවන පුද්ගලයින්ට එය පැහැදිලිව පවසන ගොටෝට වඩා විවේකයක් ගෙන යන්නේ කොතැනට දැයි බැලීමට ගැටලු ඇති වේ. ඔබ අනන්ත පුඩුවක් භාවිතා කරන අතර එය එක් වරක් පමණක් ධාවනය වන අතර එය අවුල් සහගත වනු ඇත. අවාසනාවකට මෙන් do { ... } while(0)හරියටම කියවිය නොහැක, මන්ද ඔබ දකින්නේ එය අවසානයට පැමිණෙන විට එය විහිලු බ්ලොක් එකක් පමණක් වන අතර සී වෙනත් කොටස් වලින් කැඩීමට සහාය නොදක්වන බැවිනි (පර්ල් මෙන් නොව).
ජෑන් හුඩෙක්

12
function FileContentsExists(file) {
    return FileExists(file) ? OpenFile(file) : null;
}

...

contents = FileContentExists(file);
if(contents && SomeTest(contents))
{
    DoSomething(contents);
}
else
{
    DefaultAction();
}

නැතහොත් අමතර පිරිමියා වෙත ගොස් අතිරේක FileExistsAndConditionMet (ගොනු) ක්‍රමයක්
සාදන්න

ගොනු වර්ගය පරික්ෂා SomeTestකරන්නේ නම් @herby ට ගොනු පැවැත්මට සමාන අර්ථකථන තිබිය හැකිය SomeTest, උදාහරණයක් ලෙස .gif සැබවින්ම GIF ගොනුවක් දැයි පරීක්ෂා කරයි.
ඇබික්ස්

1
ඔව්. රඳා පවතී. En බෙන්ජෝල් වඩා හොඳින් දනී.
හර්බි

3
... ඇත්ත වශයෙන්ම මම අදහස් කළේ "අමතර මයිල් යන්න" ... :)
අන්කල් සීව්

2
පවා මම යන්නේ නැහැ (සහ මම අන්ත කිරීමට රැවියෝලි ගනිමින් මම මේ අන්ත) ... මම දැන් එය සලකා අවසරයෙන් කියවිය හැකි හිතන්නේ contents && f(contents). තවත් එකක් ඉතිරි කිරීමට කාර්යයන් දෙකක් ?!
හර්බි

12

එක් හැකියාවක්:

boolean handled = false;

if(FileExists(file))
{
    contents = OpenFile(file); // <-- prevents inclusion in if
    if(SomeTest(contents))
    {
        DoSomething(contents);
        handled = true;
    }
}
if (!handled)
{
    DefaultAction();
}

ඇත්ත වශයෙන්ම, මෙය කේතය වෙනස් ආකාරයකින් තරමක් සංකීර්ණ කරයි. එබැවින් එය බොහෝ දුරට විලාසිතාවේ ප්‍රශ්නයකි.

වෙනස් ප්‍රවේශයක් වනුයේ ව්‍යතිරේක භාවිතා කිරීමයි, උදා:

try
{
    contents = OpenFile(file); // throws IO exception if file not found
    DoSomething(contents); // calls SomeTest() and throws exception on failure
}
catch(Exception e)
{
    DefaultAction();
    // and the exception should be at least logged...
}

මෙය සරල බව පෙනේ, කෙසේ වෙතත් එය අදාළ වන්නේ නම් පමණි

  • අපි දන්නා දේ හරියටම ආකාරයේ අපේක්ෂා කිරීමට ව්යතිරේකයක්, සහ DefaultAction()එක් එක් පණ අදිමින් වුවත්
  • ලිපිගොනු සැකසීම සාර්ථක වනු ඇතැයි අපි අපේක්ෂා කරමු. නැතිවූ ගොනුවක් හෝ අසමත් SomeTest()වීම පැහැදිලිවම වැරදි තත්වයකි, එබැවින් එය මත ව්‍යතිරේකයක් විසි කිරීම සුදුසුය.

19
Noooo ~! ධජ විචල්‍යයක් නොවේ, එය නියත වශයෙන්ම වැරදි ක්‍රමයකි, මන්ද එය සංකීර්ණ, තේරුම් ගැනීමට අපහසු (කොඩිය-සත්‍යය බවට පත්වන තැන) සහ ප්‍රතික්‍රියාකාරක කේත කිරීමට අපහසු නිසාය.
ඇබික්ස්

ඔබ එය හැකි තරම් දේශීය වශයෙන් සීමා කළහොත් නොවේ. (function () { ... })()ජාවාස්ක්‍රිප්ට් හි, { flag = false; ... }සී වැනි යනාදිය
හර්බි

ව්‍යතිරේක තර්කනය සඳහා +1, තත්වය අනුව වඩාත් සුදුසු විසඳුම විය හැකිය.
ස්ටීවන් ජියුරිස්

4
+1 මෙම අන්යෝන්ය 'Nooooo!' විහිලුවක්. සමහර අවස්ථාවල තත්ව විචල්‍යය සහ කලින් පැමිණීම යන දෙකම සාධාරණ යැයි මම සිතමි. වඩාත් සංකීර්ණ ක්‍රියාකාරකම් වලදී, මම තත්ව විචල්‍යය සඳහා යන්නෙමි, මන්ද සංකීර්ණත්වය එකතු කරනවාට වඩා එය සැබවින්ම කරන්නේ තර්කනය පැහැදිළි කිරීමයි. එහි කිසිදු වරදක් නැත.
ග්‍රොස්වොගල්

1
මා වැඩ කරන ස්ථානය මෙයයි. භාවිතා කළ හැකි ප්‍රධාන විකල්ප 2 "බහු ප්‍රතිලාභ" සහ "ධජ විචල්‍යයන්" ලෙස පෙනේ. මේ දෙකෙහිම සාමාන්‍යයෙන් කිසිදු ආකාරයක සැබෑ වාසියක් ඇති බවක් නොපෙනේ, නමුත් දෙකම යම් යම් තත්වයන්ට අනෙක් ඒවාට වඩා හොඳින් ගැලපේ. ඔබේ සාමාන්‍ය නඩුව සමඟ යා යුතුය. තවත් "ඊමාක්ස්" එදිරිව "වී" ආගමික යුද්ධය. :-)
බ්‍රයන් නොබ්ලෝච්

11

මෙය වියුක්ත කිරීමේ ඉහළ මට්ටමක පවතී:

if (WeCanDoSomething(file))
{
   DoSomething(contents);
}
else
{
   DefaultAction();
} 

මෙය විස්තර පුරවයි.

boolean WeCanDoSomething(file)
{
    if FileExists(file)
    {
        contents = OpenFile(file);
        return (SomeTest(contents));
    }
    else
    {
        return FALSE;
    }
}

11

කාර්යයන් එක් දෙයක් කළ යුතුය. ඔවුන් එය හොඳින් කළ යුතුයි. ඔවුන් එය කළ යුත්තේ එය පමණි.
- රොබට් මාටින් පිරිසිදු කේතයේ

සමහර අය එම ප්‍රවේශය මඳක් අන්තයට ගියත් එය ඉතා පිරිසිදුයි. පයිතන්හි නිදර්ශනය කිරීමට මට ඉඩ දෙන්න:

def processFile(self):
    if self.fileMeetsTest():
        self.doSomething()
    else:
        self.defaultAction()

def fileMeetsTest(self):
    return os.path.exists(self.path) and self.contentsTest()

def contentsTest(self):
    with open(self.path) as file:
        line = file.readline()
        return self.firstLineTest(line)

කාර්යයන් එක් දෙයක් කළ යුතු යැයි ඔහු පවසන විට, ඔහු අදහස් කරන්නේ එක් දෙයක්. processFile()පරීක්ෂණයක ප්‍රති result ලය මත පදනම් වූ ක්‍රියාවක් තෝරා ගනී, එපමණයි. fileMeetsTest()පරීක්ෂණයේ සියලුම කොන්දේසි ඒකාබද්ධ කරයි, එපමණයි. contentsTest()පළමු පේළිය වෙත මාරු කරයි firstLineTest(), එපමණයි.

එය බොහෝ කාර්යයන් මෙන් පෙනේ, නමුත් එය ප්‍රායෝගිකව සෘජු ඉංග්‍රීසි මෙන් කියවයි:

ගොනුව සැකසීමට, එය පරීක්ෂණයට අනුකූලදැයි පරීක්ෂා කරන්න. එය එසේ නම්, යමක් කරන්න. එසේ නොමැතිනම් පෙරනිමි පියවර ගන්න. ගොනුව පවතින්නේ නම් පරීක්ෂණය සපුරාලන අතර අන්තර්ගතය පරීක්ෂණය සමත් වේ. අන්තර්ගතය පරීක්ෂා කිරීම සඳහා, ගොනුව විවෘත කර පළමු පේළිය පරීක්ෂා කරන්න. පළමු පේළිය සඳහා පරීක්ෂණය ...

ඇත්ත වශයෙන්ම, එය ටිකක් අපැහැදිලි ය, නමුත් නඩත්තු කරන්නෙකුට විස්තර ගැන තැකීමක් නොකරන්නේ නම්, ඔහුට පේළි 4 න් පසුව කියවීම නැවැත්විය හැකි processFile()අතර, ශ්‍රිතය කරන්නේ කුමක් ද යන්න පිළිබඳ හොඳ දැනුමක් ඔහුට තවමත් ඇති බව සලකන්න .


5
+1 එය හොඳ උපදෙසකි, නමුත් “එක් දෙයක්” යන්නෙන් අදහස් කරන්නේ වර්තමාන වියුක්ත ස්ථරය මත ය. processFile () යනු "එක් දෙයක්", නමුත් කරුණු දෙකක්: fileMeetsTest () සහ doSomething () හෝ defaultAction (). "එක් දෙයක්" යන අංගය මගින් ප්‍රාථමිකය තේරුම් නොගන්නා ආරම්භකයින් ව්‍යාකූල කරනු ඇතැයි මම බිය වෙමි .
කාලෙබ්

1
එය හොඳ ඉලක්කයක් ... මට ඒ ගැන කියන්නට ඇත්තේ එපමණයි ... ;-)
බ්‍රයන් නොබ්ලූච්

1
උදාහරණ විචල්‍යයන් ලෙස තර්ක ඉදිරිපත් කිරීමට මම කැමති නැත. ඔබ "නිෂ් less ල" නිදර්ශන විචල්‍යයන්ගෙන් පිරී ඇති අතර ඔබේ තත්වය ඉහළ නැංවීමට සහ ආක්‍රමණ බිඳ දැමීමට බොහෝ ක්‍රම තිබේ.
හියුගොම්

Ale කාලෙබ්, ප්‍රොසෙස් ෆයිල් () ඇත්ත වශයෙන්ම එක් දෙයක් කරයි. කාල් සිය ලිපියේ සඳහන් කර ඇති පරිදි, එය කුමන ක්‍රියාමාර්ගයක් ගත යුතුද යන්න තීරණය කිරීම සඳහා පරීක්ෂණයක් භාවිතා කරන අතර ක්‍රියාකාරී හැකියාවන් සත්‍ය ලෙස ක්‍රියාත්මක කිරීම වෙනත් ක්‍රමවලට කල් දමයි. ඔබ තවත් බොහෝ විකල්ප ක්‍රියාමාර්ග එකතු කරන්නේ නම්, ක්ෂණික ක්‍රමවේදය තුළ තර්කනයේ කූඩු දැමීමක් සිදු නොවන තාක් කල්, ක්‍රමවේදය සඳහා තනි අරමුණු නිර්ණායක සපුරාලනු ඇත.
එස්. රොබින්ස්

6

මෙය හැඳින්වෙන දේ සම්බන්ධයෙන්, ඔබේ කේතය වැඩි අවශ්‍යතා සපුරාලීම සඳහා වර්ධනය වන විට එය පහසුවෙන් ඊතල විරෝධී රටාව දක්වා වර්ධනය විය හැකිය ( https://softwareengineering.stackexchange.com/a/122625/33922 හි දක්වා ඇති පිළිතුරෙන් පෙන්වා ඇති පරිදි ) සහ ඊතලයකට සමාන වන කූඩු කොන්දේසි සහිත ප්‍රකාශ සහිත කේත විශාල ප්‍රමාණයක් තිබීමේ උගුලට වැටේ.

වැනි සබැඳි බලන්න;

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

http://lostechies.com/chrismissal/2009/05/27/anti-patterns-and-worst-practices-the-arrowhead-anti-pattern/

මේ පිළිබඳ තවත් බොහෝ දේ සහ වෙනත් ප්‍රති-රටා ගූගල් හි සොයාගත හැකිය.

මේ සම්බන්ධයෙන් ජෙෆ් සිය බ්ලොග් අඩවියේ සපයන විශිෂ්ට උපදෙස් කිහිපයක්;

1) ආරක්ෂක වගන්ති සමඟ කොන්දේසි ප්රතිස්ථාපනය කරන්න.

2) කොන්දේසි සහිත කොටස් වෙන් වෙන් ශ්‍රිත වලට දිරාපත් කරන්න.

3) negative ණාත්මක චෙක්පත් ධනාත්මක චෙක්පත් බවට පරිවර්තනය කරන්න

4) සෑම විටම අවස්ථාවාදී ලෙස ශ්‍රිතයෙන් ආපසු එන්න.

මුල් ප්‍රතිලාභ පිළිබඳ ස්ටීව් මැක්කොනෙල්ස් යෝජනා සම්බන්ධයෙන් ජෙෆ්ගේ බ්ලොග් අඩවියේ අදහස් කිහිපයක් බලන්න;

"කියවීමේ හැකියාව වැඩි කරන විට ප්‍රතිලාභයක් භාවිතා කරන්න: සමහර ක්‍රියාකාරකම් වලදී, ඔබ පිළිතුර දැනගත් වහාම එය නැවත ඇමතුම් චර්යාවට නැවත ලබා දීමට ඔබට අවශ්‍යය. දෛනිකව අර්ථ දක්වා ඇත්නම් එය තවදුරටත් පිරිසිදු කිරීමක් අවශ්‍ය නොවේ. දෝෂයක් අනාවරණය වුවහොත්, වහාම ආපසු නොපැමිණීම යන්නෙන් අදහස් වන්නේ ඔබ තවත් කේත ලිවිය යුතු බවයි.

...

"එක් එක් දෛනික කටයුතුවල ප්‍රතිලාභ ගණන අවම කරන්න: පුරුද්දක් තේරුම් ගැනීමට අපහසුය, එය පතුලේ කියවන විට, එය කොතැනක හෝ ආපසු පැමිණීමේ හැකියාව ඔබ නොදැන සිටියි. එම හේතුව නිසා ප්‍රතිලාභ සාධාරණ ලෙස භාවිතා කරන්න - ඒවා වැඩිදියුණු වූ විට පමණි කියවීමේ හැකියාව.

අවුරුදු 15 ක් හෝ ඊට පෙර මට ඉගැන්වූ දේ නිසා මම සෑම විටම ක්‍රියාකාරී න්‍යායකට 1 ප්‍රවේශය / පිටවීම සඳහා දායක වී සිටිමි. මට හැඟෙන්නේ මෙය කේතය කියවීමට පහසු වන අතර ඔබ සඳහන් කළ පරිදි වඩා නඩත්තු කළ හැකි බවයි


6

මෙය ඩ්‍රයි, ගොටෝ සහ නො-බහුවිධ ප්‍රතිලාභ රීති වලට අනුකූල වන අතර එය පරිමාණය කළ හැකි සහ මගේ මතය අනුව කියවිය හැකිය:

success = FileExists(file);
if (success)
{
    contents = OpenFile(file);
    success = SomeTest(contents);
}
if (success)
{
    DoSomething(contents);
}
else
{
    DefaultAction();
}

1
ප්‍රමිතීන්ට අනුකූල වීම හොඳ කේතයකට සමාන නොවිය යුතුය. මම දැනට මෙම කේත ස්නිපටය මත තීරණය කර නොමැත.
බ්‍රයන් නොබ්ලෝච්

මෙය 2 පෙරනිමි ක්‍රියාව () ප්‍රතිස්ථාපනය කරයි; කොන්දේසි 2 ක් සමාන නම් සහ ධජ විචල්‍යයක් එක් කරන ඉමෝ වඩා නරක ය.
රියාතල්

3
මෙවැනි ඉදිකිරීමක් භාවිතා කිරීමේ වාසිය නම්, පරීක්ෂණ ගණන වැඩි වන විට කේතය ifවෙනත් ifs තුළ කූඩු කිරීමට පටන් නොගැනීමයි . එසේම, අසාර්ථක නඩුව ( DefaultAction()) හැසිරවීමේ කේතය එක් ස්ථානයක පමණක් වන අතර නිදොස් කිරීමේ අරමුණු සඳහා කේතය උපකාරක කාර්යයන් වටා නොයනු ඇති අතර successවිචල්‍යය වෙනස් වන රේඛාවලට කඩඉම් ලකුණු එකතු කිරීමෙන් කුමන පරීක්ෂණ සමත් වී ඇත්දැයි පෙන්විය හැකිය (අවුලුවන ලද ඉහළින්) breakpoint) සහ ඒවා පරීක්ෂා කර නොමැති ඒවා (පහළ).
frozenkoi

1
Yeeaah, මම වගේ එය පැහැදීම ඇති, ඒත් මම නැවත නම් කරන්න කැමතියි හිතන්න successකිරීමට ok_so_far:)
Benjol

(1) සෑම දෙයක්ම නිවැරදිව සිදුවන විට ක්‍රියාවලිය ඉතා රේඛීය වන අතර (2) ඔබට ඊතල විරෝධී රටාවක් තිබේ නම් මෙය මා කරන දෙයට බොහෝ සෙයින් සමාන වේ. කෙසේ වෙතත්, මම අතිරේක විචල්‍යයක් එකතු කිරීමෙන් වැළකී සිටීමට උත්සාහ කරමි, එය ඊළඟ පියවර සඳහා වන පූර්වාවශ්‍යතාවයන් අනුව ඔබ සිතන්නේ නම් සාමාන්‍යයෙන් පහසුය (එය පෙර පියවරක් අසමත් දැයි විමසීමට වඩා සියුම් ලෙස වෙනස් වේ). ගොනුව තිබේ නම්, ගොනුව විවෘත කරන්න. ගොනුව විවෘත නම්, අන්තර්ගතය කියවන්න. මා සතුව අන්තර්ගතයක් තිබේ නම්, ඒවා ක්‍රියාවට නංවන්න, නැතිනම් පෙරනිමි ක්‍රියාව කරන්න.
ඒඩ්‍රියන් මැකාති

3

මම එය වෙනම ක්‍රමයකට උපුටා ගෙන පසුව:

if(!FileExists(file))
{
    DefaultAction();
    return;
}

contents = OpenFile(file);
if(!SomeTest(contents))
{
    DefaultAction();
    return;
}

DoSomething(contents);

එය ද ඉඩ දෙයි

if(!FileExists(file))
{
    DefaultAction();
    return Result.FileNotFound;
}

contents = OpenFile(file);
if(!SomeTest(contents))
{
    DefaultAction();
    return Result.TestFailed;
}

DoSomething(contents);
return Result.Success;            

එවිට ඔබට DefaultActionඇමතුම් ඉවත් DefaultActionකර ඇමතුම ක්‍රියාත්මක කිරීම අතහැර දැමිය හැකිය :

Result OurMethod(file)
{
    if(!FileExists(file))
    {
        return Result.FileNotFound;
    }

    contents = OpenFile(file);
    if(!SomeTest(contents))
    {
        return Result.TestFailed;
    }

    DoSomething(contents);
    return Result.Success;            
}

void Caller()
{
    // something, something...

    var result = OurMethod(file);
    // if (result == Result.FileNotFound || result == Result.TestFailed), or just
    if (result != Result.Success)        
    {
        DefaultAction();
    }
}

මම ජීන් පින්ඩාර්ගේ ප්‍රවේශයටද කැමතියි .


3

මෙම විශේෂිත අවස්ථාව සඳහා, පිළිතුර ප්‍රමාණවත් තරම් පහසුය ...

FileExistsසහ අතර ධාවන තත්වයක් ඇත OpenFile: ගොනුව ඉවත් කළහොත් කුමක් සිදුවේද?

මෙම විශේෂිත නඩුව සමඟ කටයුතු කිරීමට ඇති එකම හොඳ ක්‍රමය මඟ හැරීමයි FileExists:

contents = OpenFile(file);
if (!contents) // open failed
    DefaultAction();
else (SomeTest(contents))
    DoSomething(contents);

මෙම පිළිවෙලට මෙම ගැටලුව විශ්වාසනීය වෙනස හා කේතය පිරිසිදු කරයි.

පොදුවේ: ගැටලුව ගැන නැවත සිතා බැලීමට උත්සාහ කරන්න.


2

අනෙක් දේ ඕනෑවට වඩා දැකීමට ඔබ අකමැති නම් තවත් හැකියාවක් නම්, වෙනත් දේ සම්පූර්ණයෙන්ම භාවිතා කිරීම අතහැර දමා අතිරේක ප්‍රතිලාභ ප්‍රකාශයක් දැමීමයි. වෙන ඔබ එහි දෙකක් පියවර හැකි ට වඩා වැඩි නම්, තීරණය කිරීම සඳහා වඩාත් සංකීර්ණ තර්කන අවශ්ය නම් අනවශ්ය ආකාරයේ වේ.

මේ අනුව ඔබේ ආදර්ශය මෙසේ විය හැකිය:

void DoABunchOfStuff()
{
    if(FileExists(file))
    {
        DoSomethingWithFileContent(file);
        return;
    }

    DefaultAction();
}

void DoSomethingWithFileContent(file)
{        
    var contents = GetFileContents(file)

    if(SomeTest(contents))
    {
        DoSomething(contents);
        return;
    }

    DefaultAction();
}

AReturnType GetFileContents(file)
{
    return OpenFile(file);
}

පුද්ගලිකව මට වෙනත් වගන්තියක් භාවිතා කිරීම කමක් නැත, මන්ද එය තර්කනය ක්‍රියාත්මක විය යුතු ආකාරය පැහැදිලිව සඳහන් කර ඇති අතර එමඟින් ඔබේ කේතයේ කියවීමේ හැකියාව වැඩි දියුණු කරයි. කෙසේ නමුත් ඇතැම් කේතය නගර අලංකරන මෙවලම් තනි කිරීමට සරල කිරීම සඳහා කැමති නම් ප්රකාශය කුරුල්ලන් ලැග සිටින තර්ක අධෛර්යමත් කිරීමට.


2

නියැදි කේතයේ පෙන්වා ඇති නඩුව සාමාන්‍යයෙන් තනි ifප්‍රකාශයක් දක්වා අඩු කළ හැකිය . බොහෝ පද්ධති වල, ගොනුව දැනටමත් නොපවතී නම් ගොනු විවෘත ශ්‍රිතය අවලංගු අගයක් ලබා දෙනු ඇත. සමහර විට මෙය පෙරනිමි හැසිරීමයි; වෙනත් වේලාවක එය තර්කයක් හරහා නියම කළ යුතුය. මෙයින් අදහස් කරන්නේ FileExistsපරීක්ෂණය අතහැර දැමිය හැකි අතර, පැවැත්මේ පරීක්ෂණය සහ ගොනු විවෘත කිරීම අතර ගොනු මකාදැමීමේ ප්‍රති race ලයක් ලෙස ධාවන තත්වයන්ටද එය උපකාරී වේ.

file = OpenFile(path);
if(isValidFileHandle(file) && SomeTest(file)) {
    DoSomething(file);
} else {
    DefaultAction();
}

මෙය වියුක්ත-මට්ටම්-මිශ්‍ර කිරීමේ ගැටලුවට සෘජුවම ආමන්ත්‍රණය නොකරන අතර, එය බහුවිධ, හඳුනාගත නොහැකි පරීක්ෂණ පිළිබඳ ගැටළුව මුළුමනින්ම මග හරින අතර, ගොනු පැවැත්ම පරීක්ෂණයෙන් ඉවත් කිරීම වියුක්ත මට්ටම් වෙන් කිරීම සමඟ නොගැලපේ. අවලංගු ලිපිගොනු හැසිරවීම් "අසත්‍ය" ට සමාන යැයි උපකල්පනය කිරීම සහ ගොනු හැසිරවීම් විෂය පථයෙන් බැහැර වන විට වසා දමයි:

OpenFileIfSomething(path:String) : FileHandle {
    file = OpenFile(path);
    if (file && SomeTest(file)) {
        return file;
    }
    return null;
}

...

if ((file = OpenFileIfSomething(path))) {
    DoSomething(file);
} else {
    DefaultAction();
}

2

මම ශීත කළ කොයි සමඟ එකඟ වෙමි, කෙසේ වෙතත්, සී # සඳහා කෙසේ වෙතත්, ට්‍රයිපාර්ස් ක්‍රමයේ වාක්‍ය ඛණ්ඩය අනුගමනය කිරීමට එය උපකාරී වනු ඇතැයි මම සිතුවෙමි.

if(FileExists(file) && TryOpenFile(file, out contents))
    DoSomething(contents);
else
    DefaultAction();
bool TryOpenFile(object file, out object contents)
{
    try{
        contents = OpenFile(file);
    }
    catch{
        //something bad happened, computer probably exploded
        return false;
    }
    return true;
}

1

ඔබ එක් ශ්‍රිතයක් තුළ ඕනෑවට වඩා කරන නිසා ඔබේ කේතය කැතයි. ඔබට ගොනුව සැකසීමට හෝ පෙරනිමි ක්‍රියාමාර්ග ගැනීමට අවශ්‍යය, එබැවින් මෙසේ කියමින් ආරම්භ කරන්න:

if (!ProcessFile(file)) { 
  DefaultAction(); 
}

පර්ල් සහ රූබි ක්‍රමලේඛකයින් ලියයි processFile(file) || defaultAction()

දැන් ගොස් ProcessFile ලියන්න:

if (FileExists(file)) { 
  contents = OpenFile(file);
  if (SomeTest(contents)) {
    processContents(contents);
    return true;
  }
}
return false;

1

ඇත්ත වශයෙන්ම ඔබට මෙතරම් දුරක් යා හැක්කේ මෙවැනි අවස්ථා වලදී පමණි, නමුත් මෙන්න යන්න ක්‍රමයක්:

interface File<T> {
    function isOK():Bool;
    function getData():T;
}

var appleFile:File<Apple> = appleStorage.get(fileURI);
if (appleFile.isOK())
    eat(file.getData());
else
    cry();

ඔබට අතිරේක පෙරහන් අවශ්‍ය විය හැකිය. ඉන්පසු මෙය කරන්න:

var appleFile = appleStorage.get(fileURI, isEdible);
//isEdible is of type Apple->Bool and will be used internally to answer to the isOK call
if (appleFile.isOK())
    eat(file.getData());
else
    cry();

මෙයද අර්ථවත් වුවද:

function eat(apple:Apple) {
     if (isEdible(apple)) 
         digest(apple);
     else
         die();
}
var appleFile = appleStorage.get(fileURI);
if (appleFile.isOK())
    eat(appleFile.getData());
else
    cry();

හොඳම දේ කුමක්ද? එය රඳා පවතින්නේ ඔබ මුහුණ දෙන සැබෑ ලෝක ගැටලුව මත ය .
නමුත් ඉවතට ගත යුතු දෙය නම්: ඔබට සංයුතිය හා බහුමාපකය සමඟ බොහෝ දේ කළ හැකිය.


1

පැහැදිලිව පෙනෙන දේ වැරදියි

if(!FileExists(file)) {
    DefaultAction();
    return;
}
contents = OpenFile(file);
if(!SomeTest(contents))
{
    DefaultAction();
    return;
}        
DoSomething(contents);

එය මට හොඳ ප්‍රමිතියක් ලෙස පෙනේද? කුඩා දේවල් රාශියක් සිදුවිය යුතු විශාල ක්‍රියා පටිපාටියක් සඳහා, ඒ කිසිවක් අසමත් වීම දෙවැන්න වළක්වනු ඇත. ව්‍යතිරේකයන් එය විකල්පයක් නම් එය ටිකක් පිරිසිදු කරයි.


0

මෙය පැරණි ප්‍රශ්නයක් බව මට වැටහී ඇත, නමුත් සඳහන් නොකළ රටාවක් මම දුටුවෙමි; ප්‍රධාන වශයෙන්, ඔබ ඇමතීමට කැමති ක්‍රමය / ක්‍රම පසුව තීරණය කිරීම සඳහා විචල්‍යයක් සැකසීම (එසේ නම් ... වෙනත් ...).

කේතය සමඟ වැඩ කිරීම පහසු කිරීම සඳහා මෙය බැලීමට තවත් කෝණයකි. ඔබට වෙනත් ක්‍රමයක් කැඳවීමට අවශ්‍ය විටදී හෝ ඇතැම් අවස්ථාවන්හිදී කැඳවිය යුතු සුදුසු ක්‍රමය වෙනස් කිරීමටද එය ඉඩ දෙයි.

ක්‍රමයේ සියලුම සඳහන් කිරීම් ප්‍රතිස්ථාපනය කිරීමට වඩා (සමහර විට සමහර අවස්ථා මඟ හැරී ඇත), ඒවා සියල්ලම ලැයිස්තුගත කර ඇත්තේ if ... else ... අවහිර කර කියවීමට හා වෙනස් කිරීමට පහසුය. උදාහරණයක් ලෙස ක්‍රම කිහිපයක් කැඳවිය හැකි නමුත් මම කැදැල්ල තුළ නම් ... වෙනත් නම් ... තරඟ කිහිපයකදී ක්‍රමයක් හැඳින්විය හැක.

ඔබ රාජ්‍යය නිර්වචනය කරන විචල්‍යයක් සකසන්නේ නම්, ඔබට බොහෝ ගැඹුරින් කැදැලි විකල්ප තිබිය හැකි අතර යමක් සිදු කළ යුතු විට (හෝ නොකළ යුතු) තත්වය යාවත්කාලීන කරන්න.

'DoSomething' සිදුවී ඇත්දැයි අප පරික්ෂා කරන ප්‍රශ්නයේදී ඇසූ උදාහරණයේ දී මෙන් මෙය භාවිතා කළ හැකි අතර එසේ නොවේ නම් පෙරනිමි ක්‍රියාව සිදු කරන්න. නැතහොත් ඔබට ඇමතීමට අවශ්‍ය සෑම ක්‍රමයක් සඳහාම රාජ්‍යයක් තිබිය හැකිය, අදාළ වන විට සකසා, පසුව ... ... ට පිටතින් අදාළ ක්‍රමය අමතන්න ...

කැදැල්ල අවසානයේ ... වෙනත් ... ප්‍රකාශ, ඔබ තත්වය පරීක්ෂා කර ඒ අනුව ක්‍රියා කරයි. මෙයින් අදහස් කරන්නේ ඔබට යෙදිය යුතු සියලුම ස්ථාන වෙනුවට ක්‍රමවේදයක් ගැන තනි සඳහනක් පමණක් අවශ්‍ය බවයි.

bool ActionDone = false;

if (Method_1(object_A)) // Test 1
{
    result_A = Method_2(object_A); // Result 1

    if (Method_3(result_A)) // Test 2
    {
        Method_4(result_A); // Action 1
        ActionDone = true;
    }
}

if (!ActionDone)
{
    Method_5(); // Default Action
}

0

කැදැලි IF අඩු කිරීම සඳහා:

1 / මුල් ආපසු;

2 / සංයුක්ත ප්‍රකාශනය (කෙටි පරිපථ දැනුවත් කිරීම)

එබැවින්, ඔබේ උදාහරණය මේ ආකාරයට ප්‍රතිනිර්මාණය කළ හැකිය:

if( FileExists(file) && SomeTest(contents = OpenFile(file)) )
{
    DoSomething(contents);
    return;
}
DefaultAction();

0

"නැවත පැමිණීම" සමඟ මම බොහෝ උදාහරණ දුටුවෙමි, නමුත් සමහර විට මට අවශ්‍ය වන්නේ නව කාර්යයන් නිර්මාණය කිරීමෙන් වැළකී ඒ වෙනුවට ලූපයක් භාවිතා කිරීමයි:

while (1) {
    if (FileExists(file)) {
        contents = OpenFile(file);
        if (SomeTest(contents)) {
           DoSomething(contents);
           break;
        } 
    }
    DefaultAction();
    break;
}

ඔබට අඩු රේඛා ලිවීමට අවශ්‍ය නම් හෝ මා මෙන් අනන්ත ලූපවලට ඔබ වෛර කරන්නේ නම්, ඔබට ලූප් වර්ගය "කරන්න ... අතර (0)" ලෙස වෙනස් කර අවසන් "විවේකය" වළක්වා ගත හැකිය.


0

මෙම විසඳුම ගැන කෙසේද:

content = NULL; //I presume OpenFile returns a pointer 
if(FileExists(file))
    contents = OpenFile(file);
if(content != NULL && SomeTest(contents))
    DoSomething(contents);
else
    DefaultAction();

මම උපකල්පනය කළේ OpenFile විසින් දර්ශකයක් නැවත ලබා දෙන බවයි, නමුත් මෙය පෙරනිමි අගයක් ආපසු ලබා දිය නොහැකි (දෝෂ කේත හෝ ඒ හා සමාන දෙයක්) සඳහන් කිරීමෙන් අගය වර්ග ප්‍රතිලාභ සමඟද ක්‍රියා කළ හැකිය.

ඇත්ත වශයෙන්ම මම NULL පොයින්ටරයේ සොමෙටෙස්ට් ක්‍රමය හරහා යම් ක්‍රියාමාර්ගයක් බලාපොරොත්තු නොවෙමි (නමුත් ඔබ කවදාවත් නොදනී), එබැවින් මෙය සොමෙටෙස්ට් (අන්තර්ගත) ඇමතුම සඳහා NULL දර්ශකය සඳහා අමතර පරීක්‍ෂණයක් ලෙස ද දැකිය හැකිය.


0

පැහැදිලිවම, වඩාත්ම අලංකාර හා සංක්ෂිප්ත විසඳුම වන්නේ පෙර සැකසුම් සාර්ව භාවිතා කිරීමයි.

#define DOUBLE_ELSE(CODE) else { CODE } } else { CODE }

මේ වගේ ලස්සන කේත ලිවීමට ඔබට ඉඩ සලසයි:

if(FileExists(file))
{
    contents = OpenFile(file);
    if(SomeTest(contents))
    {
        DoSomething(contents);
    }
    DOUBLE_ELSE(DefaultAction();)

ඔබ බොහෝ විට මෙම තාක්ෂණය භාවිතා කරන්නේ නම් ස්වයංක්‍රීය හැඩතල ගැන්වීම මත විශ්වාසය තැබීම දුෂ්කර විය හැකි අතර සමහර IDEs වැරදියට උපකල්පනය කර ඇති දේ ගැන මඳක් කෑගසනු ඇත. කියමනට අනුව, සෑම දෙයක්ම වෙළඳාමක් වේ, නමුත් නැවත නැවත කේතයේ නපුරුකම් වලක්වා ගැනීම සඳහා ගෙවීම නරක මිලක් නොවේ යැයි මම සිතමි.


සමහර අය සඳහා, සහ සමහර භාෂාවල, preprocessor මැක්රෝස් වේ නපුරු කේතය :)
Benjol

En බෙන්ජෝල් ඔබ නපුරු යෝජනා සඳහා විවෘත බව පැවසුවා නේද? ;)
පීටර් ඕල්සන්

ඔව්, නියත වශයෙන්ම එය ඔබගේ "
නපුරෙන්

4
මෙය ඉතා භයානක ය, මට එය ඉහළ නැංවීමට සිදු විය: D
back2dos

ෂර්ලි, ඔයා බරපතල නෑ !!!!!!
ජිම් ටෙක්සාස්

-1

ඔබ කුතුහලයෙන් ඇසූ නිසාත්, ඔබේ ප්‍රශ්නය නිශ්චිත භාෂාවක් සමඟ ටැග් කර නොමැති නිසාත් (ඔබේ මනසෙහි අත්‍යවශ්‍ය භාෂාවන් ඇති බව පැහැදිලිය), කම්මැලි ඇගයීමට සහාය වන භාෂාවන් සම්පූර්ණයෙන්ම වෙනස් ප්‍රවේශයකට ඉඩ දීම එකතු කිරීම වටී. එම භාෂාවල, ප්‍රකාශන ඇගයීමට ලක් වන්නේ අවශ්‍ය විටදී පමණි, එබැවින් ඔබට "විචල්‍යයන්" නිර්වචනය කළ හැකි අතර ඒවා භාවිතා කිරීම අර්ථවත් වූ විට පමණක් භාවිතා කළ හැකිය. උදාහරණයක් ලෙස, කම්මැලි let/ inව්‍යුහයන් සහිත ප්‍රබන්ධ භාෂාවක ඔබට ප්‍රවාහ පාලනය අමතක කර ලියන්න:

let
  contents = ReadFile(file)
in
  if FileExists(file) && SomeTest(contents) 
    DoSomething(contents)
  else 
    DefaultAction()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.