Slide 1

Slide 1 text

Trust Your Code @TheQuinnGil QuinnGil.com Seattle Code Camp 2019

Slide 2

Slide 2 text

Quinn Gil Software Development Coach International Speaker on Software Development Past 15 years focused on High Quality code Blog at QuinnGil.com @TheQuinnGil QuinnGil.com

Slide 3

Slide 3 text

This is for you. @TheQuinnGil QuinnGil.com

Slide 4

Slide 4 text

Trust Your Code @TheQuinnGil QuinnGil.com

Slide 5

Slide 5 text

“Untrusted Code”? @TheQuinnGil QuinnGil.com

Slide 6

Slide 6 text

Untrusted Code - Defensive Code ● Defend the Method Perspective ○ PreConditions ○ Nulls ○ Assertions @TheQuinnGil QuinnGil.com

Slide 7

Slide 7 text

Untrusted Code - Defenses ● Defend the Method Perspective ○ PreConditions ○ Nulls ○ Assertions ● Defend the Caller Perspective ○ State Verification ○ Exception Handling ○ OK to call @TheQuinnGil QuinnGil.com

Slide 8

Slide 8 text

Untrusted Code - Defenses ● Defend the Method Perspective ○ PreConditions ○ Nulls ○ Assertions ● Defend the Caller Perspective ○ State Verification ○ Exception Handling ○ OK to call ● Defend the Using Perspective ○ Null ○ Ready ○ Valid @TheQuinnGil QuinnGil.com

Slide 9

Slide 9 text

Is “Defensive Code” really that bad? @TheQuinnGil QuinnGil.com

Slide 10

Slide 10 text

Why not “Defensive Code”? ● A defense somewhere is a defense everywhere @TheQuinnGil QuinnGil.com

Slide 11

Slide 11 text

Why not “Defensive Code”? ● A defense somewhere is a defense everywhere ● Complicates the code @TheQuinnGil QuinnGil.com

Slide 12

Slide 12 text

Why not “Defensive Code”? ● A defense somewhere is a defense everywhere ● Complicates the code ● Higher Cognitive Load @TheQuinnGil QuinnGil.com

Slide 13

Slide 13 text

Why not “Defensive Code”? ● A defense somewhere is a defense everywhere ● Complicates the code ● Higher Cognitive Load ● Write more code @TheQuinnGil QuinnGil.com

Slide 14

Slide 14 text

Why not “Defensive Code”? ● A defense somewhere is a defense everywhere ● Complicates the code ● Higher Cognitive Load ● Write more code ● Maintain more code @TheQuinnGil QuinnGil.com

Slide 15

Slide 15 text

Why not “Defensive Code”? ● A defense somewhere is a defense everywhere ● Complicates the code ● Higher Cognitive Load ● Write more code ● Maintain more code ● Dead Code? Undetectable? @TheQuinnGil QuinnGil.com

Slide 16

Slide 16 text

How do we protect the code? @TheQuinnGil QuinnGil.com

Slide 17

Slide 17 text

How do we protect the code? @TheQuinnGil QuinnGil.com I don’t

Slide 18

Slide 18 text

How do we protect the code? @TheQuinnGil QuinnGil.com I don’t... directly.

Slide 19

Slide 19 text

Trust Your Code with Technical Practices @TheQuinnGil QuinnGil.com

Slide 20

Slide 20 text

Trusting Your Code is Sustainable Code @TheQuinnGil QuinnGil.com

Slide 21

Slide 21 text

Sustainable Code through Technical Practices @TheQuinnGil QuinnGil.com

Slide 22

Slide 22 text

Sustainable Code through Technical Practices @TheQuinnGil QuinnGil.com

Slide 23

Slide 23 text

Sustainable Code through Technical Practices @TheQuinnGil QuinnGil.com

Slide 24

Slide 24 text

Tests @TheQuinnGil QuinnGil.com

Slide 25

Slide 25 text

Sustainable Code through Technical Practices ● No Getters / No Setters ● `if` Only As Guard Clause ● Isolate Their Code ● Never `null` ● No `new` inline ● Composition, Not Inheritance ● ● Be Immutable ● No Primitives ● Extract Cohesion ● No Public Statics ● Never Reflection @TheQuinnGil QuinnGil.com

Slide 26

Slide 26 text

