Skip to content

Team Aliens SwiftStyleGuide

Reswo._ edited this page Dec 15, 2023 · 1 revision

Team Aliens Swift Style Guide

์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ณ  ์ž‘์„ฑํ•˜๋Š” ๋ฐ์—, ๋” ๋„์›€์„ ์ฃผ๊ณ  ๋ช…ํ™•ํ•˜๊ฒŒ ์†Œํ†ตํ•˜๊ธฐ ์œ„ํ•œ Team Aliens์˜ Swift Style Guide์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ ๋ฆฌ๋ทฐ๋•Œ์—์„œ ์•„๋ž˜ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์‹ ๋ช…๋‚˜๊ฒŒ ์ง€์ ํ•ด์ฃผ์„ธ์š”! ๊ตฌ์„ฑ์›๋“ค์˜ ์˜์‚ฌ๊ฒฐ์ •์— ๋”ฐ๋ผ ์ˆ˜์‹œ๋กœ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชฉ์ฐจ

Naming

๋””๋ ‰ํ† ๋ฆฌ

  • ๋””๋ ‰ํ† ๋ฆฌ ์ด๋ฆ„์€ ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋‹จ์–ด๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ์— ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ํŒŒ์ผ๋“ค์ด ๋“ค์–ด์žˆ๋‹ค๋ฉด ๋‹จ์–ด์˜ ๋์— ๋ณต์ˆ˜๋กœ s๋ฅผ ๋ถ™์—ฌ์ค๋‹ˆ๋‹ค.
    • GOOD๐Ÿ‘

      - Domains, Entities, Views
    • BAD๐Ÿ‘Ž

      - Domain, Entity, View

ํŒŒ์ผ๋ช…

  • ํŒŒ์ผ๋ช…์€ UpperCamelCase๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ํŒŒ์ผ๋ช…์€ 2์–ด์ ˆ ์ด์ƒ์ผ ๊ฒฝ์šฐ ์ค„์—ฌ์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ViewController, View, ViewModel, Reactor ๋“ฑ ๋งค์นญ๋˜๋Š” **์ ‘๋‘์‚ฌ(prefix)**๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • GOOD๐Ÿ‘

      - HomeVC.swift
      - HomeVM.swift
    • BAD๐Ÿ‘Ž

      - HomeViewController.swift
      - HomeViewModel.swift

class & struct

  • class ๋ฐ struct์˜ ์ด๋ฆ„์€ UpperCamelCase๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ•จ์ˆ˜

  • ํ•จ์ˆ˜ ์ด๋ฆ„์—๋Š” lowerCamelCase๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ํ•จ์ˆ˜ ์ด๋ฆ„ ์•ž์—๋Š” ๋˜๋ก get๊ณผ ๊ฐ™์€ ๊ด‘๋ฒ”์œ„ํ•œ ์˜๋ฏธ๋ฅผ ์ง€๋‹Œ ๋‹จ์–ด์˜ ์‚ฌ์šฉ์„ ์ง€์–‘ํ•ฉ๋‹ˆ๋‹ค.

    • ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ์—ˆ์„ ๋•Œ ํ•œ ๋ฒˆ์— ์ดํ•ดํ•  ์ˆ˜ ์žˆ์„ ๋งŒํ•œ ํ•จ์ˆ˜์˜ ์•ก์…˜์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋‹จ์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      func fetchUserInfo() {
      ...
      }
    • BAD๐Ÿ‘Ž

      func getUserInfo() {
      ...
      }
  • Action ํ•จ์ˆ˜์˜ ๋„ค์ด๋ฐ์€ '์ฃผ์–ด + ๋™์‚ฌ + ๋ชฉ์ ์–ด'์˜ ํ˜•ํƒœ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    • ๋Œ€ํ‘œ์ ์ธ ๋™์‚ฌ๋กœ Tap์€ ๋ฒ„ํŠผ์ด ๋ˆŒ๋ฆฐ ํ–‰์œ„, Gesture๋Š” ํŠน์ • ์ œ์Šค์ณ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ์˜ ํ–‰์œ„, Scroll์€ ์Šคํฌ๋กค์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ์˜ ํ–‰์œ„์ž…๋‹ˆ๋‹ค.
    • will~์€ ํŠน์ • ํ–‰์œ„๊ฐ€ ์ผ์–ด๋‚˜๊ธฐ ์ง์ „์ด๊ณ , did~๋Š” ํŠน์ • ํ–‰์œ„๊ฐ€ ์ผ์–ด๋‚œ ์งํ›„์ž…๋‹ˆ๋‹ค.
    • should~์€ ์ผ๋ฐ˜์ ์œผ๋กœ Bool์„ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋ณ€์ˆ˜

  • ๋ณ€์ˆ˜ ์ด๋ฆ„์—๋Š” lowerCamelCase๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋ณ€์ˆ˜ ํƒ€์ž… ์ค‘ Boolํƒ€์ž…์€ is ์™€๊ฐ™์€ be๋™์‚ฌ๋ฅผ ์ ‘๋‘์‚ฌ๋ฅผ ๋ถ™์—ฌ์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฐฐ์—ด ํ˜น์€ ๋ฆฌ์ŠคํŠธ์™€ ๊ฐ™์ด ๋ณต์ˆ˜์˜ ์˜๋ฏธ๋ฅผ ๋‹ด๊ณ ์žˆ๋Š” ๋ณ€์ˆ˜๋ผ๋ฉด ๋์— s๋ฅผ ๋ถ™์—ฌ์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • GOOD๐Ÿ‘

      var images: [Message] = []
      var title: String = ""
      var isValid: Bool = false
    • BAD๐Ÿ‘Ž

      var image: [Message] = []
      var valid: Bool = false

