Clean up your code with C#6

45
> < next previous C#6 A cleaner code

Transcript of Clean up your code with C#6

Page 1: Clean up your code with C#6

>< nextprevious

C#6A cleaner code

Page 2: Clean up your code with C#6

Clean up your code!

>< nextprevious

Philosophy design

No New Big features … but many small ones to

to improve your code

Page 3: Clean up your code with C#6

Clean up your code!

>< nextprevious

Put C#6 In context

Let’s see how to improve our code with less boiler plate and more meanings

Page 4: Clean up your code with C#6

>< nextprevious

The language

C#1

async/await ?

var, anonymous, Lambdas, auto-properties, line

Generics, partials, iterators, nullables

C#2

C#4 C#3

C#5 C#6

History

dynamic, optional parameters

2002 2005

2007

20152012

2010

Page 5: Clean up your code with C#6

>< nextprevious

Developers should write their code to fit in a slide

Page 6: Clean up your code with C#6

News

01 Using Static classeswhy bother with static class names?

020304

>< nextprevious

String Interpolationbecause string.format sucks

Getter only propertiesbecause un-meaningful boiler plate

auto-properties initializersbecause creating a backing field for properties only don’t make sense

Page 7: Clean up your code with C#6

>< nextprevious

Using Static 01using System;

public class Code{public void LogTime(string message){

Console.Write(DateTime.Now);Console.WriteLine(message);

}}

Page 8: Clean up your code with C#6

>< nextprevious

Using Static 01using static System.Console;using static System.DateTime;

public class Code{public void Print(string message){

Write(Now);WriteLine(message);

}}

Page 9: Clean up your code with C#6

>< nextprevious

Using Static 01Console.Write(DateTime.Now);

Write(Now);

From a very technical lineYou moved to a natural

language reading friendly sentence

using static allows removal of technical

boilerplate

Page 10: Clean up your code with C#6

>< nextprevious

String Interpolation 02public void UserMessagesLog(string message, User user){

var messageToLog = string.Format("[{0}] {1} - {2}",DateTime.Now,user.Name,message);

Console.WriteLine(messageToLog);}

}

Page 11: Clean up your code with C#6

>< nextprevious

String Interpolation 02public void UserMessagesLog(string message, User user){

var messageToLog = $"[{DateTime.Now}] {User.Name} - {message}" Console.WriteLine(messageToLog);

}}

Page 12: Clean up your code with C#6

>< nextprevious

String Interpolation 02string.Format("[{0}] {1} - {2}",DateTime.Now,user.Name,message);

$"[{DateTime.Now}] {User.Name} - {message}"

sounds good enough for small strings, But…

we’re stupid, when you read the code, there will be a context switch to

interpret the result of your string if the value is not in the place you write it!

Page 13: Clean up your code with C#6

>< nextprevious

String Interpolation 02public void UserMessagesLog(string message, User user){

var messageToLog = $"[{DateTime.Now}] {User.Name} - {message}" Console.WriteLine(messageToLog);

}}

Why waiting 15

years for that?

Page 14: Clean up your code with C#6

>< nextprevious

Getter only properties 03public class Post{private string title;public string Title{get{return title;}

}public Post(string title){this.title=title

}}

C#2

Page 15: Clean up your code with C#6

>< nextprevious

Getter only properties 03public class Post{public string Title { get;private set;}

public Post(string title){Title=title

}}

C#3

Page 16: Clean up your code with C#6

>< nextprevious

Getter only properties 03public class Post{public string Title { get;}

public Post(string title){Title=title

}}

C#6

Page 17: Clean up your code with C#6

>< nextprevious

AutoProperties initializers 04public class Post{private string id="new-post";public string Id{get{return id;}

}public Post(){}

} C#2

Page 18: Clean up your code with C#6

>< nextprevious

AutoProperties initializers 04public class Post{public string Id {get;private set;}public Post(){Id="new-post";

}}

C#3

Page 19: Clean up your code with C#6

>< nextprevious

AutoProperties initializers 04public class Post{public string Id {get;} = "new-post";

}

C#6

Page 20: Clean up your code with C#6

News

05 Expression bodied propertiesbecause one expression is enough

060708

>< nextprevious

Expression bodied methodstoo much braces for a one expression function

Index initializersbecause initializer shortcuts are great

Null conditional operatorsif null then null else arg…

Page 21: Clean up your code with C#6

>< nextprevious

Expression bodied props 05public class Post{private DateTime created = DateTime.Now;public DateTime Created {get{return created;}

}public TimeSpan Elapsed {get {return (DateTime.Now-Created);

}}

}C#3

Page 22: Clean up your code with C#6

>< nextprevious

Expression bodied props 05public class Post{public DateTime Created {get;} = DateTime.Now;

public TimeSpan Elapsed => (DateTime.Now-Created);

}

C#6

Page 23: Clean up your code with C#6

>< nextprevious

Expression bodied props 05public class Post{public DateTime Created {get;} = DateTime.Now;

public DateTime Updated => DateTime;

}

C#6

Spot the difference

{get;} = value is affected once for all, stored in an hidden backing field

=> represents an expression, newly evaluated on each call

Page 24: Clean up your code with C#6

>< nextprevious

Expression Bodied Methods 06public class Post{public string Title {get;set;}public string BuildSlug(){return Title.ToLower().Replace(" ", "-"); 

}}

C#3

Page 25: Clean up your code with C#6

>< nextprevious

Expression Bodied Methods 06public class Post{public string Title {get;set;}public string BuildSlug(){return Title.ToLower().Replace(" ", "-"); 

}}

C#3never been frustrated to have to write this {return}

boilerplate since you use the => construct with lambdas?

Page 26: Clean up your code with C#6

