본문 바로가기

문법

[Swift] API Design Guidelines 읽어보기

프로그래밍에서 가장 중요하면서도 시간이 많이 투자가되는 네이밍과 규칙들을 알아보자.

영문번역을 직접시도하면 좋았으나 시간이 오래걸려 번역본글을 참고했다.

 

 

- 사용 시점을 명확하게 하는것이 가장 중요한 목표이다. 메서드와 프로퍼티같은 요소들은 반복되서 사용되지만 한번만 선언된다. 용도가 명확하고 견결하게 API를 설계한다. 설계를 평가할때, 선언된 것을 읽는 것으로 충분하지 않다. 맥락이 명확히 보이는지 확인하기 위해 항상 사례를 검토한다.

 

- 명확한 것은 간결한 것보다 중요하다. Swift는 코드를 간결하게 할 수 있지만, 가장 적은 문자들로 가장작은 코드가 가능하지만 그게 목표가 아니다. Swift코드의 간결함은 강한 타입 시스템의 부작용이 발생하고 자연스럽게 상용구를 줄이게 해준다.

 

- 모든 선언에 대해 주석문서를 작성한다. 통찰력을 얻을 수 있는 문서 작성은 설계에 중요한 영향을 미칠 수 있으므로 미루지않는다.

 

 

카테고리
- 이름짓기(Naming)
- 유창하게 사용하기 위해 노력한다(Strive for Fluent Usage)
- 전문용어를 잘 사용한다(Use Terminology Well)
- 규칙(Conventions)
- 매개변수(Parameter)
- 전달인자레이블(Argument Labels)
- 특별 지침(Special Instructions)
- 포인트정리

 

# 이름짓기(Naming)

명확한 사용을 장려한다.( Promote Clear Usage)

- 코드를 읽는 사람을 위해 이름은 애매모호함을 피하기 위해 필요한 모든단어를 포함하여 사용한다.

예를들어, 컬렉션에서 주어진 위치의 요소를 제거하는 메소드를 구성해보자.

 

바람직한예제,  O ) 

extension List {
    public mutating func remove(at position: IndexPath) -> Element
}
employees.remove(at: x)

메서드 표시에서 at단어를 생략하면, 읽는 사람에게 x가 삭제하기 위한 요소의 위치보다는 x같은요소를 삭제하는 메서드를 암시할 수 있다.

- 삭제할 위치가 아닌 요소를 삭제하는 것으로 오해할 수 있음

 

바람직하지않은 예제,  X )

employees.remove(x) // unclear: are we removing x ?

- 불필요한 단어는 생략한다. 이름에 있는 모든단어는 사용하는 곳에 핵심적인 정보를 전달해야한다.

분명한 의도나 명확한 의미를 위해 많은 단어가 필요하지만, 읽는 사람이 이미 알고 있는 장황한 정보는 생략해야 한다.

특히, 단순히 반복되는 타입정보의 단어들은 생략한다.

 

바람직하지않은 예제,  X )

public mutating func removeElement(_ member: Element) -> Element?
allViews.removeElement(cancelButton)

이 경우, Element 단어는 호출하는 곳에서 핵심적인 것을 추가하지 않았다. 아래와같은 API가 더 좋을 것이다.

바람직한예제,  O ) 

public mutating func remove(_ member: Element) -> Element?
allViews.remove(cancelButton) // clearer

가끔씩 애매모호함을 피하기 위해 반복되는 타입정보는 필요하지만, 일반적으로 매개변수의 타입보다 규칙을 설명하는 단어를 사용하는게 좋다. 자세한 내용은 다음 항목을 참조한다.

 

- 변수이름, 매개변수, 역할에 따라 관련된 타입은 제약보다 낫다.

 

바람직하지않은 예제,  X )

var string = "Hello"
protocol ViewController {
    associatedtype ViewType: View
}
class ProductionLine {
    func restock(from widgetFactory: WidgetFactory)
}

