IF-Als Designe Fehler

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 48 Antworten in diesem Thema. Der letzte Beitrag () ist von Artentus.

    EaranMaleasi schrieb:

    Ich kann dir einen halben Punkt dafür geben, dass If vielleicht OOP erst ermöglicht hat.

    Darauf war ich nicht aus und darauf kann ich dann auch gerne verzichten, dennoch ist das wieder deine Meinung. Durch OOP kann man auf viele if oder switch Statements verzichten(/reduzieren), indem man z.B. die möglichen Ergebnisse mit entsprechenden Aktionen in dein Dictionary packt. Natürlich lässt sich das nicht komplett vermieden und ist auch gar nicht Sinnvoll, aber das habe ich ja dazu geschrieben. Für mich ist das Bezug genug und finde dementsprechend meine Aussage immer noch passend.
    @Bluespide- Danke
    @mrMo - Danke
    Ist es nicht genau das ziel, so dynamisch wie möglich zu programmieren, das alles eindeutig ist, selbst bei einer Enum verwendung?

    ThuCommix schrieb:

    Enum z.B. Operations.Plus, Operations.Divide müsstest du trotzdem mit If prüfen.


    Und genau das ist ein Teil der Frage. Was sind sinnvolle alternativen?

    Schamash schrieb:

    Wie soll ich denn z.B. eine simple Prüfung ohne If machen?


    Ist ja wiederrum trozdem eine if, nur inline

    Acr0most schrieb:

    echo $a ? "passt" : "nixos passos";


    Nicht das ich wüsste, wieso?

    RodFromGermany schrieb:

    Haben wir heute den 1. April oder was




    Nochmal zur Situation:
    Als ich TeamSpeak saß kam einer an und hatte ein Problem, ich meinte ok lass mal sehen das wir da was finden.
    und schwub über TeamSpeak drauf das und quellcode watch.
    Was mir aufgefallen ist das der Code nur aus IF-Statements geschrieben war.
    Darauf hin meinte ich er solle mal schauen wir er die ganzen If's weg bekommt und dynamischer Dinge bearbeitet via Function o.ä..
    Darauf hin meinte die Person: "Eig. begehst du einen Designe sobald du eine IF/ Switch-Case nutzt, aber naja .... ".
    Was leider immer noch nicht den genauen Wortlaut wieder gibt. Bzw. Wenn nur dieser eine schwammige Hinweis dahin gerotzt wurde ist das ganz Schwach.

    Ebenfalls fehlt hier der begutachtete Code.

    Vielleicht war die Aussage bezüglich der Ifs aber auch keine generelle sondern nur auf diesen Code zugeschnittene.

    Vielleicht war der Code imperativ Programmiert und nicht prozedural, obwohl die genutzte Sprache klar Prozedural/ objektorientiert ist
    Die deutsche Sprache ist Freeware, du kannst sie benutzen, ohne dafür zu bezahlen. Sie ist aber nicht Open Source, also darfst du sie nicht verändern, wie es dir gerade passt.

    Facebamm schrieb:

    die Frage ist jetzt nicht an den Quellcode gelegt, sie ist allgemein gültig

    Dann ist die Aussage, ungeachtet der eingebildeten Reputation des Redners, schlicht und einfach Falsch!
    There is no CLOUD - just other people's computers

    Q: Why do JAVA developers wear glasses?
    A: Because they can't C#

    Daily prayer:
    "Dear Lord, grand me the strength not to kill any stupid people today and please grant me the ability to punch them in the face over standard TCP/IP."
    Nein, ist sie nicht. If ist die älteste Verzweigung in der Programmierung und eine ganz natürliche, immer wieder vorkommendene Frage.

    Auchbaußerhalb der Programmierung
    Die deutsche Sprache ist Freeware, du kannst sie benutzen, ohne dafür zu bezahlen. Sie ist aber nicht Open Source, also darfst du sie nicht verändern, wie es dir gerade passt.
    Gib es denn noch alternativen?

    Spoiler anzeigen

    C#-Quellcode

    1. using System.Collections.Generic;
    2. using System.Threading;
    3. using System.Threading.Tasks;
    4. using System.Windows.Forms;
    5. namespace CircleWare
    6. {
    7. class Controller
    8. {
    9. private Keys moveup;
    10. public Keys MoveUp { get => moveup; set => KeyValueSwitch(ref moveup, value, Direction.Up); }
    11. private Keys moveleft;
    12. public Keys MoveLeft { get => moveleft; set => KeyValueSwitch(ref moveleft, value, Direction.Left); }
    13. private Keys moveright;
    14. public Keys MoveRight { get => moveright; set => KeyValueSwitch(ref moveright, value, Direction.Right); }
    15. private Keys movedown;
    16. public Keys MoveDown { get => movedown; set => KeyValueSwitch(ref movedown, value, Direction.Down); }
    17. public Keys AutoFire { get; set; } = Keys.E;
    18. public Keys Fire { get; set; } = Keys.LButton;
    19. private Direction HorizontalActuell, HorizontalBuffer;
    20. private Direction VertikalActuell, VertikalBuffer;
    21. private CancellationTokenSource CancelMoveThreadToken;
    22. private Dictionary<Keys, Direction> KeyValue;
    23. public delegate void MoveEventHandle(Direction horizontal, Direction vertikal);
    24. public delegate void ActionEventHandle(GameAction action);
    25. public event MoveEventHandle MoveEvent;
    26. public event ActionEventHandle ActionEvent;
    27. private Controller() { }
    28. public Controller(Form content)
    29. {
    30. KeyValue = new Dictionary<Keys, Direction>();
    31. MoveUp = Keys.W;
    32. MoveLeft = Keys.A;
    33. MoveRight = Keys.D;
    34. MoveDown = Keys.S;
    35. HorizontalActuell = Direction.None;
    36. VertikalActuell = Direction.None;
    37. HorizontalBuffer = Direction.None;
    38. VertikalBuffer = Direction.None;
    39. content.KeyDown += KeyDown;
    40. content.KeyUp += KeyUp;
    41. content.FormClosing += ContentClosing;
    42. CancelMoveThreadToken = new CancellationTokenSource();
    43. Task.Factory.StartNew(() =>
    44. {
    45. while (!CancelMoveThreadToken.IsCancellationRequested)
    46. MoveEvent?.Invoke(HorizontalActuell, VertikalActuell);
    47. }, CancelMoveThreadToken.Token);
    48. }
    49. private void ContentClosing(object sender, FormClosingEventArgs e) => CancelMoveThreadToken.Cancel();
    50. private delegate void SwitchKey(ref Direction actuell, ref Direction buffer, Direction value);
    51. public void KeyDown(object sender, KeyEventArgs e) =>
    52. KeyManager(e.KeyCode, (ref Direction actuell, ref Direction buffer, Direction value) =>
    53. {
    54. if (actuell != Direction.None && actuell != value)
    55. buffer = actuell;
    56. actuell = value;
    57. });
    58. public void KeyUp(object sender, KeyEventArgs e)
    59. {
    60. KeyManager(e.KeyCode, (ref Direction actuell, ref Direction buffer, Direction value) =>
    61. {
    62. if (value != buffer)
    63. actuell = buffer;
    64. buffer = Direction.None;
    65. });
    66. if (e.KeyCode == Fire)
    67. ActionEvent?.Invoke(GameAction.FIRE);
    68. if (e.KeyCode == AutoFire)
    69. ActionEvent?.Invoke(GameAction.AUTOFIRE);
    70. }
    71. private void KeyManager(Keys keycode, SwitchKey<Direction> switchkey)
    72. {
    73. if (KeyValue.TryGetValue(keycode, out Direction value))
    74. {
    75. if (value == Direction.Left || value == Direction.Right)
    76. switchkey(ref HorizontalActuell, ref HorizontalBuffer, value);
    77. if (value == Direction.Up || value == Direction.Down)
    78. switchkey(ref VertikalActuell, ref VertikalBuffer, value);
    79. }
    80. }
    81. public Keys KeyValueSwitch(ref Keys keycode, Keys tmpkey, Direction value)
    82. {
    83. if (KeyValue.ContainsKey(keycode))
    84. KeyValue.Remove(keycode);
    85. KeyValue.Add(tmpkey, value);
    86. return tmpkey;
    87. }
    88. public enum GameAction
    89. {
    90. FIRE, AUTOFIRE
    91. }
    92. }
    93. }

    If Verzweigungen sind insofern schlechtes Design als dass jede Verzweigung die zyklomatische Komplexität einer Methode erhöht.

    Ist auch verständlich, da dabei die Anzahl der Äquivalenzklassen für einen Blackbox-Test proportional zu 2^n wächst wobei n die tiefe der tiefsten verzweigung (also geschachtele verzweigungen wobei ich von vollständigen if - else konstrukten ausgehe)

    Damit ist insbesondere der Code schwieriger wartbar, lesbar und prüfbar, da davon ausgegangen wird dass jeder Verzweigungsblock eine eigene Semantik hat (die dann mit dementsprechenden Eingabewerten zu prüfen ist).

    Das heisst man sollte versuchen sowenige Verzweigungen wie möglich zu nutzen

    Natürlich gibt es keine echte Alternative d.h. Verzweigungen sind elementare Befehle (Quasi das was Axiome an Behauptungen sind) (und werden deshalb auch vom Prozessorbefehlssatz vieler (aller?) Prozessoren von Grund auf geliefert)

    Deshalb hilft es da nur sich zu fragen, haben alle Verzweigungsblöcke eine seperate Semantik (das heisst verändert sich das Verhalten der Methode wenn zwei verschiedene Blöcke aufgerufen werden)?
    Wenn nein dann kann eine verzweigung komplett wegfallen.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „RushDen“ ()

    us4711 schrieb:

    Wie zeigt man das ohne IF-Statement?

    VB.NET-Quellcode

    1. understandings = understandings AndAlso brain IsNot Empty
    2. 'bzw
    3. understandings = understandings OrElse brain Is Empty
    Ich behaupte allerdings nicht, dass das lesbarer oder effizienter wäre.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „petaod“ ()

    @petaod würde dein Beispiel nicht intern eh wieder in einer IF-Abfrage enden ?
    Also wenn das ganze dann in IL Compiled wird ? (ich meine das AndAlso / OrElse und IsNot / Is )


    Bitte belehrt mich eines besseren wenn ich falsch liege.
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen
    @xChRoNiKx
    In diesem Fall ja, da AndAlso bzw. OrElse die rechte Seite nicht mehr auswerten, wenn das Ergebnis durch die linke Seite schon feststeht. Also bei False AndAlso Foo() wird Foo nicht aufgerufen, da das Ergebnis sowieso False ist.
    And bzw. Or machen das nicht. Ersetzt man also AndAlso mit And bzw. OrElse mit Or, dann werden im IL keine Verzweigungen bzw. Sprünge verwendet.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Man kann tatsächlich durch Vererbung sich 99% an expliziten If-Abfragen sparen, aber ob das so viel besser lesbar ist - Geschmackssache ^^
    Wer sich mal nen ziemlichen Brainfuck gönnen will kann mal versuchen Minesweeper nach diesen Regeln zu programmieren: gist.github.com/bobuss/6534934

    8-) faxe1008 8-)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „faxe1008“ ()

    Facebamm schrieb:

    C#-Quellcode

    1. private bool understandings(string brain) => !string.IsNullOrEmpty(brain);
    ist falsch, siehe Snippet von @petaod :!:
    Mach folgende Fallunterscheidung:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. brain = String.Empty
    2. understandings = False

    VB.NET-Quellcode

    1. brain = String.Empty
    2. understandings = True

    VB.NET-Quellcode

    1. brain = "Einstein"
    2. understandings = False

    VB.NET-Quellcode

    1. brain = "Einstein"
    2. understandings = True
    und dann
    • VB.NET-Quellcode

      1. If brain Is Empty then
      2. understandings = False
      3. End If
    oder

    • C#-Quellcode

      1. private bool understandings(string brain) => !string.IsNullOrEmpty(brain);
    und zuletzt

    VB.NET-Quellcode

    1. MessageBox.Show(understandings.ToString())
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RodFromGermany“ ()

    Also, ich entnehme diesem Thread:
    Möglich ist viel, sinnvoll ist jedoch deutlich weniger.

    Mir ist lesbarer, und damit wartbarer Code wichtig. Viele der hier aufgezeigten alteternativen Lösungen benötigen mehr als einen Blick, um zu erkennen, was erreicht werden soll.
    Für mich gilt also: Ich liebe mein

    VB.NET-Quellcode

    1. If ... Then ... Else ... End If
    Dann stell ich eine weitere These mal auf.
    Das IF-Statement ist in gesonderten fällen ein Designe fehler.

    Um es mal auf die Spize zu treiben.



    @RodFromGermany

    C#-Quellcode

    1. ​private static bool uc(bool brain, bool understandings) => (brain ^ understandings) || (brain || understandings);

    MrTrebron schrieb:

    besser passt
    Dagegen sprechen:
    • der persönliche Geschmack
    • firmeninterne Designvorgaben
    • die Lesbarkeit
    • ...
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!