API Design Lessons Learned: Enterprise to Startup Mohamed El-Geish - - PowerPoint PPT Presentation

api design lessons learned enterprise to startup
SMART_READER_LITE
LIVE PREVIEW

API Design Lessons Learned: Enterprise to Startup Mohamed El-Geish - - PowerPoint PPT Presentation

API Design Lessons Learned: Enterprise to Startup Mohamed El-Geish g@workfit.io 4 This presentation may contain content that WARNING contradicts how your company designs APIs 4 Startups are nimble and daring; dont try this at home work


slide-1
SLIDE 1

API Design Lessons Learned: Enterprise to Startup

Mohamed El-Geish g@workfit.io

slide-2
SLIDE 2

2

4 This presentation may contain content that contradicts how your company designs APIs 4 Startups are nimble and daring; don’t try this at home work (or do try it)! 4 YMMV

WARNING

slide-3
SLIDE 3

E N T E R P R I S E V O I C E A I

_____________________ WHAT ARE WE BUILDING?

slide-4
SLIDE 4

CAPABILITIES

Automatic Dial-in Takes Interactive Commands Transcribes Key Highlights Indexed and Searchable Meetings Interactive Meeting Dashboard Interactive Word Cloud Share Meeting Highlights Highlight Reel Meeting Recap Email

4

slide-5
SLIDE 5

LET’S TALK API DESIGN

slide-6
SLIDE 6

6

WHY API DESIGN MATTERS?

slide-7
SLIDE 7

7

BECAUSE BAD API DESIGN IS COSTLY!

slide-8
SLIDE 8

8

JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC Project 1 Project 2 Project 3 Project 4 Project 5 Project 6 Task 1 Task 2 Task 3 Task 4

TIMELINE WHEN API DESIGN IS GOOD

slide-9
SLIDE 9

9

JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC Project 1 Project 2 Project 3 Project 4 Project 5 Project 6 Task 1 Task 2 Task 3 Task 4

TIMELINE WHEN API DESIGN IS BAD

slide-10
SLIDE 10

EXAMPLE: A TALE OF TWO QUEUES

10

// We used to use a FIFO SQS queue to send messages: request, _ := q.SendMessageRequest(&sqs.SendMessageInput{ QueueUrl: aws.String(queueURL), MessageBody: aws.String(messageBody), MessageGroupId: aws.String(groupID), MessageDeduplicationId: aws.String(dedupeID), }) return request.Send() // Then we switched that code to use a standard (non-FIFO) queue. // Expectation: The API clearly denotes a FIFO-specific interface.

slide-11
SLIDE 11

EXAMPLE: A TALE OF TWO QUEUES

11

// Reality: latent errors due to ambiguous API overloading; // we can’t use the last two arguments for standard queues! // This parameter applies only to FIFO (first-in-first-out) queues. // ... [many lines later] ... // MessageGroupId is required for FIFO queues. // You can't use it for Standard queues. // One way to mitigate this is to create a FIFO-specific API: request, _ := q.SendFIFOMessageRequest(&sqs.SendFIFOMessageInput{ MessageGroupId: aws.String(groupID), MessageDeduplicationId: aws.String(dedupeID), ...

slide-12
SLIDE 12

12

LESSON 0: IMITATE THE GREAT (LEARN)

slide-13
SLIDE 13

PERCEPTUAL LEARNING

  • Study:

y: Non-pilots did better than experienced pilots; PL works for other complex fields.*

  • Cog
  • gnitive Science: PL accelerates gaining

expertise via pattern recognition.**

  • SM

SMDMTM: See one many; do one many; teach one many — we require many high- quality examples for high SNR.***

13

slide-14
SLIDE 14

14

1 Ample time and resources 2 Scrutinized processes and reviews 3 Access to a ton of code and designs 4 Formal coaching and training 5 Abundance of talent and expertise

BIG COMPANIES = GREAT FOR LEARNING

slide-15
SLIDE 15

15

LEARNING AS A TENET

THE WORKFIT WAY

4Humans are the most important factor in the success of software. 4We learn to make new mistakes. 4We invest in learning and coaching: long-term ROI. 4Accelerated learning => high iteration velocity.

slide-16
SLIDE 16

LEARNING TO DO DOING TO LEARN

16

slide-17
SLIDE 17

LET’S TALK CODE