타입 이름을 다른 용도로 사용하는 방법은 명확성과 표현성을 최적화 하는데 실패했다. 대신, 요소의 역할을 표현하는 이름을 선택하도록 노력한다.

바람직한예제,  O ) 

var greeting = "Hello"
protocol ViewController {
    associatedtype ContentView: View
}
class ProductionLine {
    func restock(from supplier: widgetFactory)
}

연관된 타입이 프로토콜 제약사항과 밀접하게 결합되어있는경우, 프로토콜 이름은 역할이고, 관련된 타입이름에 Type을 추가하여 충돌을 피한다.

protocol Sequence {
    associatedtype IteratorType: Iterator
}

- 매개변수의 역할을 명확히 하기 위해 부족한 타입 정보를 보충한다.

 

특히 매개변수 타입이 NSObject, Any, AnyObject 또는 Int나 String같은 기본 타입일때, 타입 정보와 사용시점의 상황은 의도를 완전히 전달하지못할 수 있다. 이 예제에서 선언은 명확할 수 있지만, 사용하는 곳이 분명치 않다.

바람직하지않은 예제,  X )

func add(_ observer: NSObject, for keyPath: String)
grid.add(self, for: graphics) // vague

명확하게 하려면, 각 부족한 타입 매개변수 앞에 역할을 설명하는 명사를 붙인다.

바람직한예제,  O ) 

 

func addObserver(_ observer: NSObject, forKeyPath path: String)
grid.addObserver(self, forKeyPath: graphics) // clear

 

 

 

# 유창하게 사용하기 위해 노력한다(Strive for Fluent Usage)

- 메소드와 함수 이름은 영어문법 형태를 선호한다.

바람직한예제,  O ) 

x.insert(y, at: z)  //"x, insert y at z"
s.subViews(havingColor: y) //"x's subviews having color y"
x.capitalizingNouns() // "x, capitalizing nouns"

바람직하지않은 예제,  X )

 

x.insert(y, position: z)
s.subViews(color: y)
x.nounCapitalize()

인자값이 호출에 의미를 주지않을때, 첫번째 또는 두번째 인자 뒤를 능숙하게 다음줄로 내리는 것을 허용한다.

 

AudioUnit: instantiate(
        with: description,
        option: [.inProcess], completionHandler: stopProgressBar)

 

- "make"를 사용하여 팩토리 메서드 이름을 시작한다. 예를들어, x.makeIterator()

- 초기화와 팩토리 메서드 호출은 첫 번째 인자를 포함하지 않은 구문 형태야야한다.

  예를들어, x.makeWidget(cogCount: 47)

 

예를들어, 이러한 호출에 의해 그 구문은 첫번째 인자를 포함하지 않는 것이 암시된다.

바람직한예제,  O ) 

let foreground = Color(red: 32, green: 64, blue: 128)
let newPart = factory.makeWidget(gear: 42, spindles: 14)

다음은 API작성자가 첫번째 인자와 문법적인 연속성을 만드려고 노력했다.

바람직하지않은 예제,  X )

 

let foreground = Color(havingRGBValueRed: 32, green: 62, andBlue: 128)
let newPart = factory.makeWidget(havingGearCount: 42, andSpindleCount: 14)

실제로 이 가이드 라인은 인자레이블을 따른다. 호출할때 첫번째 인자에 대한 레이블이 필요하지 않는 실제로 이 가이드 라인은 첫번째 인자가 레이블이 필요하지 않는 것을 의미하는 인자 레이블을 따르며, 값을 유지하기 위한 타입변환을 실행한다.

let rgbForeground = RGBColor(cmykForeground)

 

 

