| 

.NET C# Java Javascript Exception

3
ich habe mir das FizzBuzz Kata mal angeshen. Und immer wieder stoße ich auf viele IF Anweisungen. Ich würde mir das etwas anderes wünschen.

Was haltet Ihr davon:

internal static class FizzBuzzChecker
{
public static IEnumerable<string> Generate(int max)
{
return Enumerable.Range(0, max).Select(Transform);
}

public static void Dump(this IEnumerable<string> enumer)
{
foreach (var fizzBuzz in enumer)
{
Console.WriteLine(fizzBuzz);
}
}

public class IfOption<T,TReturn>
{
public IfOption(T value, TReturn defaultReturn)
{
Value = value;
IfTrue = false;
ReturnValue = defaultReturn;
}

public T Value { get; private set; }
public TReturn ReturnValue;
public bool IfTrue;
}

public static IfOption<T, TReturn> WhereSelect<T, TReturn>(this IfOption<T, TReturn> value, Predicate<T> where, Func<T, TReturn> select)
{
// if already a value found
if (value.IfTrue)
{
return value;
}

// check with the current where
if (where(value.Value))
{
value.IfTrue = true;
value.ReturnValue = select(value.Value);
return value;
}

// go to the next where
return value;
}

private static string Transform(int number)
{
return new IfOption<int, string>(number,number.ToString())
.WhereSelect(IsFizzBuzz, isFizzBuzz => "FizzBuzz")
.WhereSelect(IsFizz, isFizz => "Fizz")
.WhereSelect(IsBuzz, isBuzz => "Buzz").ReturnValue;

//Console.WriteLine("transform {0}",number);)))
//if (IsFizzBuzz(number)) return "FizzBuzz";
//if (IsFizz(number))return "Fizz";
//return IsBuzz(number) ? "Buzz" : number.ToString();
}

internal static bool IsFizzBuzz(int number)
{
return IsFizz(number) && IsBuzz(number);
}

internal static bool IsFizz(int number)
{
return number%3 == 0;
}

internal static bool IsBuzz(int number)
{
return number%5 == 0;
}
}

klar das If verschwindet nicht, es wird nur verdeckt. Aber ist die If Option nicht ein wenig besser lesbar?
Habt Ihr eine bessere Idee?
News:
16.02.2011
tire0011 109 1 6
gefällt mir :-)
Jürgen Gutsch 16.02.2011
2
Ich versteh leider nicht, was dir an 2-3 If-Anweisungen bei einer üblichen Lösung nicht gefällt. Du treibst viel Aufwand - aber zu welchem Zweck?
Ralf Westphal 16.02.2011
1
Ich finde Deinen Code als Beispiel sehr gut, würde es aber trotzdem in der Praxis nicht so machen, da diese Implementierung eigentlich keinen weiteren Nutzen bringt, ausser jemandem zu veranschaulichen, wie man es "fluent" implementieren könnte. Leider macht Dein Vorschlag den Code meiner Meinung nach deutlich schwerer zu verstehen und zu warten.
Torsten Weber 16.02.2011
5 Antworten
3
Ich muss zugeben, dass der Ansatz "etwas hat". Es erinnert mich an einen Blogeintrag, den ich irgendwo vor Jahren einmal gelesen habe (und leider nicht mehr finde), wo es um ein eigentlich supertriviales Problem ging, das dann nach und nach immer komplexer gelöst wurde - bis wir schließlich beim "Highly Sophisticated OOP Approach" waren (falls irgendwer diesen Blogeintrag kennt und noch hat, wäre ich dankbar für einen Link!).

Was mir an dem Ansatz gefällt, ist die Fluent-Schreibweise, und die Formulierung mit den Methoden. Was mir überhaupt nicht gefällt, ist, dass der Code nicht leichter wartbar wird, im Vergleich zu der direkten if-Methode.

Das Problem ist meines Erachtens: Wenn ich die if-Variante verwende, und eine neue Regel hinzukommt, muss ich den Code ändern - ich muss also alles neu testen, und kann nicht nur die neue Regel hinzufügen (und diese isoliert testen). Der Punkt ist also: Das Hinzufügen neuer Funktionalität ist nicht mit dem eigentlichen Hinzufügen getan, sondern es muss auch an anderer Stelle noch etwas ergänzt werden (nämlich beim Aufruf). Das ist schlecht, weil ich so nicht nur das Hinzugefügte (die neue Regel) testen muss, sondern wieder alles.

Das gleiche Problem habe ich bei der hier vorgestellten Version ebenfalls. Insofern ist die syntaktisch zwar nett, bringt aber in meinen Augen keinen zusätzlichen Nutzen.

Was ich mir als Verbesserung wünschen würde, beziehungsweise was ich anders machen würde, wäre, die Regeln zum Beispiel in eine Liste zu registrieren, die dann durchlaufen wird. In diesem Fall muss beim Ergänzen einer Regel nur die Regel geschrieben werden, und sie muss als ein weiteres Add der Liste hinzugefügt werden - die eigentliche Prüflogik bliebe aber immer die gleiche, egal ob ich zwei oder zwanzig Regeln habe.