์ƒ์ˆ˜

  • ์ƒ์ˆ˜ ์ด๋ฆ„์—๋Š” lowerCamelCase๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋ณ€์ˆ˜ ํƒ€์ž… ์ค‘ Boolํƒ€์ž…์€ is ์™€๊ฐ™์€ be๋™์‚ฌ๋ฅผ ์ ‘๋‘์‚ฌ๋ฅผ ๋ถ™์—ฌ์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฐฐ์—ด ํ˜น์€ ๋ฆฌ์ŠคํŠธ์™€ ๊ฐ™์ด ๋ณต์ˆ˜์˜ ์˜๋ฏธ๋ฅผ ๋‹ด๊ณ ์žˆ๋Š” ๋ณ€์ˆ˜๋ผ๋ฉด ๋์— s๋ฅผ ๋ถ™์—ฌ์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • GOOD๐Ÿ‘

      let horizontalMargin: CGFloat = 40
    • BAD๐Ÿ‘Ž

      let HORIZONTAL_MARGIN: CGFloat = 40

enum

  • ์—ด๊ฑฐํ˜• enum ๋ณ€์ˆ˜๋“ค์€ lowerCamelCase๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • GOOD๐Ÿ‘

      enum MessageType {
        case text
        case image
        case video
      }
    • BAD๐Ÿ‘Ž

      enum MessageType {
        case TEXT
        case IMAGE
        case VIDEO
      }

์•ฝ์–ด

  • ์•ฝ์–ด๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ณ€์ˆ˜์˜ ๊ฒฝ์šฐ ์†Œ๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • ์•ฝ์–ด๋กœ ์‹œ์ž‘ํ•˜๋Š” class, struct, enum์˜ ๊ฒฝ์šฐ ๋Œ€๋ฌธ์ž๋ฃŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋ณ€์ˆ˜, ํด๋ž˜์Šค ๋“ฑ์˜ ์ค‘๊ฐ„์— ์•ฝ์–ด๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ๊ฒฝ์šฐ ๋Œ€๋ฌธ์ž๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • GOOD๐Ÿ‘

      let html: String
      let userID: String
      class URLConvertible {}
    • BAD๐Ÿ‘Ž

      let HTML: String
      let userId: String
      class UrlConvertible {}

Formatting

์ตœ๋Œ€ ์ค„๊ธธ์ด

  • ํ•œ์ค„ ์ตœ๋Œ€ ๊ธธ์ด๋Š” 100์ž๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • XCode > Preferences > Text Editing > Display > Page guide at column์—์„œ ์„ค์ •ํ•  ์‹œ ํŽธํ•ฉ๋‹ˆ๋‹ค.