- 함수와 메소드 이름에 따른 부작용

    * 부작용이 없이, 명사구 처럼읽어야 한다. 예를들어, x.distance(to: y), i.successor()

    * 부작용이 있으면, 필수 동사 구 처럼 읽어야한다. 예를들어 print(x), x.sort(), x.append(y)

    * 가변/불변한 메서드 한 쌍의 이름은 일관되게 짓는다. 가변 메서드는 종종 불변과 비슷한 의미로 변형되지만

      인스턴스를 갱신하는 것보다 새로운 값을 반환하는게 낫다.

        - 동작이 자연스럽게 동사로 설명될때, 가변 메서드에 대해 동사의 명령형을 사용하고 불변메서드

          이름을 보완하기 위해 접미사로 "ed"나 "ing"를 추가한다.

          

          가변(Mutating   |   불변(NonMutating)

          x.sort()               |   z = x.sorted()

          x.append(y)      |   z = x.appending(y)

바람직한예제,  O ) 

동사의 과거 분사(일반적으로 "ed"를 붙임)를 사용하여 불변 메서드와 다른 이름을 선호한다.
/// Reverses 'self' in-place
mutating func reverse()

///Returns a reversed copy of 'self'
func reversed() -> Self

x.reverse()
let y = x.reversed()

"ed"를 추가할때 동사가 목적어를 가지고 있기때문에 문법에 맞지 않는 경우, 동사의 현재 분사를 사용하여 "ing"를 붙여
불변 메서드와 다른 이름이 된다.

///Strips all the newlines from 'self'
mutating func stripNewlines()

///Return a copy of 'self' with all the newlines stripped.
func strippingNewlines() -> String

s.stripNewlines()
let oneLine = t.strippingNewlines()

동작이 자연스럽게 명사로 설명될때 불변 메서드에 대해 명사로 사용하고 가변쪽에는 이름앞에 'form'을 붙인다.

 

        불변(Nonmutating) |   가변(Mutating)

        x = y.union(z)          |   y.formUnion(z)

        j = c.successor(i)    |  c.formSuccessor(&i)

 

- 불변(nonmutating)으로 사용할때 Boolean 메서드와 프로퍼티 사용은 수신자에 관한 주장처럼 읽어야한다.

  예를들어 x.isEmpty, line1.intersects(line2)

- 무언가를 설명하는 프로토콜은 명사처럼 읽어야한다 예를들어, Collection

- able, ible, ing이름에 접미사를 사용하여 프로토콜이 할 수 있는 능력을 설명한다. 예를들어 EQuatable,

  ProgressReporting

- 다른 타입, 프로퍼티, 변수, 상수의 이름은 명사처럼 읽어야한다.

 

 

 

# 전문용어를 잘 사용한다(Use Terminology Well)

용어집(Term of Art)

명사(noun) - 하나의 단어나, 정확한 문구, 특정 영역 또는 직업에서의 특별한 의미

 

- 일반적인 단어가 의미를 더 잘 전달할 수 있다면 애매한 용어는 피한다.

"skin(피부)"가 목적을 전달 할 수 있다면  "epidermis(표피)"라고 하지 않는다. 용어집은(Terms of art)필수적인 커뮤니케이션 도구이지만, 중요한 의미를 잡는데 사용되어야 하며, 그렇지 않으면 의미를 잃어버릴것이다.

 

- 용어집을 사용하는 경우, 기존 의미에 충실해야한다.

기술적인 용어를 사용하는 이유는 무언가에 대해 일반적인 단어보다 더 정확하게 표현하기 때문이고, 그렇지 않으면 모호하거나 불분명할것이다. 그러므로 API는 허용된 의미에 따라 엄격한 용어를 사용해야한다.

 

    * 전문가를 놀라게 하지말라: 새로운 의미를 만들어 내면, 용어에 익숙한 사람은 놀라게 되고, 화를낼것이다.

    * 초보자에게 혼동을 주지말라: 용어를 배우려는 사람은 웹검색을 하여, 전통적인 의미를 찾으려 할것이다.

 

- 약어를 피하라.

약어, 특히 표준이 아닌 것은, 축약되지않은 상태의 정확한 번역에 의존해서 이해하기 때문에, 용어집이 효과적이다.

[약어에 대한 의미는 웹검색으로 쉽게 찾을 수 있다.]

 

