Designing Beautiful APIs...Designing Beautiful APIs 2 / 55 About Me I Tobias Schlitt (Toby) I Degree...

Preview:

Citation preview

Designing Beautiful APIsInternational PHP Conference 2012

Tobias Schlitt (@tobySen)

October 16, 2012

Designing Beautiful APIs 1 / 55

About Me

I Tobias Schlitt (Toby)I Degree in computer scienceI More than 10 years of

professional PHPI Open source enthusiastI Software Architecture,

Design, Testing . . .

Qafoopassion for software quality

Designing Beautiful APIs 2 / 55

About Me

I Tobias Schlitt (Toby)I Degree in computer scienceI More than 10 years of

professional PHPI Open source enthusiastI Software Architecture,

Design, Testing . . .

Qafoopassion for software quality

Designing Beautiful APIs 2 / 55

About Me

I Tobias Schlitt (Toby)I Degree in computer scienceI More than 10 years of

professional PHPI Open source enthusiastI Software Architecture,

Design, Testing . . .

Qafoopassion for software quality

Designing Beautiful APIs 2 / 55

About Me

I Tobias Schlitt (Toby)I Degree in computer scienceI More than 10 years of

professional PHPI Open source enthusiastI Software Architecture,

Design, Testing . . .

Qafoopassion for software quality

Designing Beautiful APIs 2 / 55

About Me

I Tobias Schlitt (Toby)I Degree in computer scienceI More than 10 years of

professional PHPI Open source enthusiastI Software Architecture,

Design, Testing . . .

Co-founder of

Qafoopassion for software quality

Designing Beautiful APIs 2 / 55

About Me

I Tobias Schlitt (Toby)I Degree in computer scienceI More than 10 years of

professional PHPI Open source enthusiastI Software Architecture,

Design, Testing . . .

Co-founder of

Qafoopassion for software quality

Helping teams to createhigh quality web

applications.

Designing Beautiful APIs 2 / 55

About Me

I Tobias Schlitt (Toby)I Degree in computer scienceI More than 10 years of

professional PHPI Open source enthusiastI Software Architecture,

Design, Testing . . .

Co-founder of

Qafoopassion for software quality

Helping teams to createhigh quality web

applications.

http://qafoo.com

Designing Beautiful APIs 2 / 55

Before we start . . .

I Please take a minute after the talk . . .I . . . to rate this talk . . .I . . . to make it better for . . .

I . . . OrganizersI . . . SpeakersI . . . You

I Just go to https://joind.in/7312I I’ll show the link later again :)

Designing Beautiful APIs 3 / 55

Before we start . . .

I Please take a minute after the talk . . .I . . . to rate this talk . . .I . . . to make it better for . . .

I . . . OrganizersI . . . SpeakersI . . . You

I Just go to https://joind.in/7312I I’ll show the link later again :)

Designing Beautiful APIs 3 / 55

Before we start . . .

I Please take a minute after the talk . . .I . . . to rate this talk . . .I . . . to make it better for . . .

I . . . OrganizersI . . . SpeakersI . . . You

I Just go to https://joind.in/7312I I’ll show the link later again :)

Designing Beautiful APIs 3 / 55

Before we start . . .

I Please take a minute after the talk . . .I . . . to rate this talk . . .I . . . to make it better for . . .

I . . . OrganizersI . . . SpeakersI . . . You

I Just go to https://joind.in/7312I I’ll show the link later again :)

Designing Beautiful APIs 3 / 55

Before we start . . .

I Please take a minute after the talk . . .I . . . to rate this talk . . .I . . . to make it better for . . .

I . . . OrganizersI . . . SpeakersI . . . You

I Just go to https://joind.in/7312I I’ll show the link later again :)

Designing Beautiful APIs 3 / 55

Before we start . . .

I Please take a minute after the talk . . .I . . . to rate this talk . . .I . . . to make it better for . . .

I . . . OrganizersI . . . SpeakersI . . . You

I Just go to https://joind.in/7312I I’ll show the link later again :)

Designing Beautiful APIs 3 / 55

Outline

On the beauty of APIs

Detecting APIs

Getting into code

Summary

Designing Beautiful APIs 5 / 55

A beautiful API . . .

“A beautiful API enables you to realize evenunforseen features with elegant code.”

–Tobias Schlitt

Designing Beautiful APIs 6 / 55

“Realize”

“A beautiful API enables you to realize even unforseen featureswith elegant code.”I It enables you to solve a taskI Helps you to reach your goal with less effortI Supports you in generating business value

Designing Beautiful APIs 7 / 55

“Unforseen”

“A beautiful API enables you to realize even unforseen featureswith elegant code.”I It keeps you flexible to

I add new featuresI react to changing requirements

I Is open for adjustment and extension

Designing Beautiful APIs 8 / 55

“Elegant Code”

“A beautiful API enables you to realize even unforseen featureswith elegant code.”I As few code as possibleI As much code as necessaryI Easy to read and understandI Simple and testable

