Skip to content

Latest commit

History

20 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Swift Code Convension Guide

Swift 개발에 있어 범용적으로 사용할 수 있는 코드 컨벤션 가이드입니다

이 가이드는 코드의 일관성을 유지하고, 팀원 간의 협업을 원활하게 하기 위해 만들어졌습니다


Index


Contributors

imgimgimgimg

Indentation

  • 기본 4 whiteSpace 들여쓰기 사용

    Details
    if exampleCode {
    // ...
    }

Naming

  • 타입과 프로토콜의 이름에는 PascalCase를 사용하고, 그 외에는 lowerCamelCase를 사용하기

    Details
    protocolSpaceThing{
    // ...
    }classSpaceFleet:SpaceThing{enumFormation{
    // ...
    }classSpaceship{
    // ...
    }varships:[Spaceship]=[]staticletworldName:String="Earth"func addShip(_ ship:Spaceship){
    // ...
    }}letmyFleet=SpaceFleet()

  • @ViewBuilder 메서드 경우 PascalCase 사용

    Details
    @ViewBuilderprivatefunc ExampleComponent()->someView{...}

  • Bool 타입 변수 선언 시, is || has 로 시작 할 수 있도록 선언

    Details
    varisShowing:Bool=false

  • 동작을 의미하는 변수 및 메서드 선언 시, 동사가 맨 앞으로 오도록 선언

    Details
    enumAction{case showDialog
    ...}

  • API - fetch, add, update, delete 명칭 사용 ( not used - remove, get, create … )

    Details
    func fetchList(){...}

  • extension 사용 시, 파일명 xxxxx +.swift


Style

  • 식별자 바로 뒤에 콜론(:)을 놓고 그 뒤에 공백을 두기

    Details
    varsomething:String="코드 컨벤션 만들기"func addWork(_ work:String){
    // ...
    }

  • 쉽게 추론할 수 있는 유형은 타입 표기 생략하기 ( 객체 생성 )

    Details
    // WRONG
    lethost:Host=Host()
    // RIGHT
    lethost=Host()
    enumDirection{case left
    case right
    }func someDirection()->Direction{
    // WRONG
    returnDirection.left
    // RIGHT
    return.left
    }

  • self. - 네이밍이 겹치지 않는 이상 사용하지 않기

    Details
    finalclassListing{init(capacity:Int, allowsPets:Bool){
    // WRONG
    self.capacity = capacity
    self.isFamilyFriendly = !allowsPets // `self.` not required here
    // RIGHT
    self.capacity = capacity
    isFamilyFriendly = !allowsPets
    }privateletisFamilyFriendly:Boolprivatevarcapacity:Intprivatefunc increaseCapacity(by amount:Int){
    // WRONG
    self.capacity += amount
    // RIGHT
    capacity += amount
    // WRONG
    self.save()
    // RIGHT
    save()}}

  • 여러 줄이 있는 배열은 각 괄호가 별도의 줄에 있도록 하기 ( 배열 속성 2개 이상의 경우 )

    Details
    // WRONG
    letrowContent=[listingUrgencyDatesRowContent(),listingUrgencyBookedRowContent(),listingUrgencyBookedShortRowContent()]
    // RIGHT
    letrowContent=[listingUrgencyDatesRowContent(),listingUrgencyBookedRowContent(),listingUrgencyBookedShortRowContent()]

  • guard let 구문 - else 문 클로저가 return 이 아닐 경우, 클로저 줄 내려서 사용 ( 조건 여러개는 당연히 조건에만 여러 줄 사용 )

    Details
    guardlet xxxx = xxxx else{return}guardlet xxxx = xxxx,
    xxxx.sdsda.isEmpty,
    xxxx.ssss.isEmpty else{return}guardlet xxxx = xxxx else{throw abcdError.aaaaa
    }

  • switch case 문은 각 case 별로 한줄씩 띄어서 사용

    Details
    func handle(_ action:SpaceshipAction){switch action {case.engageWarpDrive:
    warpDrive.engage()case.enableArtificialGravity:
    artificialGravityEngine.enable(strength:.oneG)case.scanPlanet(let planet):
    scanner.scan(planet)case.handleIncomingEnergyBlast:
    energyShields.engage()}}

  • 한줄 주석과 여러줄 주석을 구분하기

    Details
    한줄 주석
    //
    여러줄 주석
    ///

Functions

  • 함수 정의에서 Void 리턴 타입을 생략하기

    Details
    // WRONG
    func doSomething()->Void{...}
    // RIGHT
    func doSomething(){...}

  • 긴 함수의 호출 ( 파라미터 2개 이상 )

    Details
    // WRONG
    universe.generateStars(at: location, count:5, color: starColor, withAverageDistance:4)
    // WRONG
    universe.generateStars(at: location,
    count:5,
    color: starColor,
    withAverageDistance:4)
    // RIGHT
    universe.generateStars(
    at: location,
    count:5,
    color: starColor,
    withAverageDistance:4)
    // RIGHT
    func generateStars(
    at location:Point,
    count:Int,
    color:StarColor,
    withAverageDistance averageDistance:Float)asyncthrows->String{populateUniverse()}
    // RIGHT
    func generateStars(
    at location:Point,
    count:Int,
    color:StarColor,
    withAverageDistance averageDistance:Float){populateUniverse()}

Closures

  • 사용하지 않는 클로저 파라미터의 이름은 밑줄(_)로 표시하기

    Details
    // WRONG
    someAsyncThing(){ argument1, argument2, argument3 inprint(argument3)}
    // RIGHT
    someAsyncThing(){ _, _, argument3 inprint(argument3)}