- 선례를 받아들인다.

기존문화를 받아들이는데 부담이 되는 모든 초보자를 위해 용어를 최적화하지말라. 연속적인 데이터 구조의 이름은 List처럼 단순한 용어를 사용하는것보다 Array가 더 낫다. 비록 초보자가 더 쉬운 List의 의미를 파악할 수 있더라도 말이다. 배열은 현대 컴퓨터의 기초이다. 모든 프로그래머가 배열이 무엇인지 알고(또는 곧 배울것이다)있다. 대부분의 프로그램들은 익숙한 용어를 사용하고 웹 검색하고 질문으로 보상을 받을 것이다.

 

- 수학같은 특정 프로그래밍영역에서, 널리 알려진 sin(x)용어는 verticalPositionOnInitCircleAtOriginOfEndOfRadiusWithAndle(x)같은 설명문구 보다 더 바람직하다.

이경우, 약어를 피하라는 이전 가이드라인을 넘어선것을 주의 한다. 비로 정확한 단어는 sine이지만, "sin(x)"는 수십년동안 프로그래머와 수 셋기동안 수학자들 사이에서 일반적으로 사용되고 있다.

 

 

# 규칙(Conventions)

 

일반규칙(General Conventions)

- 0(1)이 아닌계산된 프로퍼티의 복잡성을 문서화한다.

사람들은 종종 프로퍼티에 대한 접근이 중요한 계산과 관련되어있지 않다고 가정한다. 이는 저장된 프로퍼티가 정신적인 모델 (mental model)을 가지기 때문이다. 이러한 가정이 어긋날때 알려줘야한다.

 

- 자유 함수(free functions)보다는 메서드와 프로퍼티를 선호한다.

자유함수는 특별한 경우에만 사용된다.

 

    1. self가 분명하지 않을때

    min(x, y, z)

    

    2. 함수가 제약이 없는 제네릭일때

    print(x)

 

    3. 함수의 문법이 기존 영역의 일부분일때

    sin(x)

 

- 규칙을 따른다.

타입과 프로토콜의 이름은 UpperCamelCase이다. 나머지는 lowerCamelCase이다.

일반적으로 미국식 영어에서 모두 대문자로 나타내는 머릿글자는 규칙에 따라 모두 대문자 또는 소문자가 되어야한다.

var utf8bytes: [UTF8.CodeUnit]
var isRepresentAsASCII = true
var userSMTPServer: SecureSMTPServer

다른 머릿글자들은 일반 단어로 취급되어야 한다.

var radarDetector: RedarScanner
var enjoysScubaDiving = true

- 같은 기본의미를 공유할때나 다른 영역에서 동작할때 메서드 기본이름을 공유할 수 있다.

 

예를들어, 메서드가 본질적으로 같은 일을 하기 때문에 담으르 권장한다.

바람직하지않은 예제,  X )

extension Collection where Element: Equatable {
    /// Returns `true` iff `self` contains an element equal to
    /// `sought`.
    func contains(_ sought: Element) -> Bool {}
}

그러나 index메서드는 다른 의미를 가지고 있고, 이름을 다르게 해야한다.

바람직한예제,  O ) 

extension Database {
    /// Rebuilds the database's search index
    func index() {}
    /// Returns the `n`th row in the given table.
    func index(_ n: Int, inTable: TableID) -> TableRow {}
}

 

 

마지막으로 기존타입을 추측하는데애매하기때문에, "반환타입의 재정의는" 피한다.

바람직하지않은 예제,  X )

extension Box {
    /// Returns the `Int` stored in `self`, if any, and
    ///  `nil` otherwise.
    func value() -> Int? {}
    /// Returns the `String` stored in `self`, if any, and
    /// `nil` otherwise.
    func value() -> String? {}
}

 

 

 

# 매개변수(Parameter)

//func move(from: start: Point, to end: Point)

- 문서에 제공할 매개변수 이름을 선택한다. 매개변수 이름이 함수나 메서드를 사용할 때 나타나지 않더라도, 중요한 역할을 설명한다.

 

