Technical Practices for Sustainable Code

Technical Practices for Sustainable Code

Highly maintainable code is hard to produce.
Without maintainability we can not have sustainable code, it will rot and have to be re-written. As an industry we're often given principles to follow which sound FANTASTIC... but don't layout the "how" of reaching these ideals.
We'll go into detail of four technical practices that have the biggest impact towards improving maintainability of the code we write.
As agile developers, what we want to do is deliver value to the customer quickly and consistently. As an agile developer and team, coding technical practices are the only way to develop code to quickly and consistently deliver value to the customer for the life of the product.
These technical practices produce simple, understandable, testable code which results in extremely maintainable code that we'll be able to enjoy working on for a long time.

5b92c5ea42bc2c2ab28d973d5da63cd6?s=128

Quinn

May 23, 2019
Tweet

Transcript

  1. Feature Parity in 25% of the Dev Hours with Technical

    Practices for Sustainable Code @TheQuinnGil QuinnGil.com
  2. Feature Parity in 25% of the Dev Hours @TheQuinnGil QuinnGil.com

  3. @TheQuinnGil QuinnGil.com Technical Practices for Sustainable Code

  4. Quinn Gil Blog -- QuinnGil.com Twitter -- TheQuinnGil Github --

    Fyzxs @TheQuinnGil QuinnGil.com
  5. This is for you.

  6. Sustainable Code through Technical Practices @TheQuinnGil QuinnGil.com

  7. Sustainable Code through Technical Practices @TheQuinnGil QuinnGil.com

  8. Sustainable Code through Technical Practices @TheQuinnGil QuinnGil.com

  9. Tests

  10. 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 • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection @TheQuinnGil QuinnGil.com
  11. 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 • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection No Getters / No Setters @TheQuinnGil QuinnGil.com
  12. Technical Practices - No Getters / No Setters class FizzBuzzBag

    { public int Input { get; set; } public string Result { get; set; } } class FizzBuzzBag: def __init__(self): self._result = None self._input = None @property def result(self): return self._result @result.setter def result(self, value): self._result = value @property def input(self): return self._input @input.setter def input(self, value): self._input = value class FizzBuzzBag{ private int input; private String result; public String getResult(){ return result; } public void setResult(String value){ result = value; } public int getInput(){ return input; } public void setInput(int value){ input = value; } } class FizzBuzzBag attr_accessor :input attr_accessor :result end
  13. Technical Practices - No Getters / No Setters No Way

  14. No Getters / No Setters Technical Practices

  15. Technical Practices - No Getters Why No Getters?

  16. Technical Practices - No Setters Why No Setters?

  17. Technical Practices - No Getters / No Setters How?

  18. No Getters / No Setters - How? The Class Does

    It
  19. Technical Practices - No Getters / No Setters public class

    FizzBuzz{ public int Input { get; set; } public string Result { get; set; } } public static class FizzBuzzUtils{ public static void Calculate(FizzBuzz fb){ if (fb.Input % 3 == 0){ fb.Result = "Fizz"; } if (fb.Input % 5 == 0){ if (fb.Result == null){ fb.Result = "Buzz"; } else { fb.Result += "Buzz"; } } if (string.IsNullOrEmpty(fb.Result)){ fb.Result = fb.Input.ToString(); } } }
  20. Technical Practices - No Getters / No Setters public class

    FizzBuzz{ private readonly int _input; public FizzBuzz(int input) => _input = input; public string Result(){ string result = null; if (_input % 3 == 0) result = "Fizz"; if (_input % 5 == 0){ if (result == null) result = "Buzz"; else result += "Buzz"; } if (string.IsNullOrEmpty(result)){ result = _input.ToString(); } return result; } } public class FizzBuzz{ public int Input { get; set; } public string Result { get; set; } } public static class FizzBuzzUtils{ public static void Calculate(FizzBuzz fb){ if (fb.Input % 3 == 0){ fb.Result = "Fizz"; } if (fb.Input % 5 == 0){ if (fb.Result == null){ fb.Result = "Buzz"; } else { fb.Result += "Buzz"; } } if (string.IsNullOrEmpty(fb.Result)){ fb.Result = fb.Input.ToString(); } } }
  21. Technical Practices - No Getters / No Setters Benefits

  22. Sustainable Code through Technical Practices No Getters / No Setters

    @TheQuinnGil QuinnGil.com • No Getters / No Setters • `if` Only As Guard Clause • Isolate Their Code • Never `null` • No `new` inline • Composition, Not Inheritance • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection
  23. 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 • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection `if` Only As Guard Clause @TheQuinnGil QuinnGil.com
  24. Technical Practices - `if` Only As Guard Clause No Way

  25. Technical Practices - `if` Only As Guard Clause Default Path

  26. `if` Only As Guard Clause - Default Path public class

    FizzBuzz{ private readonly int _input; public FizzBuzz(int input) => _input = input; public string Result(){ string result = null; if (_input % 3 == 0) result = "Fizz"; if (_input % 5 == 0){ if (result == null) result = "Buzz"; else result += "Buzz"; } if (string.IsNullOrEmpty(result)){ result = _input.ToString(); } return result; } }
  27. public class FizzBuzz{ private readonly int _input; public FizzBuzz(int input)

    => _input = input; public string Result(){ string result = null; if (_input % 3 == 0) result = "Fizz"; if (_input % 5 == 0){ if (result == null) result = "Buzz"; else result += "Buzz"; } if (string.IsNullOrEmpty(result)){ result = _input.ToString(); } return result; } } `if` Only As Guard Clause - Default Path public class FizzBuzz{ private int _input; public FizzBuzz(int input) => _input = input; public string Result(){ if (_input % 15 == 0) return "FizzBuzz"; if (_input % 3 == 0) return "Fizz"; if (_input % 5 == 0) return "Buzz"; return _input.ToString(); } }
  28. Technical Practices - `if` Only As Guard Clause Cascading Changes

  29. Technical Practices - `if` Only As Guard Clause Cascading Changes

    switch and else - always evil
  30. Technical Practices - `if` Only As Guard Clause How?

  31. `if` Only As Guard Clause - Default Path public class

    FizzBuzz{ private int _input; public FizzBuzz(int input) => _input = input; public string Result(){ if (_input % 15 == 0) return "FizzBuzz"; if (_input % 3 == 0) return "Fizz"; if (_input % 5 == 0) return "Buzz"; return _input.ToString(); } } public class FizzBuzz{ private readonly int _input; public FizzBuzz(int input) => _input = input; public string Result(){ string result = null; if (_input % 3 == 0) result = "Fizz"; if (_input % 5 == 0){ if (result == null) result = "Buzz"; else result += "Buzz"; } if (string.IsNullOrEmpty(result)){ result = _input.ToString(); } return result; } }
  32. Sustainable Code through Technical Practices `if` Only As Guard Clause

    @TheQuinnGil QuinnGil.com • No Getters / No Setters • `if` Only As Guard Clause • Isolate Their Code • Never `null` • No `new` inline • Composition, Not Inheritance • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection
  33. 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 • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection Isolate Their Code @TheQuinnGil QuinnGil.com
  34. Technical Practices - Isolate Their Code - 3rd Party public

    class FizzBuzz{ private readonly string _input; public FizzBuzz(string input) => _input = input; public string Result(){ JObject jObject = JObject.Parse(_input); int input = jObject.Value<int>("number"); if (IsFizzBuzz(input)) return "FizzBuzz"; if (IsFizz(input)) return "Fizz"; if (IsBuzz(input)) return "Buzz"; return input.ToString(); } }
  35. Technical Practices - Isolate Their Code - 3rd Party public

    class FizzBuzz{ private readonly string _input; private readonly IParser _parser; public string Result(){ IParsedObject pObject = _parser.Parse(_input); int input = pObject.IntValue("input"); if (IsFizzBuzz(input)) return "FizzBuzz"; if (IsFizz(input)) return "Fizz"; if (IsBuzz(input)) return "Buzz"; return input.ToString(); } }
  36. What Else? Technical Practices - Isolate Their Code

  37. Operating System Technical Practices - Isolate Their Code

  38. How? Technical Practices - Isolate Their Code

  39. Technical Practices - Isolate Their Code - How? internal class

    HttpClientBookEnd : IHttpClientBookEnd { private static HttpClient _testClient; #if DEBUG public static void SetTestClient(HttpClient testClient) => _testClient = testClient; #endif private readonly HttpClient _httpClient; public HttpClientBookEnd() : this(new HttpClient()) { } private HttpClientBookEnd(HttpClient httpClient) => _httpClient = httpClient; public void SendRequestAsync(HttpRequestMessage msg) => HttpClient().SendAsync(msg); private HttpClient HttpClient() => _testClient ?? _httpClient; }
  40. User Interface Technical Practices - Isolate Their Code

  41. 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 • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection
  42. 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 • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection Never `null` @TheQuinnGil QuinnGil.com
  43. Why? Technical Practices - Never `null`

  44. How? Technical Practices - Never `null`

  45. 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; }
  46. 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"; }
  47. 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(); }
  48. 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); //... }
  49. 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(); //... }
  50. 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(); //... }
  51. Languages and Null

  52. 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 • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection
  53. 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 • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection No `new` inline @TheQuinnGil QuinnGil.com
  54. Technical Practices - No `new` inline public class FizzBuzz{ private

    readonly int _input; public FizzBuzz(int input) => _input = input; public string Result(){ if (new Mod15(_input).Remainder() == 0) return "FizzBuzz"; if (new Mod3(_input).Remainder() == 0) return "Fizz"; if (new Mod5(_input).Remainder() == 0) return "Buzz"; return _input.ToString(); } }
  55. Technical Practices - No `new` inline public class FizzBuzz{ private

    readonly int _input; public FizzBuzz(int input) => _input = input; public string Result(){ if (Mod15().Remainder() == 0) return "FizzBuzz"; if (Mod3().Remainder() == 0) return "Fizz"; if (Mod5().Remainder() == 0) return "Buzz"; return _input.ToString(); } private IRemainder Mod15() => new Mod15(_input); private IRemainder Mod3() => new Mod3(_input); private IRemainder Mod5() => new Mod5(_input); }
  56. Technical Practices - No `new` inline public class FizzBuzz{ private

    readonly int _input; private readonly ModFactory factory; public FizzBuzz(int input) => _input = input; public string Result(){ if (factory.Mod15(_input).Remainder() == 0) return "FizzBuzz"; if (factory.Mod3(_input).Remainder() == 0) return "Fizz"; if (factory.Mod5(_input).Remainder() == 0) return "Buzz"; return _input.ToString(); } } public class ModFactory{ public IRemainder Mod15(int input) => new Mod15(input); public IRemainder Mod3(int input) => new Mod3(input); public IRemainder Mod5(int input) => new Mod5(input); }
  57. Where DO we Create? Technical Practices

  58. No `new` inline - Where DO We Create? public class

    FizzBuzz{ public string Result(){ IFizzBuzzInput input = new FizzBuzzInput(); if (input.EvenlyDivisibleBy(15)) return "FizzBuzz"; if (input.EvenlyDivisibleBy(3)) return "Fizz"; if (input.EvenlyDivisibleBy(5)) return "Buzz"; return input.ToString(); } }
  59. No `new` inline - Where DO We Create? public class

    FizzBuzz{ private readonly IFizzBuzzInput _input; public FizzBuzz() : this(new FizzBuzzInput()) { } private FizzBuzz(IFizzBuzzInput fizzBuzzInput) => _input = fizzBuzzInput; public string Result(){ if (_input.EvenlyDivisibleBy(15)) return "FizzBuzz"; if (_input.EvenlyDivisibleBy(3)) return "Fizz"; if (_input.EvenlyDivisibleBy(5)) return "Buzz"; return _input.ToString(); } } public class FizzBuzz{ public string Result(){ IFizzBuzzInput input = new FizzBuzzInput(); if (input.EvenlyDivisibleBy(15)) return "FizzBuzz"; if (input.EvenlyDivisibleBy(3)) return "Fizz"; if (input.EvenlyDivisibleBy(5)) return "Buzz"; return input.ToString(); } }
  60. No `new` inline - Where DO We Create? public class

    FizzBuzz{ private readonly IFizzBuzzService _service; public FizzBuzz() : this(new FizzBuzzService()) { } private FizzBuzz(IFizzBuzzService fizzBuzzService) => _service = fizzBuzzService; public string Result(){ IFizzBuzzInput input = _service.FizzBuzzInput(); if (input.EvenlyDivisibleBy(15)) return "FizzBuzz"; if (input.EvenlyDivisibleBy(3)) return "Fizz"; if (input.EvenlyDivisibleBy(5)) return "Buzz"; return input.ToString(); } } public class FizzBuzzService : IFizzBuzzService { public IFizzBuzzInput FizzBuzzInput() { return new FizzBuzzInputFromNetwork(_foo); } }
  61. Just Two Places No `new` inline

  62. Why? No `new` inline

  63. Testability No `new` inline - Why?

  64. No `new` inline - Why? - Testability public class FizzBuzz{

    private readonly IFizzBuzzInput _input; public FizzBuzz() : this(new FizzBuzzInput()) { } private FizzBuzz(IFizzBuzzInput fizzBuzzInput) => _input = fizzBuzzInput; public string Result(){ if (_input.EvenlyDivisibleBy(15)) return "FizzBuzz"; if (_input.EvenlyDivisibleBy(3)) return "Fizz"; if (_input.EvenlyDivisibleBy(5)) return "Buzz"; return _input.ToString(); } }
  65. No `new` inline - Why? - Testability public class FizzBuzz{

    private readonly IFizzBuzzInput _input; public FizzBuzz() : this(new FizzBuzzInput()) { } private FizzBuzz(IFizzBuzzInput fizzBuzzInput) => _input = fizzBuzzInput; public string Result(){ if (_input.EvenlyDivisibleBy(15)) return "FizzBuzz"; if (_input.EvenlyDivisibleBy(3)) return "Fizz"; if (_input.EvenlyDivisibleBy(5)) return "Buzz"; return _input.ToString(); } } public class FizzBuzz{ private readonly IFizzBuzzService _service; public FizzBuzz() : this(new FizzBuzzService()) { } private FizzBuzz(IFizzBuzzService fizzBuzzService) => _service = fizzBuzzService; public string Result(){ IFizzBuzzInput input = _service.FizzBuzzInput(); if (input.EvenlyDivisibleBy(15)) return "FizzBuzz"; if (input.EvenlyDivisibleBy(3)) return "Fizz"; if (input.EvenlyDivisibleBy(5)) return "Buzz"; return input.ToString(); } }
  66. Expose Existing Cohesion No `new` inline - Why?

  67. No `new` inline - Why? - Expose Existing Cohesion public

    class FizzBuzz{ private readonly int _input; public FizzBuzz(int input) => _input = input; public string Result(){ if (new Mod15(_input).IsMultipleOf()) return "FizzBuzz"; if (new Mod3(_input).IsMultipleOf()) return "Fizz"; if (new Mod5(_input).IsMultipleOf()) return "Buzz"; return _input.ToString(); } }
  68. No `new` inline - Why? - Expose Existing Cohesion public

    class FizzBuzz{ public FizzBuzz(int input):this(input, new Mod15(input), new Mod3(input), new Mod5(input)) public string Result(){ if (_mod15.IsMultipleOf()) return "FizzBuzz"; if (_mod3.IsMultipleOf()) return "Fizz"; if (_mod5.IsMultipleOf()) return "Buzz"; return _input.ToString(); } }
  69. No `new` inline - Why? - Expose Existing Cohesion public

    class FizzBuzz{ public FizzBuzz(int input):this(new IntToString(input), new Mod15(input), new Mod3(input), new Mod5(input)) public string Result(){ if (_mod15.IsMultipleOf()) return "FizzBuzz"; if (_mod3.IsMultipleOf()) return "Fizz"; if (_mod5.IsMultipleOf()) return "Buzz"; return _toString.Value(); } }
  70. No `new` inline - Why? - Expose Existing Cohesion public

    class FizzBuzz{ public FizzBuzz(int input):this(new IntToString(input), new Mod15(input), new Mod3(input), new Mod5(input)) public string Result(){ if (_mod15.IsMultipleOf()) return _mod15.Value(); if (_mod3.IsMultipleOf()) return _mod3.Value(); if (_mod5.IsMultipleOf()) return _mod5.Value(); return _toString.Value(); } }
  71. No `new` inline - Why? - Expose Existing Cohesion public

    class FizzBuzz{ public FizzBuzz(int input):this(new ToStringResult(input), new FizzBuzzResult(input), new FizzResult(input), new BuzzResult(input)) public string Result(){ if (_fizzBuzz.ShouldReturn()) return _fizzBuzz.Value(); if (_buzz.ShouldReturn()) return _buzz.Value(); if (_fizz.ShouldReturn()) return _fizz.Value(); return _toString.Value(); } }
  72. 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 • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection No `new` inline @TheQuinnGil QuinnGil.com
  73. 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 • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection @TheQuinnGil QuinnGil.com
  74. Feature Parity in 25% of the Dev Hours @TheQuinnGil QuinnGil.com

  75. THANK YOU! @TheQuinnGil QuinnGil.com

  76. 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 • <Strong opinions loosely held> • Be Immutable • No Primitives • Extract Cohesion • No Public Statics • Never Reflection @TheQuinnGil QuinnGil.com