Designing Beautiful APIs 9 / 55

Outline

On the beauty of APIs

Detecting APIs

Getting into code

Summary

Designing Beautiful APIs 10 / 55

So, where . . .

Where do you find APIs?

Designing Beautiful APIs 11 / 55

Web APIs

I REST (or what calls itsel)I (XML)-RPCI SOAPI . . . and friends.I Not covered here . . .I . . . but principles apply in a similar way

Designing Beautiful APIs 12 / 55

Web APIs

I REST (or what calls itsel)I (XML)-RPCI SOAPI . . . and friends.I Not covered here . . .I . . . but principles apply in a similar way

Designing Beautiful APIs 12 / 55

Web APIs

I REST (or what calls itsel)I (XML)-RPCI SOAPI . . . and friends.I Not covered here . . .I . . . but principles apply in a similar way

Designing Beautiful APIs 12 / 55

Code APIs

I Libraries / frameworksI Layer boundaries / components / modulesI Interfaces (and abstract classes!)I . . . every fu**ing class?!

Designing Beautiful APIs 13 / 55

Code APIs

I Libraries / frameworksI Layer boundaries / components / modulesI Interfaces (and abstract classes!)I . . . every fu**ing class?!

Designing Beautiful APIs 13 / 55

Code APIs

I Libraries / frameworksI Layer boundaries / components / modulesI Interfaces (and abstract classes!)I . . . every fu**ing class?!

Designing Beautiful APIs 13 / 55

Code APIs

I Libraries / frameworksI Layer boundaries / components / modulesI Interfaces (and abstract classes!)I . . . every fu**ing class?!

Designing Beautiful APIs 13 / 55

Levels of Beauty

I Code beauty (of the API)I OOP / OODI Consistent, good looking codeI Tests

I Syntactic / semantical beautyI Code structureI Naming & meaning

I DocumentationI API docsI Examples & TutorialsI User generated docs (comments)I Not further examined here

Designing Beautiful APIs 14 / 55

Levels of Beauty

I Code beauty (of the API)I OOP / OODI Consistent, good looking codeI Tests

I Syntactic / semantical beautyI Code structureI Naming & meaning

I DocumentationI API docsI Examples & TutorialsI User generated docs (comments)I Not further examined here

Designing Beautiful APIs 14 / 55

Levels of Beauty

I Code beauty (of the API)I OOP / OODI Consistent, good looking codeI Tests

I Syntactic / semantical beautyI Code structureI Naming & meaning

I DocumentationI API docsI Examples & TutorialsI User generated docs (comments)I Not further examined here

Designing Beautiful APIs 14 / 55

Outline

On the beauty of APIs

Detecting APIs

Getting into code

Summary

Designing Beautiful APIs 15 / 55

The Example

I Search componentI Index / search for arbitrary objectsI Apply filters to results

Designing Beautiful APIs 16 / 55

Step 1: Usage

1 <?php2

3 use qafoo \Search\Search ;4

5 / / Index6

7 $product = new Product ( ’ Glow Stone Driveway ’ ) ;8 Serv ice : : get ( )−>add ( $product ) ;9

10 / / Search11

12 $products = Search : : get ( )−> f e t ch (13 ’ type = ” Product ” AND name LIKE ”%stone%” ’14 ) ;

Designing Beautiful APIs 17 / 55

Step 1: Usage

1 <?php2

3 use qafoo \Search\Search ;4

5 / / Index6

7 $product = new Product ( ’ Glow Stone Driveway ’ ) ;8 Serv ice : : get ( )−>add ( $product ) ;9

10 / / Search11

12 $products = Search : : get ( )−> f e t ch (13 ’ type = ” Product ” AND name LIKE ”%stone%” ’14 ) ;

Designing Beautiful APIs 17 / 55

Step 1: Usage

1 <?php2

3 use qafoo \Search\Search ;4

5 / / Index6

7 $product = new Product ( ’ Glow Stone Driveway ’ ) ;8 Serv ice : : get ( )−>add ( $product ) ;9

10 / / Search11

12 $products = Search : : get ( )−> f e t ch (13 ’ type = ” Product ” AND name LIKE ”%stone%” ’14 ) ;

Designing Beautiful APIs 17 / 55

Step 1: API

1 namespace qafoo \Search ;2 class Serv ice3 {

4 public s t a t i c function get ( )5 { }

6 public function f e t ch ( $search , ar ray $conf ig = ar ray ( ) )7 { }

8 public function suggest ( $p re f i x , a r ray $ f i e l d s )9 { }

10 public function add ( $ob jec t )11 { }

12 }

Designing Beautiful APIs 18 / 55

Step 1: Issues

I IndescriptiveI Ambiguous

Designing Beautiful APIs 19 / 55

Step 1: Issues

I IndescriptiveI Ambiguous

Designing Beautiful APIs 19 / 55

