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

The source of all technical debt

The source of all technical debt

Indebted code is any code that is hard to scan. Technical debt is anything that increases the difficulty of reading code. As software engineers we spend most of the time reading code, and our job is to understand it and modify it in order to do more things with it. If we can’t understand the code, or we can’t even find it, the amount of technical debt accumulated will be over the roof.

David González

March 22, 2017
Tweet

More Decks by David González

Other Decks in Programming

Transcript

  1. Indebted code is any code that is hard to scan.

    Technical debt is anything that increases the difficulty of reading code.
  2. Programmers spend around 60-70% of their entire programming time reading

    code. Completely made up number based on my last month
  3. Cyclomatic complexity Software metric (measurement), used to indicate the complexity

    of a program. It is a quantitative measure of the number of linearly independent paths through a program's source code.
  4. Reducing technical debt Decide where to look Reading things, usually

    names In a name or assertion Name your commit
  5. Not just for functions public class DataManager public class DataProvider

    public class DataRepository public class DataOperations
  6. Name by what it does, not by what it is

    @BindView(R.id.password_text_input_layout) TextInputLayout passwordTextInputLayout; @BindView(R.id.password_edit_text) EditText etPassword; @BindView(R.id.password) EditText passwordInput;
  7. Rest API don’t de!ne your language { "files": { "Hello.txt":

    { "type": "text/plain", "content": "Hello World!\n" } }, "created_at": "2014-05-27T02:31:35Z", "updated_at": "2015-08-29T14:01:51Z" }
  8. Rest API don’t de!ne your language public final class Gist

    { Map<String, GistFile> files; @SerializedName("created_at") Date createdAt; @SerializedName("updated_at") Date updatedAt; }
  9. Naming your tests DraftDialogPresenter.java @Test public void showsMessageWhenDraftIsSavedAndReloadsData() @Test public

    void testDraftDialogPresenterShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void draftDialogShowsMessageAfterClickingSaveButtonAndReloadsData()
  10. Naming your tests DraftDialogPresenter.java @Test public void testDraftDialogPresenterShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public

    void draftDialogShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void showsMessageWhenDraftIsSavedAndReloadsData()
  11. Naming your tests DraftDialogPresenter.java @Test public void showsMessageWhenDraftIsSaved() @Test public

    void testDraftDialogPresenterShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void draftDialogShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void showsMessageWhenDraftIsSavedAndReloadsData()
  12. Naming your tests DraftDialogPresenter.java @Test public void testDraftDialogPresenterShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public

    void draftDialogShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void showsMessageWhenDraftIsSavedAndReloadsData() @Test public void showsMessageWhenDraftIsSaved()
  13. Naming your tests DraftDialogPresenter.java @Test public void showsSuccessMessageWhenDraftIsSaved() @Test public

    void testDraftDialogPresenterShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void draftDialogShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void showsMessageWhenDraftIsSavedAndReloadsData() @Test public void showsMessageWhenDraftIsSaved()
  14. Naming your tests DraftDialogPresenter.java @Test public void testDraftDialogPresenterShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public

    void draftDialogShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void showsMessageWhenDraftIsSavedAndReloadsData() @Test public void showsMessageWhenDraftIsSaved() @Test public void showsSuccessMessageWhenDraftIsSaved()
  15. Naming your tests DraftDialogPresenter.java @Test public void showsErrorMessageWhenDraftIsNotSaved() @Test public

    void testDraftDialogPresenterShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void draftDialogShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void showsMessageWhenDraftIsSavedAndReloadsData() @Test public void showsMessageWhenDraftIsSaved() @Test public void showsSuccessMessageWhenDraftIsSaved()
  16. Naming your tests DraftDialogPresenter.java @Test public void testDraftDialogPresenterShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public

    void draftDialogShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void showsMessageWhenDraftIsSavedAndReloadsData() @Test public void showsMessageWhenDraftIsSaved() @Test public void showsSuccessMessageWhenDraftIsSaved() @Test public void showsErrorMessageWhenDraftIsNotSaved()
  17. Naming your tests DraftDialogPresenter.java @Test public void shows_error_mesage_when_draft_is_not_saved() @Test public

    void testDraftDialogPresenterShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void draftDialogShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void showsMessageWhenDraftIsSavedAndReloadsData() @Test public void showsMessageWhenDraftIsSaved() @Test public void showsSuccessMessageWhenDraftIsSaved() @Test public void showsErrorMessageWhenDraftIsNotSaved()
  18. Naming your tests DraftDialogPresenter.java @Test public void testDraftDialogPresenterShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public

    void draftDialogShowsMessageAfterClickingSaveButtonAndReloadsData() @Test public void showsMessageWhenDraftIsSavedAndReloadsData() @Test public void showsMessageWhenDraftIsSaved() @Test public void showsSuccessMessageWhenDraftIsSaved() @Test public void showsErrorMessageWhenDraftIsNotSaved() @Test public void shows_error_mesage_when_draft_is_not_saved()
  19. Naming your tests DraftDialogPresenter.java // Groovy def "Should show success

    message after successfully saved a draft"() // Kotlin fun `Should show success message after successfully saved a draft`()
  20. Naming your tests @Test public void showsErrorMessageWhenDraftIsNotSaved() {} @Test public

    void shows_error_mesage_when_draft_is_not_saved() {} // Groovy def "Should show success message after successfully saved a draft"() // Kotlin fun `Should show success message after successfully saved a draft`()
  21. Styles <style name="Widget.Subject" parent="TextAppearance.AppCompat.Body1"> <item name="android:textSize">@dimen/convo_subject_text</item> <item name="android:ellipsize">end</item> <item name="android:maxLines">1</item>

    </style> <style name="Widget.Subject.Pending"> <item name="android:textColor">@color/convo_preview_pending</item> </style> convo-preview-styles.xml
  22. Dimensions <style name="Widget.PreviewText" parent="TextAppearance.AppCompat.Body1"> <item name="android:textSize">@dimen/convo_preview_text</item> <item name="android:ellipsize">end</item> <item name="android:maxLines">1</item>

    </style> convo-preview-styles.xml <dimen name="conversation_preview_text">@dimen/text_subhead</color> convo-preview-dimens.xml <dimen name="text_subhead">11sp</dimen> dimens.xml
  23. Strings <?xml version="1.0" encoding="utf-8"?> <resources> <string name="convo_preview_archived">@string/convo_archived</string> <string name="convo_preview_restored">@string/convo_restored</string> </resources>

    convo-preview-strings.xml <string name="conversation_archived">Conversation archived.</string> <string name="conversation_restored">Conversation status restored.</string> strings-translatable.xml
  24. Enforce conventions <code_scheme name="Novoda"> ... <option name="RIGHT_MARGIN" value="150" /> ...

    <indentOptions> <option name="INDENT_SIZE" value="2" /> <option name="CONTINUATION_INDENT_SIZE" value="2" /> <option name="TAB_SIZE" value="2" /> </indentOptions> ... </code_scheme>
  25. Enforce conventions <module name="ConstantNameCheck"> <metadata name="altname" value="ConstantName" /> <property name="applyToPublic"

    value="true" /> <property name="applyToProtected" value="true" /> <property name="applyToPackage" value="true" /> <property name="applyToPrivate" value="false" /> <property name="format" value="^([A-Z][A-Z0-9]*(_[A-Z0-9]+)*|FLAG_.*)$" /> <message key="name.invalidPattern" value="Variable ''{0}'' should be in ALL_CAPS (if it is a constant) or be private (otherwise)." /> <property name="severity" value="warning" /> </module> team-props/checkstyle/modules.xml <module name="MethodNameCheck"> <metadata name="altname" value="MethodName" /> <property name="format" value="^[a-z][a-zA-Z0-9]*(_[a-zA-Z0-9]+)*$" /> <property name="severity" value="warning" /> </module>
  26. Enforce conventions <rule ref="rulesets/java/design.xml"> <exclude name="TooFewBranchesForASwitchStatement" /> <exclude name="ConfusingTernary" />

    <!-- we frequently do this on purpose when connecting to the Android life-cycle --> <exclude name="UncommentedEmptyMethod" /> <!-- we do this for Dagger --> <exclude name="UncommentedEmptyConstructor" /> <exclude name="UseVarargs" /> <!-- we always create singletons for this classes and doing this would not allow mocking --> <exclude name="ClassWithOnlyPrivateConstructorsShouldBeFinal" /> <exclude name="NonThreadSafeSingleton" /> </rule> team-props/pmd/ruleset.xml
  27. Enforce conventions static-analysis.gradle apply plugin: 'checkstyle' def rulesDir = new

    File(project.teamPropsDir, 'rules') task checkstyleMain(type: Checkstyle) { description 'Checks whether Java source code complies with coding rules.' ... } staticAnalysis.dependsOn checkstyleMain task verifyNoCheckstyleWarnings { doLast { File warningsFile = file('buildMessage/reports/checkstyle/main.xml') if (warningsFile.exists() && warningsFile.text.contains("<error ")) { throw new GradleException("There were checkstyle warnings! For more info check $warningsFile") } } }
  28. Enforce conventions static-analysis.gradle apply plugin: 'findbugs' task findbugsMain(type: FindBugs) {

    description 'Uses static analysis to look for bugs in Java code.' ... } staticAnalysis.dependsOn findbugsMain apply plugin: 'pmd' task pmdMain(type: Pmd) { description 'Finds common programming flaws throw static analysis of code.' } staticAnalysis.dependsOn pmdMain check.dependsOn staticAnalysis
  29. Good naming is a process, not a single step -

    http://arlobelshee.com/good-naming-is-a-process-not-a-single-step/ 1 Resources Just say hNo to hungarian notation - http://jakewharton.com/just-say-no-to-hungarian-notation/ How We Rethought our Complete Package Structure for Buffer on Android and the Awesome Effect It’s Had on Our Workflows - https://overflow.buffer.com/2016/09/26/android-rethinking-package-structure/ Share the settings with the whole team - https://tips.seebrock3r.me/share-settings-with-the-team-a-year-later- e28c24fc07aa#.sihndb3f3
  30. Novoda IDE Settings - https://github.com/novoda/novoda/tree/master/ide-settings 1 Resources Buffer’s Android Guidelines

    - https://github.com/bufferapp/android-guidelines Vincent Brison’s Static Analysis with Gradle - https://github.com/vincentbrison/vb-android-app-quality