๋“ค์—ฌ์“ฐ๊ธฐ

  • ๋“ค์—ฌ์“ฐ๊ธฐ๋Š” 4 spaces๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • XCode > Preferences > Text Editing > Indentation์—์„œ ์„ค์ • ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋„์–ด์“ฐ๊ธฐ

  • ์ฝœ๋ก (:) ๋’ค์—๋Š” ๋„์–ด์“ฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      let userID: String
    • BAD๐Ÿ‘Ž

      let userID : String
  • ์‚ผํ•ญ์—ฐ์‚ฐ์ž์˜ ๊ฒฝ์šฐ (:)์˜ ์•ž์—๋„ ๋„์–ด์“ฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      isLike ? "heart.fill" : "heart"
    • BAD๐Ÿ‘Ž

      isLike ? "heart.fill": "heart"
  • ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•  ๋•Œ ํŒŒ๋ผ๋ฏธํ„ฐ ๋’ค(,)์—๋Š” ๋„์–ด์“ฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค

    • GOOD๐Ÿ‘

      func sum(x: Int, y: Int) -> Int
    • BAD๐Ÿ‘Ž

      func sum(x: Int,y: Int) -> Int
  • ์—ฐ์‚ฐ์ž ์•ž๋’ค๋กœ ๊ณต๋ฐฑ์„ ์ถ”๊ฐ€ํ•ด์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      let x = 1 + 2
    • BAD๐Ÿ‘Ž

      let x = 1+2

์ค„๋ฐ”๊ฟˆ

  • ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ํ˜น์€ ์ด๋ฆ„์ด ๊ธธ์–ด์ ธ 100๊ธ€์ž๋ฅผ ๋„˜์–ด๊ฐˆ ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ค„๋ฐ”๊ฟˆํ•ฉ๋‹ˆ๋‹ค

    • GOOD๐Ÿ‘

      func animationController(
          forPresented presented: UIViewController,
          presenting: UIViewController,
          source: UIViewController
      ) -> UIViewControllerAnimatedTransitioning? {
      ...
      }
    • BAD๐Ÿ‘Ž

      func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
      ...
      }
  • ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์ตœ๋Œ€ ๊ธธ์ด๋ฅผ ์ดˆ๊ณผํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์„ ๊ธฐ์ค€์œผ๋กœ ์ค„๋ฐ”๊ฟˆํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      self.navigationController?.pushViewController(
        viewController, 
        animated: true
      )
    • BAD๐Ÿ‘Ž

      self.navigationController?.pushViewController(viewController, animated: true)

    ๋‹จ, ํŒŒ๋ผ๋ฏธํ„ฐ์— ํด๋กœ์ €๊ฐ€ 2๊ฐœ ์ด์ƒ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ฌด์กฐ๊ฑด ๋‚ด๋ ค์“ฐ๊ธฐํ•ฉ๋‹ˆ๋‹ค.

    UIView.animate(
        withDuration: 0.25,
        animations: {
        ...
        },
        completion: { finished in
        ...
        }
    )
  • ๋ฐฐ์—ด์˜ ์ปจํ…์ธ ๋ฅผ ์ •์˜ํ•  ๋•Œ ๊ธธ์ด๊ฐ€ ๊ธธ์–ด์ง„๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ค„๋ฐ”๊ฟˆํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      self.addSubViews([
        titleLabel,
        titleButton,
        nextButton
      ])
    • BAD๐Ÿ‘Ž

      self.addSubViews([titleLabel, titleButton,
        nextButton])
  • ๋ณ€์ˆ˜์˜ ๋„ค์ด๋ฐ๊ณผ ํƒ€์ž…๋ช…์ด ๊ธธ์–ด์„œ ์ •์˜ํ•˜๋Š”๋ฐ 100์ค„์ด ๋„˜์–ด๊ฐ„๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ค„๋ฐ”๊ฟˆ ํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      private var myPageTableViewDataSource = 
        RxTableViewSectionedReloadDataSource<MyPageSecionModel>()
    • Bad๐Ÿ‘Ž

      private var myPageTableViewDataSource = RxTableViewSectionedReloadDataSource<MyPageSecionModel>()
  • if let ๊ตฌ๋ฌธ์ด ๊ธธ์–ด์งˆ ๊ฒฝ์šฐ์—๋Š” ์‰ผํ‘œ ์ดํ›„์— ์ค„๋ฐ”๊ฟˆ์„ ํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      if let user = user,
        let compete = compete {
      ...
      }
    • BAD๐Ÿ‘Ž

      if let user = user, let compete = compete {
      ...
      }
  • guard let ... else ๋Š” ํ•œ์ค„์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      guard let user = optionalUser else { return }
    • BAD๐Ÿ‘Ž

      guard let user = optionalUser
      else { return }
  • guard let ๊ตฌ๋ฌธ์ด ๊ธธ ๊ฒฝ์šฐ์—๋Š” ์ค„๋ฐ”๊ฟˆํ•˜๊ณ  ํ•œ ์นธ ๋“ค์—ฌ์”๋‹ˆ๋‹ค. else๋Š” guard์™€ ๊ฐ™์€ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      guard 
          let user = optionalUser,
          let compete = optionalCompete
      else {
          return
      }
    • BAD๐Ÿ‘Ž

      guard let user = optionalUser, let compete = optionalCompete else { return }