Sustainable Code through Technical Practices Isolate Their Code @TheQuinnGil QuinnGil.com ● No Getters / No Setters ● `if` Only As Guard Clause ● Isolate Their Code ● Never `null` ● No `new` inline ● Composition, Not Inheritance ● ● Be Immutable ● No Primitives ● Extract Cohesion ● No Public Statics ● Never Reflection

Slide 27

Slide 27 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { HttpClient httpClient = new HttpClient(); HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.Content.ReadAsStringAsync(); JObject jsonContent = JObject.Parse(readAsStringAsync); string value = jsonContent.Value("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 28

Slide 28 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { //COUPLING HttpClient httpClient = new HttpClient(); HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.Content.ReadAsStringAsync(); JObject jsonContent = JObject.Parse(readAsStringAsync); string value = jsonContent.Value("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 29

Slide 29 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { //COUPLING HttpClient httpClient = new HttpClient(); //EXCEPTION HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.Content.ReadAsStringAsync(); JObject jsonContent = JObject.Parse(readAsStringAsync); string value = jsonContent.Value("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 30

Slide 30 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { //COUPLING HttpClient httpClient = new HttpClient(); //EXCEPTION HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.Content.ReadAsStringAsync(); //EXCEPTION, COUPLING JObject jsonContent = JObject.Parse(readAsStringAsync); string value = jsonContent.Value("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 31

Slide 31 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { //COUPLING HttpClient httpClient = new HttpClient(); //EXCEPTION HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.Content.ReadAsStringAsync(); //EXCEPTION, COUPLING JObject jsonContent = JObject.Parse(readAsStringAsync); //IMPERATIVE string value = jsonContent.Value("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 32

Slide 32 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { //COUPLING HttpClient httpClient = new HttpClient(); //EXCEPTION HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.Content.ReadAsStringAsync(); //EXCEPTION, COUPLING JObject jsonContent = JObject.Parse(readAsStringAsync); //IMPERATIVE string value = jsonContent.Value("some_key"); //EXCEPTION return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 33

Slide 33 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { HttpClient httpClient = new HttpClient(); HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.Content.ReadAsStringAsync(); JObject jsonContent = JObject.Parse(readAsStringAsync); string value = jsonContent.Value("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 34

Slide 34 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { IHttpClientBookEnd httpClient = new HttpClientFacade(); HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.Content.ReadAsStringAsync(); JObject jsonContent = JObject.Parse(readAsStringAsync); string value = jsonContent.Value("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 35

Slide 35 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { IHttpClientBookEnd httpClient = new HttpClientFacade(); IHttpResponseMessageBookEnd httpResponseMessage = await httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.Content.ReadAsStringAsync(); JObject jsonContent = JObject.Parse(readAsStringAsync); string value = jsonContent.Value("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 36

Slide 36 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { IHttpClientBookEnd httpClient = new HttpClientFacade(); IHttpResponseMessageBookEnd httpResponseMessage = await httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.ContentAsStringAsync(); JObject jsonContent = JObject.Parse(readAsStringAsync); string value = jsonContent.Value("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 37

Slide 37 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { IHttpResponseMessageBookEnd httpResponseMessage = await _httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.ContentAsStringAsync(); JObject jsonContent = JObject.Parse(readAsStringAsync); string value = jsonContent.Value("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 38

Slide 38 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { IHttpResponseMessageBookEnd httpResponseMessage = await _httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.ContentAsStringAsync(); IParsedObject parsedObject = _parser.Parse(readAsStringAsync); string value = parsedObject.StringValue("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 39

Slide 39 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { IHttpResponseMessageBookEnd httpResponseMessage = await _httpClient.SendAsync(r); IParsedObject parsedObject = await httpResponseMessage.ParsedContent(_parser); string value = parsedObject.StringValue("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 40

Slide 40 text

Technical Practices - Isolate Their Code - 3rd Party public async Task NetworkCall(HttpRequestMessage r) { HttpClient httpClient = new HttpClient(); HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(r); string readAsStringAsync = await httpResponseMessage.Content.ReadAsStringAsync(); JObject jsonContent = JObject.Parse(readAsStringAsync); string value = jsonContent.Value("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } public async Task NetworkCall(HttpRequestMessage r) { IHttpResponseMessageBookEnd httpResponseMessage = await _httpClient.SendAsync(r); IParsedObject parsedObject = await httpResponseMessage.ParsedContent(_parser); string value = parsedObject.StringValue("some_key"); return value.Contains("expected_Value") ? "Success" : "Failure"; } @TheQuinnGil QuinnGil.com

Slide 41

Slide 41 text

What Else? Technical Practices - Isolate Their Code @TheQuinnGil QuinnGil.com

Slide 42

Slide 42 text

Operating System Technical Practices - Isolate Their Code @TheQuinnGil QuinnGil.com

Slide 43

Slide 43 text

How? Technical Practices - Isolate Their Code @TheQuinnGil QuinnGil.com

Slide 44

Slide 44 text

Technical Practices - Isolate Their Code - How? internal class HttpClientFacade : IHttpClientBookEnd { private static HttpClient _testClient; #if DEBUG public static void SetTestClient(HttpClient testClient) => _testClient = testClient; #endif private readonly HttpClient _httpClient; public HttpClientFacade() : this(new HttpClient()) { } private HttpClientFacade(HttpClient httpClient) => _httpClient = httpClient; public async Task SendRequestAsync(HttpRequestMessage msg) => new HttpResponseMessageAdapter(await HttpClient().SendAsync(msg)); private HttpClient HttpClient() => _testClient ?? _httpClient; } @TheQuinnGil QuinnGil.com

Slide 45

Slide 45 text

Technical Practices - Isolate Their Code - How? internal class HttpClientFacade : IHttpClientBookEnd { private static HttpClient _testClient; #if DEBUG public static void SetTestClient(HttpClient testClient) => _testClient = testClient; #endif private readonly HttpClient _httpClient; public HttpClientFacade() : this(new HttpClient()) { } private HttpClientFacade(HttpClient httpClient) => _httpClient = httpClient; public async Task SendRequestAsync(HttpRequestMessage msg) => new HttpResponseMessageAdapter(await HttpClient().SendAsync(msg)); private HttpClient HttpClient() => _testClient ?? _httpClient; } @TheQuinnGil QuinnGil.com

Slide 46

Slide 46 text

Technical Practices - Isolate Their Code - How? internal class HttpClientFacade : IHttpClientBookEnd { private static HttpClient _testClient; #if DEBUG public static void SetTestClient(HttpClient testClient) => _testClient = testClient; #endif private readonly HttpClient _httpClient; public HttpClientFacade() : this(new HttpClient()) { } private HttpClientFacade(HttpClient httpClient) => _httpClient = httpClient; public async Task SendRequestAsync(HttpRequestMessage msg) => new HttpResponseMessageAdapter(await HttpClient().SendAsync(msg)); private HttpClient HttpClient() => _testClient ?? _httpClient; } @TheQuinnGil QuinnGil.com

Slide 47

Slide 47 text

Technical Practices - Isolate Their Code - How? internal class HttpClientFacade : IHttpClientBookEnd { private static HttpClient _testClient; #if DEBUG public static void SetTestClient(HttpClient testClient) => _testClient = testClient; #endif private readonly HttpClient _httpClient; public HttpClientFacade() : this(new HttpClient()) { } private HttpClientFacade(HttpClient httpClient) => _httpClient = httpClient; public async Task SendRequestAsync(HttpRequestMessage msg) => new HttpResponseMessageAdapter(await HttpClient().SendAsync(msg)); private HttpClient HttpClient() => _testClient ?? _httpClient; } @TheQuinnGil QuinnGil.com

Slide 48

Slide 48 text

User Interface Technical Practices - Isolate Their Code @TheQuinnGil QuinnGil.com

Slide 49

Slide 49 text

Sustainable Code through Technical Practices Isolate Their Code @TheQuinnGil QuinnGil.com ● No Getters / No Setters ● `if` Only As Guard Clause ● Isolate Their Code ● Never `null` ● No `new` inline ● Composition, Not Inheritance ● ● Be Immutable ● No Primitives ● Extract Cohesion ● No Public Statics ● Never Reflection Trust Your Code by controlling interactions with 3rd Party Code

Slide 50

Slide 50 text

Sustainable Code through Technical Practices Never `null` @TheQuinnGil QuinnGil.com ● No Getters / No Setters ● `if` Only As Guard Clause ● Isolate Their Code ● Never `null` ● No `new` inline ● Composition, Not Inheritance ● ● Be Immutable ● No Primitives ● Extract Cohesion ● No Public Statics ● Never Reflection

Slide 51

Slide 51 text

Why? Technical Practices - Never `null` @TheQuinnGil QuinnGil.com

Slide 52

Slide 52 text

How? Technical Practices - Never `null` @TheQuinnGil QuinnGil.com

Slide 53

Slide 53 text

Technical Practices - Never `null` public string CalculateThing(ICanBeNull canBeNull) { if (canBeNull == null) return "Default"; IAlsoNull alsoNull = canBeNull.Example(); if (alsoNull == null) return "Default"; string sample = alsoNull.Sample(); if (sample == null) return "Default"; return sample; } @TheQuinnGil QuinnGil.com

Slide 54

Slide 54 text

Technical Practices - Never `null` public string CalculateThing(ICanBeNull canBeNull) { if (canBeNull == null) return "Default"; IAlsoNull alsoNull = canBeNull.Example(); if (alsoNull == null) return "Default"; string sample = alsoNull.Sample(); if (sample == null) return "Default"; return sample; } public string CalculateThing(ICanBeNull canBeNull) { return canBeNull?.Example()?.Sample() ?? "Default"; } @TheQuinnGil QuinnGil.com

Slide 55

Slide 55 text

Technical Practices - Never `null` public string CalculateThing(ICanBeNull canBeNull) { if (canBeNull == null) return "Default"; IAlsoNull alsoNull = canBeNull.Example(); if (alsoNull == null) return "Default"; string sample = alsoNull.Sample(); if (sample == null) return "Default"; return sample; } public string CalculateThing(ICanBeNull canBeNull) { return canBeNull?.Example()?.Sample() ?? "Default"; } public string CalculateThing(ICanNotBeNull canNotBeNull) { return canNotBeNull.Example().Sample(); } @TheQuinnGil QuinnGil.com

Slide 56

Slide 56 text

Technical Practices - Never `null` public string CalculateThing(ICanBeNull canBeNull) { if (canBeNull == null) return "Default"; IAlsoNull alsoNull = canBeNull.Example(); if (alsoNull == null) return "Default"; string sample = alsoNull.Sample(); if (sample == null) return "Default"; return sample; } public string CalculateThing(ICanBeNull canBeNull) { return canBeNull?.Example()?.Sample() ?? "Default"; } public string CalculateThing(ICanNotBeNull canNotBeNull) { return canNotBeNull.Example().Sample(); } public void Foo() { string thing = _bar.CalculateThing(_canBeNull); //... } @TheQuinnGil QuinnGil.com

Slide 57

Slide 57 text

Technical Practices - Never `null` public string CalculateThing(ICanBeNull canBeNull) { if (canBeNull == null) return "Default"; IAlsoNull alsoNull = canBeNull.Example(); if (alsoNull == null) return "Default"; string sample = alsoNull.Sample(); if (sample == null) return "Default"; return sample; } public string CalculateThing(ICanBeNull canBeNull) { return canBeNull?.Example()?.Sample() ?? "Default"; } public string CalculateThing(ICanNotBeNull canNotBeNull) { return canNotBeNull.Example().Sample(); } public void Foo() { string thing = _bar.CalculateThing(_canBeNull); //... } public void Foo() { string thing = _canNotBeNull.Example().Sample(); //... } @TheQuinnGil QuinnGil.com

Slide 58

Slide 58 text

Technical Practices - Never `null` public class NullObject : ICanNotBeNull { public IAlsoNotNull Example() => new NullObjectAlso(); } public class NullObjectAlso : IAlsoNotNull { public string Sample() => "Default"; } public string CalculateThing(ICanBeNull canBeNull) { if (canBeNull == null) return "Default"; IAlsoNull alsoNull = canBeNull.Example(); if (alsoNull == null) return "Default"; string sample = alsoNull.Sample(); if (sample == null) return "Default"; return sample; } public void Foo() { string thing = _canNotBeNull.Example().Sample(); //... } @TheQuinnGil QuinnGil.com

Slide 59

Slide 59 text

Sustainable Code through Technical Practices Never `null` @TheQuinnGil QuinnGil.com ● No Getters / No Setters ● `if` Only As Guard Clause ● Isolate Their Code ● Never `null` ● No `new` inline ● Composition, Not Inheritance ● ● Be Immutable ● No Primitives ● Extract Cohesion ● No Public Statics ● Never Reflection Trust Your Code by always having valid objects

Slide 60

Slide 60 text

Sustainable Code through Technical Practices No Primitives @TheQuinnGil QuinnGil.com ● No Getters / No Setters ● `if` Only As Guard Clause ● Isolate Their Code ● Never `null` ● No `new` inline ● Composition, Not Inheritance ● ● Be Immutable ● No Primitives ● Extract Cohesion ● No Public Statics ● Never Reflection

Slide 61

Slide 61 text

Primitives? Technical Practices - No Primitives @TheQuinnGil QuinnGil.com

Slide 62

Slide 62 text

Technical Practices - What are Primitives? ● Data (string, int, double, float, ...) @TheQuinnGil QuinnGil.com

Slide 63

Slide 63 text

Technical Practices - What are Primitives? ● Data (string, int, double, float, ...) ● Collections (List, Map, Dictionary, ...) @TheQuinnGil QuinnGil.com

Slide 64

Slide 64 text

Technical Practices - What are Primitives? ● Data (string, int, double, float, ...) ● Collections (List, Map, Dictionary, ...) ● Enums @TheQuinnGil QuinnGil.com

Slide 65

Slide 65 text

Technical Practices - What are Primitives? ● Data (string, int, double, float, ...) ● Collections (List, Map, Dictionary, ...) ● Enums ● More? @TheQuinnGil QuinnGil.com

Slide 66

Slide 66 text

Why not Primitives? Technical Practices - No Primitives @TheQuinnGil QuinnGil.com

Slide 67

Slide 67 text

● Object oriented programming wants object interaction, not data manipulation Technical Practices - Why No Primitives? @TheQuinnGil QuinnGil.com

Slide 68

Slide 68 text

● Object oriented programming wants object interaction, not data manipulation ● Primitives are data, not objects Technical Practices - Why No Primitives? @TheQuinnGil QuinnGil.com

Slide 69

Slide 69 text

● Object oriented programming wants object interaction, not data manipulation ● Primitives are data, not objects ● Primitives force complex imperative code Technical Practices - Why No Primitives? @TheQuinnGil QuinnGil.com

Slide 70

Slide 70 text

● Object oriented programming wants object interaction, not data manipulation ● Primitives are data, not objects ● Primitives force complex imperative code ● Primitives hinder Emergent Design Technical Practices - Why No Primitives? @TheQuinnGil QuinnGil.com

Slide 71

Slide 71 text

● Object oriented programming wants object interaction, not data manipulation ● Primitives are data, not objects ● Primitives force complex imperative code ● Primitives hinder Evolutionary Architecture ● Primitives limit use of Design Patterns Technical Practices - Why No Primitives? @TheQuinnGil QuinnGil.com

Slide 72

Slide 72 text

Instead? Technical Practices - No Primitives @TheQuinnGil QuinnGil.com

Slide 73

Slide 73 text

Represent the Concept Technical Practices - No Primitives @TheQuinnGil QuinnGil.com

Slide 74

Slide 74 text

Technical Practices - No Primitives - Age Example public bool ThirteenOrLess(DataPerson person) { DateTime birthDate = DateTime.Parse(person.BirthDate); int age = DateTime.Now.Year - birthDate.Year; /* is this right?*/ return age <= 13; } @TheQuinnGil QuinnGil.com

Slide 75

Slide 75 text

public bool ThirteenOrLess(DataPerson person) { DateTime birthDate = DateTime.Parse(person.BirthDate); int age = DateTime.Now.Year - birthDate.Year; if (birthDate.Date > DateTime.Now.AddYears(-age)) age--; return age <= 13; } @TheQuinnGil QuinnGil.com Technical Practices - No Primitives - Age Example

Slide 76

Slide 76 text

public bool ThirteenOrLess(DataPerson person) { DateTime birthDate = DateTime.Parse(person.BirthDate); int age = DateTime.Now.Year - birthDate.Year; if (birthDate.Date > DateTime.Now.AddYears(-age)) age--; switch (person.State) { case "WA": return age <= 13; case "AK": return age <= 14; } return false; } @TheQuinnGil QuinnGil.com Technical Practices - No Primitives - Age Example

Slide 77

Slide 77 text

public bool IsMinor(DataPerson person) { DateTime birthDate = DateTime.Parse(person.BirthDate); int age = DateTime.Now.Year - birthDate.Year; if (birthDate.Date > DateTime.Now.AddYears(-age)) age--; switch (person.State) { case "WA": return age <= 13; case "AK": return age <= 14; } return false; } @TheQuinnGil QuinnGil.com Technical Practices - No Primitives - Age Example

Slide 78

Slide 78 text

public class Age : IAge { public bool IsMinor() { DateTime birthDate = DateTime.Parse(_birthdate); int age = DateTime.Now.Year - birthDate.Year; if (birthDate.Date > DateTime.Now.AddYears(-age)) age--; switch (_state) { case "WA": return age <= 13; case "AK": return age <= 14; } return false; } } @TheQuinnGil QuinnGil.com Technical Practices - No Primitives - Age Example

Slide 79

Slide 79 text

public class Age : IAge { public bool IsMinor() { DateTime birthDate = DateTime.Parse(_birthdate); int age = DateTime.Now.Year - birthDate.Year; if (birthDate.Date > DateTime.Now.AddYears(-age)) age--; switch (_state) { case "WA": return age <= 13; case "AK": return age <= 14; } return false; } } public class Person { private readonly string _birthdate; private readonly string _state; public IAge Age() => new Age(_birthdate, _state); } @TheQuinnGil QuinnGil.com Technical Practices - No Primitives - Age Example

Slide 80

Slide 80 text

public class Age : IAge { public bool IsMinor() { DateTime birthDate = DateTime.Parse(_birthdate); int age = DateTime.Now.Year - birthDate.Year; if (birthDate.Date > DateTime.Now.AddYears(-age)) age--; return age <= _state.MinorAge(); } } public class Person { private readonly string _birthdate; private readonly State _state; public IAge Age() => new Age(_birthdate, _state); } @TheQuinnGil QuinnGil.com Technical Practices - No Primitives - Age Example

Slide 81

Slide 81 text

Technical Practices - No Primitives - Age Example @TheQuinnGil QuinnGil.com Represent the Concept

Slide 82

Slide 82 text

Technical Practices - No Primitives - Units public float Convert(float value) @TheQuinnGil QuinnGil.com

Slide 83

Slide 83 text

Technical Practices - No Primitives - Units public float Convert(float value) { return value * 1.609334f; } @TheQuinnGil QuinnGil.com

Slide 84

Slide 84 text

Technical Practices - No Primitives - Units public float Convert(float value) { return value * 1.609334f; } Money? @TheQuinnGil QuinnGil.com

Slide 85

Slide 85 text

Technical Practices - No Primitives - Units public float Convert(float value) { return value * 1.609334f; } Money? Distance? @TheQuinnGil QuinnGil.com

Slide 86

Slide 86 text

Technical Practices - No Primitives - Units public float Convert(float value) { return value * 1.609334f; } @TheQuinnGil QuinnGil.com Money? Distance? Convert To? From?

Slide 87

Slide 87 text

Technical Practices - No Primitives - Units public float Convert(float distance) { return distance * 1.609334f; } Missing Meta Data Convert To? From? @TheQuinnGil QuinnGil.com Money? Distance?

Slide 88

Slide 88 text

Technical Practices - No Primitives - Units public class Distance ... distance.ToKilometer(); ... With Meta Data @TheQuinnGil QuinnGil.com

Slide 89

Slide 89 text

Technical Practices - No Primitives - Age Example @TheQuinnGil QuinnGil.com Represent the Concept

Slide 90

Slide 90 text

Sustainable Code through Technical Practices No Primitives @TheQuinnGil QuinnGil.com Trust Your Code by having objects represent the concepts in the code ● No Getters / No Setters ● `if` Only As Guard Clause ● Isolate Their Code ● Never `null` ● No `new` inline ● Composition, Not Inheritance ● ● Be Immutable ● No Primitives ● Extract Cohesion ● No Public Statics ● Never Reflection

Slide 91

Slide 91 text

Sustainable Code through Technical Practices @TheQuinnGil QuinnGil.com ● No Getters / No Setters ● `if` Only As Guard Clause ● Isolate Their Code ● Never `null` ● No `new` inline ● Composition, Not Inheritance ● ● Be Immutable ● No Primitives ● Extract Cohesion ● No Public Statics ● Never Reflection

Slide 92

Slide 92 text

Feature Parity in 25% of the Dev Hours @TheQuinnGil QuinnGil.com

Slide 93

Slide 93 text

THANK YOU! @TheQuinnGil QuinnGil.com

Slide 94

Slide 94 text

Sustainable Code through Technical Practices ● No Getters / No Setters ● `if` Only As Guard Clause ● Isolate Their Code ● Never `null` ● No `new` inline ● Composition, Not Inheritance ● ● Be Immutable ● No Primitives ● Extract Cohesion ● No Public Statics ● Never Reflection @TheQuinnGil QuinnGil.com