Skip to content

Latest commit

 

History

History
275 lines (234 loc) · 10 KB

영어변수명을잘지어보자.md

File metadata and controls

275 lines (234 loc) · 10 KB

개발자를 위한 영어

"Programs should be written for people to read, and only incidentally for machines to execute"
"프로그램은 사람들에게 읽히기 위한 목적으로 만들어져야 하고, 우연히 컴퓨터가 실행할 수 있다면 더욱 좋다."

출처: Structures and Interpretation of Computer Programs 컴퓨터 프로그램의 구조와 해석

영어 컨벤션
O X 이질적인 느낌 (ex. Android와 iOS에서 사용되는 단어의 차이)
X O 해석이 오래 걸릴수도 있다.
O O 잘 읽히는 코드

잘 읽히는 코드는 영어와 컨벤션을 모두 만족하는 코드이다.

프로그램 = 글

// 주어(view) / 동사(insertSubView) / 목적어(gradientView) / 어떻게(at: 2)
view.insertSubView(gradientView, at: 2)

객체(주어)가 시작을 하고 메서드가 실행(동사)하고 파라미터(목적어)들이 어떻게 사용된다.
위와 같이 코드가 문장처럼 읽히게 된다. 그렇다면 위와 같이 문장처럼 읽히려면 무엇을 지켜야하는가?

1️⃣ 올바른 품사 사용

// 명사(view) / 동사(insertSubView) / 형용사 + 명사(gradientView) / 전치사(at: 2)
view.insertSubView(gradientView, at: 2)

가장 중요한 첫번째는 올바른 품사를 사용한다. (ex. buyButton = 명사 + 명사)
언어를 배우는 가장 첫 번째 단계는 단어를 알고 그 단어의 품사를 알아야 문장으로 바꿀 수 있는데
품사라는 것은 결국에 단어의 성질을 나타낸다는 부분이 중요하다.

명사를 단독으로 사용하지않고 설명을 붙이게된다.
명사를 꾸밀때는 또 다른 명사를 붙여서 꾸며주거나 형용사를 붙여서 사용하게된다.
올바른 품사를 사용할 때 가장 걸림돌이 되는 경우가 있는데... 동사가 계속 변형된다는 점이다.

1-1. 🔥 동사의 변형

동사 원형(~하다) 과거형(~했다) 과거 분사형
request requested requested
make made made
hide hid hidden

🟢 동사 원형

  • 함수 / 메서드에 사용
  • 조동사(can/should/will 등) 뒤에
    • e.g. canBecomeFirstResponder
  • Life Cycle 관련 delegate
    • e.g. didReceive, willAppear, didComplete

⛔️ 과거형

  • 쓸 일이 없음! 🎉

🟢 과거 분사

  • 과거분사 = 형용사 라고 생각하면 편하다
  • 수동의 의미
    • e.g. requestedData, hiddenView
  • Bool 변수
    • e.g. isHidden, isSelected

1-2. 명사와 같은 동사

명사 동사
request request
start start
play play
  • 위 예시와 같이 명사와 동사가 같은 경우도 있음

2️⃣ Bool

의미 예시
is + 명사 ~인가? isDescandant(of:), isVideo, isFavorite
is + 현재진행형(~ing) ~하는 중인가? isExecuting, isPending
is + 형용사 ~인가?
~되었는가?
isOpaque, isEditable
isSelected, isHidden
can/should/will + 동사원형 ~할 수 있나?, ~해야하나?, ~할 것인가? canBecomeFirstResponder
has + 명사 ~을 가지고 있는가? hasVideo, hasiCloudAccount
has + 과거분사 ~되었는가? (상태의 지속 강조) hasConnected, hasEnded
동사원형 용법 - preservesSuperviewLayoutMargins
❗️ is + 동사원형 흔히 하는 실수 isAuthorize, isDelete, isFind, isAdd

3️⃣ 단수와 복수

let album: Album
let albums: [Album]

for album in albums {

}

var album: Album?
let artwork = album.map { downloader.image(from: $0.artworkURL) } // ??

var album: [Album]
let coverSongs = album.map { $0.coverSong }     // ??

3-1. 불규칙 복수형

단수 복수
view views
box boxes
hash hashes
category categories
factory factories
half halves
child children
person people
index indexes, indices
datum data
  • 외울 필요는 없고 사전을 그때 그때 찾아보면서 진행하자!

4️⃣ 타입별 Naming Convention

// ⛔️
var profileImage: String
var profileImageURL: String
var profileImage: URL
var thumbnail: URL
var thumb: UIImage
var profileImage: UIImage

iOS Framework를 확인해보면 위 경우를 명확하게 사용하는 것을 보여준다.

4-1. URL

URL 타입들은 모두 뒤에 URL 단어가 붙어서 정확히 URL 타입을 명시해준다.

var fullSizeImageURL: URL?  // PHContentEditingInput
var renderedContentURL: URL // PHContentEditingOutput
var originalURL: URL?       // MLMediaObject
var thumbnailURL: URL?      // MLMediaObject
var assetURL: URL?          // MLMediaItem
var referenceURL: URL       // SCNReferenceNode

4-2. UIImage

Image 또한 모두 뒤에 붙어서 타입을 명시해준다.

var referenceImage: ARReferenceImage?   // ARImageAnchor
var displaySizeImage: UIImage?          // PHContentEditingInput
var fullSizeImage: CIImage              // PHLivePhotoEditingContent
var iconImage: NSImage?                 // MLMediaGroup
var artworkImage: NSImage?              // MLMediaObject

