Keep Code Left - How to write better code in almost any language

23
Keep Code Left Mick Andrew GGMUG January 8 th 2015

Transcript of Keep Code Left - How to write better code in almost any language

Page 1: Keep Code Left - How to write better code in almost any language

Keep Code Left

Mick Andrew

GGMUG

January 8th 2015

Page 2: Keep Code Left - How to write better code in almost any language

2

Speaker Background

• Developing code or managing developers for 25+ years

• .Net developer since 2000

• Unix/C, some Java, some Javascript

• Director of Development at Sage

– Sage is hiring …. Check us out at www.sage.com

Page 3: Keep Code Left - How to write better code in almost any language

3

Agenda

• Can one hour help you write better code?

• The approach of Keep Code Left

• How do this help in Code Reviews?

• Reading the whole code

• Examples

• Worked examples on real production code

• Questions and Discussions welcome throughout the

talk!

Page 4: Keep Code Left - How to write better code in almost any language

4

Keep Code Left

• A style of writing code for better readability

• Goal of KCL is to provide easy-to-apply rules which

foster

– simpler code logic

– which is easier to read

– and leads to fewer bugs during future maintenance

– Simple verification at review time

• Enables us to write code with simpler logic

• Learn to read many lines of code at once

– See the flow

Page 5: Keep Code Left - How to write better code in almost any language

5

Code Reviews / Inspections / Walkthroughs

• There are at least three independent goals for code reviews:– Share knowledge

– Look for bugs

– Verify standards compliance

• These can be in conflict; dependencies on the reviewing team’s..– Domain knowledge

– Coding skill level

– Personalities

• Standards compliance is the easiest to apply effectively– Less dependencies on individual skills

– Spot patterns/anti-patterns without specific domain knowledge

• KCL provides a cookbook approach to assist at both... – the time of coding, and

– for reviewing with no domain knowledge necessary

Page 6: Keep Code Left - How to write better code in almost any language

6

KCL: Claims and Mindset

• Ideal code has no branches (if statements)

– Few real-world methods are ideal!

• The one “main purpose” of any method should be in code

which is not indented

• If you need to branch, think about why

• Equivalent branch statements can be written several ways

if (condition == true)if (!condition == false)

– Think about which way you should write any boolean expression

– e.g. if (i > j) versus if (j <= i)

– What should be in the then clause versus the elseclause… and do you need the else clause anyway?

Page 7: Keep Code Left - How to write better code in almost any language

7

Let’s review some code:

what happens in the else?

Methoda();Methodb();

// Some useful commentvar foo = new Whatever(s);string s = Getastring(foo);

int x = DoSomething(s);x = Manipulate(x);return x;

}

int DoSomething(string s){

if (s != null){

ImportantMethod (s);int rc = SomethingElse(s);return modify(rc);

}else{

Page 8: Keep Code Left - How to write better code in almost any language

8

We scroll up a bit:

int x = DoSomething(s);x = Manipulate(x);return x;

}

int DoSomething(string s){

if (s != null){

ImportantMethod(s);int rc = SomethingElse(s);return modify(rc);

}else{

throw new ArgumentException("null string");}

}

Page 9: Keep Code Left - How to write better code in almost any language

9

Let’s review the same logic with KCL

Before..

Methoda();Methodb();

// Some useful commentvar foo = new Whatever(s);string s = Getastring(foo);

int x = DoSomething(s);x = Manipulate(x);return x;

}

