Clean Code in Swift: Principles and Practical Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Clean Code in Swift: Principles and Practical Examples

\n\n

Clean Code is not just a trendy term, but a fundamental skill for a professional developer. In the Swift ecosystem (iOS/macOS), code quality directly affects development speed, the number of bugs, and the ease of project maintenance. In this article, we will break down the key principles of Clean Code as applied to Swift and show their implementation with practical examples.

\n\n

1. Naming: Speak the Language of the Domain

\n\n

A good name for a variable, function, or class replaces comments. In Swift, with its rich type system and optional values, proper naming is especially important.

\n\n

Bad example:

\n
func calc(a: [String: Any]) -> Double {\n    var x = 0.0\n    for (_, v) in a {\n        if let n = v as? Double {\n            x += n\n        }\n    }\n    return x\n}
\n\n

Good example (Clean Code):

\n
func calculateTotalPrice(of products: [Product]) -> Double {\n    return products.reduce(0) { $0 + $1.price }\n}
\n\n

Naming principles in Swift:

\n
    \n
  • Clarity over brevity: remove(at:) is better than rem(at:).
  • \n
  • Use nouns for types: UserViewController, NetworkManager.
  • \n
  • Verbs for functions: fetchData(), saveToCache().
  • \n
  • Boolean variables: start with is, has, should — isEnabled, hasContent.
  • \n
  • Avoid abbreviations: backgroundColor instead of bgColor.
  • \n
\n\n

2. Single Responsibility Principle (SRP) in Swift

\n\n

Each class, structure, or function should have only one reason to change. In iOS development, this is especially relevant for ViewControllers, which often turn into "god objects".

\n\n

SRP violation (typical ViewController):

\n
class ProfileViewController: UIViewController {\n    @IBOutlet weak var nameLabel: UILabel!\n    @IBOutlet weak var avatarImageView: UIImageView!\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // Loading data\n        let url = URL(string: "https://api.example.com/user")!\n        let data = try! Data(contentsOf: url)\n        let json = try! JSONSerialization.jsonObject(with: data) as! [String: Any]\n        nameLabel.text = json["name"] as? String\n        \n        // Loading avatar\n        let imageUrl = URL(string: json["avatar"] as! String)!\n        let imageData = try! Data(contentsOf: imageUrl)\n        avatarImageView.image = UIImage(data: imageData)\n        \n        // Saving to cache\n        UserDefaults.standard.set(json, forKey: "cachedUser")\n    }\n}
\n\n

Refactoring with SRP compliance:

\n
// 1. Separate service for network operations\nclass UserNetworkService {\n    func fetchUser(completion: @escaping (Result<User, Error>) -> Void) {\n        // ... network logic\n    }\n}\n\n// 2. Separate cache manager\nclass UserCacheManager {\n    func saveUser(_ user: User) {\n        // ... caching logic\n    }\n}\n\n// 3. ViewModel for business logic\nclass ProfileViewModel {\n    private let networkService = UserNetworkService()\n    private let cacheManager = UserCacheManager()\n    \n    func loadProfile(completion: @escaping (User) -> Void) {\n        networkService.fetchUser { [weak self] result in\n            switch result {\n            case .success(let user):\n                self?.cacheManager.saveUser(user)\n                completion(user)\n            case .failure:\n                // Load from cache on error\n                if let cachedUser = self?.cacheManager.lo                

Blogs

Book Recommendations