Swift API 가이드라인 - 1

rbw·2023년 5월 15일
0

TIL

목록 보기
80/98

Swift API Design Guideline - 1

야곰님의 스위프트 API 스위프트 가이드라인을 보고 정리한 글임니다 아마 번역글이라고 들은듯함다

Fundamentals(핵심개념)

API 설계의 가장 중요한 목적은 사용하는 시점의 명료성입니다. 항상 문맥에 알맞도록 명확하게 설계하였는지 실질적인 사용 예시를 통해 확인해야합니다.

명료성은 간결성보다 더 중요합니다

모든 선언문에 문서 주석을 작성합니다

/// 동일한 요소들을 포함하는 `self`의 "view"를 역순으로 변환
func reversed() -> ReverseCollection

선언된 개체를 설명하는 요약부터 시작하세요.

요약에 초점을 맞추세요

가능하다면, 한 문장 구성 단위(구, 절)를 사용하고 끝에 마침표로 끝내세요 완전한 문장으로 사용하는 것은 지양합니다.

함수 또는 메서드가 하는 일이 무엇이고, 어떤 것을 반환하는지 설명하세요

/// `self`의 시작 부분에 `newHead` 삽입
mutating func prepend(_ newHead: Int)

/// `self`의 요소에 있는 'head`가 포함된 `List` 반환
func prepending(_ head: Element) -> List

/// 비어있지 않다면 `self`의 첫 번째 요소를 반환 및 제거하고, 비어 있다면 `nil` 반환
mutating func popFirst() -> Element?

드문 경우에, popFirst() 같이 콤마(세미콜론)를 이용하여 여러 문장 구성 단위(구,절) 형태로 요약을 작성할 수 있습니다.

경우에 따라, 한 개 이상의 절과 글머리 기호로 이어갈 수 있습니다 절은 빈줄로 구별하고 완벽한 문장을 사용하세요

/// 표준 출력에 `items`의 각 요소에 대한 텍스트 표현을 작성합니다. <- Summary (요약)
/// Blank Line (빈줄)
/// 각 요소인 `x`에 대한 텍스트 표현은 `String(x)` 표현식에 의해 만들어집니다. <- Additional discuttion (추가 설명)
///
/// - 매개변수 sepapator: 요소 사이에 출력되는 텍스트
/// - 매개변수 terminator: 끝부분에 출력되는 텍스트 -> 매개변수 부분
///
/// - 주의(Note): 줄 바꿈을 하지 않으려면 `terminator: ""` 입력
/// - 참조(SeeAlso): `CustomDebugStringConvertible`, `debugPrint`. -> 기호 명령
public func print(_ items: Any..., separator: String = " ", terminator: String = "\n")

글머리 기호와 심볼 명령 구문을 알고 사용합니다 여러 심볼들이 존재합니다. Complexity, Important, Date, Note, Parameter, SeeAlso, Warning, Todo, Returns, Requires, Todo 등등

Naming

Promote Clear Usage(명확하게 사용하기)

이름이 사용된 코드를 읽을 사람들을 위해 모호하지 않도록 필요한 모든 단어를 포함합니다

예로, 컬렉션 내 주어진 위치에 있는 요소를 제거하는 메서드를 들어보갰습니다.

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

메서드 서명에서 at이라는 단어를 생략한다면, 읽는 사람에게 제거할 요소의 위치를 나타내기 위해 x를 사용했다기보다, x와 같은 요소를 제거한다는 의미일 가능성을 제시합니다.

불필요한 단어는 생략합니다 이름 내 모든 단어는 사용 장소에서 핵심적인 정보를 전달해야 합니다.

분명한 의도나 모호하지 않은 의미를 위해 더 많은 단어가 필요할 수 있지만, 읽는 사람이 이미 알고 있는 중복되는 정보는 생략합니다. 특히, 타입 정보만 반복하는 단어는 생략합니다.

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

때때로는 모호함을 피하기 위해 타입 정보를 반복하는 것이 필요하지만, 일반적으로 타입보다는 매개변수의 역할을 설명하는 단어를 사용하는 것이 더 낫습니다.

타입 제약이 아닌 해당 역할에 따라 변수, 매개변수, 및 연관 타입을 명명합니다

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

이런 방식으로 타입 이름을 고치는 것은 명확성과 표현성을 최적화하지 못합니다. 대신 개체의 역할을 나타내는 이름을 선택하도록 노력합니다.

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

매개변수의 역할을 명확하게 하기 위해 약한 타입 정보를 보완합니다

특히 매개변수 타입이 NSObject, Any, AnyObject 또는 Int나 String 같은 기본 타입인 경우, 사용 시점에 타입정보와 컨텍스트가 의도를 전달하지 못할 수 있습니다. 아래 예제에서 선언은 명확할 수 있지만, 사용 장소가 모호합니다.

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

// 명확하게 하려면 각 약한 타입의 매개변수 앞에 그 역할을 설명하는 명사를 위치시킵니다func addObserver(_ observer: NSObject, forKeyPath path: String)
grid.addObserver(self, forKeyPath: graphics) // clear