Das fände ich persönlich geschickter.
16.02.2011
Golo Roden 2,7k 3 9
Meinst Du das:
http://chaosinmotion.com/blog/?p=622
Holger Sachs 01.03.2011
Das war's leider nicht, ist aber auch interessant zu lesen ;-)
Golo Roden 01.03.2011
1
animmiert durch die beiden Antworten. Besonders von Daniel, wobei bei dem ODER habe ich eine Weile gebraucht :-). Habe ich auch eine zweite Lösung, sogar ebenfalls ohne if. Die Testbarkeit wird dabei jedoch immer noch nicht erhöht. Aber es macht doch irgendwie Spaß...
Aber vielleicht liefert ja jemand eine nicht If die man super testen kann...

Zumindest habe ich durch die Kata schon einiges gelernt :-)

class Program
{
static void Main(string[] args)
{
Enumerable.Range(1, 100).Select(FizzBuzzChecker.Transform).Dump();

Console.ReadLine();
}
}

internal static class FizzBuzzChecker
{
public static void Dump(this IEnumerable<string> enumer)
{
foreach (var fizzBuzz in enumer)
{
Console.WriteLine(fizzBuzz);
}
}

public static string Transform(int number)
{
//Console.WriteLine("transform {0}",number);)))
//if (IsFizzBuzz(number)) return "FizzBuzz";
//if (IsFizz(number))return "Fizz";
//return IsBuzz(number) ? "Buzz" : number.ToString();

return new IfLinq<int, string>(testValue => testValue.ToString())
.If(IsFizzBuzz,"FizzBuzz")
.If(IsBuzz,"Buzz")
.If(IsBuzz,"Fizz")
.Run(number);
}

internal class IfLinq<TTestValue,TReturnValue>
{
readonly Dictionary<Predicate<TTestValue>, TReturnValue> m_patterns = new Dictionary<Predicate<TTestValue>, TReturnValue>();
private readonly Func<TTestValue, TReturnValue> m_defaultValue;


internal IfLinq(Func<TTestValue, TReturnValue> defaultValue)
{
m_defaultValue = defaultValue;
}

internal IfLinq<TTestValue, TReturnValue> If(Predicate<TTestValue> pattern, TReturnValue returnValue)
{
m_patterns.Add(pattern,returnValue);
return this;
}

internal TReturnValue Run(TTestValue testValue)
{
foreach (var pattern in m_patterns.Where(pattern => pattern.Key(testValue)))
{
return pattern.Value;
}

return m_defaultValue(testValue);
}
}

internal static bool IsFizzBuzz(int number)
{
return IsFizz(number) && IsBuzz(number);
}

internal static bool IsFizz(int number)
{
return number%3 == 0;
}

internal static bool IsBuzz(int number)
{
return number%5 == 0;
}
}
16.02.2011
tire0011 109 1 6
1
Es führen viele Wege nach Rom,

in meinen Augen ist elegant kein Kriterium für Software.
Wer kennt ihn nicht, den C Code der wie ein Indianerkopf aussieht?
NETT? JA! Sinnvoll? NEIN!
Ich stosse im Alltag immer wieder auf Code, dem man ansieht das er von jemand geschrieben wurde der sich für einen Künstler hielt, jetzt ist der Künstler weg und seinen Code zu verstehen ist die eigentliche Kunst. "Künstler" sind in meinen Augen Egoisten, die allen die nach Ihnen kommen das Leben schwer machen.
Ich sehe nichts falsches bei 3 IFs; IF ist ein "Standardbauteil" das von Jedem verstanden wird und auch von Anfängern keine Recherche verlangt um den Code zu warten.

Softwareentwicklung sollte meiner Meinung Ingenieurmässig bzw. Handwerksmässig betrieben werden
Soweit ich betroffen bin ist Nachvollziehbarkeit, Wartbarkeit und Prägnanz ein Hauptkriterium für Softwareentwickler.
Mein Motto:
Always code as if the person who will maintain your code is a maniac serial killer that knows where you live
01.03.2011
Richard 391 7
0
Der Beitrag hat mich dazu animiert, auch noch ein wenig rumzuspielen. Eine Lösung die ohne ein einziges if Statement auskommt, könnte wie folgt aussehen:

void Main()
{
var fb = Enumerable.Range(1, 100).Select(Answer);
fb.Dump(); // LINQPad
}

static readonly Func<int, string>[] Answers = new Func<int, string>[]
{
(number) => number.ToString(),
(number) => "Fizz",
(number) => "Buzz",
(number) => "FizzBuzz"
};

static string Answer(int number)
{
var x = ((number % 5 == 0) ? 2 : 0)
| ((number % 3 == 0) ? 1 : 0);
return Answers[x](number);
}

Was die Lesbarkeit betrifft, das ist wohl Geschmackssache, aber ich bevorzuge kürzere Lösungen.
16.02.2011
Daniel Kuppitz 596 1 7
Finde ich übersichtlicher als die Lösung oben aber irgendwie immer noch schwerer nachzuvollziehen als deutliche ifs. Wie Du schon schreibst ist das aber Geschmackssache bzw. auch 'ne Frage der Gewohnheit.
Torsten Weber 16.02.2011
0
Here the homepage for amazon free gift card codes online.
19.06.2017

Stelle deine Programmieren-Frage jetzt!