関数/メソッドをカスケーディングスタイルで呼び出す状況があります。説明と質問については、次の例を参照してください。私はこの状況の技術的な言葉を知りたがっています。人々が私が何を話しているのかを理解することはより簡単になります。
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;
}
子メソッドが正常に実行された場合、以前の呼び出しメソッド/関数に戻るプロセスを回避するにはどうすればよいですか?
たとえば、ログインメソッドは checkForSomething( "johndoe")
を呼び出しています。 checkForSomething( "johndoe")
が渡された場合、DoOpenDashboardを呼び出してDashboardウィンドウを開きます。この時点で私のプロセスはcheckforsoemthingに戻り、ログインするべきではありません。それが理にかなってほしい。
あなたがここで何を求めているのかは分かりません。あなたの疑似コードは、あなたのクラスのコンストラクタで呼び出されているLogin()メソッドを示しています。これが本当にあなたのコードがどのように動作しているのであれば、再びLoginを呼び出すのを防ぐために、このクラスの新しいインスタンスの作成を避ける必要があります。
しかし、私はあなたが本当に矢のアンチパターンについて尋ねていると思います:
http://codinghorror.com/blog/2006/01/flattening-arrow -code.html
EDIT
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:
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
(他のテクニックも掲載されていることに注意してください。しかし、私はこの最初のもので十分でしょう)
このようにして、チェックが失敗すると、メソッド呼び出しが失敗した場合、それぞれの追加チェックで別のネストされたチェックが行われることはありません。これは、button1_Clickがbool(成功の場合はtrue、失敗の場合はfalse)を返す関数を呼び出し、失敗した場合はfalseを返すことによって例外をスローすることなく行うこともできます。
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;
}
あなたのメソッドが一度だけチェックされていることを確認しようとしていますか?おそらく、いくつかのプロパティを複数回クエリする必要があるかもしれませんが、一度だけテストします。
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();
}
}