Strive for Fluent Usage(자연스러운 사용을 위해 노력하기)

사용되는 곳의 메서드와 함수의 이름은 영어 문법에 맞는 구가 되도록 하는 것이 좋습니다

✅
x.insert(y, at: z)         // “x, insert y at z” “x의, z에 y를 삽입한다”
x.subViews(havingColor: y) // “x's subviews having color y” “y 색상인, x의 하위 뷰”
x.capitalizingNouns()      // “x, capitalizing nouns” “x의 명사 대문자화”

첫 번째 또는 두 번째 전달인자 이후의 전달인자가 호출 의미의 핵심이 아닌 경우엔 자연스러움이 떨어져도 괜찮습니다.

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

x.makeIterator()와 같이, 팩토리 메서드의 이름은 "make"로 시작합니다.

x.makeWidget(cogCount: 47)처럼, 이니셜라이저와 팩토리 메서드 호출에 대한 첫 번째 전달인자는 함 수이름으로 시작하는 구로 형성하면 안됩니다.

let foreground = Color(red: 32, green: 64, blue: 128)
let newPart = factory.makeWidget(gears: 42, spindles: 14)
let ref = Link(target: destination)

함수와 메서드 이름은 그 부수 효과에 따라 명명합니다

예를 들어, x.distance(to: y), i.successor()는, 부수 효과가 없는 함수 및 메서드는 명사 구로 읽어야 합니다.

print(x), x.sort(), x.append(y) 와 같은 부수 효과가 있는 함수 및 메서드는 명령형인 동사구로 읽어야 합니다.

변환 / 비변환 메서드 쌍은 일관되도록 명명합니다. 변환 메서드는 종종 비슷한 의미를 가진 비변환 함수를 갖지만, 해당 메서드는 인스턴스 자체를 업데이트하기 보다는 새로운 값읇 반환합니다.

기능이 동사로 자연스럽게 설명 되는 경우, 변환 메서드는 동사의 명령형을 사용하고, "ed" 또는 "ing" 접미사를 붙여 그에 대응하는 비변환 메서드 이름에 적용합니다.

  • Mutaing: x.sort(), x.append(y)
  • Nonmutating: z = x.sorted(), z = x.appending(y)

동사가 직접 목적어를 가지고있어서 "ed"를 추가하는 것이 문법적이지 않는 경우, 비변호나 형태는 "ing"를 붙여 동사의 현재분사형으로 명명합니다.

/// `self`에서 모든 줄바꿈을 제거합니다.
mutating func stripNewlines()

/// 모든 줄바꿈이 제거된 `self`의 복사본을 반환합니다.
func strippingNewlines() -> String

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

기능이 명사로 자연스럽게 설명되는 경우에 비변환 메서드에 명사를 사용하고, “form” 접두사를 붙여 그에 대응하는 변환 메서드 이름에 적용합니다.

  • Mutating: x.formUnion(z), c.formSuccessor(&i)
  • Nonmutating: x = y.union(z), j = c.successor(i)

x.isEmpty, line1.intersects(line2) 처럼, 부울 메서드 및 프로퍼티의 사용은 비변환 메서드일 때, 수신자에 대한 주장처럼 읽어야 합니다

무언가를 설명하는 프로토콜은 명사로 읽어야 합니다. (Collection 등)

능력을 설명하는 프로토콜은 able, ible 또는 ing 접미사를 사용해서 명명해야 합니다. (Equatable, ProgressReporting 등)

다른 타입, 프로퍼티, 변수 그리고 상수의 이름은 명사로 읽어야 합니다.

Use Terminology Well(적절한 기술 용어 사용하기)

만약 일반적으로 사용되는 단어로도 충분히 의미가 전달된다면 이해하기 힘든 용어는 사용하지 않도록 합니다 "피부"라는 단어만으로도 의도가 전달된다면 "표피"라는 단어로 표현하지 않도록 합니다.

전문가가 경악하지 않도록 합니다 만약 용어를 기존의 의미가 아닌 쓰이지 않던 새로운 의미로 사용한다면 그 용어에 대해 이미 익숙한 사람은 경악하고 불쾌해 할 것입니다.

초심자 입장에서 혼동되지 않도록 합니다 누군가는 웹 검색을 통해 사용된 용어가 가지고 있는 고유한 의미를 찾아내려고 할 것입니다.

축약어를 피하도록 합니다. 표준 축약어가 아닌 축약어들은 실질적으로 기술 용어입니다. 축약되지 않은 표현으로 얼마나 잘 번역하는지에 따라 그 기술 용어에 대한 이해도가 달라지기 때문입니다.

선례를 따르도록 합니다 일반적으로 사용해오던 기존의 용어를 대체하면서까지 초심자의 눈높이에 맞춰 용어를 최적화하지 않도록 합니다.'verticalPositionOnUnitCircleAtOriginOfEndOfRadiusWithAngle(x)' 보다는 'sin(x)'를 사용하는 것이 좋습니다.

profile
hi there 👋

0개의 댓글