# Perfect is the Enemy of the Good

DevFeed: [Perfect is the Enemy of the Good](<https://devfeed.tech/articles/perfect-is-the-enemy-of-the-good-22305.md>)

Original publisher: [Read original article](<https://www.thecodedself.com/Perfect-Is-The-Enemy-Of-The-Good/>)

Author: Keegan Rush

Published: 2018-11-13T00:00:00Z

Content type: opinion

Language: en

Sources: [The Coded Self](<https://devfeed.tech/sources/the-coded-self.md>)

Topics: [Development](<https://devfeed.tech/topics/development.md>), [Programming](<https://devfeed.tech/topics/programming.md>), [Concurrency](<https://devfeed.tech/topics/concurrency.md>), [reactive](<https://devfeed.tech/topics/reactive.md>), [Dependency injection](<https://devfeed.tech/topics/dependency-injection.md>), [Mocking](<https://devfeed.tech/topics/mocking.md>), [App](<https://devfeed.tech/topics/app.md>)

Tags: [architecture](<https://devfeed.tech/tags/architecture.md>), [architecture-pattern](<https://devfeed.tech/tags/architecture-pattern.md>), [async](<https://devfeed.tech/tags/async.md>), [concurrency](<https://devfeed.tech/tags/concurrency.md>), [dependency-injection](<https://devfeed.tech/tags/dependency-injection.md>), [development](<https://devfeed.tech/tags/development.md>), [dispatchqueue](<https://devfeed.tech/tags/dispatchqueue.md>), [mocking](<https://devfeed.tech/tags/mocking.md>), [programming](<https://devfeed.tech/tags/programming.md>), [queue](<https://devfeed.tech/tags/queue.md>), [reactive](<https://devfeed.tech/tags/reactive.md>), [reactive-programming](<https://devfeed.tech/tags/reactive-programming.md>)

## AI overview

The author reflects on a side project whose elaborate architecture and extensive tooling created hidden complexity, debugging difficulties, and development friction. The article examines the use of RxSwift, VIPER, Swinject, Cuckoo, and Flow Operations in an app and argues that architectural perfection can undermine practical progress.

## Source excerpt

How the Wrong Architecture Can Cripple Development A couple of years ago, I was working on a side project with a few friends. We thought that it would be the next big thing. We put our collective best efforts into it; I worked long, hard hours fleshing out the scaffolding of the perfect architecture. Little did I know that my effort would doom the project to join the abyss of failed projects as quickly as it had begun. We had the best tools Since this was The Next Big Thing™, we used everything at our disposal. RxSwift for reactive programming VIPER for our architecture pattern Swinject for dependency injection Cuckoo for mocking Flow Operations for managing navigation The Flow Operations were a particularly interesting concept, inspired by the Advanced NSOperations session from WWDC 2015. We used Flow Operations to manage navigation in the app. For instance, if you wanted to register a new user, you'd invoke a RegisterFlowOperation. A FlowOperation was a subclass of Operation: class FlowOperation: Operation The Operation class represents the code and data for a task of your choosing. It also handles concurrency and dependencies. So, our Flow Operations represented the task of flowing from one screen to another in an app. Operations can be dependent on each other - for instance, the EditProfileFlowOperation is dependent on the SignInFlowOperation. If you've already signed in, you can edit your profile, but if you haven't, then you'll be directed to sign in if you invoke the EditProfileFlowOperation. How does it work? There was a lot of hidden complexity in the Flow Operation system, and some trickiness that you wouldn't notice until you started using it. I'll briefly go over some of the code. You could sell products in this app we were building. This is how you'd start the Sell Flow: private func startSellFlow() { DispatchQueue.global().async { [navController = navController] in let flow = SellFlowOperation(navigationController: navController) flow.beginFlow() flow.