4-3. Size, Date, Data

위 또한 마찬가지로 프로퍼티에 타입을 다 명시해준다.

var physicalSize: CGSize                // ARReferenceImage
var startDate: Date                     // AVMutable...Group
var creationDate: Date?                 // PHAsset
var arrivalDate: Date                   // CLVisit
var adjustmentData: PHAdjustmentData?   //PHContentEditingInput

5️⃣ etc

ID vs Id vs identifier

var identifier: AVMetadataIdentifier? { get }     // AVMetadataItem
var localIdentifier: String { get }               // PHObject
var formatIdentifier: String { get }              // PHAdjustmentData
var identifier: String { get }                    // CLRegion
var identifier: String { get }                    // MLMediaGroup
var identifier: String { get }                    // SCNReferenceNode
var identifier: String { get }                    // NSPersistentStore
var objectID: NSManangeObjectID { get }           // NSManageObjectID
var recordID: CKRecordID { get }                  // CKRecord
var uniqueID: String? { get }                     // AVMetadataGroup

무조건 identifier로 늘려서 사용하거나 ID의 타입 자체를 새로 만드는 경우인 커스텀 타입에서는 대문자로 사용한다.
그래도 대부분은 늘려서 identifier를 사용한다.

isHidden vs hidden

var isHidden: Bool { get set }
@property(nonatomic, getter=isHidden) BOOL hidden;

Bool 변수를 작성할 때 is를 사용해도되고 사용하지 않아도 문법적으로는 문제가 없다. 그래도 애플에서의 컨벤션으로는 앞에 is를 붙이는 것으로 보인다.

6️⃣ 중복 제거

// ⛔️
struct User {
  let userID: String
}
let id = user.userID

// ✅
struct User {
  let identifier: String
}
let id = user.identifier
// ⛔️
struct ImageDownloader {
  func downloadImage(from url: URL) { }
}
let imageDownloader = ImageDownloader()
imageDownloader.downloadImage(from: imageURL)

// ✅
imageDownloader.download(from: imageURL)
imageDownloader.fetch(from: imageURL)
imageManager.download(from: imageURL)

각 프로퍼티와 메서드명을 알맞게 작성하여도 호출부에서는 문장처럼 느껴지지 않을 수 있다.
그러므로 실제로 사용할 때는 문장처럼 보이도록 노력해보자!

7️⃣ get ❌

Swift는 get을 사용하지 않는 것이 컨벤션인 것 같다.

// 구현부
func date(from string: String) -> Date?
func anchor(for node: SCNNode) -> ARAnchor?
func distance(from location: CLLocation) -> CLLocationDistance
func track(withTrackID trackID: COMPersistentTrackID) -> AVAssetTrack?

// 호출부
let date = formatter.date(from: dateString)
let imageAnchor = sceneView.anchor(for: node)
let distance = startLocation.distance(from: destination)
let track = asset.track(withTrackID: identifier)

8️⃣ 메서드

메서드 네이밍에 관해 이야기해보자.

get
fetch
request
execute / perform

통일된 규칙을 정의할 수 없지만, 많이 쓰는 단어들이 위와 같다.
iOS에서보면 위 단어를 명확하게 구분해서 사용한다.

//MARK: - get
//Async - 비동기 작업에서 네이밍 되어짐, completionHandler를 사용
//Fail(실패)할 수 있다. - Error, nil일 가능성이 있는 경우
//User의 권한을 받아올 때 사용된다.
func getPlaylist(with uuid: UUID, creationMetadata: MPMediaPlaylistCreationMetadata?, completionHandler: @escaping (MPMediaPlaylist?, Error?) -> Void)

//MARK: - fetch
//결과를 바로 리턴할때 사용
class func fetchAssets(withLocalIdentifiers identifiers: [String], options: PHFetchOptions?) -> PHFetchResult<PHAsset>

//MARK: - request
//Async - 비동기 작업에서 네이밍 되어짐, resultHandler를 사용
func requestImage(for asset: PHAsset, targetSize: CGSize, contentMode: PHImageContentMode, options: PHImageRequestOptions?, resultHandler: @escaping (UIImage?, [AnyHashable: Any]?) -> Void) -> PHImageRequestID

//MARK: - execute / perform
//작업 자체가 request 혹은 클로저에 감싸져 있을 때
func execute(_ request: NSPersistentStoreRequest) throws -> NSPersistentStroeResult

8-1. fetch

//PHAsset
class func fetchAssets(withLocalIdentifiers identifiers: [String], options: PHFetchOptions?) -> PHFetchResult<PHAsset>

//PHAssetCollection
class func fetchAssets(in assetCollection: PHAssetCollection, options: PHFetchOptions?) -> PHFetchResult<PHAsset>

//NSManageObjectContext
func fetch<T>(_ request: NSFetchRequest<T>) throws -> [T] where T: NSFetchRequestResult

함수의 리턴값으로 결과를 보내주며 작업이 오래걸리지 않고 바로 결과를 알려주는 느낌.
강아지와 공놀이 하는 것을 play fetch라고 부른다. (물어온다, 당연히 가져와야하는)

마무리

  • 남이 나의 코드를 읽을 때를 고려
  • ⭐️ 동의어 사전 애용(http://www.thesaurus.com)
  • 표준 라이브러리 및 프레임워크 읽어보기