문서를 쉽게 읽을 수 있는 이름을 선택한다. 예를들어, 이러한 이름은 문서를 자연스럽게 읽을 수 있게 한다.

바람직한예제,  O ) 

// Return an 'Array' containing the elements of 'self'
//  that satisfy 'predicate'.
func filter(_ predicate: (Element) -> Bool) -> [Generator.Elememt]

// Replace the given 'subRange' of elemments with 'newElements'
mutating func replaceRange(_ subRange: Range, with newElements: [E])

 

그러나 문서를 어색하고 문법에 맞지 않게 만든다

바람직하지않은 예제,  X )

func filter(_ includedInResult: (Element) -> Bool) -> [Generator.Element]

mutating func replaceRange(_ r: Range, with: [E])

 

 

- 일반적인 사용을 간소화 할때 기본 매개변수의 장점을 활용한다. 모든 매개변수는 일반적으로 사용되는 하나의 값을 기본으로 사용할 수 있다.

 

기본 인자들은 무관한 정보를 숨겨주어 가독성을 높여준다. 예를들어

바람직하지않은 예제,  X )

let order = lastName.compare(royalFamilyName, options: [], range: nil, locale: nil)

더 간단하게 만들 수 있다.

바람직한예제,  O ) 

let order = lastName.compare(royalFamilyName)

API를 이해하는데 부담이 적기 때문에, 기본 인자들은 일반적으로 메소드 집합(families)을 사용하는 것을 선호한다.

 

 

바람직한예제,  O ) 

extension String {
    public func compare()
  _ other: String, options: CompareOption = [],
range: Range? = nil, locale: Locale? = nil
) -> Ordering
}

위는 간단하지 않지만, 다음 보다는 훨씬 간단하다

 

바람직하지않은 예제,  X )

extension String {
    public func compare(_ other: String) -> Ordering

    public func compare(_ other: String, options: CompareOptions) -> Ordering

    public func compare(
        other: String, options: CompareOptions, range: Range) -> Ordering

    public func compare(
        _ other: String, options: StringCompareOptions,
        range: Range, locale: Locale) -> Ordering
}

메서드 집합의 모든 멤버는 별로도 문서화하고, 사용자를 이해시킬 필요가 있다. 그것들 사이에서 결정하려면, 사용자는 모든것을 이해할

필요하고, 때때로 놀라운 관계를-예를들어, foo(bar:nil) 과 foo() 는 항상같지않다.

 

- 거의 동일한 문서에서 작은 차이를 찾아내는 과정은 지루하다. 하나의 메서드에 기본값을 사용하면 훨씬 우수한 프로그래머 경험을 제공한다.

 

- 매개변수 목록에서 기본값이 있는 매개변수 위치는 끝쪽을 선호한다. 기본값이 없는 매개변수는 일반적으로 메서드 의미에 대해 더 중요하고

메소드가 호출되는 경우 안정적인 초기화 패턴을 제공한다.

 

 

# 전달인자레이블(Argument Labels)

func move(from start: Point, to end: Point)
x.move(from: x, to: y)

- 인자가 유용하게 구별할 수 없는 경우, 모든 레이블은 생략한다. 예를들어 min(numner1, number2), zip(sequence1, sequence2)

 

- 초기화값을 저장하는 타입 변환을 실행하며, 첫번째 인자 레이블은 생략한다. 예들들어, Int64(someUInt32) 첫번재 인자는 언제나 변환되는 원본이 된다.

extension String {
    init(_ x: Bighht, radix: Int = 10)
}

text = "The value is: "
text += String(veryLargeNumber)
text += " and in hexadecimal, it's "
text += String(veryLargeNumber, radix: 16)

좁은 (narrowing) ""타입변환에서 좁아지는(narrowing)것을 설명하는 레이블은 추천한다.

extension UInt32 {
    init(_ value: Int16)
    init(truncating source: UInt64)
    init(saturating valueToApproximate: UInt64)
}

