Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Экологически чистая разработка

Экологически чистая разработка

Сергей Михайлов

Alexander Saenko

December 07, 2019
Tweet

More Decks by Alexander Saenko

Other Decks in Programming

Transcript

  1. Что же это за признаки - Отсутствие тестов - Отсутствие

    инженерной документации - Отсутствие единого стиля кодирования (code conventions)
  2. Тесты - Зачем нужны? - Убедиться, что ничего не сломал(а)

    в результате изменений - Уменьшение времени на “поверхностное” тестирование
  3. Тесты - Зачем нужны? - Убедиться, что ничего не сломал(а)

    в результате изменений - Уменьшение времени на “поверхностное” тестирование - Показатель качества процесса разработки
  4. Тесты - Зачем нужны? - Убедиться, что ничего не сломал(а)

    в результате изменений - Уменьшение времени на “поверхностное” тестирование - Показатель качества процесса разработки - Не страшно делать рефакторинги и оптимизации
  5. Тесты - Зачем нужны? - Убедиться, что ничего не сломал(а)

    в результате изменений - Уменьшение времени на “поверхностное” тестирование - Показатель качества процесса разработки - Не страшно делать рефакторинги и оптимизации - Позволяет держать экосистему проекта на уровне “не ниже чем”
  6. Тесты - Зачем нужны? - Убедиться, что ничего не сломал(а)

    в результате изменений - Уменьшение времени на “поверхностное” тестирование - Показатель качества процесса разработки - Не страшно делать рефакторинги и оптимизации - Позволяет держать экосистему проекта на уровне “не ниже чем” - Проект с тестами не стыдно передать следующим поколениям
  7. Тесты - Стоимость - Возможно не нужны на проектах класса

    MVP и prototype - +20% ко времени разработки (TDD)
  8. Тесты - На какие части продукта писать тесты - Протокол

    взаимодействия с РЕАЛЬНЫМ сервером
  9. Тесты - На какие части продукта писать тесты - Протокол

    взаимодействия с РЕАЛЬНЫМ сервером. И это ОБЯЗАННОСТЬ разработчика мобильного приложения
  10. Тесты - На какие части продукта писать тесты - Протокол

    взаимодействия с РЕАЛЬНЫМ сервером. И это ОБЯЗАННОСТЬ разработчика мобильного приложения - Математика
  11. Тесты - На какие части продукта писать тесты - Протокол

    взаимодействия с РЕАЛЬНЫМ сервером. И это ОБЯЗАННОСТЬ разработчика мобильного приложения - Математика - ViewModel/Presenter
  12. Тесты - На какие части продукта писать тесты - Протокол

    взаимодействия с РЕАЛЬНЫМ сервером. И это ОБЯЗАННОСТЬ разработчика мобильного приложения - Математика - ViewModel/Presenter - Persistence (CoreData)
  13. Стиль кодирования (coding conventions) - (NSString *)legacyIDWithStorageID:(NSString *)withStorageID itemID:(NSString *)itemID

    { return [IALegacyID legacyIDWithStorageID:withStorageID itemID:itemID]; } - (NSString *) makeSha1From:(NSString *)string { return [string sha1]; } - (NSString*) cleansedFilename: (NSString*) name { return [name cleansedFilename]; }
  14. Стиль кодирования (coding conventions) - (NSString *)legacyIDWithStorageID:(NSString *)withStorageID itemID:(NSString *)itemID

    { return [IALegacyID legacyIDWithStorageID:withStorageID itemID:itemID]; } - (NSString *) makeSha1From:(NSString *)string { return [string sha1]; } - (NSString*) cleansedFilename: (NSString*) name { return [name cleansedFilename]; }
  15. Стиль кодирования (coding conventions) - (NSString *)legacyIDWithStorageID:(NSString *)withStorageID itemID:(NSString *)itemID

    { return [IALegacyID legacyIDWithStorageID:withStorageID itemID:itemID]; } - (NSString *) makeSha1From:(NSString *)string { return [string sha1]; } - (NSString*) cleansedFilename: (NSString*) name { return [name cleansedFilename]; }
  16. Стиль кодирования (coding conventions) - (NSString *)legacyIDWithStorageID:(NSString *)withStorageID itemID:(NSString *)itemID

    { return [IALegacyID legacyIDWithStorageID:withStorageID itemID:itemID]; } - (NSString *) makeSha1From:(NSString *)string { return [string sha1]; } - (NSString*) cleansedFilename: (NSString*) name { return [name cleansedFilename]; }
  17. Стиль кодирования (coding conventions) - (NSString *)legacyIDWithStorageID:(NSString *)withStorageID itemID:(NSString *)itemID

    { return [IALegacyID legacyIDWithStorageID:withStorageID itemID:itemID]; } - (NSString *) makeSha1From:(NSString *)string { return [string sha1]; } - (NSString*) cleansedFilename: (NSString*) name { return [name cleansedFilename]; }
  18. Стиль кодирования (coding conventions) - (NSString *)legacyIDWithStorageID:(NSString *)withStorageID itemID:(NSString *)itemID

    { return [IALegacyID legacyIDWithStorageID:withStorageID itemID:itemID]; } - (NSString *) makeSha1From:(NSString *)string { return [string sha1]; } - (NSString*) cleansedFilename: (NSString*) name { return [name cleansedFilename]; }
  19. Стиль кодирования (coding conventions) - (NSString *)legacyIDWithStorageID:(NSString *)withStorageID itemID:(NSString *)itemID

    { return [IALegacyID legacyIDWithStorageID:withStorageID itemID:itemID]; } - (NSString *) makeSha1From:(NSString *)string { return [string sha1]; } - (NSString*) cleansedFilename: (NSString*) name { return [name cleansedFilename]; }
  20. Стиль кодирования (coding conventions) - (NSString *)legacyIDWithStorageID:(NSString *)withStorageID itemID:(NSString *)itemID

    { return [IALegacyID legacyIDWithStorageID:withStorageID itemID:itemID]; } - (NSString *) makeSha1From:(NSString *)string { return [string sha1]; } - (NSString*) cleansedFilename: (NSString*) name { return [name cleansedFilename]; }
  21. Стиль кодирования (coding conventions) - (NSString *)legacyIDWithStorageID:(NSString *)withStorageID itemID:(NSString *)itemID

    { return [IALegacyID legacyIDWithStorageID:withStorageID itemID:itemID]; } - (NSString *) makeSha1From:(NSString *)string { return [string sha1]; } - (NSString*) cleansedFilename: (NSString*) name { return [name cleansedFilename]; }
  22. Стиль кодирования (coding conventions) - (NSString*) legacyIDWithStorageID:(NSString*) withStorageID itemID:(NSString*) itemID

    { return [IALegacyID legacyIDWithStorageID:withStorageID itemID:itemID]; } - (NSString*) makeSha1From:(NSString*) string { return [string sha1]; } - (NSString*) cleansedFilename:(NSString*) name { return [name cleansedFilename]; }
  23. Стиль кодирования (coding conventions) private func batchCopy(_ items: [StorageItem], _

    mdriver: StorageDriverInternal & SupportingBatchOperations, _ folder: FolderItem) -> Observable<GroupStorageTask<StorageItem>> { return Observable .from(items) .flatMap { self.resolve(item: $0) } .toArray() .flatMap { mdriver.copy(items: $0, to: folder) } .map { $0.result } .filterNil() .flatMap { items -> Observable<StorageTask<StorageItem>> in let result = items .map { StorageTask<StorageItem>(item: $0, progress: 1.0, result: $0) } .map { Observable.just($0) } return Observable.from(result).concat() } .scan(GroupStorageTask(count: items.count)) { group, task in return group.updated(with: task) } }
  24. Стиль кодирования (coding conventions) private func batchCopy(_ items: [StorageItem], _

    mdriver: StorageDriverInternal & SupportingBatchOperations, _ folder: FolderItem) -> Observable<GroupStorageTask<StorageItem>> { return Observable .from(items) .flatMap { self.resolve(item: $0) } .toArray() .flatMap { mdriver.copy(items: $0, to: folder) } .map { $0.result } .filterNil() .flatMap { items -> Observable<StorageTask<StorageItem>> in let result = items .map { StorageTask<StorageItem>(item: $0, progress: 1.0, result: $0) } .map { Observable.just($0) } return Observable.from(result).concat() } .scan(GroupStorageTask(count: items.count)) { group, task in return group.updated(with: task) } }
  25. Стиль кодирования (coding conventions) private func batchCopy(_ items: [StorageItem], _

    mdriver: StorageDriverInternal & SupportingBatchOperations, _ folder: FolderItem) -> Observable<GroupStorageTask<StorageItem>> { return Observable .from(items) .flatMap { self.resolve(item: $0) } .toArray() .flatMap { mdriver.copy(items: $0, to: folder) } .map { $0.result } .filterNil() .flatMap { items -> Observable<StorageTask<StorageItem>> in let result = items .map { StorageTask<StorageItem>(item: $0, progress: 1.0, result: $0) } .map { Observable.just($0) } return Observable.from(result).concat() } .scan(GroupStorageTask(count: items.count)) { group, task in return group.updated(with: task) } }
  26. Стиль кодирования (coding conventions) private func batchCopy(_ items: [StorageItem], _

    mdriver: StorageDriverInternal & SupportingBatchOperations, _ folder: FolderItem) -> Observable<GroupStorageTask<StorageItem>> { return Observable .from(items) .flatMap { self.resolve(item: $0) } .toArray() .flatMap { mdriver.copy(items: $0, to: folder) } .map { $0.result } .filterNil() .flatMap { items -> Observable<StorageTask<StorageItem>> in let result = items .map { StorageTask<StorageItem>(item: $0, progress: 1.0, result: $0) } .map { Observable.just($0) } return Observable.from(result).concat() } .scan(GroupStorageTask(count: items.count)) { group, task in return group.updated(with: task) } }
  27. Стиль кодирования (coding conventions) private func batchCopy(_ items: [StorageItem], _

    mdriver: StorageDriverInternal & SupportingBatchOperations, _ folder: FolderItem) -> Observable<GroupStorageTask<StorageItem>> { return Observable .from(items) .flatMap { self.resolve(item: $0) } .toArray() .flatMap { mdriver.copy(items: $0, to: folder) } .map { $0.result } .filterNil() .flatMap { items -> Observable<StorageTask<StorageItem>> in let result = items .map { StorageTask<StorageItem>(item: $0, progress: 1.0, result: $0) } .map { Observable.just($0) } return Observable.from(result).concat() } .scan(GroupStorageTask(count: items.count)) { group, task in return group.updated(with: task) } }
  28. Стиль кодирования (coding conventions) typealias CompletionBlock = () -> Void

    private func doSomething(completion: @escaping CompletionBlock) { doSomethingImpl(completion: completion) }
  29. Стиль кодирования (coding conventions) typealias CompletionBlock = () -> Void

    private func doSomething(completion: @escaping CompletionBlock) { doSomethingImpl(completion: completion) } private func doSomethingImpl(completion: @escaping CompletionBlock) { doEvenMore(completion: completion) }
  30. Стиль кодирования (coding conventions) typealias CompletionBlock = () -> Void

    private func doSomething(completion: @escaping CompletionBlock) { doSomethingImpl(completion: completion) } private func doSomethingImpl(completion: @escaping CompletionBlock) { doEvenMore(completion: completion) } private func finallyDoSomething(completion: @escaping CompletionBlock) { // Perform some work completion() }
  31. Стиль кодирования (coding conventions) typealias CompletionBlock = () -> Void

    private func doSomething(completion: @escaping CompletionBlock) { doSomethingImpl(completion: completion) } private func doSomethingImpl(completion: @escaping CompletionBlock) { doEvenMore(completion: completion) } private func finallyDoSomething(completion: @escaping CompletionBlock) { // Perform some work completion() } doSomething { // Handle completion }
  32. Стиль кодирования (coding conventions) typealias CompletionBlock = () -> Void

    private func doSomething(completion: @escaping CompletionBlock) { doSomethingImpl(completion: completion) } private func doSomethingImpl(completion: @escaping CompletionBlock) { doEvenMore(completion: completion) } private func finallyDoSomething(completion: @escaping CompletionBlock) { // Perform some work completion() } doSomething { // Handle completion } outerCode >>> doSomething >>> doSomethingImpl >>> finallyDoSomething
  33. Стиль кодирования (coding conventions) typealias CompletionBlock = () -> Void

    private func doSomething(completion: @escaping CompletionBlock) { doSomethingImpl(completion: completion) } private func doSomethingImpl(completion: @escaping CompletionBlock) { doEvenMore(completion: completion) } private func finallyDoSomething(completion: @escaping CompletionBlock) { // Perform some work completion() } doSomething { // Handle completion } outerCode >>> doSomething >>> doSomethingImpl >>> finallyDoSomething outerCode <<< doSomething <<< doSomethingImpl <<< finallyDoSomething
  34. Стиль кодирования (coding conventions) typealias CompletionBlock = () -> Void

    private func doSomething(completion: @escaping CompletionBlock) { doSomethingImpl(completion: completion) } private func doSomethingImpl(completion: @escaping CompletionBlock) { doEvenMore(completion: completion) } private func finallyDoSomething(completion: @escaping CompletionBlock) { // Perform some work completion() } doSomething { // Handle completion } outerCode >>> doSomething >>> doSomethingImpl >>> finallyDoSomething outerCode <<< finallyDoSomething
  35. Стиль кодирования (coding conventions) typealias CompletionBlock = () -> Void

    private func doSomething(completion: @escaping CompletionBlock) { doSomethingImpl(completion: completion) } private func doSomethingImpl(completion: @escaping CompletionBlock) { doEvenMore(completion: completion) } private func finallyDoSomething(completion: @escaping CompletionBlock) { // Perform some work completion() } doSomething { // Handle completion } outerCode >>> doSomething >>> doSomethingImpl >>> finallyDoSomething outerCode <<< doSomething <<< doSomethingImpl <<< finallyDoSomething
  36. Стиль кодирования (coding conventions) typealias CompletionBlock = () -> Void

    private func doSomething(completion: @escaping CompletionBlock) { doSomethingImpl { completion() } } private func doSomethingImpl(completion: @escaping CompletionBlock) { doEvenMore { completion() } } private func finallyDoSomething(completion: @escaping CompletionBlock) { // Perform some work completion() } doSomething { // Handle completion }
  37. Стиль кодирования (coding conventions) typealias CompletionBlock = () -> Void

    private func doSomething(completion: @escaping CompletionBlock) { doSomethingImpl { // Invoke completion block explicitly to ease-up debugging. completion() } } private func doSomethingImpl(completion: @escaping CompletionBlock) { doEvenMore { // Invoke completion block explicitly to ease-up debugging. completion() } } private func finallyDoSomething(completion: @escaping CompletionBlock) { // Perform some work completion() } doSomething { // Handle completion }
  38. Стиль кодирования (coding conventions) class MyClass { var flag1: Bool

    var flag2: Bool var someValue: Int var someCalculatedProperty: Int { return 10 } init() { } func doSomething() { } func doAnotherMagic() { } deinit { } }
  39. Стиль кодирования (coding conventions) internal class MyClass { var flag1:

    Bool var flag2: Bool var someValue: Int var someCalculatedProperty: Int { return 10 } init() { } func doSomething() { } func doAnotherMagic() { } deinit { } }
  40. Стиль кодирования (coding conventions) internal class MyClass { public var

    flag1: Bool public var flag2: Bool private var someValue: Int public var someCalculatedProperty: Int { return 10 } public init() { } public func doSomething() { } private func doAnotherMagic() { } deinit { } }
  41. Стиль кодирования (coding conventions) internal class MyClass { public var

    flag1: Bool public var flag2: Bool private var someValue: Int public var someCalculatedProperty: Int { return 10 } public init() { } public func doSomething() { } private func doAnotherMagic() { } deinit { } }
  42. Стиль кодирования (coding conventions) internal class MyClass { public var

    flag1: Bool public var flag2: Bool public var someCalculatedProperty: Int { return 10 } public init() { } public func doSomething() { } deinit { } private func doAnotherMagic() { } private var someValue: Int }
  43. Стиль кодирования (coding conventions) internal class MyClass { public var

    flag1: Bool public var flag2: Bool public var someCalculatedProperty: Int { return 10 } public init() { } public func doSomething() { } deinit { } private func doAnotherMagic() { } private var someValue: Int }
  44. Стиль кодирования (coding conventions) internal class MyClass { public var

    flag1: Bool public var flag2: Bool public init() { } deinit { } public var someCalculatedProperty: Int { return 10 } public func doSomething() { } private func doAnotherMagic() { } private var someValue: Int }
  45. Стиль кодирования (coding conventions) // Class description internal class MyClass

    { // MARK: - Public methods and properties public var flag1: Bool public var flag2: Bool public init() { } public var someCalculatedProperty: Int { return 10 } public func doSomething() { } // MARK: - Internal methods and properties private func doAnotherMagic() { } // MARK: - Internal fields private var someValue: Int }
  46. Recap - Тесты - Ускорить разработку в среднесрочной и долгосрочной

    перспективе - Получить более структурированный код
  47. Recap - Тесты - Ускорить разработку в среднесрочной и долгосрочной

    перспективе - Получить более структурированный код - Получить примеры использования кода, которые потом можно вставлять в документацию
  48. Recap - Тесты - Ускорить разработку в среднесрочной и долгосрочной

    перспективе - Получить более структурированный код - Получить примеры использования кода, которые потом можно вставлять в документацию - Предоставить дополнительную психологическую уверенность, что все не развалилось, хотя гарантий нет
  49. Recap - Тесты - Ускорить разработку в среднесрочной и долгосрочной

    перспективе - Получить более структурированный код - Получить примеры использования кода, которые потом можно вставлять в документацию - Предоставить дополнительную психологическую уверенность, что все не развалилось, хотя гарантий нет - Coding conventions
  50. Recap - Тесты - Ускорить разработку в среднесрочной и долгосрочной

    перспективе - Получить более структурированный код - Получить примеры использования кода, которые потом можно вставлять в документацию - Предоставить дополнительную психологическую уверенность, что все не развалилось, хотя гарантий нет - Coding conventions - Делают код приятным для сопровождения