SOLID Principles and Clean Code
Single Responsibility One reason to change Split InvoiceForm logic into InvoiceCalculator + InvoiceRepository Extend without modifying
New IDiscountRule implementations instead of editing Select Case Liskov Substitution Subtypes behave like base types
Square shouldn't inherit a mutable Rectangle Interface Segregation Small, focused interfaces
IReader + IWriter rather than a fat IRepository everywhere Dependency Inversion Depend on abstractions
Constructor-inject IEmailSender instead of New SmtpClient Clean code:
Intention-revealing names, small methods, guard clauses (early Return), no magic numbers (Const).
Avoid deep nesting.
Use domain types (Money, EmailAddress) instead of primitives (avoiding primitive obsession).
Comments explain *why*, not *what*.
Follow DRY, KISS, YAGNI. Apply the Boy Scout rule.
' Open/Closed with strategies
Public Interface IDiscountRule
Function Applies(order As Order) As Boolean
Function Discount(order As Order) As Decimal
End Interface
Public Class DiscountCalculator
Private ReadOnly _rules As IEnumerable(Of IDiscountRule)
Public Sub New(rules As IEnumerable(Of IDiscountRule)) ' DI injects all registered rules
_rules = rules
End Sub
Public Function Calculate(order As Order) As Decimal
Return _rules.Where(Function(r) r.Applies(order)).Sum(Function(r) r.Discount(order))
End Function
End Class