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

Can you read my code?

Can you read my code?

This is the enhanced version of original talk I gave at MobileOptimized 2017. This version has contribution by Sebastiano Gottardo and was the keynote talk at Droidcon Krakow 2017.

Ivan Morgillo

December 01, 2017
Tweet

Other Decks in Programming

Transcript

  1. COMMENTS COMMENT THE WHY NOT THE WHAT "foo() looks like

    this because it turned out all the other 15 solutions we tried sucked”
  2. COMMENTS COMMENT MAGIC CONSTANTS val NUM_THREAD = 8 // My

    desk legs * 2 val MAGIC_CONSTANT = 42 // The Answer
  3. COMMENTS USE COMMON MARKERS // TODO “We should [add random

    task] in the future” // HACK “This works but is kinda hacky” // HERE BE DRAGONS
  4. COMMENTS USE YOUR OWN ANNOTATIONS @TechDebt(jira = "https://biowink.atlassian.net/browse/ATD-28") class BackupActivity

    : BaseActivity() { … } /** * The [TechDebt] annotation can be used… */ annotation class TechDebt(val jira: String)
  5. COMMENTS DO NOT COMMENT ▸ Constructors, getters, setters… Seriously! ▸

    Bad functions names. Fix them! ▸ Everything that can be inferred from the context and the code.
  6. COMMENTS FROM YOUR HEART TO YOUR CODE What you actually

    mean and should write: “Careful! This routine is not thread-safe!” What you might write while panicking or thinking you are funny or helpful: “Sh*t! This thing will blow up the moment 
 we start using threads! Fingers crossed!”
  7. COMMENTS FROM YOUR HEAD TO YOUR CODE scrollsSubscription = calendar

    .scrollEvents() .map { it.scrollState() } .filter { it == OnScrollListener.SCROLL_STATE_IDLE } .skip(5) .subscribe( { scrollsCount++ }, { Timber.e(it, "Scroll events observable died ") } )
  8. COMMENTS FROM YOUR HEAD TO YOUR CODE /* To be

    able to effectively track scroll events we start observing every scroll event we focus on the scroll state we ignore everything that's not [OnScrollListener.SCROLL_STATE_IDLE] we skip the first 5 events because Android fires 5 bogus events on screen loading we increment the counter that we will later use when the user navigates away from the screen. */ scrollsSubscription = calendar .scrollEvents() .map { it.scrollState() } .filter { it == OnScrollListener.SCROLL_STATE_IDLE } .skip(5) .subscribe( { scrollsCount++ }, { Timber.e(it, "Scroll events observable died ") } )
  9. COMMENTS FROM YOUR HEAD TO YOUR CODE interface AdsManager {

    fun hasPrefetchedAd(placement: Placement): Boolean }
  10. COMMENTS FROM YOUR HEAD TO YOUR CODE interface AdsManager {

    /** * This method checks if there is a prefetched ad for the given [placement]. * * @param placement the placement for which to check if a prefetched ad is * available * @return true if a prefetched ad for the given placement is available, * false otherwise */ fun hasPrefetchedAd(placement: Placement): Boolean }
  11. VARIABLES PACK INFORMATION IN THE NAME ▸Is being temporary the

    only actual quality of tmp? ▸If retval is a list of employees that we are returning, why don’t we call it employees? ▸Can those loop indexes improve the general readability somehow?
  12. VARIABLES HELPERS VARIABLES val email = … val username =

    email.toUsername() if (username == “root”) { … }
  13. FUNCTIONS SIDE NOTES ‣ Aim for small reusable functions ‣

    Aim for pure functions 1. Dependencies IN 2. Result OUT 3. No side effects
  14. IF THEN WHAT? THE ORDER ‣ Left: the expression being

    interrogated, the one more likely to change ‣ Right: the expression being compared against, the one that stays the same over time
  15. IF THEN WHAT? THE ORDER ‣ Positive case first ‣

    Simpler case first ‣ More interesting case first ‣ The case that returns earlier first
  16. IF THEN WHAT? TERNARY OPERATOR Given that lines are free

    When one single line can be replaced with four lines of more easy-to-understand code Then don't be a j*rk! ⚠
  17. IF THEN WHAT? TERNARY OPERATOR fun isUserOfAge(user: User?) = if

    (user == null) false else user.age >= 18
  18. THE USER PROFILE OBTAINING THE USER PROFILE fun loadUser(): Single<User>

    loadUser() .subscribeOn(Schedulers.io()) […]
  19. WRAPPING UP HEALTHY DEV TEAM TIPS ‣ YAGNI and KISS

    ‣ Keep your codebase small ‣ Create a routine of removing bad code ‣ Keep writing and maintaining your tests
  20. WRAPPING UP FURTHER READINGS ‣ The Art of Readable Code

    ‣ Working effectively with legacy code ‣ The pragmatic programmer ‣ Mini Habits: Smaller Habits, Bigger Results