40
Control Flow, Conditional Statements and Loops Correctly Organizing the Control Flow Logic Stefan Dobrev Telerik Corporation www.telerik. com

Control Flow, Conditional Statements and Loops

  • Upload
    tareq

  • View
    44

  • Download
    1

Embed Size (px)

DESCRIPTION

Control Flow, Conditional Statements and Loops. Correctly Organizing the Control Flow Logic. Stefan Dobrev. Telerik Corporation. www.telerik.com. Organizing Straight-line Code. Order and separate your dependencies correctly. Source: http://www.flickr.com/photos/blackcustard/81680010/. - PowerPoint PPT Presentation

Citation preview

Page 1: Control Flow, Conditional Statements and Loops

Control Flow, Conditional

Statements and Loops

Correctly Organizing the Control Flow Logic

Stefan DobrevTelerik

Corporationwww.telerik.com

Page 2: Control Flow, Conditional Statements and Loops

Organizing Straight-line

CodeOrder and separate your dependencies

correctly Source: http://www.flickr.com/photos/blackcustard/81680010/

Page 3: Control Flow, Conditional Statements and Loops

Straight-line Code When statements’ order matters

Make dependencies obvious Name methods according to

dependencies Use method parameters

Document the control flow if needed3

data = GetData();groupedData = GroupData(data);PrintGroupedData(groupedData);

GetData();GroupData();Print();

Page 4: Control Flow, Conditional Statements and Loops

Straight-line Code (2) When statements’ order does not matter Make code read from top to bottom

like a newspaper Group related statements together Make clear boundaries for

dependencies Use blank lines to separate

dependencies User separate methods 4

Page 5: Control Flow, Conditional Statements and Loops

Straight-line Code – Examples

5

ReportFooter CreateReportFooter(Report report){ ...}ReportHeader CraeteReportHeader(Report report){ ...}

Report CreateReport(){ var report = new Report(); report.Footer = CreateReportFooter(report); report.Content = CreateReportContent(report);

report.Header = CraeteReportHeader(report); return report;}

ReportContent CreateReportContent(Report report){ ...}

Page 6: Control Flow, Conditional Statements and Loops

Straight-line Code – Examples

6

Report CreateReport(){ var report = new Report(); report.Header = CraeteReportHeader(report); report.Content = CreateReportContent(report); report.Footer = CreateReportFooter(report); return report;}

ReportHeader CraeteReportHeader(Report report){ ...}

ReportContent CreateReportContent(Report report){ ...}

ReportFooter CreateReportFooter(Report report){ ...}

Page 7: Control Flow, Conditional Statements and Loops

Using Control

ConstructsUsing Conditional Statements and Loops

Correctly

Page 8: Control Flow, Conditional Statements and Loops

Using Conditional Statements

Always use { and } for the conditional statements body, even when it is a single line:

Why omitting the brackets could be harmful?

This is misleading code + misleading formatting

8

if (condition){ DoSometing();}

if (condition) DoSomething(); DoAnotherThing();DoDifferentThing();

Page 9: Control Flow, Conditional Statements and Loops

Using Conditional Statements (2)

Always put the normal (expected) condition after the if clause.

Start from most common cases first, then go to the unusual ones

9

var responce = GetHttpWebResponce();if (responce.Code == Code.OK){ ...}else{ if (responce.Code == Code.NotFound) { ... }}

var responce = GetHttpWebResponce();if (responce.Code == Code.NotFound){ ...}else{ if (response.Code == Code.OK) { ... }}

Page 10: Control Flow, Conditional Statements and Loops

Using Conditional Statements (3)

Avoid double negation

Write if clause with a meaningful statement

Use meaningful boolean expressions, which read like sentence

10

if (HasErrors){ DoSometing();}

if (!HasNoError){ DoSomething();}

if (HasErrors){ DoSometing();}

if (!HasError);else{ DoSometing(); }

Page 11: Control Flow, Conditional Statements and Loops

Using Conditional Statements (4)

Be aware of copy/paste problems in if-else bodies

11

Person p = null;if (SomeCondition){ p = GetSomePerson();}else{ p = GetOtherPerson();}

p.SendMail();p.SendSms();

if (SomeCondition){ var p = GetSomePerson(); p.SendMail(); p.SendSms();}else{ var p = GetOtherPerson(); p.SendMail(); p.SendSms();}

Page 12: Control Flow, Conditional Statements and Loops

Use Simple Conditions Do not use complex if conditions

You can always simplify them by introducing boolean variables or boolean methods

Incorrect example:

Complex boolean expressions are harmful

How you will find the problem if you get IndexOutOfRangeException?

12

if (x > 0 && y > 0 && x < Width-1 && y < Height-1 && matrix[x, y] == 0 && matrix[x-1, y] == 0 && matrix[x+1, y] == 0 && matrix[x, y-1] == 0 && matrix[x, y+1] == 0 && !visited[x, y])

Page 13: Control Flow, Conditional Statements and Loops

The last example can be easily refactored into self-documenting code:

Now the code is: Easy to read – the logic of the

condition is clear Easy to debug – breakpoint can be