slide-18
SLIDE 18

EXAMPLE: PACKAGE MUST

18

// We noticed a pattern when declaring main package variables // We also noticed a pattern in Go’s standard library: // MustCompile is like Compile but panics if the expression cannot be // parsed. It simplifies safe initialization of global variables holding // compiled regular expressions. func MustCompile(str string) *Regexp { regexp, error := Compile(str) if error != nil { panic(`regexp: Compile(` + quote(str) + `): ` + error.Error()) } return regexp }

slide-19
SLIDE 19

EXAMPLE: PACKAGE MUST

19

// So we imitated the same pattern into package must: // CreateMeetingsClient wraps fabric.NewMeetingsClient // with default parameters. func CreateMeetingsClient() fabric.MeetingsClient { client, err := fabric.NewMeetingsClient( context.TODO(), fabric.DefaultClientConfig) if err != nil { reportPanic(err) } return client } var meetingsClient = must.CreateMeetingsClient() // how it’s called

slide-20
SLIDE 20

ANOTHER EXAMPLE: PACKAGE ERRORS

20

// Visual Studio TFS errors have IDs to reference them in docs*; // free-form errors are hard to map into a single TSG/failure mode; // our errors package allows for consistency, reuse, strong contracts, // brevity, testability, error handling hooks, and localizability. const wf11200 = `WF11200: HTTP response status code was not 2xx` // WF11200 occurs when an HTTP response has a status code other than 2xx. func WF11200(response interface{}) error { log.Error(wf11200, "response", response) return newError(wf11200) }

slide-21
SLIDE 21

21

LESSON 1: FIND YOUR NORTH STAR

slide-22
SLIDE 22

22

“As to the methods there may be a million and then some, but principles are few. The man who grasps principles can successfully select his own methods. The man who tries methods, ignoring principles, is sure to have trouble.”

RALPH WALDO EMERSON

slide-23
SLIDE 23

WHAT? WHY? HOW?

  • A north star guides your decision-making

processes including API design choices.

  • In ever-changing environments, one can

get lost and distracted by myopic goals.

  • Align design goals with business goals;

we don’t design in a vacuum.

  • Find your treasure and guard it well.

23

slide-24
SLIDE 24

KEY CHALLENGES STARTUPS & NEW PROJECTS FACE

  • A

A blank canvas: an overwhelming number of decisions to make -> decision fatigue.

  • Ve

Velocity is s life; grow fast st or die sl slow: “If a software company grows at [20% annually], it has a 92 percent chance of ceasing to exist within a few years.”*

  • Se

Security ity: it’s inconvenient; it’s everyone’s responsibility; and it can slow us down.

24

slide-25
SLIDE 25

25

SETTING GOALS & GUIDING PRINCIPLES

4Scope: short- vs. long- term. 4Agreeing on guiding principles -> a decision-making framework -> conflict-resolution mechanism. 4We strive to foster wisdom and autonomy.

THE WORKFIT WAY

slide-26
SLIDE 26

GOALS AND GUIDING PRINCIPLES

  • Sh

Short rt-te term: security, correctness, iteration velocity, availability, performance, throughput, scalability, and maintainability.

  • Lo

Long-te term: security, correctness, availability, throughput, performance, scalability, maintainability, and iteration velocity.

  • Ba

Balance: Design with scalability and maintainability in mind; trade off only when necessary.

  • Me

Meth thods: encryption, ACLs, cyber hygiene, CI, testing, SOA, A/B testing, tracking and telemetry, KISS, etc.

26

slide-27
SLIDE 27

SHORT-TERM GUIDING PRINCIPLES IN ACTION

  • Dat

Data a Fo Formats: Binary or textual?

  • Co

Cont ntracts: Whether or not to enforce schemas?

  • Pr

Prog

  • gramming Languages: Why Go, C++, Python, and Java?
  • In

Investing in CI: I: Travis, Docker, and DC/OS.

  • Ri

Rich Log

  • gging: verbose and structured; multi-engine; and secure.

27

slide-28
SLIDE 28

EXAMPLE: LIFECYCLE OF A MICROSERVICE

28

5

Scale on DC/OS

4

Productionize (Go & Docker)

3

Test the hypothesis

2

Deploy to AWS (EC2)

1

Prototype in any language

slide-29
SLIDE 29

LET’S TALK MORE ABOUT CHALLENGES

  • La

