we knew better. 2. Code that was written by someone else, who is no longer a maintainer. 3. Code that doesn't have tests. 4. Code that we're unable to/afraid to change because everything might break. @AdamMc331 #AndroidSummit 3
we knew better. 2. Code that was written by someone else, who is no longer a maintainer. 3. Code that doesn't have tests. 4. Code that we're unable to/afraid to change because everything might break. 5. Code without any type of comments or documentation. @AdamMc331 #AndroidSummit 3
we knew better. 2. Code that was written by someone else, who is no longer a maintainer. 3. Code that doesn't have tests. 4. Code that we're unable to/afraid to change because everything might break. 5. Code without any type of comments or documentation. 6. All of the above! @AdamMc331 #AndroidSummit 3
a blocker for new development. 2. Legacy code can prevent us from shipping with confidence. 3. Legacy code can be confusing and difficult to build on top of. @AdamMc331 #AndroidSummit 5
a blocker for new development. 2. Legacy code can prevent us from shipping with confidence. 3. Legacy code can be confusing and difficult to build on top of. 4. Legacy code is not fun to work with for these, and many other reasons. @AdamMc331 #AndroidSummit 5
new practices will always arise. However, we can examine our own experiences with legacy code to help ensure our future selves and teammates have a better developer experience. @AdamMc331 #AndroidSummit 7
avoid people moving on to new opportunities. » One day, YOU will be that someone. » Your past self from one year ago also wrote code like a different person. @AdamMc331 #AndroidSummit 9
2. Code that doesn't leverage proper dependency injection. These unclear static dependencies can sometimes indicate fragile code that people are afraid to change. @AdamMc331 #AndroidSummit 16
MyErrorTool is difficult to mock for unit tests. » We don't want our negative tests to actually log errors to our production tool. @AdamMc331 #AndroidSummit 18
MyErrorTool is difficult to mock for unit tests. » We don't want our negative tests to actually log errors to our production tool. » This tool could be running setup that crashes our tests. @AdamMc331 #AndroidSummit 18
party vendors (analytics trackers, error reporters). » Companies may change tech stacks (REST to GraphQL). » New image loading libraries are made every few years. @AdamMc331 #AndroidSummit 21
party vendors (analytics trackers, error reporters). » Companies may change tech stacks (REST to GraphQL). » New image loading libraries are made every few years. » Code that doesn't allow these things to be changed is likely to become legacy code. @AdamMc331 #AndroidSummit 21
private val errorTool: MyErrorTool = MyErrorTool.getInstance() ) : ViewModel() » This class is strictly tied to MyErrorTool method contracts. @AdamMc331 #AndroidSummit 22
private val errorTool: MyErrorTool = MyErrorTool.getInstance() ) : ViewModel() » This class is strictly tied to MyErrorTool method contracts. » Despite dependency injection, this will make swapping our error tool difficult. @AdamMc331 #AndroidSummit 22
the reporter supplied by your DI manager, * the entire app just updates! */ single<ErrorReporter> { FirebaseErrorReporter() // SentryErrorReporter() // EmbraceErrorReporter() } } @AdamMc331 #AndroidSummit 26
this method makes it easy to update our project * if the library changes its method signature. */ override fun reportError(error: Throwable) { // Firebase.getInstance().logException(error) Firebase.getInstance().logError(error) } } @AdamMc331 #AndroidSummit 27
» We have testable code that we can ship with confidence. » We have decoupled third party tools, giving us freedom to swap vendors with ease. @AdamMc331 #AndroidSummit 28
» We have testable code that we can ship with confidence. » We have decoupled third party tools, giving us freedom to swap vendors with ease. » We can confidently upgrade our third party tools and limit the code changes required. @AdamMc331 #AndroidSummit 28
the code understood what they were writing. 2. The author felt that the code was self documenting. 3. The author didn't provide additional context. @AdamMc331 #AndroidSummit 31
the code understood what they were writing. 2. The author felt that the code was self documenting. 3. The author didn't provide additional context. 4. The author leaves the team, only for someone else to find this class much later. @AdamMc331 #AndroidSummit 31
the code understood what they were writing. 2. The author felt that the code was self documenting. 3. The author didn't provide additional context. 4. The author leaves the team, only for someone else to find this class much later. 5. The new team has no idea how this code works, or if it can be changed. @AdamMc331 #AndroidSummit 31
XYZ requires a ViewPager like experience, but * without the user being able to control each step. We've * implemented a ViewPager that rejects any user interraction. * * Source: https://stackoverflow.com/a/9650884/3131147 */ class NonSwipeableViewPager( context: Context, attrs: AttributeSet? = null ) : ViewPager(context, attrs) { } @AdamMc331 #AndroidSummit 33
XYZ requires a ViewPager like experience, but * without the user being able to control each step. We've * implemented a ViewPager that rejects any user interraction. * * Source: https://stackoverflow.com/a/9650884/3131147 */ class NonSwipeableViewPager( context: Context, attrs: AttributeSet? = null ) : ViewPager(context, attrs) { } » This allows future devs to understand why this class was added, and explore if there are new first-party solutions. @AdamMc331 #AndroidSummit 33
to github.com/company/library/issues/1234 we needed * to implement this work around to prevent a crash on * Android devices running API 21. */ private fun doLibraryWorkAround() { // ... } @AdamMc331 #AndroidSummit 34
to github.com/company/library/issues/1234 we needed * to implement this work around to prevent a crash on * Android devices running API 21. */ private fun doLibraryWorkAround() { // ... } » This allows future devs to understand what this block of code is doing, and explore if the bug has been fixed in a subsequent library update. @AdamMc331 #AndroidSummit 34
{ because("This dependency allows us to use EncryptedSharedPreferences to store sensitive information.") } » This allows future devs to update version numbers with confidence, as well as understanding what to test, and why this library was chosen. @AdamMc331 #AndroidSummit 35
developers refactor with confidence. » Wrapping dependencies allows future developers to update and replace tooling easily. » Documenting certain decisions allows future developers to confidently understand, refactor, and replace code written by someone else. @AdamMc331 #AndroidSummit 38