Since I have been a speaker and a teacher, I have always stressed the importance of practicing proper object-oriented programming (OOP) techniques. If you don’t practice OOP, no matter what language you are using, I guarantee you will end up with a “house of cards” and they all eventually fall.

The first “pillar” of OOP is encapsulation which means the practice of data hiding. No code gets to the data in the type unless it uses properties or methods. As I always say, “bad data in, bad data out”. If that bad data gets saved to a database it could get corrupted, it could upset customers and will cause more work and money to fix it. Is this a good example of OOP coding?

  1. public class OrderData
  2. {
  3. public string ORDER;
  4. private string wherehouseID = "";
  5. public string OrderNumber = "";
  6. public string openClosed = "";
  7. public string transType = "";
  8. public string dateOpened = "";
  9. public string dateClosed = "";
  10. public string dateShop = "";
  11. public OrderData(string _ORDER)
  12. {
  13. this.ORDER = _ORDER;
  14. }
  15. //Code removed for brevity
  16. }

NO, it is not! This type, currently in production, does not practice good encapsulation since the actual code contains over 198 public string fields! I would say over 90 percent of code I see as a consultant does not even get this first pillar right. The first line of all your properties and methods should be validating the data before proceeding.

To make this easier, always use proper data types since they will help you with validation. If the type needs a date, then use DateTime. If the type needs a URL, then use the Uri type etc. If I had the codebase to the type above, I would have changed it to something like this.

  1. public class Order
  2. {
  3. private ReplacementType _replacementType;
  4. private OrderType _orderType;
  5. private DateTime? _closedOn;
  6. private DateTime? _customerPickupOn;
  7. private TransactionType _transactionType;
  8. private DateTime _openedOn;
  9. private string _orderNumber;
  10. public string OrderNumber
  11. {
  12. get
  13. {
  14. return _orderNumber;
  15. }
  16. set
  17. {
  18. if (string.IsNullOrEmpty(value))
  19. {
  20. throw new ArgumentNullException();
  21. }
  22. _orderNumber = value;
  23. }
  24. }
  25. public bool IsClosed { get; private set; }
  26. public TransactionType TransactionType
  27. {
  28. get
  29. {
  30. return _transactionType;
  31. }
  32. set
  33. {
  34. if (!System.Enum.IsDefined(typeof(TransactionType), value))
  35. {
  36. throw new ArgumentOutOfRangeException();
  37. }
  38. _transactionType = value;
  39. }
  40. }
  41. public int EmployeeId { get; set; }
  42. public DateTime OpenedOn
  43. {
  44. get
  45. {
  46. return _openedOn;
  47. }
  48. set
  49. {
  50. if (value <= DateTime.MinValue)
  51. {
  52. throw new ArgumentOutOfRangeException();
  53. }
  54. _openedOn = value;
  55. }
  56. }
  57. public DateTime? CustomerPickupOn
  58. {
  59. get
  60. {
  61. return _customerPickupOn;
  62. }
  63. set
  64. {
  65. if (this.OpenedOn <= DateTime.MinValue)
  66. {
  67. throw new ArgumentOutOfRangeException(nameof(OpenedOn));
  68. }
  69. if (value < this.OpenedOn)
  70. {
  71. throw new ArgumentOutOfRangeException(nameof(CustomerPickupOn), "Value must be the same or later than OpenedOn");
  72. }
  73. _customerPickupOn = value;
  74. }
  75. }
  76. public DateTime? ClosedOn
  77. {
  78. get
  79. {
  80. return _closedOn;
  81. }
  82. set
  83. {
  84. if (this.OpenedOn <= DateTime.MinValue)
  85. {
  86. throw new ArgumentOutOfRangeException(nameof(OpenedOn));
  87. }
  88. if (value < this.OpenedOn)
  89. {
  90. throw new ArgumentOutOfRangeException(nameof(ClosedOn), "Value must be the same or later than OpenedOn");
  91. }
  92. _closedOn = value;
  93. this.IsClosed = true;
  94. }
  95. }
  96. public OrderType OrderType
  97. {
  98. get
  99. {
  100. return _orderType;
  101. }
  102. set
  103. {
  104. if (!System.Enum.IsDefined(typeof(OrderType), value))
  105. {
  106. throw new ArgumentOutOfRangeException();
  107. }
  108. _orderType = value;
  109. }
  110. }
  111. public ReplacementType ReplacementType
  112. {
  113. get
  114. {
  115. return _replacementType;
  116. }
  117. set
  118. {
  119. if (!System.Enum.IsDefined(typeof(ReplacementType), value))
  120. {
  121. throw new ArgumentOutOfRangeException();
  122. }
  123. _replacementType = value;
  124. }
  125. }
  126. // Code removed for brevity
  127. }

As you can see in the code above, I’m using the proper data types and even created a few enums. I am also validating all the data coming into the type and if it fails, I throw the proper exception.

If you use proper data types, then I guarantee this will help your team. If you are a Microsoft .NET developer, please be sure to pick up a copy of my coding standards book. Please share comments you might have below.