[SWIFT] Verbesserung des schwer lesbaren Codes durch lesbaren Code ~ Allgemein

Hallo, das ist Nekokichi ( @ nekokichi1_yos2 ).

Dies ist die 4. lesbare Codeverbesserungsserie.

(Weitere Informationen finden Sie im Folgenden.) Verbesserung des schwer lesbaren Codes durch lesbaren Code ~ Vorbereitung [Verbesserung des schwer lesbaren Codes durch lesbaren Code ~ Name] (https://qiita.com/NEKOKICHI2/items/dc774bd79b1623032712) Verbesserung des schwer lesbaren Codes durch lesbaren Code ~ Beauty Verbesserung des schwer lesbaren Codes durch lesbaren Code ~ Kommentare

** Dieses Mal werden wir den gesamten Code verbessern. ** **.

Unterrichten von lesbarem Code

"Bedingte Ausdrücke ausrichten" ・ Verwenden Sie das Bestätigungsformular für Bedingungen ・ Schreiben Sie zuerst leicht verständliche Bedingungen

"Der ternäre Operator ist nichts Erstaunliches" ・ Der Code kann gekürzt werden, ist aber schwer zu lesen.

"Funktion frühzeitig zurückgeben" ・ Bereiten Sie mehrere Ausgänge vor ・ Der Code wird nicht redundant

"Verschachtelung ist einfach und unkompliziert" ・ Je tiefer das Nest, desto mehr Belastung für den Leser ・ Es ist notwendig, sich immer an bedingte Ausdrücke und Variablen zu erinnern und sich darauf zu konzentrieren, das Innere des Nestes zu verstehen.

"Erklärende Variablen, zusammenfassende Variablen" -Erklärende Variable: Gibt an, welchen Wert der Variablenname hat. ・ Zusammenfassungsvariablen: Sammeln Sie große Werte und Ausdrücke mit Variablen

"Missbrauch der Kurzschlussauswertung" ・ Einfach weniger Code ist nicht gut ・ Auch wenn der Inhalt derselbe ist, ist es wünschenswert, dass er leicht zu verstehen ist.

"Teile einen riesigen Ausdruck" ・ Wenn derselbe Ausdruck mehrmals vorkommt, verwenden Sie eine Zusammenfassungsvariable -Vorteile: Tippfehler, kürzerer Code, leichter zu korrigieren

"Variable löschen"

"Reduzieren Sie den Umfang der Variablen" ・ Ein großer Anwendungsbereich macht es schwierig zu verfolgen, wo Änderungen vorgenommen wurden. ・ Reduzieren Sie den Bereich von global auf lokal

"Verringern Sie die Position der Definition" -Wenn Sie es in Definition und Verarbeitung unterteilen, müssen Sie immer den Wert der Variablen kennen. ・ Wenn Sie die Definition und Verarbeitung als Satz festlegen, können Sie die erforderlichen Variablen finden und leichter lesbar machen.

"Variablen nur einmal schreiben" ・ Wenn die Anzahl der Änderungen groß ist, ist der aktuelle Wert nicht bekannt. -Verwenden Sie let oder private, um dauerhafte Änderungen zu verbieten ・ Reduzieren Sie die Anzahl der Änderungen aufgrund erklärender Variablen usw.

Teilen Sie einen großen Ausdruck

Ich konvertiere den attributierten Text von memoTextView in Data (), aber es ist gefährlich, den Wert der Benutzeroberfläche so zuzuweisen, wie er ist, und der Eigenschaftsname ist lang. Deshalb habe ich ihn in die Variable inputAttrText in der Guardlet-Anweisung eingefügt.

AddMemo.swift


let attributedMemoData = try! NSKeyedArchiver.archivedData(withRootObject: memoTextView.attributedText!, requiringSecureCoding: false)

AddMemo.swift


guard let inputAttrText = memoTextView.attributedText else { return }
let attributedMemoData = try! NSKeyedArchiver.archivedData(withRootObject: inputAttrText, requiringSecureCoding: false)

Der Wert wird der Übergangszielvariablen in prepare () zugewiesen.

Ich beziehe mich auf den ausgewählten zeilenweisen Wert von memoTableView, aber da der Eigenschaftsname zu lang und schwer zu erkennen ist, habe ich eine Variable indexPathRow vorbereitet und die Länge des zuzuweisenden Ausdrucks verkürzt.

ViewController.swift


let vc = segue.destination as! DisplayMemo
vc.selectedMemoObject   = memoListForRealm[memoTableView.indexPathForSelectedRow!.row]
vc.selectedMemoString   = memoList[memoTableView.indexPathForSelectedRow!.row]
vc.selectedIndexPathRow = memoTableView.indexPathForSelectedRow!.row

ViewController.swift


let vc = segue.destination as! DisplayMemo
guard let indexPathRow = memoTableView.indexPathForSelectedRow?.row else {
    return
}
vc.selectedMemoObject   = memoListForRealm[indexPathRow]
vc.selectedMemoString   = memoList[indexPathRow]
vc.selectedIndexPathRow = indexPathRow

Variablen und Lesbarkeit

Löschen Sie unnötige Variablen

Zuweisen eines Werts zur Eigenschaft der Variablen memoObject.

Ich habe jedoch den in Data () konvertierten inputAttrText der Variablen zugeschriebenMemoData zugewiesen, aber die Variable attributedMemoData gelöscht, da durch direkte Übergabe der Code um einen Satz reduziert werden kann, anstatt ihn durch die Variable zu übergeben.

AddMemo.swift


@IBAction func addMemo(_ sender: Any) {
    guard let inputAttrText = memoTextView.attributedText else { return }
    let memoObject             = MemoModel()
    // memoTextView.attributedText -> Data()
    let attributedMemoData     = try! NSKeyedArchiver.archivedData(withRootObject: inputAttrText, requiringSecureCoding: false)
    memoObject.data            = attributedMemoData
    memoObject.identifier      = String().randomString()

AddMemo.swift


@IBAction func addMemo(_ sender: Any) {
    guard let inputAttrText = memoTextView.attributedText else { return }
    let memoObject             = MemoModel()
    // memoTextView.attributedText -> Data()
    memoObject.data            = try! NSKeyedArchiver.archivedData(withRootObject: inputAttrText, requiringSecureCoding: false)
    memoObject.identifier      = String().randomString()

Wenn Sie zum Löschen einer Zelle wischen, löschen Sie die entsprechenden Werte des für Realm und tableView verwendeten Arrays.

Realm löschte jedoch unnötige Verarbeitung, da die Änderung durch Manipulieren der in Results angegebenen Variablen wiedergegeben wird.

ViewController.swift


func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    let selectedMemo = memoListForRealm[indexPath.row]

    //Realm-Delete
    try! realm.write() {
        realm.delete(selectedMemo)
        realm.delete(memoListForRealm[indexPath.row])
    }

ViewController.swift


func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {

    //Realm-Delete
    try! realm.write() {
        realm.delete(memoListForRealm[indexPath.row])
    }

Verkleinern Sie den Bereich der Variablen

private ist ein Zugriffsmodifikator, der Referenzen (get) und Änderungen (sets) einschränkt.

Indem Sie private angeben, können Sie verhindern, dass es von anderen Dateien und Funktionen verwendet wird, und Sie müssen sich nicht um Änderungen und Verweise in anderen Dateien kümmern.

Auch privat (Diese Variable wird in anderen Dateien nicht verwendet.) Kann explizit angezeigt werden, wodurch der Aufwand für die Verfolgung des Codes entfällt.

Also habe ich, wann immer möglich, allen Variablen und Funktionen private hinzugefügt.

Es ist nicht notwendig, @IBAction privat hinzuzufügen, aber wenn es kein Qualifikationsmerkmal gibt, denke ich, dass es irgendwo ausgeführt wird, also habe ich es gewagt, es hinzuzufügen.

ViewController.swift


@IBOutlet weak var memoTableView: UITableView!

//Erinnerungen zum Speichern in Realm
var memoListForRealm:Results<MemoModel>!
// Realm
let realm               = try! Realm()
//Memoliste
var memoList            = [NSAttributedString]()

ViewController.swift


@IBOutlet private weak var memoTableView: UITableView!

//Erinnerungen zum Speichern in Realm
private var memoListForRealm:Results<MemoModel>!
// Realm
private let realm               = try! Realm()
//Memoliste
private var memoList            = [NSAttributedString]()

AddMemo.swift


let realm       = try! Realm()
let imagePicker = UIImagePickerController()

@IBAction func addMemo(_ sender: Any) {
    
@IBAction func attachImageGesture(_ sender: UILongPressGestureRecognizer) {

AddMemo.swift


private let realm       = try! Realm()
private let imagePicker = UIImagePickerController()

@IBAction private func addMemo(_ sender: Any) {

@IBAction private func attachImageGesture(_ sender: UILongPressGestureRecognizer) {

EditMemo.swift


@IBOutlet weak var memoTextView: UITextView!

// Realm
let realm                       = try! Realm()
let imagePicker                 = UIImagePickerController()

@IBAction func attachImageGesture(_ sender: UILongPressGestureRecognizer) {

@IBAction func updateMemo(_ sender: Any) {

EditMemo.swift


@IBOutlet private weak var memoTextView: UITextView!

// Realm
private let realm                       = try! Realm()
private let imagePicker                 = UIImagePickerController()

@IBAction private func attachImageGesture(_ sender: UILongPressGestureRecognizer) {

@IBAction private func updateMemo(_ sender: Any) {

DisplayMemo.swift


@IBOutlet weak var memoTextView: UITextView!

DisplayMemo.swift


@IBOutlet private weak var memoTextView: UITextView!

final ist ein Modifikator, der die Vererbung begrenzt und überschreibt.

Geben Sie explizit an, dass diese Klasse nicht vererbt oder überschrieben werden kann.

class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
class AddMemo: UIViewController {
class DisplayMemo: UIViewController {
class EditMemo: UIViewController {

final class ViewController:UIViewController,UITableViewDelegate,UITableViewDataSource {
final class AddMemo: UIViewController {
final class EditMemo: UIViewController {
final class DisplayMemo: UIViewController {

Verringern Sie die Position der Definition

Es ist einfacher zu erkennen, ob Sie die Variablendeklaration von der Funktionsausführung trennen. Wenn Sie sich jedoch nicht an die Existenz jeder Variablen erinnern, kennen Sie die Reihenfolge der Verarbeitung nicht.

Durch Verringern der Position, an der die Variable definiert ist, wird daher die erforderliche Variable in der Nähe der auszuführenden Verarbeitung definiert, was das Verständnis verbessert.

Im folgenden Code werden die Definition von Variablen und die Verarbeitung von Funktionen getrennt, da für jeden Code viele Codes vorhanden sind.

Es gibt jedoch viele definierte Variablen, und es war schwierig, die spätere Verarbeitung zu verstehen, während man sich alle auf einmal merkt.

Daher habe ich die zugehörigen Variablen und Prozesse als Satz organisiert.

ViewController.swift


func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    if let pickerImage = info[.originalImage] as? UIImage {
        //Für die Konvertierung in NSAttributedString erforderliche Parameter
        let width                 = pickerImage.size.width
        let padding               = self.view.frame.width / 2
        let scaleRate             = width / (memoTextView.frame.size.width - padding)
        // 10%Komprimiertes Bild zu
        let resizedImage          = pickerImage.resizeImage(withPercentage: 0.1)!
        let imageAttachment       = NSTextAttachment()
        var imageAttributedString = NSAttributedString()
        // memoTextView.attributedText -> NSMutableAttributedString
        let mutAttrMemoText       = NSMutableAttributedString(attributedString: memoTextView.attributedText)

        // resizedImage -> NSAttributedString()
        imageAttachment.image = UIImage(cgImage: resizedImage.cgImage!, scale: scaleRate, orientation: resizedImage.imageOrientation)
        imageAttributedString = NSAttributedString(attachment: imageAttachment)
        mutAttrMemoText.append(imageAttributedString)
        //Text nach dem Hinzufügen eines Bildes-> memoTextView.attributedText
        memoTextView.attributedText = mutAttrMemoText
    }
    dismiss(animated: true, completion: nil)
}

ViewController.swift


func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    if let pickerImage = info[.originalImage] as? UIImage {
        let width                 = pickerImage.size.width
        let padding               = self.view.frame.width / 2
        let scaleRate             = width / (memoTextView.frame.size.width - padding)
        // 10%Komprimiertes Bild zu
        let resizedImage          = pickerImage.resizeImage(withPercentage: 0.1)!
        let imageAttachment       = NSTextAttachment()
        // resizedImage -> NSAttributedString()
        imageAttachment.image = UIImage(cgImage: resizedImage.cgImage!, scale: scaleRate, orientation: resizedImage.imageOrientation)

        var imageAttributedString = NSAttributedString()
        imageAttributedString = NSAttributedString(attachment: imageAttachment)

        // memoTextView.attributedText -> NSMutableAttributedString()
        let mutAttrMemoString     = NSMutableAttributedString(attributedString: memoTextView.attributedText)
        mutAttrMemoString.append(imageAttributedString)
        //Text nach dem Hinzufügen eines Bildes-> memoTextView.attributedText
        memoTextView.attributedText = mutAttrMemoString
    }
    dismiss(animated: true, completion: nil)
}

Eine Reihe von Definitionen und Implementierungen für zwei UIAlertActions, die für UIAlertController verwendet werden.

@IBAction private func attachImageGesture(_ sender: UILongPressGestureRecognizer) {
    let alert = UIAlertController(title: "Bild anhängen", message: nil, preferredStyle: .actionSheet)

    let okAction = UIAlertAction(title: "OK", style: .default) { (action) in
        self.present(self.imagePicker, animated: true, completion: nil)
    }
    let cancelAction = UIAlertAction(title: "Stornieren", style: .cancel, handler: nil)

    alert.addAction(okAction)
    alert.addAction(cancelAction)
    
    present(alert, animated: true, completion: nil)
}

@IBAction private func attachImageGesture(_ sender: UILongPressGestureRecognizer) {
    let alert = UIAlertController(title: "Bild anhängen", message: nil, preferredStyle: .actionSheet)

    let okAction = UIAlertAction(title: "OK", style: .default) { (action) in
        self.present(self.imagePicker, animated: true, completion: nil)
    }
    alert.addAction(okAction)

    let cancelAction = UIAlertAction(title: "Stornieren", style: .cancel, handler: nil)
    alert.addAction(cancelAction)
    
    present(alert, animated: true, completion: nil)
}

Zusammenfassung

Bisher habe ich den Code durch Bezugnahme auf den lesbaren Code verbessert, aber ich fand, dass dieses Buch ein königlicher Weg ist, um grundlegendes Refactoring zu lernen.

Es gibt keine Möglichkeit, die Menge an Code drastisch zu reduzieren und schönen Code zu schreiben, den jeder verstehen kann.

Einfach ・ Ändern Sie die Namen von Variablen und Funktionen ・ Fügen Sie leicht verständliche Kommentare hinzu ・ Ändern Sie die Reihenfolge der Verarbeitung Es war nur eine einfache Methode.

Refactoring = Bereinigen des Codes ist jedoch nur ein stetiger Prozess.

Weil es eine einfache Methode ist, denke ich, dass es eine natürliche Methode ist, die Sie niemals vergessen sollten.

Der Inhalt dieses Buches ist im technischen Buch leicht zu lesen, enthält jedoch die Refactoring-Methode, die den Grundlagen treu bleibt.

Wenn Sie in Zukunft als Ingenieur leben möchten, wird empfohlen, das Refactoring aus diesem Buch zu lernen.

Recommended Posts

Verbesserung des schwer lesbaren Codes durch lesbaren Code ~ Allgemein
Lombok mit VS Code
Docker-Management mit VS-Code
Formatieren Sie Ruby mit VS-Code
Hallo Welt mit VS Code!
Reduzieren Sie redundanten Code mit Lombok