KEMBAR78
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰 | PDF
https://github.com/godrm/ChessMate
🤩
?
?
?
?
?
API 



SwiftLint

CI
API 



SwiftLint

CI
Best Practices & Styles
✱ Tab vs. Space
✱ Braces Styles
✱ Variable, Function, Class - Naming Rules
✱ Computed Properties vs. Methods
✱ Protocol + Extension + Generic
✱ Value Types vs. Reference Types
Software maintenance is
not 'keep it working like before'.
It is 'keep it being useful in a changing world'
- Jessica Kerr
1.
. .
2.
/ .
3.
.
4.
.
5.
/ .
6.
.
7.
. .
, ,
http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
?
+
+
Main - , , ,
Reusability - DRY, components, generics
Reliability - Exception handling and cleanup
Extensibility
Security - , , ,
Performance - , Lazy Loading, ,
Scalability -
Usability -
https://c4model.com
🤩
A B C D E F G H
8
7
6
5
4
3
2
1
Person
ChessMate System
Email System
App Store
Person
ChessMate System
Email System
ChessMate System
iOS App
Android App
API ServerDatabase
Apple
App Store
Google
Play Store
Person
ChessMate System
Mobile App
AppDelegate
ChessView
Controller
API Server
Network
Manager
APNS Server
Background
View
1. SRP (Single-Responsibility Principle)
( , , ) .
- .
2. OCP (Open-Close Principle)
, .
.
3. LSP (Liskov Substitution Principle)
( ) . ( )
.
4. DIP (Dependency-Inversion Principle)
. ( )
, .
5. ISP (Interface-Segregation Principle)
.
struct InputView {
func readInput() {
print(" .")
let userInput = readLine()
guard let input = userInput else { return }
print(seperateCoordinates(userInput: input))
}
//…
}
struct InputView {
func readLine(prompt: String) -> String {
print(prompt)
let line = readLine()
guard let input = line else { return "" }
return input
}
//…
}
class BackgroundView: UIView {
private let Steps = 8
//
convenience init() { self.init(frame: ChessBackgroundView.centralRect()) }
private static func centralRect() -> CGRect {
let screenRect = UIScreen.main.bounds
let verticalMargin = (screenRect.height - screenRect.width) / 2
return CGRect(x: 0, y: verticalMargin,
width: screenRect.width, height: screenRect.width)
}
override func draw(_ rect: CGRect) {
let width = frame.width / CGFloat(Steps)
let height = frame.height / CGFloat(Steps)
var binaryFlag = false
for y in 0..<Steps {
for x in 0..<Steps {
let boxFrame = CGRect(x: CGFloat(x) * width, y: CGFloat(y) * height,
width: width, height: height)
(binaryFlag ? UIColor.white : UIColor.black).setFill()
UIBezierPath.init(rect: boxFrame).fill()
binaryFlag.toggle()
}
binaryFlag.toggle()
}
}
}
UIScreen
GUI
Engine
ChessMate System
BackgroundView
draw(rect:)
init()
centralRect()
UIScreen
GUI
Engine
ChessMate System
BackgroundView
draw(rect:)
init(frame:)
centralRect()
BackgroundPresenter
Person
ChessMate System
Mobile App
AppDelegate
ChessView
Controller
Background
Presenter
Background
View
Person
ChessMate System
Mobile App
AppDelegate
ChessView
Controller
Background
Presenter
Background
View
Pawn
View
King
View
Queen
View …
View DataSource
View
DataSource
DataSource
<Protocol>
Protocol-Oriented Programming
Piece enum
PieceType
.pawn
.king
.queen
.rook
.bishop
.knight
type
Piece
Pawn
type
PieceType
<Protocol>
King Queen Rook Bishop Knight
Person
ChessMate System
Mobile App
AppDelegate
ChessView
Controller
Background
Presenter
Background
View
Piece
<Protocol>
Piece
Constructor Injection
Setter Injection
Interface Injection
class BackgroundView: UIView {
private var presenter : BackgroundPresenter!
convenience init(presenter: BackgroundPresenter) {
self.init(frame: presenter.centralRect())
self.presenter = presenter
}
}
protocol GameManagerAction {
func positionMap() -> Array<Array<Piece?>>
func defaultFrame(path:(x : Int, y: Int)) -> CGRect
}
class ViewController: UIViewController {
private var manager : GameManagerAction!
func setManager(_ manager : GameManagerAction) {
self.positionManager = manager
}
}
protocol PieceImageSetter {
func setImageBy(piece: Piece)
}
class PieceImageView: UIImageView, PieceImageSetter {
func setImageBy(piece: Piece) {
self.image = piece.type.image(color: piece.color.rawValue)
}
}
protocol GameManagerAction {
func positionMap() -> Array<Array<Piece?>>
}
protocol GameManagerGeometric {
func defaultFrame(for: (x : Int, y: Int)) -> CGRect
}
class ViewController: UIViewController {
private var positionManager :
(GameManagerAction & GameManagerGeometric)!
func setManager(_ manager :
GameManagerAction & GameManagerGeometric) {
self.positionManager = manager
}
protocol GameManagerAction {
func positionMap() -> Array<Array<Piece?>>
func defaultFrame(path:(x : Int, y: Int)) -> CGRect
}
Person
ChessMate System
Mobile App
AppDelegate
ChessView
Controller
Background
Presenter
Background
View
Game
Manager
<Action>
Game
Manager
Geometric
.
Don’t get it, Just ask them.
struct GamePositionManager {
var positionMap = Array<Array<Piece?>>()
struct GamePositionManager {
var positionMap = Array<Array<Piece?>>()
(Driver)(Navigator)
http://cameracourage.com/2012/11/what-does-a-rally-co-driver-do/
• .

• .

• , .

• .

• .

• , , !

• .

• .

• .

• ( 10 ~20 ) .

• TDD . ( …)
• .

• .

• .

• .

• .
, .

• .

• .

• .

• : .
• .

• ' ' .

• .

• * * .

• .

• .

• .

• .

• .

• .
• review .

• 

• , 

• 😱

• 

• 

• . .
https://github.com/godrm/ChessMate
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰

Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