Keep in Mind

I Find descriptive namesI Know your audienceI Start with usage examples!

Designing Beautiful APIs 20 / 55

Keep in Mind

I Find descriptive namesI Know your audienceI Start with usage examples!

Designing Beautiful APIs 20 / 55

Keep in Mind

I Find descriptive namesI Know your audienceI Start with usage examples!

Designing Beautiful APIs 20 / 55

Step 2: Usage

1 <?php2

3 use qafoo \Search\Search ;4

5 / / Index6

7 $product = new Product ( ’ Glow Stone Driveway ’ ) ;8 Search : : ge t Ins tance ( )−> index ( $product ) ;9

10 / / Search11

12 $products = Search : : ge t Ins tance ( )−> f i n d (13 ’ type = ” Product ” AND name LIKE ”%stone%” ’14 ) ;

Designing Beautiful APIs 21 / 55

Step 2: Usage

1 <?php2

3 use qafoo \Search\Search ;4

5 / / Index6

7 $product = new Product ( ’ Glow Stone Driveway ’ ) ;8 Search : : ge t Ins tance ( )−> index ( $product ) ;9

10 / / Search11

12 $products = Search : : ge t Ins tance ( )−> f i n d (13 ’ type = ” Product ” AND name LIKE ”%stone%” ’14 ) ;

Designing Beautiful APIs 21 / 55

Step 2: Usage

1 <?php2

3 use qafoo \Search\Search ;4

5 / / Index6

7 $product = new Product ( ’ Glow Stone Driveway ’ ) ;8 Search : : ge t Ins tance ( )−> index ( $product ) ;9

10 / / Search11

12 $products = Search : : ge t Ins tance ( )−> f i n d (13 ’ type = ” Product ” AND name LIKE ”%stone%” ’14 ) ;

Designing Beautiful APIs 21 / 55

Step 2: API

1 namespace qafoo \Search ;2 class Search3 {

4 public s t a t i c function get Ins tance ( )5 { }

6 public function f i n d ( $searchQuery , a r ray $conf ig = ar ray ( ) )7 { }

8 public function suggest ( $p re f i x , a r ray $ f i e l d s )9 { }

10 public function index ( $ob jec t )11 { }

12 }

Designing Beautiful APIs 22 / 55

Step 2: Issues

I Not configurableI Not easily mockableI STATIC DEPENDENCY

Designing Beautiful APIs 23 / 55

Step 2: Issues

I Not configurableI Not easily mockableI STATIC DEPENDENCY

Designing Beautiful APIs 23 / 55

Step 2: Issues

I Not configurableI Not easily mockableI STATIC DEPENDENCY

Designing Beautiful APIs 23 / 55

Keep in Mind

I Don’t force to violate Law of Demeter (LoD)I Leave instancitation / configuration to the userI DON’T FORCE STATIC DEPENDENCIES

Designing Beautiful APIs 24 / 55

Keep in Mind

I Don’t force to violate Law of Demeter (LoD)I Leave instancitation / configuration to the userI DON’T FORCE STATIC DEPENDENCIES

Designing Beautiful APIs 24 / 55

Keep in Mind

I Don’t force to violate Law of Demeter (LoD)I Leave instancitation / configuration to the userI DON’T FORCE STATIC DEPENDENCIES

Designing Beautiful APIs 24 / 55

Step 3: Usage

1 <?php2

3 use qafoo \Search\Search ;4

5 / / Index6

7 $search = new Search ( ) ;8 $product = new Product ( ’ Glow Stone Driveway ’ ) ;9 $search−> index ( $product ) ;

10

11 / / Search12

13 $search = new Search ( ) ;14 $products = $search−> f i n d (15 ’ type = ” Product ” AND name LIKE ”%stone%” ’16 ) ;

Designing Beautiful APIs 25 / 55

Step 3: Usage

1 <?php2

3 use qafoo \Search\Search ;4

5 / / Index6

7 $search = new Search ( ) ;8 $product = new Product ( ’ Glow Stone Driveway ’ ) ;9 $search−> index ( $product ) ;

10

11 / / Search12

13 $search = new Search ( ) ;14 $products = $search−> f i n d (15 ’ type = ” Product ” AND name LIKE ”%stone%” ’16 ) ;

Designing Beautiful APIs 25 / 55

Step 3: Usage

1 <?php2

3 use qafoo \Search\Search ;4

5 / / Index6

7 $search = new Search ( ) ;8 $product = new Product ( ’ Glow Stone Driveway ’ ) ;9 $search−> index ( $product ) ;

10

11 / / Search12

13 $search = new Search ( ) ;14 $products = $search−> f i n d (15 ’ type = ” Product ” AND name LIKE ”%stone%” ’16 ) ;

Designing Beautiful APIs 25 / 55

Step 3: API