값을 저장하는 타입 변환은 단일형이다. 즉, 원본 결과의 값에서 모든 차이점은 결과 값의 차이이다. 예를들어 언제나 다른 Int8 값은 다른 Int64값으로 변환되기 때문에 Int8에서 Int64로 변환은 값을 유지한다. 다른 반향으로 전환하면 값을 유지할 수 없다.

Int64는 Int8로 표현할 수 있는것보다 더많은 값을 가진다.

주의 : 원래의 값을 검색하는 기능은 변환 값이 유지되는지 아닌지 아무런 관계가 없다.

 

- 첫번째 인자가 전치사구의 일부일때 , 인자레이블을 제공한다. 인자 레이블은 일반적으로 전치사로 시작한다. 예를들어

  x.removeBoxes(havingLength: 12)

 

처음 두개의 인자들이 하나의 추상화 부분을 나타낼때는 예외이다.

 

바람직하지않은 예제,  X )

a.move(toX: b, y: c)
a.fade(fromRed: b, green: c, blue: d)

이와 같은 경우, 명확한 추상화를 위해, 전치사 뒤에 인자레이블을 시작한다.

바람직한예제,  O ) 

 

a.moveTo(x: b, y: c)
a.fadeFrom(red: b, green: c, blue: d)

- 반면, 첫번째 인자가 문법적인 구의 일부일때 레이블을 생략한다. 기본이름의 앞에 단어를 추가한다. 예를들의 x.addSubView(y)

 

이 가이드 라인은 첫번째 인자가 문법에 맞지 않는 경우, 레이블을 가지는 것을 의미한다.

 

바람직한예제,  O ) 

view.dismiss(animated: false)
let text = words.split(maxSplits: 12)
let studentByName = students.sorted(isOrderedBefore: Student.namePrecedes)

그 구가 정확한 의미를 전달하는것이 중요하다. 다음은 문법에 맞지 않는 표현이다.

 

바람직하지않은 예제,  X ) 

view.dismiss(false)
words.split(12)

 

인자의 기본값을 생략할 수 있음을 유의해야하고, 이 경우 문법에 맞지 않기 때문에 항상 레이블을 가져야 한다.

- 다른 모든 인자는 레이블이 있다.

 

 

 

# 특별 지침(Special Instructions)

- API에서 나타나는 클로져 매개변수와 튜플 멤버에 레이블한다.

이러한 이름은 설명의 능력을 가지고 있고, 문서의 주석을 참조할 수 있고, 튜플 멤버에 대한 접근을 제공한다.

/// Ensure that we hold uniquely-referenced storage for at least
/// `requestedCapacity
/// If more storage is needed, `allocate` is called with
/// `byteCount` equal to the number of maximally-aligned
/// bytes to allocate.
/// - Returns:
///  - reallocated: `true` iff a new block of memory
/// was allocated
/// - capacityChanged: `true` iff `capacity` was updated.
mutating func ensureUniqueStorage(minumumCapacity requestedCapacity: Int,
                                  allocate: (byteCount: Int) -> 
                                  UnsafePointer<void>) -> 
                                  (reallocated: Bool, capacityChanged: Bool)

비록 클로저에서 사용될때 기술적으로 인자 레이블이지만, 이러한 레이블을 선택하고 매개변수 이름인 것처럼 문서에서 사용한다.

함수 본문에서 클로저 호출은 첫번째 인자를 포함하지 않는 기본이름에서 구문을 시작하는 함수를 일관되게 읽을 수 있을 것이다.

allocate(byteCount: newCount * elementSize)

- 오버로드 설정에서 애매모호함을 피하기 위해 자유로운 다형성에 좀더 주의를 기울인다.

예를 들어 Any, AnyObject 자유로운 제네릭 매개변수)

예를들어, 오버로드 설정을 고려한다.

바람직하지않은 예제,  X ) 

