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

[DevDojo] Ship Code Faster - 2024

[DevDojo] Ship Code Faster - 2024

This session will cover the productivity metrics used by various tech companies, discuss development and engineering practices to reduce the time from development start to feature release. It will also provide tangible steps on career progression for engineers who are new to their careers.

mercari

May 30, 2024
Tweet

More Decks by mercari

Other Decks in Technology

Transcript

  1. 2 Confidential 2014-2019
 - Bachelors + Masters in Computer Science,

    IIT Kharagpur (India)
 
 2019 - Joined Mercari as a newgrad
 
 Jan 2020 - Sep 2021 
 - US@Tokyo, Search Backend
 
 Oct 2021 - present
 - MK Product Data/Metadata, Backend
 @kaustubh

  2. 7 Confidential Repeated metrics Deploys/service Ease of delivery Change failure

    rate No. of PRs, reviews PR Cycle Time Ease of recovery
  3. 11 Confidential Code reviews Who here has done them in

    the past ? Q. Why don’t we let people merge their code straight to master ?
  4. 12 Confidential Code reviews Who here has done them in

    the past ? Q. Why don’t we let people merge their code straight to master ? - Human errors - Optimizations - Domain education - Feature conflicts
  5. 14 Confidential Code review (a short story) Developer A B

    https://github.com/octocat/Hello-World/pull/1 Ref: http://slack.com/
  6. 22 Confidential Code review (a short story) Developer A B

    Comment A B Context switch is costly ! For humans and computers Ref: https://newsletter.pragmaticengineer.com/p/measuring-developer-productivity-bae
  7. 23 Confidential Code review (real story) - Previous team: Average

    time to review (not ship): 10-14 days - Introduce systems that aided faster review and releases - Open PRs should not go stale - Result: 3-5 days
  8. 24 Confidential Code review (real story) - Previous team: Average

    time to review (not ship): 10-14 days - Introduce systems that aided faster review and releases - Open PRs should not go stale - Result: 3-5 days You can also try to introduce these practices to your teams to make the team’s release process more efficient.
  9. 27 Confidential What does a stale PR mean ? How

    does it go stale ? - PRs merged - Feature conflicts - Test updates - No activity
  10. 33 Confidential C2. Summarize your code changes in description If

    a release goes wrong, another engineer may have to revert your PR. Ref: https://github.com/
  11. 38 Confidential D1. Align with Design principles - DRY -

    SOLID - AHA - Discover abstractions, don’t design with them.
  12. 39 Confidential D1. Align with Design principles - DRY -

    SOLID - AHA - Discover abstractions, don’t design with them. - Effective Go / language specific guidelines
  13. 40 Confidential D1. Align with Design principles - DRY -

    SOLID - AHA - Discover abstractions, don’t design with them. - Effective Go / language specific guidelines NOTE: Guidelines, not rules to live by
  14. 41 Confidential D2. getDBRecord(id string) record { // calls DB

    // return record if found } // HTTP endpoint, no DB call GetRecordPropertyByID( id string) { // some checks record := getDBRecord(id) return record.property; }
  15. 42 Confidential D2. getDBRecord(id string) record { // calls DB

    // return record if found } // HTTP endpoint, no DB call GetRecordPropertyByID( id string) { // some checks record := getDBRecord(id) return record.property; } What is the problem here ?
  16. 43 Confidential D2. Null case - expect nothing getDBRecord(id string)

    record { // calls DB // return record if found } // HTTP endpoint, no DB call GetRecordPropertyByID( id string) { // some checks record := getDBRecord(id) return record.property; } What if db returns nil ?
  17. 45 Confidential D3. getDBRecord(id string) record { // calls DB

    } // HTTP endpoint, no DB call GetRecordByID(id string) { // some checks getDBRecord(id) // check, return data } getDBRecord(id string) record { // calls DB } // HTTP endpoint, no DB call GetRecordByID(id string) { // some checks record := getDBRecord(id) // check, return data }
  18. 46 Confidential D3. getDBRecord(id string) record { // calls DB

    } // HTTP endpoint, no DB call GetRecordByID(id string) { // some checks record := getDBRecord(id) // check, return data } // HTTP endpoint, no DB call GetRecordsByIDs(ids string) { // some checks For id := range ids { records = append(records, getDBRecord(id) ) } // check, return data
  19. 47 Confidential D3. getDBRecord(id string) record { // calls DB

    } // HTTP endpoint, no DB call GetRecordByID(id string) { // some checks record := getDBRecord(id) // check, return data } // HTTP endpoint, no DB call GetRecordsByIDs(ids string) { // some checks For id := range ids { records = append(records, getDBRecord(id) ) } // check, return data Is there a problem here ?
  20. 48 Confidential D3. N+1 query getDBRecord(id string) record { //

    calls DB } // HTTP endpoint, no DB call GetRecordByID(id string) { // some checks record := getDBRecord(id) // check, return data } // HTTP endpoint, no DB call GetRecordsByIDs(ids string) { // some checks For id := range ids { records = append(records, getDBRecord(id) ) } // check, return data 100 DB calls for 100 ids ! Having a batch method has no benefits over single method
  21. 49 Confidential D3. N+1 query getDBRecord(id string) record { //

    calls DB } // HTTP endpoint, no DB call GetRecordByID(id string) { // some checks record := getDBRecord(id) // check, return data } // HTTP endpoint, no DB call GetRecordsByIDs(ids string) { // some checks For id := range ids { records = append(records, getDBRecord(id) ) } // check, return data 100 DB calls for 100 ids ! Having a batch method has no benefits over single method
  22. 50 Confidential D4. Internal Panics - Missing file - Security

    flaw Recover from panics, hard to detect // pkg internal implementation // we may not be able to change it func divide(a, b int) int { if b == 0 { panic("Divide by zero") } return a / b }
  23. 51 Confidential D4. Internal Panics - Missing file - Security

    flaw Recover from panics, hard to detect - Incident // pkg internal implementation // we may not be able to change it func divide(a, b int) int { if b == 0 { panic("Divide by zero") } return a / b }
  24. 52 Confidential D4. Internal Panics - Missing file - Security

    flaw Recover from panics, hard to detect - Incident - Stripe Interview Q // pkg internal implementation // we may not be able to change it func divide(a, b int) int { if b == 0 { panic("Divide by zero") } return a / b }
  25. 53 Confidential D5. Eager exits GetRecordByID(id string) { // checks

    record := getDBRecord(id) if record != null { // formatting return something; } else return null; }
  26. 54 Confidential D5. Eager exits GetRecordByID(id string) { // checks

    record := getDBRecord(id) if record != null { // formatting return something; } else return null; } GetRecordByID(id string) { // checks record := getDBRecord(id) if record != null { // formatting // conversion functions // empty checks // function on record.property return something; } else return null;
  27. 55 Confidential D5. Eager exits GetRecordByID(id string) { // checks

    record := getDBRecord(id) if record != null { // formatting return something; } else return null; } GetRecordByID(id string) { // checks record := getDBRecord(id) if record != null { // formatting // conversion functions // empty checks // function on record.property return something; } else return null;
  28. 56 Confidential D5. Eager exits (opinion) GetRecordByID(id string) { //

    checks record := getDBRecord(id) if record == null { return nil; } else // formatting return something; } GetRecordByID(id string) { // checks record := getDBRecord(id) if record != null { // formatting // conversion functions // empty checks // function on record.property return something; } else return null;
  29. 58 Confidential P1. Unit tests / Integration tests What does

    a unit test mean? Integration test ? Why are they really required ?
  30. 59 Confidential P1. Unit tests / Integration tests What does

    a unit test mean? Integration test ? Why are they really required ? Unit test - test only new functionality Integration test - Test the new function with other components Find potential issues in overall flow, but not this feature alone
  31. 60 Confidential P1. Unit tests / Integration tests HTTP server

    Input Output Feature 1 Feature 2 Feature N
  32. 61 Confidential P1. Unit tests / Integration tests HTTP server

    Input Output Feature 1 Feature 2 Feature N Unit test Integration test
  33. 63 Confidential P3. Prove you are right - Stackoverflow links

    - Go Playground - Official pkg docs Ref: https://github.com/
  34. 64 Confidential P3. Prove you are right - Stackoverflow links

    - Go Playground - Official pkg docs Ref: https://github.com/
  35. 65 Confidential P4. Review your own PR in the third

    person Check areas of your PR that a reviewer may have concerns about - Add comments on your PR to explain your decisions. - Highlight areas for review - Performance concerns
  36. 66 Confidential P5. Boring is good - Don’t introduce something

    brand new not discussed before - Are there better/simpler ways to do it ? - Your idea may not work (DB, language versions) - (Complex projects) Discuss with Tech Lead beforehand, confirm your approach makes sense. - OK to explore as you go, but try not to delay release too much
  37. 67 Confidential P5. Boring is good - Don’t introduce something

    brand new not discussed before - Are there better/simpler ways to do it ? - Your idea may not work (DB, language versions) - (Complex projects) Discuss with Tech Lead beforehand, confirm your approach makes sense. - OK to explore as you go, but try not to delay release too much People only like surprises when it’s a gift, 🎁 not for code review 🤮
  38. 68 Confidential P6. Commit etiquette - Each commit should do

    exactly one task. - There is a sweet spot for a commit size.
  39. 69 Confidential BAD - Implement feature - address feedback GOOD

    P6. Commit etiquette GOOD - [chore] / [add] / [fix] Depends on repo enforcements - “[CGT-123] add test for method” Shell Automations Debugging larger repos
  40. 72 Confidential P7. Code can be neat How to do

    it ? Ref: https://github.com/
  41. 73 Confidential P7. Code can be neat How to do

    it ? <details> <summary> Text </summary> Details </details> Ref: https://github.com/
  42. 74 Confidential P7. Code can be neat How to do

    it ? <details> <summary> Text </summary> Details </details> There are tons of markdown features like this, please use them ! Ref: https://github.com/
  43. 76 Confidential P9. Know the entire codebase - Impractical at

    start, but expect to know in 6 months - First 3 months: WHAT features, HOW to implement - Next 3: WHO calls the service, WHY certain design decisions made, WHEN a consumer started using the service - Can reuse existing functions / abstract if required - Know how existing problems are solved
  44. 78 Confidential How an engineer is different from a developer

    - Communicate effectively with other roles (PMs, designers) - Understand the feature; think of the users, simplify architecture - Identify potential issues in implementation; yours and others - Be responsible for your domain
  45. 79 Confidential Improving as an engineer - Read tech articles

    - See how others do code review / Prepare their PR - After the first 2-3 months, see EVERY PR reviewed and merged recently - Good for feature education, decision making process
  46. 80 Confidential Traffic CPU, mem DB Service cost User Inquiry

    Actual implementation Releasing a new backend feature