1 namespace qafoo \Search ;2 class Search3 {

4 public function construct ( )5 { }

6 public function f i n d ( $searchQuery , a r ray $conf ig = ar ray ( ) )7 { }

8 public function suggest ( $p re f i x , a r ray $ f i e l d s )9 { }

10 public function index ( $ob jec t )11 { }

12 }

Designing Beautiful APIs 26 / 55

Step 3: Issues

I Search & index are different concernsI Not easily replaceableI Missing abstraction

Designing Beautiful APIs 27 / 55

Step 3: Issues

I Search & index are different concernsI Not easily replaceableI Missing abstraction

Designing Beautiful APIs 27 / 55

Step 3: Issues

I Search & index are different concernsI Not easily replaceableI Missing abstraction

Designing Beautiful APIs 27 / 55

Keep in Mind

I Make implementations replaceableI Stay flexible for changing requirementsI See concerns on different levels

Designing Beautiful APIs 28 / 55

Keep in Mind

I Make implementations replaceableI Stay flexible for changing requirementsI See concerns on different levels

Designing Beautiful APIs 28 / 55

Keep in Mind

I Make implementations replaceableI Stay flexible for changing requirementsI See concerns on different levels

Designing Beautiful APIs 28 / 55

Step 4: Usage

1 use qafoo \Search\Search ;2

3 / / Object cons t r uc t i on4 $search = new Search (5 new Backends\SolrSearchBackend ( /∗ . . . ∗ / ) ,6 new Backends\ZeroMqIndexBackend ( /∗ . . . ∗ / )7 ) ;8

9 / / Index10 $product = new Product ( ’ Glow Stone Driveway ’ ) ;11 $search−> index ( $product ) ;12

13 / / Search14 $products = $search−> f i n d (15 ’ type = ” Product ” AND name LIKE ”%stone%” ’16 ) ;

Designing Beautiful APIs 29 / 55

Step 4: Usage

1 use qafoo \Search\Search ;2

3 / / Object cons t r uc t i on4 $search = new Search (5 new Backends\SolrSearchBackend ( /∗ . . . ∗ / ) ,6 new Backends\ZeroMqIndexBackend ( /∗ . . . ∗ / )7 ) ;8

9 / / Index10 $product = new Product ( ’ Glow Stone Driveway ’ ) ;11 $search−> index ( $product ) ;12

13 / / Search14 $products = $search−> f i n d (15 ’ type = ” Product ” AND name LIKE ”%stone%” ’16 ) ;

Designing Beautiful APIs 29 / 55

Step 4: Usage

1 use qafoo \Search\Search ;2

3 / / Object cons t r uc t i on4 $search = new Search (5 new Backends\SolrSearchBackend ( /∗ . . . ∗ / ) ,6 new Backends\ZeroMqIndexBackend ( /∗ . . . ∗ / )7 ) ;8

9 / / Index10 $product = new Product ( ’ Glow Stone Driveway ’ ) ;11 $search−> index ( $product ) ;12

13 / / Search14 $products = $search−> f i n d (15 ’ type = ” Product ” AND name LIKE ”%stone%” ’16 ) ;

Designing Beautiful APIs 29 / 55

Step 4: Usage

1 use qafoo \Search\Search ;2

3 / / Object cons t r uc t i on4 $search = new Search (5 new Backends\SolrSearchBackend ( /∗ . . . ∗ / ) ,6 new Backends\ZeroMqIndexBackend ( /∗ . . . ∗ / )7 ) ;8

9 / / Index10 $product = new Product ( ’ Glow Stone Driveway ’ ) ;11 $search−> index ( $product ) ;12

13 / / Search14 $products = $search−> f i n d (15 ’ type = ” Product ” AND name LIKE ”%stone%” ’16 ) ;

Designing Beautiful APIs 29 / 55

Step 4: API

1 namespace qafoo \Search ;2 class Search3 {

4 public function construct ( SearchBackend $searchBackend ,IndexBackend $indexBackend )

5 { }

6 public function f i n d ( $searchQuery , a r ray $conf ig = ar ray ( ) )7 { }

8 public function suggest ( $p re f i x , a r ray $ f i e l d s )9 { }

10 public function index ( $ob jec t )11 { }

12 }

Designing Beautiful APIs 30 / 55

Step 4: Issues

I Query parsing is a dedicated concernI Back ends use different syntaxI Writing strings in code sucks

Designing Beautiful APIs 31 / 55

Step 4: Issues

I Query parsing is a dedicated concernI Back ends use different syntaxI Writing strings in code sucks

Designing Beautiful APIs 31 / 55

Step 4: Issues

I Query parsing is a dedicated concernI Back ends use different syntaxI Writing strings in code sucks

Designing Beautiful APIs 31 / 55

Keep in Mind

I Separate concernsI Avoid code is strings

Designing Beautiful APIs 32 / 55

Keep in Mind

I Separate concernsI Avoid code is strings

Designing Beautiful APIs 32 / 55

Step 5: Usage

