Оцените качество кода (Swift)
Пишу на свифте около недели, вот начал разрабатывать очередное недоприложение.
Регистрация реализована на двух экранах: - На первом нужно ввести логин, пароль, подтверждение пароля; - На втором - имя и фамилию.
Приведенный ниже кусок кода просто проверяет наличие хотя бы одного символа в каждом из необходимых текстфилдов
Вопрос: насколько хорошо написан код с точки зрения расширения функционала и насколько корректен относительно стиля кодинга на свифт? Может что-то назвать покороче?
//
// RegisterFormValidator.swift
// RegisterApp
//
// Created by Max Groshevsky on 27.03.20.
// Copyright © 2020 Max Groshevsky. All rights reserved.
//
// MARK: - Error codes
enum RegisterFormErrorCode {
// First register page
case usernameEmpty // Field Username is empty
case passwordEmpty // Field Password is empty
case confirmPasswordEmpty // Field Confirm password is empty
case passwordsNotEqual // Fields Password and Confirm password not equal
// Second register page
case firstNameEmpty // Field First name is empty
case lastNameEmpty // Field Last name is empty
}
// MARK: - Configure response to Presenter
struct RegisterFormErrorArray {
var code: RegisterFormErrorCode
var message: String
init(errorCode: RegisterFormErrorCode, errorMessage: String) {
self.code = errorCode
self.message = errorMessage
}
}
// MARK: - Register Form Verifyer
class RegisterFormValidator {
// MARK: - First Register Page
func pageFirst(username: String, password: String, confirmPassword: String) -> [RegisterFormErrorArray] {
let getErrorCode = RegisterFormErrorCode.self
var errors: [RegisterFormErrorArray] = []
// ERROR: Field Username not filled
if username.characters.count == 0 {
let code = getErrorCode.usernameEmpty
let message = "Field Username not filled"
let error = RegisterFormErrorArray(errorCode: code, errorMessage: message)
errors.append(error)
}
// ERROR: Field Password not filled
if password.characters.count == 0 {
let code = getErrorCode.passwordEmpty
let message = "Field Password not filled"
let error = RegisterFormErrorArray(errorCode: code, errorMessage: message)
errors.append(error)
}
// ERROR: Field Confirm password not filled
if confirmPassword.characters.count == 0 {
let code = getErrorCode.confirmPasswordEmpty
let message = "Field Confirm password not filled"
let error = RegisterFormErrorArray(errorCode: code, errorMessage: message)
errors.append(error)
}
// ERROR: Passwords not filled
if password != confirmPassword {
let code = getErrorCode.passwordEmpty
let message = "Passwords not equal"
let error = RegisterFormErrorArray(errorCode: code, errorMessage: message)
errors.append(error)
}
return errors
}
// MARK: - Second Register Page
func pageSecond(firstName: String, lastName: String) -> [RegisterFormErrorArray] {
let getErrorCode = RegisterFormErrorCode.self
var errors: [RegisterFormErrorArray] = []
// ERROR: FirstName not filled
if firstName.characters.count == 0 {
let code = getErrorCode.firstNameEmpty
let message = "Field First name not filled"
let error = RegisterFormErrorArray(errorCode: code, errorMessage: message)
errors.append(error)
}
// ERROR: LastName not filled
if lastName.characters.count == 0 {
let code = getErrorCode.firstNameEmpty
let message = "Field Last name not filled"
let error = RegisterFormErrorArray(errorCode: code, errorMessage: message)
errors.append(error)
}
return errors
}
}
Заранее благодарю
Ответы (2 шт):
Первое, ошибки:
enum RegisterFormErrorCode {
// First register page
case usernameEmpty ...
Посмотрите в документации Errors
Используйте стандартный механизм
enum RegisterFormError: Error {
case usernameEmpty ...
и описание к ним
extension RegisterFormError: LocalizedError {
var errorDescription: String? { ...
Так Вам не нужно инициализировать code, message, error и со стандартными ошибками работать удобнее.
Данная проверка:
if username.characters.count == 0 {
плоха сложностью O(n). Мелочь, но из мелочей строится грандиозное. Используйте isEmpty O(1)
userName.isEmpty
Ну и воспринимается легче.
Ну и второй метод будет, условно, таким, коли его суть возвращать ошибки:
func pageSecond(firstName: String, lastName: String) -> [RegisterFormError] {
var errors: [RegisterFormError] = []
if firstName.isEmpty {
errors.append(.firstNameEmpty)
}
if lastName.isEmpty {
errors.append(.lastNameEmpty)
}
return errors
}
Это первое за что зацепился глаз по Вашему коду.
Насчет именования - это наверное один из крупнейших камней преткновения. Придерживайтесь Swift code style, хорошо расписано у raywenderlich, ну и конечно же API Design Guidelines. Но многое может перекрываться соглашениями/требованиями в команде.
Просто заметил... В этом блоке:
// ERROR: LastName not filled
if lastName.characters.count == 0 {
let code = getErrorCode.firstNameEmpty
let message = "Field Last name not filled"
let error = RegisterFormErrorArray(errorCode: code, errorMessage: message)
errors.append(error)
}
константа let code должна быть инициализирована getErrorCode.lastNameEmpty
Можно создание ошибки в виде code и message вынести в отдельную функцию, чтобы исключить дублирование кода и ошибки копи-паста)))...
func errorConstructer(code: RegisterFormErrorCode) -> RegisterFormErrorArray {
var error = RegisterFormErrorArray(errorCode: code, errorMessage: "")
switch code {
case .confirmPasswordEmpty:
error.message = "Field Confirm password not filled"
return error
case .firstNameEmpty:
error.message = "Field First name not filled"
return error
case .lastNameEmpty:
error.message = "Field Last name not filled"
return error
case .passwordEmpty:
error.message = "Field Password not filled"
return error
case .passwordsNotEqual:
error.message = "Passwords not equal"
return error
case .usernameEmpty:
error.message = "Field Username not filled"
return error
}
}
Таким образом предыдущие блоки кода будут иметь вид...
// ERROR: Field Username not filled
if username.characters.count == 0 {
let error = errorConstructer(code: getErrorCode.usernameEmpty)
errors.append(error)
}