๋นˆ ์ค„

  • ๋นˆ ์ค„์—๋Š” ๊ณต๋ฐฑ์ด ํฌํ•จ๋˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ชจ๋“  ํŒŒ์ผ์€ ๋นˆ ์ค„๋กœ ๋๋‚˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • MARK ๊ตฌ๋ฌธ ์œ„์™€ ์•„๋ž˜์—๋Š” ๊ณต๋ฐฑ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
    • GOOD๐Ÿ‘

      // MARK: - Layout
      
      override func layoutSubviews() {
      ...
      }
      
      // MARK: - Actions
      
      func menuButtonDidTap() {
      ...
      }
    • BAD๐Ÿ‘Ž

      // MARK: - Layout
      override func layoutSubviews() {
      ...
      }
      // MARK: - Actions
      func menuButtonDidTap() {
      ...
      }
      

Switch

  • switch๋ฌธ ์•ˆ์˜ case๋ฌธ์€ ์ค„๋ฐ”๊ฟˆ ํ›„ ๋‚ด์šฉ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

  • case๋ฌธ๋“ค ์‚ฌ์ด์—๋Š” ํ•œ ์ค„ ๊ณต๋ฐฑ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      switch user.status {
      case .success:
        ...
      
      case .failure:
        ...
      }
    • BAD๐Ÿ‘Ž

      switch user.status {
      case .success:
        ...
      case .failure: ...
      }
  • switch๋ฌธ ๋‚ด๋ถ€์˜ case์— ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ let์„ ๋งจ ์•ž์— ์œ„์น˜ ์‹œํ‚ต๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      switch user.status {
      case let .success(res):
      ...
      case let .failure(error):
      ...
      }
    • BAD๐Ÿ‘Ž

      switch user.status {
      case .success(let res):
      ...
      case .failure(let error):
      ...
      }

class & struct

  • ๋”์ด์ƒ ์ƒ์†์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ํด๋ž˜์Šค๋Š” ํ•ญ์ƒ final ํ‚ค์›Œ๋“œ๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

  • ํด๋ž˜์Šค์™€ ๊ตฌ์กฐ์ฒด ๋‚ด๋ถ€์—์„œ๋Š” self๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ๋‹จ, ํŒŒ๋ผ๋ฏธํ„ฐ์— ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ self๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘
      class ViewController: UIViewController {
          override func viewDidLoad() {
              super.viewDidLoad()
              self.fetchData(user: userName)
          }
      }
    • BAD๐Ÿ‘Ž
      class ViewController: UIViewController {
          override func viewDidLoad() {
              super.viewDidLoad()
              fetchData(user: self.userName)
          }
      }
  • ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•  ๊ฒฝ์šฐ, ๊ฐ€๊ธ‰์  extension์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    • Good๐Ÿ‘

      class ViewController: UIViewController {
      ...
      }
       
      extension ViewController: UITableViewDelegate {
      ...
      }
    • Bad๐Ÿ‘Ž

      class ViewController: UIViewController, UITableViewDelegate {
      ...
      }

Closure

  • ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๋ฆฌํ„ด ํƒ€์ž…์ด ์—†๋Š” Closure ์ •์˜์‹œ์—๋Š” () -> Void๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      let completionBlock: (() -> Void)?
    • BAD๐Ÿ‘Ž

      let completionBlock: (() -> ())?
      let completionBlock: ((Void) -> (Void))?
  • ํด๋กœ์ € ๋‚ด์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ๊ด„ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      let closure = { arg1, arg2 in
      ...
      }
    • BAD๐Ÿ‘Ž

      let closure = { (arg1, arg2) in
      ...
      }
  • Closure ์ •์˜์‹œ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ํƒ€์ž… ์ •์˜๋ฅผ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      let closure = { arg1 in
      ...
      }
    • BAD๐Ÿ‘Ž

      let closure = { (arg1: String) in
      ...
      }
  • ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํด๋กœ์ € ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” _๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      let closure = { _, arg2 in
          print(arg2)
      }
    • BAD๐Ÿ‘Ž

      let closure = { (arg1, arg2) in
          pring(arg2)
      }
  • Closure ํ˜ธ์ถœ์‹œ ๋˜๋‹ค๋ฅธ ์œ ์ผํ•œ Closure๋ฅผ ๋งˆ์ง€๋ง‰ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š” ๊ฒฝ์šฐ, ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์„ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      UIView.animate(withDuration: 0.5) {
      ...
      }
    • BAD๐Ÿ‘Ž

      UIView.animate(withDuration: 0.5, animations: { () -> Void in
      ...
      })

