Good

  • ํ”„๋กœ์ ํŠธ ํŒŒ์ผ ๊ตฌ์กฐ ๋ณ€๊ฒฝ
  • ๋ฌธ์„œ ๋ฐฑ์—… ์Šคํฌ๋ฆฝํŠธ ๋งŒ๋“ฌ!! ํ›„ํ›„ ์ด์ œ ์–ธ์ œ๋“  ๋‹ค๋ฅธ ํ”Œ๋žซํผ์œผ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Œ.
  • ์ง‘์ค‘ํ•ด์„œ ํ•ซํ”ฝ์Šค ๋ฌธ์ œ ํ•ด๊ฒฐ
  • ๋””๋ฒ„๊ทธ ๋ฉ”๋‰ด ๊ณจ๊ฒฉ ๋ฐ ํ™”๋ฉด ๊ตฌ์„ฑ.
  • ๊พธ์ค€ํ•œ ์šด๋™ 3๋‹ฌ์งธ ๋‹ฌ์„ฑ์ค‘.

Bad

  • ๋งˆ์Œ์— ํ™”๊ฐ€ ๋งŽ์•„์กŒ๋‹ค.
  • ๊ฐœ๋ฐœ ์„œ์  ๊ณต๋ถ€ ๋ฐ ๋น„ํŠธ์ฝ”์ธ ๊ณต๋ถ€๋ฅผ ํ•  ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค.
  • ๋ธ”๋กœ๊ทธ ๊ธ€์„ ์“ฐ์ง€ ๋ชปํ–ˆ๋‹ค.

Learns

// AS-IS
if let crossoverData = data.crossover,
   let id = crossoverData.id,
   let name = crossoverData.name {
    self.crossover = AuxTypeData(id: id, name: name)
} else {
    self.crossover = nil
}
 
// TO-BE    
let crossover = aux.crossover.flatMap {
    curry(AuxTypeData.init(id:name:)) <*> $0.id <*> $0.name
}
 
public func curry<A, B, C>(_ f: @escaping (A, B) -> C) -> (A) -> (B) -> C {
    { a in { b in f(a, b) } }
}
 
public func <*><A, B>(lhs: ((A) -> B)?, rhs: A?) -> B? {
    guard let lhs = lhs,
          let rhs = rhs else {
        return nil
    }
 
    return lhs(rhs)
}
  • ์—ฐ์†์ ์œผ๋กœ nil์ด ๋œจ๋Š” ๊ตฌ์กฐ์˜ ๊ฒฝ์šฐ์—๋Š” flatMap์„ ์‚ฌ์šฉํ•˜์ž.
  • ๋‚ด๋ถ€ ๋ณ€์ˆ˜๊ฐ€ nil์ธ ๊ฒฝ์šฐ instance๊ฐ€ ์ƒ์„ฑ๋  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๋‹ค.
  • ์›๋ž˜ ๊ฐ™์œผ๋ฉด, nil ์ฒดํฌ๋ฅผ ํ•œ๋‹ค์Œ์— ์—†์œผ๋ฉด nil๋กœ ์„ธํŒ…ํ•ด์คฌ๋Š”๋ฐ,
  • ์ƒ์„ฑ์ž๊ฐ€ ํ•จ์ˆ˜์ธ์ ์„ ์ด์šฉํ•ด์„œ currying์„ ์‚ฌ์šฉํ•˜์—ฌ ์ผ๋‹จ ์ธ์ž์™€ ํ•จ์ˆ˜์™€์˜ ์ปคํ”Œ๋ง์„ ์—†์•ค๋‹ค.
  • ๊ทธ ๋‹ค์Œ, ํ•จ์ˆ˜์™€ ์ธ์ž๊ฐ€ nil์ธ ๊ฒฝ์šฐ์— ๋Œ€ํ•œ ์—ฐ์‚ฐ์ž(<*>)๋ฅผ ์ •์˜ํ•˜๊ณ , ๊ทธ๋Ÿด ๊ฒฝ์šฐ nil์„ ๋˜์ง€๋Š” ๊ฒƒ์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.

Commitment

  • C์–ธ์–ด ๊ฐ•์˜
  • SwiftUI ๊ฐ•์˜
  • ๊ตฌํ˜„ํŒจํ„ด

์ด๊ฑฐ ์–ธ์ œํ•จ?

  • ๋น„ํŠธ์ฝ”์ธ์— ๊ด€๋ จ๋˜์–ด์„œ ๋‚ด๊ฐ€ ์•„๋Š” ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ๋ชจ์‹๋„๋ฅผ ๊ทธ๋ ค๋ด์•ผ ํ• ๋“ฏ.
  • ์ง€๊ฐ‘์•ฑ์„ ๋งŒ๋“ค์–ด๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์Œ
  • ์ด ๊ณผ์ •์—์„œ Swift UI ์‚ฌ์šฉ
  • ์‹œ์ค‘์— ๋‚˜์™€ ์žˆ๋Š” ์ง€๊ฐ‘์•ฑ์ด ์•ฝ๊ฐ„ ๋ณ„๋กœ์ž„.
  • ์•„์นจ์— ์ข€๋” ์ผ์ฐ ์ผ์–ด๋‚˜์•ผ ํ• ๋“ฏ ใ… 
  • ์ฒด์ง€๋ฐฉ 22%๋ฅผ ์œ„ํ•ด ๋‹ฌ๋ ค๋ณด์ž.