Operators

  • 중위 연산자는 양쪽에 공백이 하나씩 두기 및 다양한 공백 너비보다는 괄호를 사용하여 연산자가 많은 문을 시각적으로 그룹화하기

    Details
    // WRONG
    letcapacity=1+2letcapacity= currentCapacity ??0letmask=(UIAccessibilityTraitButton|UIAccessibilityTraitSelected)letcapacity=newCapacity
    letlatitude= region.center.latitude - region.span.latitudeDelta/2.0
    // RIGHT
    letcapacity=1+2letcapacity= currentCapacity ??0letmask=(UIAccessibilityTraitButton | UIAccessibilityTraitSelected)letcapacity= newCapacity
    letlatitude= region.center.latitude -(region.span.latitudeDelta /2.0)

  • 삼항 연산자의 표현이 너무 길어지면, 줄 내려서 사용하기

    Details
    letxx= ab ? a : b
    letdestinationPlanet= solarSystem.hasPlanetsInHabitableZone ?
    solarSystem.planetsInHabitableZone.first :
    solarSystem.uninhabitablePlanets.first

  • 조건이 여러 개의 경우, 각 조건이 별도의 줄에 있도록 하기 ( 조건 2개 이상의 경우 )

    Details
    // WRONG
    if selectImage != userSaveImage && userNickname != nickname && userManager.uid !=""{
    // ...
    }
    // RIGHT
    if selectImage != userSaveImage &&
    userNickname != nickname && userManager.uid !=""{
    // ...
    }

Patterns

  • 열거형에서 switch를 사용할 때 default case를 사용하지 말기

    Details
    // WRONG
    switch trafficLight {case.greenLight:
    // Move your vehicle
    default:
    // Stop your vehicle
    }
    // RIGHT
    switch trafficLight {case.greenLight:
    // Move your vehicle
    case .yellowLight,.redLight:
    // Stop your vehicle
    }

  • 기본 클래스는 final

    Details
    // WRONG
    classSettingsRepository{
    // ...
    }
    // RIGHT
    finalclassSettingsRepository{
    // ...
    }

  • 한줄일 경우엔return 생략

    Details
    // WRONG
    ["1","2","3"].compactMap{returnInt($0)}varsize:CGSize{returnCGSize(
    width:100.0,
    height:100.0)}func makeInfoAlert(message:String)->UIAlertController{returnUIAlertController(
    title:"ℹ️ Info",
    message: message,
    preferredStyle:.alert)}var alertTitle:String{if issue.severity ==.critical {return"💥 Critical Error"}else{return"ℹ️ Info"}func type(of planet:Planet)->PlanetType{switch planet {case.mercury,.venus,.earth,.mars:return.terrestrial
    case.jupiter,.saturn,.uranus,.neptune:return.gasGiant
    }}
    // RIGHT
    ["1","2","3"].compactMap{Int($0)}varsize:CGSize{CGSize(
    width:100.0,
    height:100.0)}func makeInfoAlert(message:String)->UIAlertController{UIAlertController(
    title:"ℹ️ Info",
    message: message,
    preferredStyle:.alert)}var alertTitle:String{if issue.severity ==.critical {"💥 Critical Error"}else{"ℹ️ Info"}func type(of planet:Planet)->PlanetType{switch planet {case.mercury,.venus,.earth,.mars:.terrestrial
    case.jupiter,.saturn,.uranus,.neptune:.gasGiant
    }}

File Organization

  • 서로 다른 종류의 프로퍼티 선언 사이에 빈 줄을 추가하기

    Details
    // WRONG
    staticletgravityEarth:CGFloat=9.8staticletgravityMoon:CGFloat=1.6vargravity:CGFloat
    // RIGHT
    staticletgravityEarth:CGFloat=9.8staticletgravityMoon:CGFloat=1.6vargravity:CGFloat

  • import 문 관리

    내부 / 외부 한 줄 띄고 관리 ( 외부를 상단에, 내부를 하단에, test 최하단 )

    a-z 알파벳 순으로

    Details
    import Constellation
    import DLSPrimitives
    import Epoxy
    import Foundation
    @testableimport Epoxy

  • 프로퍼티 순서

    • 한줄 띄어서 구분
    • propertyWrapper 가 붙는 프로퍼티를 최상단에 선언
    • EnvironmentObject, StateObject, ObservedObject, State, Binding, private 순으로 선언
    • var / let 의 경우, var 를 상단에 let 을 하단에 선언

    Details
    structxxx{@EnvironmentObjectvar...
    @StateObject var...
    @ObservedObject var...
    @State var...
    @Binding var...
    @Presents var ppp:... private var...var aaa
    var bbb
    var ccc
    let ddd
    let eee
    }

    • 연산 프로퍼티는 프로퍼티 중 맨 밑에 선언

    Details
    // WRONG
    varatmosphere:Atmosphere{
    didSet {print("oh my god, the atmosphere changed")}}vargravity:CGFloat
    // RIGHT
    vargravity:CGFloatvaratmosphere:Atmosphere{
    didSet {print("oh my god, the atmosphere changed")}}

  • In TCA

    • @Dependency 위치는 Action 과 body 사이에 사용
    • @Dependency 도 알파벳 순으로 선언

    Details
    enumAction{...}@Dependency(\.dismiss)vardismiss@Dependency(\.swiftDataService)varswiftDatavarbody:someReducerOf<Self>{

    • 프로퍼티 && 액션
      • 관련 기능끼리 모으는걸 우선시하고, 내부에서는 알파벳 순으로 정렬하기

About

Swift 개발에 있어 범용적으로 사용할 수 있는 Swift Code Convension Guide를 정리합니다.

Topics

Resources

Code of conduct

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors