编写漂亮的代码作用经常被低估,初学者更是很少重视。其主要的原因在于编写漂亮的代码耗时太长,短时间看收益甚微。
何为漂亮的代码
漂亮的代码是干净的、组织良好、易升级、易于阅读,理解和定位。为了创建和维护这样的代码,笔者遵循以下八个简单的原则。
1.有编码标准
编码标准是一组编码规则。没有通用的编码标准,每个开发团队都可能有自己的书面和不成文规则。而我一般会从以下方面去考虑,有些可以参考官方文档。
- 命名变量和命名方法,
- 如何分组方法以及如何对类进行分组,
- 方法顺序的安排,
- 如何导入依赖项,
- 如何存储数据
当你查看团队中其他开发人员的代码但无法识别是谁编写的代码时,您就知道要有良好的编码规范的重要性了。
规范的代码更容易理解。代码规范可以使你在所有正在工作的项目中保持一致。如果你是第一次查看公司的某个项目,您将知道在哪里搜索您需要的内容。从长远来看,代码规范可以为您节省大量时间 ——从查看代码到升级以前没有使用过的功能,因为您知道会发生什么。
让我们看一下命名变量和方法的一些好的和坏的例子:
// MARK: - Do
var cellEstimateHight = 152
var shouldReloadData = false
var itemsPerPage = 10
var currentPage = 0
// MARK: - Don't
var a = 152
var b = false
var c = 10
var p = 0
// MARK: - Do
func calculateHypotenuse(sideA: Double, sideB: Double) -> Double {
return sqrt(sideA*sideA + sideB*sideB)
}
// MARK: - Don't
func calculate(a: Int, b: Int) -> Int {
return sqrt(a*a + b*b)
}
对方法进行分组,相关方法的放在同个区域,方便查找。
// MARK: - Do
override func viewDidLoad() {
super.viewDidLoad()
self.prepareCollectionView()
self.addLongPressGesture()
self.continueButton.enable()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.showAlertDialogueIfNeeded()
}
private func prepareCollectionView() {
self.collectionView.register(UINib(nibName: "PhotoCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "PhotoCollectionViewCell")
self.collectionView.allowsSelection = false
}
private func addLongPressGesture() {
self.longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongGesture(gesture:)))
self.collectionView.addGestureRecognizer(longPressGesture)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.selectedAssets.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCollectionViewCell", for: indexPath) as? PhotoCollectionViewCell
return cell!
}
// MARK: - Don't
override func viewDidLoad() {
super.viewDidLoad()
self.prepareCollectionView()
self.addLongPressGesture()
self.continueButton.enable()
}
private func prepareCollectionView() {
self.collectionView.register(UINib(nibName: "PhotoCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "PhotoCollectionViewCell")
self.collectionView.allowsSelection = false
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.selectedAssets.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCollectionViewCell", for: indexPath) as? PhotoCollectionViewCell
return cell!
}
private func addLongPressGesture() {
self.longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongGesture(gesture:)))
self.collectionView.addGestureRecognizer(longPressGesture)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.showAlertDialogueIfNeeded()
}
此外,在谈论代码规范时,不要忘记工作区的代码文件的组织规范。要快速定位代码,在创建项目时代码文件的存放同样需要些规范比如:创建彼此相关的文件组、为所有项目保持相同的组织。那样的话如果您处理多个项目,你同样能很快的找到所需的资源。
2.使用自定义的符号
这也可以是编码标准,但我想指出一些关于这个概念的事情。
首先,您清楚地了解什么是全局,什么是当前范围的局部变量。虽然Xcode为全局变量设置了不同的颜色,但这对我来说并不是很好。使用自定义的符号时,识别它会容易得多。
另一方面,如果你有许多处理程序的代码,你必须在其中使用自定义的符号。在处理程序之外使用它也可以使代码统一。
3.使用MARK标记
// MARK 用于将方法划分为有意义且易于导航的部分。在使用和不使用短划线( - )的时候,预览方面有两种类型的标记。带有短划线( - )MARK标记的前面会有一个水平分隔符。
// MARK: -
// MARK: A
// MARK: B
如上,我们可以使用// MARK: -
用于大块的划分,// MARK: A
这种用于子块的注释。
相较于右边的图片,左边图片的代码更易于理解,导航和查看。在我们进行代码review时。如果
没有// MARK: -
或方法的代码放在错误的// MARK: -
下,应该重新打回修改后提交审核。
4.常量
你的类中不应该有任何字符常量或任何其他常量。常量是没有太大价值的信息,所以你不应该注意它。而且,它们可能命名很长使得你的代码可读性下降。
您应该做的是创建一个包含常量的文件,为命名常量创建代码规范,使用MARK标记对它们进行分组,然后在类中使用它们。这样的常量的另一个好处就是你可以重用它们,如果需要改变,那么只在一个地方修改即可。
5.类的规模
根据您正在进行的项目,您应该预先确定类的规模。理想情况下,一个类不应该超过300行,不包含注释,规模小的类会更容易理解,管理和迭代。但当然会有例外。
要先把握类的规模,你必须从架构上考虑。在标准MVC中,控制器的代码要小于300行是很难的。这就是为什么你应该尝试其他类型的架构,如MVVM或Viper。在那里,控制器的代码量不会那么庞大,因为它们只负责表示逻辑。业务逻辑被转移到了其他文件中。
但是,请注意。代码可读性的优先级是高于类的规模。与此同时您的函数也应该控制行数,便于代码的阅读和理解。你应该规定一个函数的最大行数,如果函数超过你既定的最大函数行时,你应该重构它:
// MARK: - Do
override func viewDidLoad() {
super.viewDidLoad()
self.setupTextFields()
self.setupTableView()
self.bindUI()
}
private func setupTableView() {
self.view.backgroundColor = .red
self.tableView.dataSource = self
self.tableView.delegate = self
self.tableView.register(UINib(nibName: "MealTableViewCell", bundle: nil), forCellReuseIdentifier: "MealTableViewCell")
self.tableView.separatorStyle = .none
self.tableView.backgroundColor = .blue
self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 80, right: 0)
}
private func setupTextFields() {
self.emailTextField.delegate = self
self.fullNameTextField.delegate = self
self.passwordTextField.delegate = self
self.passwordTextField.isSecureTextEntry = true
self.confirmPasswordTextField.delegate = self
self.confirmPasswordTextField.isSecureTextEntry = true
self.userRoleTextField.delegate = self
}
// MARK: - Don't
override func viewDidLoad() {
super.viewDidLoad()
self.emailTextField.delegate = self
self.fullNameTextField.delegate = self
self.passwordTextField.delegate = self
self.passwordTextField.isSecureTextEntry = true
self.confirmPasswordTextField.delegate = self
self.confirmPasswordTextField.isSecureTextEntry = true
self.userRoleTextField.delegate = self
self.view.backgroundColor = .red
self.tableView.dataSource = self
self.tableView.delegate = self
self.tableView.register(UINib(nibName: "MealTableViewCell", bundle: nil), forCellReuseIdentifier: "MealTableViewCell")
self.tableView.separatorStyle = .none
self.tableView.backgroundColor = .blue
self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 80, right: 0)
self.bindUI()
}
6.创建重用组件
为获得代码量更少,更易于理解的类的另一个技巧是创建具有以下特征的可重用组件,该组件有一下特征:
- 它处理业务流程
- 它可以访问另一个组件
- 它相对独立于软件
- 它只有一个责任
7.使用设计模式
为了解决问题,我们会引入一些现存的解决方案 - 设计模式。每个模式都像一个蓝图,您可以自定义以解决代码中的特定问题,经过一些练习后,很容易理解和实现。设计模式使开发人员之间的通信更有效。资深的开发人员在参考用于解决特定问题的模式名称时,可以立即在其头脑里有个大概的一个伪代码的实现。
每个应用程序都需要一组不同的模式,但每个应用程序都应该实现常见的模式 - 委托,观察者,工厂,依赖注入。
8.代码审查
虽然代码审查的主要目的应该是在功能上,但我们还需要注意代码的可读性和组织。如果代码没有遵守这些原则,则打回重写修改提交审核。
有些工具可以帮助您进行代码审查,如:SwiftLint或Tailor等来减轻我们代码审查的工作量,因此我强烈建议您使用。
代码审查可能需要一些时间,但它们是对未来的投资。新开发人员将通过查看代码并获取有关他们的反馈来了解这些原则。此外,干净的代码将节省您几个月后回来更改功能的时间。
在审核代码时要严格审核包括自己的代码。如果代码审核的力度太轻,慢慢的代码的审核会越来越随意。你会创造一个可以犯错的氛围。如果代码存在缺陷,请不要合并代码。不然可能在合并代码后忘记解决它们。
结论
代码的功能方面是开发应用程序的重要部分。但是,要轻松维护和升级应用程序,代码必须干净,有条理,易于阅读,理解和定位,或者我们在这里称之为漂亮。
这些是我用来使代码变得美丽的原则。它肯定需要更多的时间来编写和审查,但它将在未来为您节省更多。
原文地址:Beautiful Code Principles