1 use qafoo \Search\Search ;2 use qafoo \Search\ C r i t e r i o n ;3

4 / / Object cons t r uc t i on5 $search = new Search ( /∗ . . . ∗ / ) ;6

7 / / Search8 $products = $search−> f i n d (9 new C r i t e r i o n (

10 new C r i t e r i o n ( ’ type ’ , C r i t e r i o n : : EQUALS, ’ Product ’ ) ,11 C r i t e r i o n : : L AND ,12 new C r i t e r i o n ( ’name ’ , C r i t e r i o n : : LIKE , ’%stone%’ )13 )14 ) ;

Designing Beautiful APIs 33 / 55

Step 5: Usage

1 use qafoo \Search\Search ;2 use qafoo \Search\ C r i t e r i o n ;3

4 / / Object cons t r uc t i on5 $search = new Search ( /∗ . . . ∗ / ) ;6

7 / / Search8 $products = $search−> f i n d (9 new C r i t e r i o n (

10 new C r i t e r i o n ( ’ type ’ , C r i t e r i o n : : EQUALS, ’ Product ’ ) ,11 C r i t e r i o n : : L AND ,12 new C r i t e r i o n ( ’name ’ , C r i t e r i o n : : LIKE , ’%stone%’ )13 )14 ) ;

Designing Beautiful APIs 33 / 55

Step 5: Usage

1 use qafoo \Search\Search ;2 use qafoo \Search\ C r i t e r i o n ;3

4 / / Object cons t r uc t i on5 $search = new Search ( /∗ . . . ∗ / ) ;6

7 / / Search8 $products = $search−> f i n d (9 new C r i t e r i o n (

10 new C r i t e r i o n ( ’ type ’ , C r i t e r i o n : : EQUALS, ’ Product ’ ) ,11 C r i t e r i o n : : L AND ,12 new C r i t e r i o n ( ’name ’ , C r i t e r i o n : : LIKE , ’%stone%’ )13 )14 ) ;

Designing Beautiful APIs 33 / 55

Step 5: Usage

1 use qafoo \Search\Search ;2 use qafoo \Search\ C r i t e r i o n ;3

4 / / Object cons t r uc t i on5 $search = new Search ( /∗ . . . ∗ / ) ;6

7 / / Search8 $products = $search−> f i n d (9 new C r i t e r i o n (

10 new C r i t e r i o n ( ’ type ’ , C r i t e r i o n : : EQUALS, ’ Product ’ ) ,11 C r i t e r i o n : : L AND ,12 new C r i t e r i o n ( ’name ’ , C r i t e r i o n : : LIKE , ’%stone%’ )13 )14 ) ;

Designing Beautiful APIs 33 / 55

Step 5: Usage

1 use qafoo \Search\Search ;2 use qafoo \Search\ C r i t e r i o n ;3

4 / / Object cons t r uc t i on5 $search = new Search ( /∗ . . . ∗ / ) ;6

7 / / Search8 $products = $search−> f i n d (9 new C r i t e r i o n (

10 new C r i t e r i o n ( ’ type ’ , C r i t e r i o n : : EQUALS, ’ Product ’ ) ,11 C r i t e r i o n : : L AND ,12 new C r i t e r i o n ( ’name ’ , C r i t e r i o n : : LIKE , ’%stone%’ )13 )14 ) ;

Designing Beautiful APIs 33 / 55

Step 5: Usage

1 use qafoo \Search\Search ;2 use qafoo \Search\ C r i t e r i o n ;3

4 / / Object cons t r uc t i on5 $search = new Search ( /∗ . . . ∗ / ) ;6

7 / / Search8 $products = $search−> f i n d (9 new C r i t e r i o n (

10 new C r i t e r i o n ( ’ type ’ , C r i t e r i o n : : EQUALS, ’ Product ’ ) ,11 C r i t e r i o n : : L AND ,12 new C r i t e r i o n ( ’name ’ , C r i t e r i o n : : LIKE , ’%stone%’ )13 )14 ) ;

Designing Beautiful APIs 33 / 55

Step 5: API

1 class Search2 {

3 public function construct ( SearchBackend $searchBackend ,IndexBackend $indexBackend )

4 { }

5 public function f i n d ( C r i t e r i o n $ c r i t e r i o n , ar ray $conf ig =ar ray ( ) )

6 { }

7 public function suggest ( $p re f i x , a r ray $ f i e l d s )8 { }

9 public function index ( $ob jec t )10 { }

11 }

Designing Beautiful APIs 34 / 55

Step 5: API

1 namespace qafoo \Search ;2 class UserQueryParser3 {

4 public function parseQuery ( $querySt r ing )5 { }

6 }

Designing Beautiful APIs 35 / 55

Step 5: API

1 namespace qafoo \Search ;2 class UserQueryParser3 {

4 public function parseQuery ( $querySt r ing )5 { }

6 }

Designing Beautiful APIs 35 / 55

Step 5: API