struct Array {
    ///Inserts `newElement` at `self.endIndex`.
    public mutating  func append(_ newElement: Element)
    ///Inserts the contents of `newElements`, in order, at
    /// self.endIndex`.
    public mutating func append(_ newElements: S)
    where S.Generator.Element == Element
}

이 메소드들은 의미론적인 집합 형태이고, 인자 타입은 확연히 구분되도록 처음에 나타난다. 그러나, Element가 Any일때 하나의 요소는 요소의 시퀀스 처럼 같은 타입을 가질 수 있다.

바람직하지않은 예제,  X ) 

var values: [Any] = [1, "a"]
values.append([2,3,4])

애매모호한 것을 제거하기 위해, 더 명시적으로 두번째 오버로드 이름을

바람직한예제,  O ) 

struct Array {
    ///Inserts `newElement` at `self.endIndex`.
    public mutating  func append(_ newElement: Element)
    ///Inserts the contents of `newElements`, in order, at
    /// self.endIndex`.
    public mutating func append(contentOf newElement: S)
    where S.Generator.Element == Element
}

새로운 이름이 문서 주석과 더 일치하는지 알 수 있다. 이런 경우 문서 주석을 작성하는 행동은 실제로 API작성자의 관심이 문제가 된다.

 

 

포인트정리

- 사용시점을 명확하게하는것이 가장 중요한 목표이다.

- 명확한 것은 간결한 것보다 중요하다.

- 모든 선언에 대해 주석문서를 작성한다.

- 분명한 의도나 명확한 의미를 위해 많은 단어가 필요하지만, 읽는 사람이 이미 알고 있는 장황한 정보는 생략해야 한다.

- 메서드 구현시 각 부족한 타입 매개변수 앞에 역할을 설명하는 명사를 붙인다.

- 메소드와 함수 이름은 영어문법 형태를 선호한다.

- "make"를 사용하여 팩토리 메서드 이름을 시작한다.

- 함수는 명사구처럼읽어야하며 가변메서드는 동사형을 불변메서드는 접미사 ed, ing를 추가하여 보완한다.

- 다른 타입, 프로퍼티, 변수, 상수의 이름은 명사처럼 읽어야한다.

- 프로토콜을 만들때는 기능을 설명하는 able, ible, ing 와 같은 접미사를 사용하여 트로토콜의 능력을 표현한다.

- 불변(nonmutating)으로 사용할때 Boolean 메서드와 프로퍼티 사용은 수신자에 관한 주장처럼 읽어야한다.

- 명사(noun) - 하나의 단어나, 정확한 문구, 특정 영역 또는 직업에서의 특별한 의미

- 모호한 단어와 약어를 피하고, 전문가를 놀라게하지말고 초보자에게 혼동을 주지말자.

- 연속적인 데이터구조의 이름은 List처럼 단순한 용어를 사용하는것보다 Array가 더 나음

- 타입과 프로토콜은 UpperCamelCase로 작성하고 그외는 다 LowwerCamelCase로 작성한다.

- 첫번째 인자가 전치사구의 일부일때 , 인자레이블을 제공한다.

 

Reference

- https://kka7.tistory.com/37

 

Swift API Design Guidelines

Swift API Design Guidelines Swift 개발문서 API Design Guidelines 기본 원칙(Fundamentals) 사용 시점을 명확하게 하는 것이 가장 중요한 목표이다. 메소드와 프로퍼티 같은 요소들은 반복되서 사용되지만 한..

kka7.tistory.com

Another

원본 - https://www.swift.org/documentation/api-design-guidelines/

 

Swift.org

Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.

www.swift.org

- https://github.com/StyleShare/swift-style-guide#%EB%84%A4%EC%9D%B4%EB%B0%8D

 

GitHub - StyleShare/swift-style-guide: StyleShare에서 작성한 Swift 한국어 스타일 가이드

StyleShare에서 작성한 Swift 한국어 스타일 가이드. Contribute to StyleShare/swift-style-guide development by creating an account on GitHub.

github.com