int DoSomething(string s){

if (s != null){

ImportantMethod(s);int rc = SomethingElse(s);return modify(rc);

}else{

Page 10: Keep Code Left - How to write better code in almost any language

10

Let’s review the same logic with KCL

After..

Methoda();Methodb();

// Some useful commentvar foo = new Whatever(s);string s = Getastring(foo);

int x = DoSomething(s);x = Manipulate(x);return x;

}

int DoSomething(string s){

if (s == null)throw new ArgumentException("null string");

ImportantMethod(s);int rc = SomethingElse(s);return modify(rc);

}

Page 11: Keep Code Left - How to write better code in almost any language

11

KCL: anti-patterns

• This example show how branch (if) statements are often coded poorly in code samples (and real code!!)

int DoSomething(string s){

if (s != null){

Something1(s);int rc = Something2(s);return modify(rc);

}else{

throw new ArgumentException("null string");}

}

This is the main body of the

code but it is indented in an if

statement

Why is this condition coded the way it is?

It pushes the main body to the right – anti-pattern

This is a Keep Code Left anti-pattern:

A standalone return or throw in an else block

2

3

1

Page 12: Keep Code Left - How to write better code in almost any language

12

Let’s fix it – Introducing the Filter

pattern

• The first statement in the example method causes all

of our problems. By inverting the if condition we can

apply a KCL pattern called a Filter

int DoSomething(string s)

{

if (s == null)

throw new ArgumentException("null string");

Something1(s);

int rc = Something2(s);

return rc;

}

We have made a Filter. The code “filters out”

non-interesting cases which do not qualify for the

body of the method to be applied. Get out of the

method as quickly as possible

1

Body of the method is now

completely left, with no

branching.

2

Page 13: Keep Code Left - How to write better code in almost any language

13

Examples of good KCL layout

if (condition)return;

if (condition)return;

code;code;code;return;

if (condition)return;

code;while (condition){

if (condition)continue;

code;code;if (condition)

break;code;code;

}return;

if (condition)return;

code;code;if (condition)

return;code;code;return;

Page 14: Keep Code Left - How to write better code in almost any language

14

Examples of KCL red flag layout

if (condition){

code;code;code;

}else{

return error;}

code;return typical-case;

if (condition){

if (condition){

code;code;code;code;

}else{

code;}

}else{

code;}

if (condition){

code;code;code;

}else{

return error;}

if (condition)return typical-case;

return error;

Page 15: Keep Code Left - How to write better code in almost any language

15

Keep Code Left rules

• Keep Code Left is for almost any language.

• Filter out uninteresting or inapplicable cases at the start of the method. – Often return null, zero, false, or empty objects.

• Filter out more cases as soon as possible– Good KCL code will start with filters, then some logic, then more filters, then more logic,

keeping most of the code left.

• Keep the main body of the code with as few branches as possible. Keep it to the left.

• Think about each if condition. Should it be inverted?

• Avoid the else keyword (is it really necessary?)

• return statements should always be in the “then” part of a branch, rarely in the else.

• Put smaller code blocks in the then clause. Don’t leave “hidden” elseclauses after long then clauses.

• Apply Keep Code Left rules in loops, using the continue and break statements.

– Filter conditions out for each iteration of the loop.

• Look at the code as a whole. Use your eyes to see the structure of several lines all at once. (Practice!)

– Do this when reviewing all code.

Page 16: Keep Code Left - How to write better code in almost any language

16

… as with all “rules”

• Look to apply them in all cases…

• BUT!

• Be happy with applying the 80/20 rule

– Don’t throw out the approach because you find a difficult case

– KCL does not solve every programming problem

– “red flag” doesn’t mean its wrong… just that it might be, and

is a good place to examine

– Don’t use an exception case as an excuse to discard the

entire approach

Page 17: Keep Code Left - How to write better code in almost any language

17

Keep Code Left red flags

• Watch for these code patterns and statements

– while you are writing code

– When you are code reviewing (easier than reviewing the

logic!)

• if statements which contain many lines of code

• else statements(!)

• else statements which contain one or two lines, often

error handling.

• Methods which end with return 0/false/null/throw exception/empty objects;

– methods should end with the goal, not an error case

• Code with lots of braces{ { { } } }

Page 18: Keep Code Left - How to write better code in almost any language

18

See all the code at once

• Look at the code in the next two slides and see which

you can grasp as a whole, rather than line-by-line

• How easily can you see the “goal” of this code?

Page 19: Keep Code Left - How to write better code in almost any language

19

Sample A

public static void KeepCodeLeft()

{

foreach (var id in tmpArr)

{

var item = Sitecore.Context.Database.GetItem(id);

if (item != null)

{

MultilistField mf = item.Fields["Templates"];

if (mf != null)

{

foreach (var targetId in mf.TargetIDs)

{

var targetItem = Sitecore.Context.Database.GetItem(targetId);

if (targetItem != null && !string.IsNullOrEmpty(targetItem["Template"]))

{

listContentTypes.Add(targetItem["Template"]);

}

}

}

}

}

}

Page 20: Keep Code Left - How to write better code in almost any language

20

Sample B

public static void KeepCodeLeft()

{

foreach (var id in tmpArr)

{

var item = Sitecore.Context.Database.GetItem(id);

if (item == null)

continue;

MultilistField mf = item.Fields["Templates"];

if (mf == null)

continue;

foreach (var targetId in mf.TargetIDs)

{

var targetItem = Sitecore.Context.Database.GetItem(targetId);

if (targetItem == null || string.IsNullOrEmpty(targetItem["Template"]))

continue;

listContentTypes.Add(targetItem["Template"]);

}

}

}

Page 21: Keep Code Left - How to write better code in almost any language

21

Refactoring for KCL

• If the code is working, think carefully before

refactoring just to satisfy any preferred coding style

– even KCL !

• Refactor when you are modifying the code for another

reason

– Bug fix

– Enhancement

• Whenever you refactor

– TEST

– TEST

– TEST!

Page 22: Keep Code Left - How to write better code in almost any language

22

Lets refactor some real code!

Page 23: Keep Code Left - How to write better code in almost any language

23

Questions?

• Share good examples

• Share problem cases

• Mick Andrew

[email protected]

• http://www.linkedin.com/in/mickan

• http://www.slideshare.net

– Search for “Keep Code Left”