Skip to content

Code convention

이도연 edited this page Sep 23, 2024 · 15 revisions

Naming

Constant

  • 상수는 UpperCamelCase로 작성한다
static let ItemHeight: CGFloat = 166
static let GroupSpacing: CGFloat = 8
  • 일반적으로 static let로 선언하고, 제네릭 사용으로 인해 static let 사용이 불가능한 경우 let으로 선언한다.

static으로 선언하는 이유는 외부에서 상수에 접근해야하는 경우 쉽게 하기 위함인데, 외부에서 접근하지 않는 상수에서도 static을 붙여야할지는 고민

Action

  • on+동사+a: 컴포넌트로 외부(상위)로 전달하는 액션
    • e.g. onTap or onTapButton
    • 사용하는 경우: 하위 컴포넌트에서 발생한 액션을 상위 컴포넌트로 단순 전달할 때 e.g. Void
    • 주로 Subject나 컴플리션 핸들러로 구현된다.
  • 동사+a: 상위에서 하위 컴포넌트로 전달하는 액션
    • e.g. tap or tapButton
    • 사용하는 경우: 상위 컴포넌트에서 발생하는 액션에 대해 로직을 실행시킬 때
    • 주로 일반 메서드로 구현된다.

Usecase

  • Get+a: 서버, 혹은 로컬 DB에서 정보를 가져오는 동작.
  • Create+a: 서버, 혹은 로컬 DB에서 정보를 추가하는 동작.
  • Update+a: 서버, 혹은 로컬 DB에서 정보를 수정하는 동작.
  • Delete+a: 서버, 혹은 로컬 DB에서 정보를 삭제하는 동작.

Style

Import

  • 애플 프레임워크(first party)
  • 모듈
  • 라이브러리 (third party) 순으로 구분해서 작성한다.
import UIKit
// ✓
import DesignSystem
import Assets
// ✓
import SnapKit
import Then

Class

  • class 바로 밑 줄은 띄우지 않는다.
// ❌
public class BaseButton: UIControl {

    public typealias ViewBuilder = () -> [UIView]

// ✅
public class BaseButton: UIControl {
    public typealias ViewBuilder = () -> [UIView]
  • 주석이 바로 밑에 위치하는 것은 허용한다.
public class SignupTermsView: BaseView {
    // MARK: UI Constant
    private let additionalPagePadding: CGFloat = 14

Variable

  • 변수 선언은 한 줄 씩 여백을 둔다
// ❌
private var headerComponents: [UIView] = []
private var contentComponents: [UIView] = []
private var footerComponents: [UIView] = []

// ✅
private var headerComponents: [UIView] = []

private var contentComponents: [UIView] = []

private var footerComponents: [UIView] = []
  • 단, 두 변수의 연관성이 높을 경우 붙여쓰기를 허용한다.
private var _onTap: PublishSubject<Void> = PublishSubject()
public var onTap: Observable<Void> {
    return _onTap.asObservable()
}
  • 주석이 있는 경우에도 한줄 띄워쓴다.
/// Title of the announcement
public let title: String
    
/// Body text of the announcement
public let body: String
    
/// Event date or deadline (optional)
public let date: Date?

UI declaration

  • 관련 컴포넌트들은 // - 대문자 시작 주석으로 구분한다.
// MARK: UI Component
// - Page title
lazy var pageTitleLabel = UILabel().then {
    $0.text = "그룹의 이름이 무엇인가요?"
    $0.setTypo(.heading3)
    $0.textColor = .grey800
}
  • 다른 컴포넌트를 참조하는 컴포넌트를 위에 선언하고 참조되는 컴포넌트를 그 아래 선언한다.
// - Event date card
lazy var eventDateCard = BaseCard() {
    [
        eventDateLabel
    ]
}.then {
    $0.styled()
}

lazy var eventDateLabel = UILabel().then {
    $0.text = "2024.07.27(토) 14:02"
    $0.setTypo(.body1m)
    $0.textColor = .grey800
    $0.numberOfLines = 2
}

Setup

  • 컴포넌트 별로 한 줄씩 여백을 둔다.
// ❌
public override func setupHierarchy() {
    addSubview(contentView)
    contentView.addSubview(pageTitleLabel)
    contentView.addSubview(pageDescriptionLabel)
}

public override func setupLayout() {
    contentView.snp.makeConstraints {
        $0.top.bottom.equalToSuperview()
        $0.left.right.equalToSuperview().inset(GlobalViewConstant.pagePadding)
    }
    pageTitleLabel.snp.makeConstraints {
        $0.top.equalToSuperview()
            .offset(FunnelConstant.spacingUnit * 2)
        $0.left.right.equalToSuperview()
            .inset(additionalPagePadding)
    }
    pageDescriptionLabel.snp.makeConstraints {
        $0.top.equalTo(pageTitleLabel.snp.bottom)
            .offset(FunnelConstant.spacingUnit)
        $0.left.right.equalToSuperview()
            .inset(additionalPagePadding)
    }
}

// ✅
public override func setupHierarchy() {
    addSubview(contentView)

    contentView.addSubview(pageTitleLabel)

    contentView.addSubview(pageDescriptionLabel)
}

public override func setupLayout() {
    contentView.snp.makeConstraints {
        $0.top.bottom.equalToSuperview()
        $0.left.right.equalToSuperview().inset(GlobalViewConstant.pagePadding)
    }

    pageTitleLabel.snp.makeConstraints {
        $0.top.equalToSuperview()
            .offset(FunnelConstant.spacingUnit * 2)
        $0.left.right.equalToSuperview()
            .inset(additionalPagePadding)
    }

    pageDescriptionLabel.snp.makeConstraints {
        $0.top.equalTo(pageTitleLabel.snp.bottom)
            .offset(FunnelConstant.spacingUnit)
        $0.left.right.equalToSuperview()
            .inset(additionalPagePadding)
    }
}

Snapkit

  • offset, inset은 한 줄 내려서 작성한다.
// ❌
$0.top.equalTo(allAgreeCheckBox.snp.bottom).offset(FunnelConstant.spacingUnit * 1.5)

// ✅
$0.top.equalTo(allAgreeCheckBox.snp.bottom)
    .offset(FunnelConstant.spacingUnit * 1.5)

Clone this wiki locally