>< nextprevious

Expression Bodied Methods 06public class Post{public string Title {get;set;}public string BuildSlug()=> Title

.ToLower()

.Replace(" ", "-");}

C#6

Page 27: Clean up your code with C#6

>< nextprevious

Index initializers 07public class Author{public Dictionary<string,string> Contacts {get;private set;};

public Author(){

Contacts = new Dictionary<string,string>();Contacts.Add("mail", "[email protected]");Contacts.Add("twitter", "@rhwy");Contacts.Add("github", "@rhwy");

}}

C#2

Page 28: Clean up your code with C#6

>< nextprevious

Index initializers 07public class Author{public Dictionary<string,string> Contacts {get;} = new Dictionary<string,string>() {

["mail"]="[email protected]",["twitter"]="@rhwy",["github"]="@rhwy"

};}

C#6

Page 29: Clean up your code with C#6

>< nextprevious

Index initializers 07public class Author{public Dictionary<string,string> Contacts {get;} = new Dictionary<string,string>() {

{"mail","[email protected]"},{"twitter","@rhwy"},{"github","@rhwy"}

};}

C#3

Page 30: Clean up your code with C#6

>< nextprevious

Null Conditional Operators 08public class Post{

//"rui carvalho"public string Author {get;private set;};//=>"Rui Carvalho"public string GetPrettyName(){

if(Author!=null){

if(Author.Contains(" ")){

string result;var items=Author.Split(" ");forEach(var word in items){

result+=word.SubString(0,1).ToUpper()+word.SubString(1).ToLower()+ " ";

}return result.Trim();

}}return Author;

}}

C#3

Page 31: Clean up your code with C#6

>< nextprevious

Null Conditional Operators 08public class Post{//"rui carvalho"public string Author {get;private set;};//=>"Rui Carvalho"

public string GetPrettyName()=> (string.Join("",

Author?.Split(' ').ToList().Select( word=>

word.Substring(0,1).ToUpper()+word.Substring(1).ToLower()+ " ")

)).Trim();

C#6

Page 32: Clean up your code with C#6

>< nextprevious

Null Conditional Operators 08public class Post{//"rui carvalho"public string Author {get;private set;};//=>"Rui Carvalho"

public string GetPrettyName()=> (string.Join("",

Author?.Split(' ').ToList().Select( word=>

word.Substring(0,1).ToUpper()+word.Substring(1).ToLower()+ " ")

)).Trim();

C#6

We have now one expression only but

maybe not that clear or testable ?

Page 33: Clean up your code with C#6

>< nextprevious

Null Conditional Operators 08public string PrettifyWord (string word) =>

word.Substring(0,1).ToUpper()+word.Substring(1).ToLower()+ " ";

public IEnumerable<string> PrettifyTextIfExists(string phrase)=> phrase?

.Split(' ')

.Select( PrettifyWord);

public string GetPrettyName()=> string

.Join("",PrettifyTextIfExists(Author))

.Trim();

C#6

Refactoring !

We have now 3 small independent functions with

Names and meanings

Page 34: Clean up your code with C#6

News

09 Exception filtersnot new in .Net

101112

>< nextprevious

nameof Operatorconsistent refactorings

await in catchwho never complained about that?

and in finallythe last step

Page 35: Clean up your code with C#6

News

09 Exception filtersnot new in .Net

101112

>< nextprevious

nameof Operatorconsistent refactorings

await in catchwho never complained about that?

and in finallythe last step

these ones are just good improvements but not that important for our code readability

Page 36: Clean up your code with C#6

>< nextprevious

Exception Filters 09try { //production code

} catch (HttpException ex){ if(ex.StatusCode==500) //do some specific crash scenario if(ex.StatusCode==400)//tell client that he’s stupid

}catch (Exception otherErrors) { // ...

}

C#2

Page 37: Clean up your code with C#6

>< nextprevious

Exception Filters 09try { //production code

} catch (HttpException ex) when (ex.StatusCode == 500) { //do some specific crash scenario }catch (HttpException ex) when (ex.StatusCode == 400) { //tell the client he’s stupid } catch (Exception otherException) { // ...

}

C#6

Page 38: Clean up your code with C#6

>< nextprevious

nameof Operator 10public string SomeMethod (string word) {if(word == null)throw new Exception("word is null");

return word;}

C#3

Page 39: Clean up your code with C#6

>< nextprevious

nameof Operator 10public string SomeMethod (string text) {if(word == null)throw new Exception("word is null");

return word;}

C#3

Refactoringarg, information

lost!

Page 40: Clean up your code with C#6

>< nextprevious

nameof Operator 10public string SomeMethod (string word) {if(word == null)throw new Exception($"{nameof(word)} is null");

return word;}

C#6

parameter name is now pure code & support refactoring

Page 41: Clean up your code with C#6

>< nextprevious

await in catch 11try { return await something();

} catch (HttpException ex){ error = ex;}return await CrashLogger.ServerError(error);

C#5

Page 42: Clean up your code with C#6

>< nextprevious

await in catch 11try { await something();

} catch (HttpException ex){ await CrashLogger.ServerError(ex);}

C#6

Page 43: Clean up your code with C#6

>< nextprevious

await in finally 12try { return await Persistence.Query(query);

} catch (PersistenceException ex){ await CrashLogger.ServerError(ex);} finally{ await Persistence.Close();

} C#6

Page 44: Clean up your code with C#6

>< nextprevious

To FinishC#6 helps to be more functional & write cleaner code by

removing lots of boilerplate!

refactoring to small functions, add new words to

your app vocabulary

Page 45: Clean up your code with C#6

>< nextprevious

Thanks

@rhwy

ncrafts.ioaltnet.fr

rui.io