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