put at the if

Simplifying Boolean Conditions

13

bool inRange = x > 0 && y > 0 && x < Width-1 && y < Height-1;bool emptyCellAndNeighbours = matrix[x, y] == 0 && matrix[x-1, y] == 0 && matrix[x+1, y] == 0 && matrix[x, y-1] == 0 && matrix[x, y+1] == 0;if (inRange && emptyCellAndNeighbours && !visited[x, y])

Page 14: Control Flow, Conditional Statements and Loops

Use object oriented approach

Simplifying Boolean Conditions (2)

14

class Maze{ Cell CurrentCell {get; set;} IList<Cell> VisitedCells {get;} IList<Cell> NeighbourCells {get;} Size Size {get;} bool IsCurrentCellInRange() { return Size.Contains(CurrentCell); } bool IsCurrentCellVisited() { return VisitedCells.Contains(CurrentCell); } (continues on the next slide)

Page 15: Control Flow, Conditional Statements and Loops

Simplifying Boolean Conditions (3)

15

Now the code: Models the real scenario Stays close to the problem domain

bool AreNeighbourCellsEmpty() { ... }

bool ShouldVisitCurrentCell() { return IsCurrentCellInRange() && CurrentCell.IsEmpty() && AreNeighbourCellsEmpty() && !IsCurrentCellVisited() }}

Page 16: Control Flow, Conditional Statements and Loops

Sometimes a decision table can be used for simplicity

Use Decision Tables

16

var table = new Hashtable();table.Add("A", new AWorker());table.Add("B", new BWorker());table.Add("C", new CWorker());

string key = GetWorkerKey();

var worker = table[key];if (worker != null){ ... worker.Work(); ...}

Page 17: Control Flow, Conditional Statements and Loops

Positive Boolean Expressions

Starting with a positive expression improves readability

Use DeMorgan’s laws for negative checks

17

if (IsValid){ DoSometing();}else{ DoSometingElse();}

if (!IsValid){ DoSometingElse();}else{ DoSometing();}

if (!(IsValid && IsVisible))

if (!IsValid || !IsVisible)

Page 18: Control Flow, Conditional Statements and Loops

Avoid complex boolean conditions without parenthesis

Using parenthesis helps readability as well as ensure correctness

Too many parenthesis have to be avoided as well. Consider separate boolean methods in those cases

Use Parentheses for Simplification

18

if (a < b && b < c || c == d)

if (a < b && (b < c || c == d))

Page 19: Control Flow, Conditional Statements and Loops

Most modern languages evaluate from left to right and stop evaluation as soon as some of the boolean operands is satisfied

There are languages that does not follow this “short-circuit” rule

Think about parallel execution

Boolean Expression Evaluation

19

if (FalseCondition && OtherCondition)if (TrueCondition || OtherCondition)

= true

= false

Page 20: Control Flow, Conditional Statements and Loops

Write numeric boolean expressions as they are presented on a number line Contained in an interval

Outside of an interval

Numeric expressions as operands

20

if (x > a && b > x)if (a < x && x < b)

a bx

if (a > x || x > b)if (x < a || b < x)

a bx x

Page 21: Control Flow, Conditional Statements and Loops

Avoid Deep Nesting of Blocks

Deep nesting of conditional statements and loops makes the code unclear Deeply nested code is complex and

hard to read and understand Usually you can extract portions of

the code in separate methods This simplifies the logic of the code Using good method name makes the

code self-documenting21

Page 22: Control Flow, Conditional Statements and Loops

Deep Nesting – Example

22

if (maxElem != Int32.MaxValue){ if (arr[i] < arr[i + 1]) { if (arr[i + 1] < arr[i + 2]) { if (arr[i + 2] < arr[i + 3]) { maxElem = arr[i + 3]; } else { maxElem = arr[i + 2]; } } else { if (arr[i + 1] < arr[i + 3]) { maxElem = arr[i + 3]; } else { maxElem = arr[i + 1]; } } } (continues on the next slide)

Page 23: Control Flow, Conditional Statements and Loops

Deep Nesting – Example (2)

23

else { if (arr[i] < arr[i + 2]) { if (arr[i + 2] < arr[i + 3]) { maxElem = arr[i + 3]; } else { maxElem = arr[i + 2]; } } else { if (arr[i] < arr[i + 3]) { maxElem = arr[i + 3]; } else { maxElem = arr[i]; } } }}

Page 24: Control Flow, Conditional Statements and Loops

Avoiding Deep Nesting – Example

24

private static int Max(int i, int j){ if (i < j) { return j; } else { return i; }}

private static int Max(int i, int j, int k){ if (i < j) { int maxElem = Max(j, k); return maxElem; } else { int maxElem = Max(i, k); return maxElem; }} (continues on the next slide)

Page 25: Control Flow, Conditional Statements and Loops

Avoiding Deep Nesting – Example

25

private static int FindMax(int[] arr, int i){ if (arr[i] < arr[i + 1]) { int maxElem = Max(arr[i + 1], arr[i + 2], arr[i + 3]); return maxElem; } else { int maxElem = Max(arr[i], arr[i + 2], arr[i + 3]); return maxElem; }}

