-
Notifications
You must be signed in to change notification settings - Fork 0
Team Aliens SwiftStyleGuide
์ฝ๋๋ฅผ ์ดํดํ๊ณ ์์ฑํ๋ ๋ฐ์, ๋ ๋์์ ์ฃผ๊ณ ๋ช ํํ๊ฒ ์ํตํ๊ธฐ ์ํ Team Aliens์ Swift Style Guide์ ๋๋ค. ์ฝ๋ ๋ฆฌ๋ทฐ๋์์ ์๋ ๋ด์ฉ์ ๋ฐํ์ผ๋ก ์ ๋ช ๋๊ฒ ์ง์ ํด์ฃผ์ธ์! ๊ตฌ์ฑ์๋ค์ ์์ฌ๊ฒฐ์ ์ ๋ฐ๋ผ ์์๋ก ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค.
- ๋๋ ํ ๋ฆฌ ์ด๋ฆ์ ๋๋ฌธ์๋ก ์์ํ๋ ๋จ์ด๋ก ์ค์ ํฉ๋๋ค.
- ํด๋น ๋๋ ํ ๋ฆฌ์ ๋น์ทํ ๊ธฐ๋ฅ์ ํ๋ ํ์ผ๋ค์ด ๋ค์ด์๋ค๋ฉด ๋จ์ด์ ๋์ ๋ณต์๋ก
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์ ์ด๋ฆ์
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 ๋ณ์๋ค์
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 {}
-
- ํ์ค ์ต๋ ๊ธธ์ด๋ 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๋ฌธ ์์ 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): ... }
-
-
๋์ด์ ์์์ด ๋ฐ์ํ์ง ์๋ ํด๋์ค๋ ํญ์
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) } }
-
GOOD๐
-
ํ๋กํ ์ฝ์ ์ฑํํ ๊ฒฝ์ฐ, ๊ฐ๊ธ์
extension
์ ์ฌ์ฉํฉ๋๋ค.-
Good๐
class ViewController: UIViewController { ... } extension ViewController: UITableViewDelegate { ... }
-
Bad๐
class ViewController: UIViewController, UITableViewDelegate { ... }
-
-
ํ๋ผ๋ฏธํฐ์ ๋ฆฌํด ํ์ ์ด ์๋ 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 ํจ์