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

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

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

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

Avatar for Alexander Saenko

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 - Делают код приятным для сопровождения