์ฃผ์„

  • ๋ฌธ์„œํ™”๋ฅผ ํ•  ๊ฒฝ์šฐ ///์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      /// ์‚ฌ์šฉ์ž ํ”„๋กœํ•„์„ ๊ทธ๋ ค์ฃผ๋Š” ๋ทฐ
      class ProfileView: UIView {
      
        /// ์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„์„ ๊ทธ๋ ค์ฃผ๋Š” ๋ผ๋ฒจ
        var nameLabel: UILabel!
      }
    • BAD๐Ÿ‘Ž

      // ์‚ฌ์šฉ์ž ํ”„๋กœํ•„์„ ๊ทธ๋ ค์ฃผ๋Š” ๋ทฐ
      class ProfileView: UIView {
      
          // MARK: ์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„์„ ๊ทธ๋ ค์ฃผ๋Š” ๋ผ๋ฒจ
          var nameLabel: UILabel
      }
  • // MARK: - ๋˜๋Š” // MARK:๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์—ฐ๊ด€๋œ ์ฝ”๋“œ๋ฅผ ๊ตฌ๋ถ„์ง“์Šต๋‹ˆ๋‹ค.

  • // MARK: -๋Š” ๋Œ€์ œ๋ชฉ, // MARK:๋Š” ์†Œ์ œ๋ชฉ๊ฒฉ์œผ๋กœ ๊ตฌ๋ถ„์ง“์Šต๋‹ˆ๋‹ค.

    • GOOD๐Ÿ‘

      // MARK: - Properties
      private let profileImageView = UIImageView()
      
      // MARK: - init
      init() {
      ...
      }
    • BAD๐Ÿ‘Ž

      // MARK: Properties
      private let profileImageView = UIImageView()
      
      // MARK: init
      init() {
      ...
      }

ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ถŒ์žฅ ์‚ฌํ•ญ

  • ์ƒ์ˆ˜๋ฅผ ์ •์˜ํ•  ๋•Œ์—๋Š” enum๋ฅผ ๋งŒ๋“ค์–ด ๋น„์Šทํ•œ ์ƒ์ˆ˜๋ผ๋ฆฌ ๋ชจ์•„๋‘ก๋‹ˆ๋‹ค. ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜ ์ธก๋ฉด์—์„œ ํฐ ํ–ฅ์ƒ์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. struct ๋Œ€์‹  enum์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š”, ์ƒ์„ฑ์ž๊ฐ€ ์ œ๊ณต๋˜์ง€ ์•Š๋Š” ์ž๋ฃŒํ˜•์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค.

  • final class ProfileViewController: UIViewController {
    
        private enum Metric {
            static let profileImageViewLeft: CGFloat = 10
            static let profileImageViewRight: CGFloat = 10
            static let nameLabelTopBottom: CGFloat = 8
            static let bioLabelTop: CGFloat = 6
        }
    
        private enum Font {
            static let nameLabel = UIFont.boldSystemFont(ofSize: 14)
            static let bioLabel = UIFont.boldSystemFont(ofSize: 12)
        }
    
        private enum Color {
            static let nameLabelText = UIColor(hex: 0x000000)
            static let bioLabelText = UIColor(hex: 0x333333)
        }
    
    }

    ์ด๋ ‡๊ฒŒ ์„ ์–ธ๋œ ์ƒ์ˆ˜๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    self.profileImageView.frame.origin.x = Metric.profileImageViewLeft
    self.nameLabel.font = Font.nameLabel
    self.nameLabel.textColor = Color.nameLabelText
  • ์ผ๋ฐ˜์ ์ธ ๋ณ€์ˆ˜, ํ•จ์ˆ˜์˜ ์„ ์–ธ ์ˆœ์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    • ์ƒ์ˆ˜
    • ๋ณ€์ˆ˜
    • ์ƒ์„ฑ์ž ๋ฐ ์†Œ๋ฉธ์ž
    • override ํ•จ์ˆ˜
    • public ํ•จ์ˆ˜
    • private ํ•จ์ˆ˜