Latent conflict of priorities: s: Go is great but it had its issues (e.g. ICS parser).

  • Bu

Build ildin ing for scale le: : balancing TTM with future projections of scalability.

  • Su

Susceptib tibility ility to to tr trib ibal al knowle ledge syndrome: how to share knowledge & move fast? e.g .g., ., log.Error(wf11200, "response", response) // what’s "response"?

  • Ma

Many choices: green-field projects with high degrees of freedom; e.g., we moved from Kubernetes to DC/OS because of: – Better support of security and stateful solutions – Stability (on AWS) – GPU Time-sharing

29

slide-30
SLIDE 30

30

LESSON 2: DESIGN FOR HUMANS

slide-31
SLIDE 31

LEARN ABOUT ALL SORTS OF DESIGN

  • Good API design qualities transcend

code.

  • Industrial design cares about interfacing

with a physical product.

  • User-centered design focuses on

usability.

  • Many analogies to draw among all sorts
  • f design.

31

slide-32
SLIDE 32

TEN PRINCIPLES OF GOOD DESIGN BY DIETER RAMS

32

1 Good Design Is In Innova vative ive 2 Good Design Is Use seful 3 Good Design Is Ae Aesthetic 4 Good Design Is Un Understandable 5 Good Design Is Un Unob

  • btrusive

6 Good Design Is Ho Honest 7 Good Design Is Lo Long-la lastin ting 8 Good Design Is Th Thorough gh 9 Good Design Is Ec Eco-fr friendly 10 Good Design Is Mi Minima mal

slide-33
SLIDE 33

PUT THE HUMAN FIRST!

33

If the human gets it, things will work quicker & better Good API design is about communicating well to humans

slide-34
SLIDE 34

34

“Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.”

DONALD KNUTH

slide-35
SLIDE 35

EXAMPLE: PACKAGE ASSERT

35

// Java projects at LinkedIn are tested using TestNG, JUnit, & AssertJ:

  • rg.testng.Assert.assertEquals(x, y) // actual, expected
  • rg.junit.Assert.assertEquals(x, y) // expected, actual -> cognitive load

Assertions.assertThat(x).isEqualTo(y); // better // Package assert* allows for easy & consist UT+DDT and test hook checks if !assert.For(t).ThatActual(x).Equals(y).Passed() { analyze(x, y) } assert.For(t).ThatActual(x).Equals(expected).ThenRunOnFail(analyze) assert.For(t).ThatActual(x).Equals(expected).ThenDiffOnFail() assert.For(t).ThatCalling(someFunc).PanicsReporting("error")

slide-36
SLIDE 36

EXAMPLE: PACKAGE ASSERT

36

// Plays well with table-driven tests: cases := []struct { id string actual interface{} expected interface{} }{ {"different values", 42, 13}, // ... } for _, c := range cases { assert.For(t, c.id).ThatActual(c.actual).Equals(c.expected) } // prints test case ID in failure messages

slide-37
SLIDE 37

EXAMPLE: PACKAGE ASSERT

37

// At Microsoft, we used the internal access modifier and friend // assemblies for testability; at LinkedIn we used package-private // methods and documented that they are @VisibleForTesting; at Workfit, // using tags, instead of comments, enables us to check test hooks: type sleeper struct { sleep func(time.Duration) `test-hook:"verify-unexported"` } // What gets exposed for testability shall not be exported! func TestHooksAreHidden(t *testing.T) { assert.For(t).ThatType(reflect.TypeOf(sleeper{})).HidesTestHooks() }

slide-38
SLIDE 38

ANOTHER EXAMPLE: API DESIGN PROCESS

38

Reiterate

5

Implement

4

Write Client Code

3

Solicit & Discuss Feedback

2

Spec

1

slide-39
SLIDE 39

FINALLY

slide-40
SLIDE 40

TAKEAWAYS: 3x3

40

LEARNING

NORTH STAR PEOPLE FIRST

  • See
  • Do
  • Teach
  • Goals
  • Tenets
  • Methods
  • Accelerate
  • Communicate
  • Empathize
slide-41
SLIDE 41

E N T E R P R I S E V O I C E A I

____________ WE’RE HIRING

slide-42
SLIDE 42

@elgeish g@workfit.io www.elgeish.com linkedin.com/in/elgeish

CONTACT INFO

42