1 namespace qafoo \Search ;2 class C r i t e r i o n3 {

4 const EQUALS = ’= ’ ;5 const LIKE = ’ LIKE ’ ;6 const L AND = ’&& ’ ;7 / / . . .8

9 public function construct ( $ f i r s t , $operator , $second )10 { }

11 }

Designing Beautiful APIs 36 / 55

Step 5: API

1 namespace qafoo \Search ;2 class C r i t e r i o n3 {

4 const EQUALS = ’= ’ ;5 const LIKE = ’ LIKE ’ ;6 const L AND = ’&& ’ ;7 / / . . .8

9 public function construct ( $ f i r s t , $operator , $second )10 { }

11 }

Designing Beautiful APIs 36 / 55

Step 5: API

1 namespace qafoo \Search ;2 class C r i t e r i o n3 {

4 const EQUALS = ’= ’ ;5 const LIKE = ’ LIKE ’ ;6 const L AND = ’&& ’ ;7 / / . . .8

9 public function construct ( $ f i r s t , $operator , $second )10 { }

11 }

Designing Beautiful APIs 36 / 55

Step 5: API

1 namespace qafoo \Search ;2 class C r i t e r i o n3 {

4 const EQUALS = ’= ’ ;5 const LIKE = ’ LIKE ’ ;6 const L AND = ’&& ’ ;7 / / . . .8

9 public function construct ( $ f i r s t , $operator , $second )10 { }

11 }

Designing Beautiful APIs 36 / 55

Step 5: Issues

I Not extensible at allI Encourages to violate Liskov

Designing Beautiful APIs 37 / 55

Step 5: Issues

I Not extensible at allI Encourages to violate Liskov

Designing Beautiful APIs 37 / 55

Keep in Mind

I Never use constants for processing instructionsI Put trees where trees belong . . .

Designing Beautiful APIs 38 / 55

Keep in Mind

I Never use constants for processing instructionsI Put trees where trees belong . . .

Designing Beautiful APIs 38 / 55

Step 6: Usage

1 use qafoo \Search\Search ;2 use qafoo \Search\ C r i t e r i o n \LogicalAnd ;3 use qafoo \Search\ C r i t e r i o n \Equals ;4 use qafoo \Search\ C r i t e r i o n \ Like ;5

6 / / Object cons t r uc t i on7 $search = new Search ( /∗ . . . ∗ / ) ;8

9 / / Search10 $products = $search−> f i n d (11 new LogicalAnd (12 new Equals ( ’ type ’ , ’ Product ’ ) ,13 new Like ( ’name ’ , ’%stone%’ )14 )15 ) ;

Designing Beautiful APIs 39 / 55

Step 6: Usage

1 use qafoo \Search\Search ;2 use qafoo \Search\ C r i t e r i o n \LogicalAnd ;3 use qafoo \Search\ C r i t e r i o n \Equals ;4 use qafoo \Search\ C r i t e r i o n \ Like ;5

6 / / Object cons t r uc t i on7 $search = new Search ( /∗ . . . ∗ / ) ;8

9 / / Search10 $products = $search−> f i n d (11 new LogicalAnd (12 new Equals ( ’ type ’ , ’ Product ’ ) ,13 new Like ( ’name ’ , ’%stone%’ )14 )15 ) ;

Designing Beautiful APIs 39 / 55

Step 6: Usage

1 use qafoo \Search\Search ;2 use qafoo \Search\ C r i t e r i o n \LogicalAnd ;3 use qafoo \Search\ C r i t e r i o n \Equals ;4 use qafoo \Search\ C r i t e r i o n \ Like ;5

6 / / Object cons t r uc t i on7 $search = new Search ( /∗ . . . ∗ / ) ;8

9 / / Search10 $products = $search−> f i n d (11 new LogicalAnd (12 new Equals ( ’ type ’ , ’ Product ’ ) ,13 new Like ( ’name ’ , ’%stone%’ )14 )15 ) ;

Designing Beautiful APIs 39 / 55

Step 6: Usage

1 use qafoo \Search\Search ;2 use qafoo \Search\ C r i t e r i o n \LogicalAnd ;3 use qafoo \Search\ C r i t e r i o n \Equals ;4 use qafoo \Search\ C r i t e r i o n \ Like ;5

6 / / Object cons t r uc t i on7 $search = new Search ( /∗ . . . ∗ / ) ;8

9 / / Search10 $products = $search−> f i n d (11 new LogicalAnd (12 new Equals ( ’ type ’ , ’ Product ’ ) ,13 new Like ( ’name ’ , ’%stone%’ )14 )15 ) ;

Designing Beautiful APIs 39 / 55

Step 6: API

1 namespace qafoo \Search ;2 abstract class C r i t e r i o n3 {

4 }

1 namespace qafoo \Search\ C r i t e r i o n ;2 use qafoo \Search\ C r i t e r i o n ;3

