どうも。Reoです。
前回「AppApp のリファクタリングを始めます!【SwiftLint 導入編】」から始まったAppAppのリファクタリング過程紹介の第2弾です。
作業をする時は常に WordPress を開いて、むしろブログを書くことをメインにしながらやっていく予定です。
しばらくは何も考えずブログを書きながらリファクタリングするマシーンになります。仕事が入ればそっちを優先しますが...
環境
- Xcode11.3.1
- Swift 5.1.3
- iOS13.3
前回 → AppApp のリファクタリングを始めます!【SwiftLint 導入編】
リポジトリは uruly/AppApp にて公開しています。
今回の目標
今回の目標は、SwiftLint の Warning と Error をなくすぞ!!!です。
黙々と作業をして、記事に書くことが特にないじゃんと思っていますが、まぁ何かしら書きます。今回は特に有益になりそうなものもないかもしれないです。
なんやかんやで書き終わってみると、長くなってしまったので今回は Error 解消だけになりました。
.swiftlint.ymlの中身
前回の最後に、disabled_rules に force_try を追加した状態になっています。後々有効化させるかもしれませんが、そこまで頑張れるか...
disabled_rules:
- force_cast
- force_try
included:
- AppApp
excluded:
- Carthage
line_length: 200
large_tuple: 5
file_length:
warning: 500
error: 1200
nesting:
type_level:
warning: 2
identifier_name:
excluded:
- id
- URL
cyclomatic_complexity: 20
都度追加するかもしれないですし、しないかもしれないです。
Errorを潰そう!
SwiftLint を導入したことによって発生した Error を修正していきます。 合計10個なのでサクッといきたいけどちゃんと書くよ。
Identifier Name
Identifier Name Violation: Variable name should be between 3 and 40 characters long: 'r' (identifier_name)
変数の名前は3〜40文字の間で設定しなさぁ〜い!ってやつです。
怒られている場所晒し。例えばこういうところ。
①
extension UIImage {
func maskCorner(radius r: CGFloat) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(self.size, true, 0.0)
let rect = CGRect(origin: CGPoint.zero, size: self.size)
UIBezierPath(roundedRect: rect, cornerRadius: r).addClip()
draw(in: rect)
let clippedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return clippedImage
}
}
if文も対象ですね。
②
for i in order ..< objects.count {
try! realm.write {
objects[i].order = i + 1
realm.add(objects[i], update: .all)
}
}
座標を示すx, y も対象です。
③
func scrollToHorizontallyCenter(index: Int, x: CGFloat) {
}
これって結構 Swift 特有だと思いませんか?
他の界隈にいると、当たり前のように i や x, y が登場してきます。
先日読んだJavaScriptの本でも当然のように出てきましたし、プログラミングをやっていて当たり前のようにi, j, x, y は出てきます。計算が多いと特にそうですね。
でも個人的にはこのルールは好きです。
むしろ他言語にいくと読めづらいと思ってしまいますね。
修正していきますね。
① -> r 部分を削除してそのまま radius にする。(なんで r にしたのかもちょっと謎)
func maskCorner(radius: CGFloat) -> UIImage? {
② -> for 文を使わないで書けないかをまず考えます。
try! realm.write {
objects.map { object in
// 変更した order より大きいものだけ並び替える
if object.order > order { return }
let newObject = object
newObject.order += 1
realm.add(newObject, update: .all)
}
}
そもそものRealmの使い方と実装がアレなのでチョットなんともいえないんですが、map等を利用してfor文自体をあんまり使わないようにするといいはず。と思っています。いや、この部分難しいな。
あとは for i in ..< hoges.count {}
よりも for hoge in hoges {}
を使おうって話かもしれないです。
いやいや配列の添字がほしいんじゃって時はよくあるので、そういう時は enumerated を使うと良いです。
for (index, object) in objects.enumerated() {}
便利!!!でも実際に使ったことってあんまりないかも。
③ -> x を何のxなのかを明確にする。targetX に変更しました。
func scrollToHorizontallyCenter(index: Int, targetX: CGFloat) {
}
Shorthand Operator
Shorthand Operator Violation: Prefer shorthand operators (+=, -=, *=, /=) over doing the operation and assigning. (shorthand_operator)
複合代入演算子を使いましょうね〜ということ。
// 修正前
label.order = label.order - 1
// 修正後
label.order -= 1
うむ。
Identifier Name(2回目)
またこれだ!
Identifier Name Violation: Variable name should only contain alphanumeric characters: 'APPLE_ID' (identifier_name)
アプリ全体の定数みたいなのを以下のようにしてたんですねぇ。
let APPLE_ID = "1319908151"
しかも結構雑に。適当なファイルに書いてるんですよねー。
これは共通の定数を各ファイルを用意(Constants.swift)して、以下のように書きました。
import UIKit
extension String {
static let appleID = "1319908151"
}
extension UInt64 {
static let schemaVersion = 5
}
これで使う時は String.appleID
もしくは .appleID
で使えます。
単純な名前変更ではないので、VSCode でフォルダごと開いてまとめて置換ってのを稀によくやります。
そもそもSchemaVersionをいろんなところで出てくる設計よ...
やったー!エラーが消えたので無事ビルドすることができました!
次回
丁寧に書こうと思って書いてたら、既に3000字を余裕で越しているので、Warning 解消は次回にします。まぁ今からやるんですけど、記事分割しますね。
次回も作業自体は今回と同様のはず。
おわりに
disabled_rules に設定している force_cast を外してみると、あらびっくり。
54回も force_cast をしているみたい!大変!
これは後々、R.swift を入れて解消をしたいところもあるので、もうしばらくは disabled のままにしておきます。
force_try の方はもれなく全部Realm関連なので、そこを修正する時にどうにかします。
さて。次行ってみよう。
コメントはありません。
現在コメントフォームは工事中です。