423 lines
14 KiB
Markdown
423 lines
14 KiB
Markdown
# iOS Naming Conventions Examples
|
|
|
|
Comprehensive examples of good and bad naming patterns in Swift.
|
|
|
|
## Classes and Types
|
|
|
|
### ✅ Good Examples
|
|
```swift
|
|
// View Controllers
|
|
class PaymentViewController: UIViewController { }
|
|
class TransactionListViewController: UIViewController { }
|
|
class RefundConfirmationViewController: UIViewController { }
|
|
|
|
// ViewModels
|
|
class PaymentViewModel: BaseViewModel<PaymentState> { }
|
|
class StoresViewModel: BaseViewModel<StoresState> { }
|
|
class TransactionHistoryViewModel: BaseViewModel<TransactionHistoryState> { }
|
|
|
|
// Use Cases
|
|
protocol PaymentUseCase { }
|
|
class PaymentUseCaseImpl: PaymentUseCase { }
|
|
protocol RefundRequestUseCase { }
|
|
|
|
// Repositories
|
|
protocol PaymentRepository { }
|
|
class PaymentRepositoryImpl: PaymentRepository { }
|
|
|
|
// Models
|
|
struct Transaction { }
|
|
struct PaymentRequest { }
|
|
struct RefundRequest { }
|
|
|
|
// Enums
|
|
enum PaymentMethod { }
|
|
enum TransactionStatus { }
|
|
enum RefundRequestError: Error { }
|
|
```
|
|
|
|
### ❌ Bad Examples
|
|
```swift
|
|
// Too abbreviated
|
|
class PayVC: UIViewController { } // → PaymentViewController
|
|
class RefReqVM { } // → RefundRequestViewModel
|
|
class TrxRepo { } // → TransactionRepository
|
|
|
|
// Too generic
|
|
class Manager { } // → PaymentManager or specific purpose
|
|
class Helper { } // → ValidationHelper or specific purpose
|
|
class Util { } // → DateFormatter or specific utility
|
|
|
|
// Missing suffixes
|
|
class Payment { } // → PaymentViewModel or PaymentUseCase
|
|
class Transaction { } // If it's a ViewModel → TransactionViewModel
|
|
```
|
|
|
|
---
|
|
|
|
## Variables and Properties
|
|
|
|
### ✅ Good Examples
|
|
```swift
|
|
class PaymentViewModel {
|
|
// State properties - descriptive
|
|
let paymentAmount = BehaviorRelay<String>(value: "")
|
|
let selectedPaymentMethod = BehaviorRelay<PaymentMethod?>(value: nil)
|
|
let transactionResult = BehaviorRelay<TransactionResult?>(value: nil)
|
|
|
|
// Boolean properties - with prefixes
|
|
let isProcessingPayment = BehaviorRelay<Bool>(value: false)
|
|
let hasNetworkConnection = BehaviorRelay<Bool>(value: true)
|
|
let shouldShowError = BehaviorRelay<Bool>(value: false)
|
|
let canSubmitPayment = BehaviorRelay<Bool>(value: false)
|
|
|
|
// Collections - plural
|
|
let transactions = BehaviorRelay<[Transaction]>(value: [])
|
|
let errorMessages = BehaviorRelay<[String]>(value: [])
|
|
let availablePaymentMethods = BehaviorRelay<[PaymentMethod]>(value: [])
|
|
|
|
// Dependencies - full names
|
|
private let paymentUseCase: PaymentUseCase
|
|
private let validationService: ValidationService
|
|
private let disposeBag = DisposeBag()
|
|
}
|
|
```
|
|
|
|
### ❌ Bad Examples
|
|
```swift
|
|
class PaymentViewModel {
|
|
// Abbreviated
|
|
let amt = BehaviorRelay<String>(value: "") // → paymentAmount
|
|
let pmtMethod = BehaviorRelay<PaymentMethod?>(value: nil) // → paymentMethod
|
|
let trxResult = BehaviorRelay<TransactionResult?>(value: nil) // → transactionResult
|
|
|
|
// Generic/meaningless
|
|
let flag = BehaviorRelay<Bool>(value: false) // → isProcessing
|
|
let data = BehaviorRelay<[Any]>(value: []) // → transactions
|
|
let temp = BehaviorRelay<String>(value: "") // → What is this?
|
|
|
|
// Boolean without prefix
|
|
let loading: Bool // → isLoading
|
|
let valid: Bool // → isValid
|
|
let enabled: Bool // → isEnabled
|
|
|
|
// Single letter
|
|
let x = 0 // → transactionCount
|
|
let a = amount // → paymentAmount
|
|
|
|
// Inconsistent abbreviations
|
|
let paymentUC: PaymentUseCase // → paymentUseCase
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Functions and Methods
|
|
|
|
### ✅ Good Examples
|
|
```swift
|
|
class TransactionViewModel {
|
|
// Actions - verb-based, descriptive
|
|
func loadTransactions() { }
|
|
func refreshTransactionList() { }
|
|
func filterTransactionsByDate(from startDate: Date, to endDate: Date) { }
|
|
func processRefundRequest(for transactionId: String) { }
|
|
func validatePaymentAmount(_ amount: String) -> Bool { }
|
|
|
|
// Queries - return information
|
|
func getTransaction(by id: String) -> Transaction? { }
|
|
func calculateTotalAmount(for transactions: [Transaction]) -> Double { }
|
|
func hasUnprocessedTransactions() -> Bool { }
|
|
func isValidPaymentAmount(_ amount: String) -> Bool { }
|
|
|
|
// State handlers - clear purpose
|
|
func handlePaymentSuccess(_ result: PaymentResult) { }
|
|
func handlePaymentError(_ error: Error) { }
|
|
func handleNetworkConnectionLost() { }
|
|
|
|
// Setup/Configuration - clear intent
|
|
func setupUI() { }
|
|
func configureTableView() { }
|
|
func bindViewModel() { }
|
|
}
|
|
```
|
|
|
|
### ❌ Bad Examples
|
|
```swift
|
|
class TransactionViewModel {
|
|
// Too vague
|
|
func doSomething() { } // → processRefundRequest()
|
|
func process() { } // Process what? → processPayment()
|
|
func get() { } // Get what? → getTransactions()
|
|
func handle() { } // Handle what? → handleError()
|
|
func go() { } // Go where? → navigateToDetails()
|
|
|
|
// Noun-based instead of verb-based
|
|
func transaction() { } // → loadTransaction() or getTransaction()
|
|
func payment() { } // → processPayment()
|
|
|
|
// Abbreviated
|
|
func procPmt() { } // → processPayment()
|
|
func getTrx() { } // → getTransaction()
|
|
func valAmt(_ amt: String) { } // → validateAmount(_ amount: String)
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## IBOutlets
|
|
|
|
### ✅ Good Examples
|
|
```swift
|
|
class PaymentViewController: UIViewController {
|
|
// Text fields - with TextField suffix
|
|
@IBOutlet weak var paymentAmountTextField: UITextField!
|
|
@IBOutlet weak var merchantCodeTextField: UITextField!
|
|
@IBOutlet weak var notesTextField: UITextField!
|
|
|
|
// Labels - with Label suffix
|
|
@IBOutlet weak var currencyLabel: UILabel!
|
|
@IBOutlet weak var totalAmountLabel: UILabel!
|
|
@IBOutlet weak var errorMessageLabel: UILabel!
|
|
|
|
// Buttons - with Button suffix
|
|
@IBOutlet weak var confirmPaymentButton: UIButton!
|
|
@IBOutlet weak var cancelButton: UIButton!
|
|
@IBOutlet weak var submitButton: UIButton!
|
|
|
|
// Tables and collections - with TableView/CollectionView suffix
|
|
@IBOutlet weak var transactionTableView: UITableView!
|
|
@IBOutlet weak var storesCollectionView: UICollectionView!
|
|
|
|
// Other views - with type suffix
|
|
@IBOutlet weak var loadingIndicator: UIActivityIndicatorView!
|
|
@IBOutlet weak var headerView: UIView!
|
|
@IBOutlet weak var footerContainerView: UIView!
|
|
@IBOutlet weak var paymentMethodSegmentedControl: UISegmentedControl!
|
|
}
|
|
```
|
|
|
|
### ❌ Bad Examples
|
|
```swift
|
|
class PaymentViewController: UIViewController {
|
|
// Missing type suffix
|
|
@IBOutlet weak var amount: UITextField! // → amountTextField
|
|
@IBOutlet weak var currency: UILabel! // → currencyLabel
|
|
@IBOutlet weak var confirm: UIButton! // → confirmButton
|
|
|
|
// Abbreviated
|
|
@IBOutlet weak var lbl: UILabel! // → titleLabel
|
|
@IBOutlet weak var btn: UIButton! // → submitButton
|
|
@IBOutlet weak var txtField: UITextField! // → amountTextField
|
|
|
|
// Too generic
|
|
@IBOutlet weak var table: UITableView! // → transactionTableView
|
|
@IBOutlet weak var view: UIView! // → headerView
|
|
@IBOutlet weak var loading: UIActivityIndicatorView! // → loadingIndicator
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Test Naming
|
|
|
|
### ✅ Good Examples
|
|
```swift
|
|
class PaymentViewModelTests: XCTestCase {
|
|
// Format: test[MethodName]_[Scenario]_[ExpectedResult]
|
|
|
|
func testProcessPayment_WithValidAmount_CompletesSuccessfully() { }
|
|
func testProcessPayment_WithEmptyAmount_ShowsValidationError() { }
|
|
func testProcessPayment_WithNetworkError_ShowsErrorState() { }
|
|
func testLoadTransactions_WithCachedData_ReturnsDataImmediately() { }
|
|
func testRefundRequest_WhenAmountExceedsTransaction_Fails() { }
|
|
|
|
func testValidateAmount_BelowMinimum_ReturnsFalse() { }
|
|
func testValidateAmount_AboveMaximum_ReturnsFalse() { }
|
|
func testValidateAmount_ValidRange_ReturnsTrue() { }
|
|
|
|
func testSubmitRefund_WithValidData_UpdatesStateToSuccess() { }
|
|
func testSubmitRefund_WithInvalidData_UpdatesStateToError() { }
|
|
}
|
|
```
|
|
|
|
### ❌ Bad Examples
|
|
```swift
|
|
class PaymentViewModelTests: XCTestCase {
|
|
func test1() { } // Meaningless number
|
|
func testPayment() { } // Too vague
|
|
func testError() { } // What error scenario?
|
|
func testStuff() { } // Meaningless
|
|
func test_payment_works() { } // snake_case (wrong)
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Complete Class Examples
|
|
|
|
### ✅ Well-Named Class
|
|
```swift
|
|
class PaymentProcessingViewModel: BaseViewModel<PaymentState> {
|
|
// Dependencies - full, descriptive names
|
|
private let paymentUseCase: PaymentUseCase
|
|
private let validationService: ValidationService
|
|
private let disposeBag = DisposeBag()
|
|
|
|
// Input properties - clear, descriptive
|
|
let paymentAmount = BehaviorRelay<String>(value: "")
|
|
let selectedMerchantId = BehaviorRelay<String?>(value: nil)
|
|
let additionalNotes = BehaviorRelay<String>(value: "")
|
|
|
|
// State properties - boolean with prefixes
|
|
let isProcessingPayment = BehaviorRelay<Bool>(value: false)
|
|
let hasValidPaymentAmount = BehaviorRelay<Bool>(value: false)
|
|
let shouldEnableSubmitButton = BehaviorRelay<Bool>(value: false)
|
|
|
|
// Output properties - descriptive
|
|
let paymentResult = BehaviorRelay<PaymentResult?>(value: nil)
|
|
let errorMessage = BehaviorRelay<String?>(value: nil)
|
|
|
|
// Initializer - parameter names match properties
|
|
init(paymentUseCase: PaymentUseCase, validationService: ValidationService) {
|
|
self.paymentUseCase = paymentUseCase
|
|
self.validationService = validationService
|
|
super.init()
|
|
setupValidation()
|
|
}
|
|
|
|
// Methods - verb-based, descriptive
|
|
func processPaymentRequest() { }
|
|
func validatePaymentAmount() -> Bool { }
|
|
func clearPaymentForm() { }
|
|
func handlePaymentSuccess(_ result: PaymentResult) { }
|
|
func handlePaymentError(_ error: Error) { }
|
|
|
|
private func setupValidation() { }
|
|
private func updateSubmitButtonState() { }
|
|
}
|
|
```
|
|
|
|
### ❌ Poorly Named Class
|
|
```swift
|
|
class PaymentVM: BaseViewModel<PaymentState> { // Abbreviated
|
|
// Abbreviated dependencies
|
|
private let pmtUC: PaymentUseCase // → paymentUseCase
|
|
private let valService: ValidationService // → validationService
|
|
private let bag = DisposeBag() // → disposeBag
|
|
|
|
// Abbreviated/unclear properties
|
|
let amt = BehaviorRelay<String>(value: "") // → paymentAmount
|
|
let mid = BehaviorRelay<String?>(value: nil) // → merchantId
|
|
let notes = BehaviorRelay<String>(value: "") // Could be clearer
|
|
|
|
// Boolean without prefix
|
|
let processing = BehaviorRelay<Bool>(value: false) // → isProcessing
|
|
let valid = BehaviorRelay<Bool>(value: false) // → hasValidAmount
|
|
|
|
// Generic names
|
|
let result = BehaviorRelay<PaymentResult?>(value: nil) // → paymentResult
|
|
let error = BehaviorRelay<String?>(value: nil) // → errorMessage
|
|
|
|
// Abbreviated initializer
|
|
init(uc: PaymentUseCase, val: ValidationService) { // Bad parameter names
|
|
self.pmtUC = uc
|
|
self.valService = val
|
|
super.init()
|
|
}
|
|
|
|
// Vague method names
|
|
func process() { } // → processPaymentRequest()
|
|
func validate() -> Bool { } // → validatePaymentAmount()
|
|
func clear() { } // → clearPaymentForm()
|
|
func handle(_ r: PaymentResult) { } // → handlePaymentSuccess()
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Refactoring Examples
|
|
|
|
### Example: Refactoring Poor Names
|
|
|
|
#### Before (Bad)
|
|
```swift
|
|
class TrxVM: BaseViewModel<TrxState> {
|
|
let trxs = BehaviorRelay<[Trx]>(value: [])
|
|
let loading = BehaviorRelay<Bool>(value: false)
|
|
|
|
func getTrx(id: String) -> Trx? {
|
|
return trxs.value.first { $0.id == id }
|
|
}
|
|
|
|
func proc() {
|
|
loading.accept(true)
|
|
// Process transactions
|
|
}
|
|
}
|
|
```
|
|
|
|
#### After (Good)
|
|
```swift
|
|
class TransactionViewModel: BaseViewModel<TransactionState> {
|
|
let transactions = BehaviorRelay<[Transaction]>(value: [])
|
|
let isLoading = BehaviorRelay<Bool>(value: false)
|
|
|
|
func getTransaction(by id: String) -> Transaction? {
|
|
return transactions.value.first { $0.id == id }
|
|
}
|
|
|
|
func processTransactions() {
|
|
isLoading.accept(true)
|
|
// Process transactions
|
|
}
|
|
}
|
|
```
|
|
|
|
**Changes Made**:
|
|
1. `TrxVM` → `TransactionViewModel` (full names, proper suffix)
|
|
2. `trxs` → `transactions` (no abbreviation, plural)
|
|
3. `loading` → `isLoading` (boolean prefix)
|
|
4. `getTrx` → `getTransaction` (full name, clear parameters)
|
|
5. `proc` → `processTransactions` (verb-based, descriptive)
|
|
|
|
---
|
|
|
|
## Quick Reference Checklist
|
|
|
|
Use this when reviewing naming:
|
|
|
|
```markdown
|
|
## Naming Conventions Checklist
|
|
|
|
### Classes/Structs/Enums
|
|
- [ ] PascalCase
|
|
- [ ] Descriptive and meaningful
|
|
- [ ] Proper suffix (ViewModel, UseCase, etc.)
|
|
- [ ] No abbreviations
|
|
|
|
### Variables/Properties
|
|
- [ ] camelCase
|
|
- [ ] Meaningful names
|
|
- [ ] Booleans have is/has/should/can prefix
|
|
- [ ] Collections are plural
|
|
- [ ] No single letters (except loops)
|
|
- [ ] No abbreviations
|
|
|
|
### Functions/Methods
|
|
- [ ] camelCase
|
|
- [ ] Verb-based (actions) or get/has/is (queries)
|
|
- [ ] Descriptive of purpose
|
|
- [ ] Clear parameter names
|
|
|
|
### IBOutlets
|
|
- [ ] Include type suffix
|
|
- [ ] Descriptive of purpose
|
|
- [ ] camelCase
|
|
|
|
### General
|
|
- [ ] No generic names (Manager, Helper, Util)
|
|
- [ ] Consistent naming style
|
|
- [ ] Easy to understand without context
|
|
```
|