4 class Equals extends C r i t e r i o n5 {

6 public function construct ( $fieldName , $value )7 { }

8 }

Designing Beautiful APIs 40 / 55

Step 6: API

1 namespace qafoo \Search ;2 abstract class C r i t e r i o n3 {

4 }

1 namespace qafoo \Search\ C r i t e r i o n ;2 use qafoo \Search\ C r i t e r i o n ;3

4 class Equals extends C r i t e r i o n5 {

6 public function construct ( $fieldName , $value )7 { }

8 }

Designing Beautiful APIs 40 / 55

Step 6: API

1 namespace qafoo \Search ;2 abstract class C r i t e r i o n3 {

4 }

1 namespace qafoo \Search\ C r i t e r i o n ;2 use qafoo \Search\ C r i t e r i o n ;3

4 class Equals extends C r i t e r i o n5 {

6 public function construct ( $fieldName , $value )7 { }

8 }

Designing Beautiful APIs 40 / 55

Step 6: API

1 namespace qafoo \Search ;2 abstract class C r i t e r i o n3 {

4 }

1 namespace qafoo \Search\ C r i t e r i o n ;2 use qafoo \Search\ C r i t e r i o n ;3

4 class LogicalAnd extends C r i t e r i o n5 {

6 public function construct ( C r i t e r i o n $ l e f t C r i t e r i o n ,C r i t e r i o n $ r i g h t C r i t e r i o n )

7 { }

8 }

Designing Beautiful APIs 41 / 55

Step 6: API

1 namespace qafoo \Search ;2 abstract class C r i t e r i o n3 {

4 }

1 namespace qafoo \Search\ C r i t e r i o n ;2 use qafoo \Search\ C r i t e r i o n ;3

4 class LogicalAnd extends C r i t e r i o n5 {

6 public function construct ( C r i t e r i o n $ l e f t C r i t e r i o n ,C r i t e r i o n $ r i g h t C r i t e r i o n )

7 { }

8 }

Designing Beautiful APIs 41 / 55

Step 6: API

1 namespace qafoo \Search ;2 abstract class C r i t e r i o n3 {

4 }

1 namespace qafoo \Search\ C r i t e r i o n ;2 use qafoo \Search\ C r i t e r i o n ;3

4 class LogicalAnd extends C r i t e r i o n5 {

6 public function construct ( C r i t e r i o n $ l e f t C r i t e r i o n ,C r i t e r i o n $ r i g h t C r i t e r i o n )

7 { }

8 }

Designing Beautiful APIs 41 / 55

Step 6: Issues

1 use qafoo \Search\Search ;2

3 / / Object cons t r u c t i on4 $search = new Search ( /∗ . . . ∗ / ) ;5

6 / / Search7 $products = $search−> f i n d (8 new LogicalAnd ( /∗ . . . ∗ / ) ,9 ar ray (

10 ’ f i l t e r s ’ => ar ray (11 ’ user ’ => ’ john doe ’12 )13 )14 ) ;

Designing Beautiful APIs 43 / 55

Step 6: Issues

I No auto completion for arrays / stringsI Almost impossible to extend

Designing Beautiful APIs 44 / 55

Step 6: Issues

I No auto completion for arrays / stringsI Almost impossible to extend

Designing Beautiful APIs 44 / 55

Keep in Mind

I Remember inversion of controlI Provide hook-in mechanism where sensible

Designing Beautiful APIs 45 / 55

Keep in Mind

I Remember inversion of controlI Provide hook-in mechanism where sensible

Designing Beautiful APIs 45 / 55

Step 7: Usage

1 use qafoo \Search\Search ;2

3 / / Object cons t r uc t i on4 $search = new Search ( /∗ . . . ∗ / ) ;5

6 / / Search7 $products = $search−> f i n d (8 new LogicalAnd ( /∗ . . . ∗ / ) ,9 new UserPerm iss ionF i l t e r ( ’ john doe ’ )

10 ) ;

Designing Beautiful APIs 46 / 55

Step 7: Usage

1 use qafoo \Search\Search ;2

3 / / Object cons t r uc t i on4 $search = new Search ( /∗ . . . ∗ / ) ;5

6 / / Search7 $products = $search−> f i n d (8 new LogicalAnd ( /∗ . . . ∗ / ) ,9 new UserPerm iss ionF i l t e r ( ’ john doe ’ )

10 ) ;

Designing Beautiful APIs 46 / 55

Step 7: API

1 namespace qafoo \Search ;2 abstract class F i l t e r3 {

4 abstract public function accepts ( Resul t $ r e s u l t ) ;5 }

Designing Beautiful APIs 47 / 55

Step 7: API

1 namespace qafoo \Search ;2 abstract class F i l t e r3 {

4 abstract public function accepts ( Resul t $ r e s u l t ) ;5 }

Designing Beautiful APIs 47 / 55

Step 7: Issues

I Results are created out of thin air?I Smells like . . .