if (maxElem != Int32.MaxValue) { maxElem = FindMax(arr, i);}

Page 26: Control Flow, Conditional Statements and Loops

Using Case Statement Choose the most effective ordering of

cases Put the normal (usual) case first Order cases by frequency Put the most unusual (exceptional) case last Order cases alphabetically or numerically

Keep the actions of each case simple Extract complex logic in separate

methods Use the default clause in a case

statement or the last else in a chain of if-else to trap errors

26

Page 27: Control Flow, Conditional Statements and Loops

Incorrect Case Statement

27

void ProcessNextChar(char ch){ switch (parseState) { case InTag: if (ch == ">") { Console.WriteLine("Found tag: {0}", tag); text = ""; parseState = ParseState.OutOfTag; } else { tag = tag + ch; } break; case OutOfTag: … }}

Page 28: Control Flow, Conditional Statements and Loops

Improved Case Statement

28

void ProcessNextChar(char ch){ switch (parseState) { case InTag: ProcessCharacterInTag(ch); break; case OutOfTag: ProcessCharacterOutOfTag(ch); break; default: throw new Exception("Invalid parse state: " + parseState); }}

Page 29: Control Flow, Conditional Statements and Loops

Use object oriented style – visitor pattern

Improved Case Statement (2)

29

abstract class CharVisitor{ public abstract void VisitCharInTag(char ch); public abstract void VisitCharOutOfTag(char ch); void VisitNextChar(char ch) { switch (parseState) { case InTag: VisitCharInTag(ch); break; case OutOfTag: VisitCharOutOfTag(ch); break;... (continues on the next slide)

Page 30: Control Flow, Conditional Statements and Loops

The code is: More robust Promotes clean separation of

concerns

Improved Case Statement (3)

30

class CharProcessorVisitor : CharVisitor{ public override void VisitCharInTag(char ch) { ProcessCharInTag(ch); } public override void VisitCharOutOfTag(char ch) { ProcessCharOutOfTag(ch); }}

Page 31: Control Flow, Conditional Statements and Loops

Using loopsChoose appropriate

loop typeand don’t forget to

breakSource: http://www.flickr.com/photos/mismyselfmelissa/3648505061/

Page 32: Control Flow, Conditional Statements and Loops

Using Loops Choosing the correct type of loop:

Use for loop to repeat some block of code a certain number of times

Use foreach loop to process each element of an array or a collection

Use while / do-while loop when you don't know how many times a block should be repeated

Avoid deep nesting of loops You can extract the loop body in a

new method32

Page 33: Control Flow, Conditional Statements and Loops

Loops: Best Practices Keep loops simple

This helps readers of your code Treat the inside of the loop as it were a routine Don’t make the reader look inside

the loop to understand the loop control

Think of a loop as a black box:

33

while (!inputFile.EndOfFile() && !hasErrors){

}

(black box code)

Page 34: Control Flow, Conditional Statements and Loops

Loops: Best Practices (2)

Keep loop’s housekeeping at the start or the end of the loop block

Use meaningful variable names to make loops readable

34

while (index < 10){ ... index += 2;}

while (index < 10){ ... index += 2; ...}

for(i=2000, i<2011, i++){ for(j=1, j<=12, j++) ...}

for(year=2000, year<2011, year++){ for(month=1, month<=12, month++) ...}

Page 35: Control Flow, Conditional Statements and Loops

Loops: Best Practices (3)

Avoid empty loops

Be aware of your language (loop) semantics C# - Access to modified closure

35

do { inputChar = Console.Read();} while (inputChar != '\n');

while ((inputChar = Console.Read()) != '\n') {}

Page 36: Control Flow, Conditional Statements and Loops

Other Control Flow

StructuresTo understand recursion, one must

first understand recursion Source: http://www.flickr.com/photos/sbprzd/183419808/

Page 37: Control Flow, Conditional Statements and Loops

Recursion Useful when you want to walk a tree(graph) like structures

Be aware of infinite recursion or indirect recursion

Recursion example:

37

void PrintWindowsRecursive(Window w){ w.Print() foreach(childWindow in w.ChildWindows) { PrintWindowsRecursive(childWindow); }}

Page 38: Control Flow, Conditional Statements and Loops

Recursion Tips Ensure that recursion stops Verify that recursion is not very exhausting Check the occupied system

resources You can always use stack classes

and iteration Don’t use recursion when there is better linear (iteration based) solution Factorials Fibonacci Numbers

Some languages optimize tail-call recursions

38

Page 39: Control Flow, Conditional Statements and Loops

Goto Avoid gotos, because they have a tendency to introduce spaghetti code

“A Case against theGO TO Statement.” by Edsger Dijkstra

Use gotos as a last resort if they make the code more maintainable

39

Source: http://www.flickr.com/photos/pookhy/3346307127/

Page 40: Control Flow, Conditional Statements and Loops

Control Flow, Conditional Statements

and Loops

Questions? ??

? ? ??

??

?http://academy.telerik.com