---
title: Không đặt quá nhiều logic trong superclass
impact: MEDIUM
impactDescription: Superclass phình to tạo coupling cao giữa subclasses, khó bảo trì và dễ vô tình break subclass khi thay đổi base class.
tags: swift, ios, inheritance, superclass, composition, architecture
---

## Không đặt quá nhiều logic trong superclass

Thay vì nhồi logic vào `BaseViewController` hay `BaseViewModel`, hãy dùng **composition** qua protocol extension hoặc delegate. Superclass chỉ nên chứa logic thực sự chung cho mọi subclass.

**Incorrect (BaseViewController quá nặng):**

```swift
class BaseViewController: UIViewController {
    // Networking
    func makeAPICall<T>(url: URL, completion: @escaping (Result<T, Error>) -> Void) { ... }

    // Analytics
    func trackScreenView(name: String) { ... }
    func trackEvent(_ event: String, parameters: [String: Any]) { ... }

    // Loading
    func showLoading() { ... }
    func hideLoading() { ... }

    // Alert
    func showAlert(title: String, message: String) { ... }
    func showErrorAlert(_ error: Error) { ... }

    // Navigation
    func pushViewController(_ vc: UIViewController, animated: Bool) { ... }

    // Keyboard
    func setupKeyboardDismissal() { ... }
    var keyboardHeight: CGFloat { ... }

    // Tất cả ViewController đều kế thừa hết dù không cần!
}
```

**Correct (composition qua protocol + extension):**

```swift
// Tách thành protocol có thể opt-in
protocol LoadingDisplayable: UIViewController {
    func showLoading()
    func hideLoading()
}

extension LoadingDisplayable {
    func showLoading() {
        LoadingOverlay.show(in: view)
    }
    func hideLoading() {
        LoadingOverlay.hide(from: view)
    }
}

protocol ErrorAlertDisplayable: UIViewController {
    func showErrorAlert(_ error: Error)
}
extension ErrorAlertDisplayable {
    func showErrorAlert(_ error: Error) {
        let alert = UIAlertController(title: "Lỗi", message: error.localizedDescription, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        present(alert, animated: true)
    }
}

// BaseViewController chỉ giữ thứ thực sự dùng ở MỌI VC
class BaseViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        setupNavigationBar()
    }
    private func setupNavigationBar() { /* common nav bar style */ }
}

// Từng VC chỉ opt-in vào tính năng cần
class OrderListViewController: BaseViewController, LoadingDisplayable, ErrorAlertDisplayable {
    func loadOrders() async {
        showLoading()
        defer { hideLoading() }
        do {
            orders = try await orderService.fetchOrders()
        } catch {
            showErrorAlert(error)
        }
    }
}
```

**Tools:** Code Review, SwiftLint (`type_body_length`)