I hidden dependenciesI black magic

Designing Beautiful APIs 48 / 55

Step 7: Issues

I Results are created out of thin air?I Smells like . . .

I hidden dependenciesI black magic

Designing Beautiful APIs 48 / 55

Keep in Mind

I Object live cycle control

Designing Beautiful APIs 49 / 55

Step 8: Usage

1 use qafoo \Search\Search ;2 use qafoo \Search\Resul tFactory ;3

4 / / Object cons t r uc t i on5 $search = new Search (6 new Backends\SolrSearchBackend ( /∗ . . . ∗ / ) ,7 new Backends\ZeroMqIndexBackend ( /∗ . . . ∗ / ) ,8 new Resul tFactoy \Dispatch ingResu l tFac tory (9 /∗ . . . ∗ /

10 )11 ) ;12

13 / / Search14 $products = $search−> f i n d (15 new LogicalAnd ( /∗ . . . ∗ / ) ,16 new UserPerm iss ionF i l t e r ( ’ john doe ’ )17 ) ;Designing Beautiful APIs 50 / 55

Step 8: Usage

1 use qafoo \Search\Search ;2 use qafoo \Search\Resul tFactory ;3

4 / / Object cons t r uc t i on5 $search = new Search (6 new Backends\SolrSearchBackend ( /∗ . . . ∗ / ) ,7 new Backends\ZeroMqIndexBackend ( /∗ . . . ∗ / ) ,8 new Resul tFactoy \Dispatch ingResu l tFac tory (9 /∗ . . . ∗ /

10 )11 ) ;12

13 / / Search14 $products = $search−> f i n d (15 new LogicalAnd ( /∗ . . . ∗ / ) ,16 new UserPerm iss ionF i l t e r ( ’ john doe ’ )17 ) ;Designing Beautiful APIs 50 / 55

Step 7: API

1 namespace qafoo \Search ;2 abstract class Resul tFactory3 {

4 abstract public function canHandle ( $className ) ;5 abstract public function crea teResu l tOb jec t ( $className , ar ray

$data ) ;6 }

Designing Beautiful APIs 51 / 55

Step 7: API

1 namespace qafoo \Search ;2 abstract class Resul tFactory3 {

4 abstract public function canHandle ( $className ) ;5 abstract public function crea teResu l tOb jec t ( $className , ar ray

$data ) ;6 }

Designing Beautiful APIs 51 / 55

Step 7: API

1 namespace qafoo \Search ;2 abstract class Resul tFactory3 {

4 abstract public function canHandle ( $className ) ;5 abstract public function crea teResu l tOb jec t ( $className , ar ray

$data ) ;6 }

Designing Beautiful APIs 51 / 55

Outline

On the beauty of APIs

Detecting APIs

Getting into code

Summary

Designing Beautiful APIs 52 / 55

Keep in mind (randomly)

I Descriptive namingI Know your audienceI Let the user create objectsI Never force static dependenciesI Separate concerns on different levelsI Make implementations replaceableI Remember inversion of controlI Avoid code in strings

Designing Beautiful APIs 53 / 55

Keep in mind (randomly)

I Descriptive namingI Know your audienceI Let the user create objectsI Never force static dependenciesI Separate concerns on different levelsI Make implementations replaceableI Remember inversion of controlI Avoid code in strings

Designing Beautiful APIs 53 / 55

Keep in mind (randomly)

I Descriptive namingI Know your audienceI Let the user create objectsI Never force static dependenciesI Separate concerns on different levelsI Make implementations replaceableI Remember inversion of controlI Avoid code in strings

Designing Beautiful APIs 53 / 55

Keep in mind (randomly)

I Descriptive namingI Know your audienceI Let the user create objectsI Never force static dependenciesI Separate concerns on different levelsI Make implementations replaceableI Remember inversion of controlI Avoid code in strings

Designing Beautiful APIs 53 / 55

Keep in mind (randomly)

I Descriptive namingI Know your audienceI Let the user create objectsI Never force static dependenciesI Separate concerns on different levelsI Make implementations replaceableI Remember inversion of controlI Avoid code in strings

Designing Beautiful APIs 53 / 55

Keep in mind (randomly)

I Descriptive namingI Know your audienceI Let the user create objectsI Never force static dependenciesI Separate concerns on different levelsI Make implementations replaceableI Remember inversion of controlI Avoid code in strings

Designing Beautiful APIs 53 / 55

Thanks for Listening!

Stay in touch

I TobyI @tobySenI toby@qafoo.comI http://qafoo.com

Rate the talk!

https://joind.in/7312

Designing Beautiful APIs 54 / 55

Attribution

I Cat photo CC-NC-BY-SA buttersweet,https://secure.flickr.com/photos/buttersweet/433993378/

I Cat photo CC-NC-BY-SA rodolphoreis,https://secure.flickr.com/photos/rodolphoreis/5252680113/

Designing Beautiful APIs 55 / 55