SlideShare une entreprise Scribd logo
1  sur  73
Pragma&c
REST
Beware
of
Dogma


Marsh
Gardiner
@earth2marsh

Brian
Mulloy
@landlessness

Apigee
@apigee
#apidesign

             2
3
What
is
Pragma&c
REST?
What
is
Pragma&c
REST?


• Not strict REST
What
is
Pragma&c
REST?


• Not strict REST
• Adoption-centered design
Why
REST
is
winning:
Why
REST
is
winning:
http://api.twitter.com/1/statuses/public_timeline.json
POST /InStock HTTP/1.1
Host: www.example.org
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 299

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
 <soap:Header>
 </soap:Header>
 <soap:Body>
   <m:GetStockPrice xmlns:m="http://www.example.org/stock">
    <m:StockName>IBM</m:StockName>
   </m:GetStockPrice>
 </soap:Body>
</soap:Envelope>
URLs
and
Verbs
URLs
and
Verbs

• URL is the LCD
URLs
and
Verbs

• URL is the LCD
• Verbs map to CRUD
Good Architecture !   Good Design
“   As
the
flexibility
of
a
system
increases,
its
usability

    decreases.


                   Flexibility‐Usability
Tradeoff
                                              Universal
Principles
of
Design
“   Successful
products
typically
follow
four
stages
of
creaEon:

    requirements,
design,
development,
and
tes&ng.


                                 Development
Cycle
                                            Universal
Principles
of
Design
We
only
need
two
URLs.
The
first
is
for
a
collecEon.
/dogs
The
second
is
for
an
element.
/dogs/1234
POST
GET
PUT
DELETE
CREATE
READ
UPDATE
DELETE
Resource      POST             GET        PUT         DELETE
              create           read      update        delete




           create
a
new
              bulk
update
 delete
all

 /dogs                   list
dogs
           dog                        dogs         dogs


                                      if
exists

                                      update
Bo
/dogs/bo   error           show
Bo                  delete
Bo
                                      if
not
                                      error



                   Wikipedia
Verbs
are
bad.
Nouns
are
good.
Plurals
are
beNer.
What
about
associaEons?
GET /owners/9876/dogs

POST /owners/9876/dogs
What
about
complex
variaEons?
Cody Simms
Sweep
variaEons
under
the
‘?’
/dogs?color=red&state=running&location=park
What
about
paginaEon?
Facebook
offset
limit


TwiNer
page
rpp


LinkedIn
start
count
/dogs?limit=25&offset=50
What
about
versioning?
earth2marsh
Twilio
/2010-04-01/Accounts/



salesforce.com
/services/data/v20.0/sobjects/Account



Facebook
?v=1.0
/v1/dogs
Please
give
me
exactly
what
I
need.
LinkedIn
/people:(id,first-name,last-name,industry)




Facebook

/joe.smith/friends?fields=id,name,picture




Google
(parEal
response)

?fields=title,media:group(media:thumbnail)
/dogs?fields=name,color,location
What
about
formats?
Google
Data
?alt=json



Foursquare
/venue.json



Digg*
Accept: application/json
?type=json
* The type argument, if present, overrides the Accept header.
“   The
Eme
it
takes
to
make
a
decision
increases
as
the

    number
of
alternaEves
increases.


                                                Hick’s
Law
                                           Universal
Principles
of
Design
/dogs.json


/dogs/bo.json
What
about
searching?
Global
/search?q=fluffy+dog



Scoped
/owners/bob/dogs/search?q=fluffy



FormaNed
/search.xml?q=fluffy
What
about
errors?
earth2marsh
Facebook            HTTP Status Code: 200

{"type":"OAuthException","message":"(#803) Some
of the aliases you requested do not exist:
foo.bar"}




Twilio              HTTP Status Code: 401

{"status":401,"message":"Authenticate","code":
20003,"more_info":"http://www.twilio.com/docs/
errors/20003"}




SimpleGeo           HTTP Status Code: 401

{"code":401,"message":"Authentication
Required"}
Code
for
code
200 - OK

401 - Unauthorized
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes




Message
for
people
{“message” : “Verbose, plain language
description of the problem with hints about
how to fix it.”
“more_info” : “http://dev.teachdogrest.com/
errors/12345”}
What
about
the
rest
of
the
URL?
Facebook    graph.facebook.com

             api.facebook.com

             developers.facebook.com



Foursquare   api.foursquare.com
             developers.foursquare.com



   TwiNer    api.twitter.com

             search.twitter.com

             stream.twitter.com

             dev.twitter.com
API
gateway
api.teachdogrest.com



Developer
connecEon
developers.teachdogrest.com



Do
web
redirects
api → developers (if from browser)

dev → developers
developer → developers
What
about
defaults?
Format
json



PaginaEon
(depends
on
data
size)
limit=10&offset=0
What
about
excepEonal
stuff?
MiguelVieira
Client
intercepts
HTTP
error
codes
TwiNer

/public_timelines.json?
suppress_response_codes=true


HTTP Status Code: 200


{"error" : "Could not authenticate
you." }
Always
returns
OK
/dogs?suppress_response_codes=true


Code
for
code
ignoring
200 - OK


Message
for
people
code
{“response_code” : “401”, “message” :
“Verbose, plain language description of the
problem with hints about how to fix it.”
“more_info” : “http://dev.teachdogrest.com/
errors/12345”, “code” : 12345}
Client
supports
limited
HTTP
methods
Method
Parameter
create

/dogs?method=post
read

/dogs
update

/dogs/bo?method=put&location=park
delete

/dogs/bo?method=delete
Really?
All
of
this?
And
iterate
it?
Application




      API Virtualization Layer




API             API              API
Be
RESTful
Only
2
URLs
No
verbs
Use
nouns
as
plurals
Sweep
complexity
behind
the
‘?’
Borrow
from
leading
APIs
Account
for
excepEonal
clients
Add
virtualizaEon
layer
THANK
YOU
Ques%ons
and
ideas
to:

#apidesign


Marsh
Gardiner           Brian
Mulloy
@earth2marsh             @landlessness
marsh@apigee.com         brian@apigee.com

Contenu connexe

Tendances

Tendances (20)

Rest api standards and best practices
Rest api standards and best practicesRest api standards and best practices
Rest api standards and best practices
 
How to design a good REST API: Tools, techniques and best practices
How to design a good REST API: Tools, techniques and best practicesHow to design a good REST API: Tools, techniques and best practices
How to design a good REST API: Tools, techniques and best practices
 
4. 대용량 아키텍쳐 설계 패턴
4. 대용량 아키텍쳐 설계 패턴4. 대용량 아키텍쳐 설계 패턴
4. 대용량 아키텍쳐 설계 패턴
 
Enterprise messaging with jms
Enterprise messaging with jmsEnterprise messaging with jms
Enterprise messaging with jms
 
Kubernetes Basics
Kubernetes BasicsKubernetes Basics
Kubernetes Basics
 
Introduction to Docker Compose
Introduction to Docker ComposeIntroduction to Docker Compose
Introduction to Docker Compose
 
Introduction to kubernetes
Introduction to kubernetesIntroduction to kubernetes
Introduction to kubernetes
 
Introduction to APIs (Application Programming Interface)
Introduction to APIs (Application Programming Interface) Introduction to APIs (Application Programming Interface)
Introduction to APIs (Application Programming Interface)
 
Distributed Transaction in Microservice
Distributed Transaction in MicroserviceDistributed Transaction in Microservice
Distributed Transaction in Microservice
 
Using the Terraform Enterprise GUI is perfect to start working with Terraform...
Using the Terraform Enterprise GUI is perfect to start working with Terraform...Using the Terraform Enterprise GUI is perfect to start working with Terraform...
Using the Terraform Enterprise GUI is perfect to start working with Terraform...
 
Bizweb Microservices Architecture
Bizweb Microservices ArchitectureBizweb Microservices Architecture
Bizweb Microservices Architecture
 
Introduction to Spring Cloud
Introduction to Spring Cloud           Introduction to Spring Cloud
Introduction to Spring Cloud
 
Laravel Introduction
Laravel IntroductionLaravel Introduction
Laravel Introduction
 
Monitoring using Prometheus and Grafana
Monitoring using Prometheus and GrafanaMonitoring using Prometheus and Grafana
Monitoring using Prometheus and Grafana
 
Containers Anywhere with OpenShift by Red Hat
Containers Anywhere with OpenShift by Red HatContainers Anywhere with OpenShift by Red Hat
Containers Anywhere with OpenShift by Red Hat
 
DevOps Taiwan Monitor Tools 大亂鬥 - Prometheus
DevOps Taiwan Monitor Tools 大亂鬥 - PrometheusDevOps Taiwan Monitor Tools 大亂鬥 - Prometheus
DevOps Taiwan Monitor Tools 大亂鬥 - Prometheus
 
Introduction to Kong API Gateway
Introduction to Kong API GatewayIntroduction to Kong API Gateway
Introduction to Kong API Gateway
 
API Management Solution Powerpoint Presentation Slides
API Management Solution Powerpoint Presentation SlidesAPI Management Solution Powerpoint Presentation Slides
API Management Solution Powerpoint Presentation Slides
 
How to create a User Defined Policy with IBM APIc (v10)
How to create a User Defined Policy with IBM APIc (v10)How to create a User Defined Policy with IBM APIc (v10)
How to create a User Defined Policy with IBM APIc (v10)
 
The eBay Architecture: Striking a Balance between Site Stability, Feature Ve...
The eBay Architecture:  Striking a Balance between Site Stability, Feature Ve...The eBay Architecture:  Striking a Balance between Site Stability, Feature Ve...
The eBay Architecture: Striking a Balance between Site Stability, Feature Ve...
 

Similaire à Pragmatic RESTful API Design: Apigee Webinar

AtlasCamp 2011 - Five Strategies to Accelerate Plugin Development
AtlasCamp 2011 - Five Strategies to Accelerate Plugin DevelopmentAtlasCamp 2011 - Five Strategies to Accelerate Plugin Development
AtlasCamp 2011 - Five Strategies to Accelerate Plugin Development
mrdon
 
Building Awesome APIs in Grails
Building Awesome APIs in GrailsBuilding Awesome APIs in Grails
Building Awesome APIs in Grails
clatimer
 

Similaire à Pragmatic RESTful API Design: Apigee Webinar (20)

RESTFul API Design and Documentation - an Introduction
RESTFul API Design and Documentation - an IntroductionRESTFul API Design and Documentation - an Introduction
RESTFul API Design and Documentation - an Introduction
 
Don't screw it up! How to build durable API
Don't screw it up! How to build durable API Don't screw it up! How to build durable API
Don't screw it up! How to build durable API
 
Introduction to python scrapping
Introduction to python scrappingIntroduction to python scrapping
Introduction to python scrapping
 
Restful design at work v2.0
Restful design at work v2.0Restful design at work v2.0
Restful design at work v2.0
 
Yahoo is open to developers
Yahoo is open to developersYahoo is open to developers
Yahoo is open to developers
 
Atmosphere Conference 2015: The 10 Myths of DevOps
Atmosphere Conference 2015: The 10 Myths of DevOpsAtmosphere Conference 2015: The 10 Myths of DevOps
Atmosphere Conference 2015: The 10 Myths of DevOps
 
Web performance optimization
Web performance optimizationWeb performance optimization
Web performance optimization
 
AtlasCamp 2011 - Five Strategies to Accelerate Plugin Development
AtlasCamp 2011 - Five Strategies to Accelerate Plugin DevelopmentAtlasCamp 2011 - Five Strategies to Accelerate Plugin Development
AtlasCamp 2011 - Five Strategies to Accelerate Plugin Development
 
Introduction to RESTful API Designs
Introduction to RESTful API DesignsIntroduction to RESTful API Designs
Introduction to RESTful API Designs
 
Creating Rich Multi-Screen Experiences on Android with Amazon Fling - Mario V...
Creating Rich Multi-Screen Experiences on Android with Amazon Fling - Mario V...Creating Rich Multi-Screen Experiences on Android with Amazon Fling - Mario V...
Creating Rich Multi-Screen Experiences on Android with Amazon Fling - Mario V...
 
APIdays Helsinki 2019 - API Versioning with REST, JSON and Swagger with Thoma...
APIdays Helsinki 2019 - API Versioning with REST, JSON and Swagger with Thoma...APIdays Helsinki 2019 - API Versioning with REST, JSON and Swagger with Thoma...
APIdays Helsinki 2019 - API Versioning with REST, JSON and Swagger with Thoma...
 
Developing Android Apps for TV in Minutes with Amazon Fire App Builder
Developing Android Apps for TV in Minutes with Amazon Fire App BuilderDeveloping Android Apps for TV in Minutes with Amazon Fire App Builder
Developing Android Apps for TV in Minutes with Amazon Fire App Builder
 
Big Data Seminar: Analytics, Hadoop, Map Reduce, Mongo and other great stuff
Big Data Seminar: Analytics, Hadoop, Map Reduce, Mongo and other great stuffBig Data Seminar: Analytics, Hadoop, Map Reduce, Mongo and other great stuff
Big Data Seminar: Analytics, Hadoop, Map Reduce, Mongo and other great stuff
 
PhoneGap talk from Singapore
PhoneGap talk from SingaporePhoneGap talk from Singapore
PhoneGap talk from Singapore
 
CSG 2012
CSG 2012CSG 2012
CSG 2012
 
Who pulls the strings?
Who pulls the strings?Who pulls the strings?
Who pulls the strings?
 
Rails 101
Rails 101Rails 101
Rails 101
 
Api anti patterns
Api anti patternsApi anti patterns
Api anti patterns
 
Wordpress Meetup 2 23 10
Wordpress Meetup 2 23 10Wordpress Meetup 2 23 10
Wordpress Meetup 2 23 10
 
Building Awesome APIs in Grails
Building Awesome APIs in GrailsBuilding Awesome APIs in Grails
Building Awesome APIs in Grails
 

Plus de Apigee | Google Cloud

Plus de Apigee | Google Cloud (20)

How Secure Are Your APIs?
How Secure Are Your APIs?How Secure Are Your APIs?
How Secure Are Your APIs?
 
Magazine Luiza at a glance (1)
Magazine Luiza at a glance (1)Magazine Luiza at a glance (1)
Magazine Luiza at a glance (1)
 
Monetization: Unlock More Value from Your APIs
Monetization: Unlock More Value from Your APIs Monetization: Unlock More Value from Your APIs
Monetization: Unlock More Value from Your APIs
 
Apigee Demo: API Platform Overview
Apigee Demo: API Platform OverviewApigee Demo: API Platform Overview
Apigee Demo: API Platform Overview
 
Ticketmaster at a glance
Ticketmaster at a glanceTicketmaster at a glance
Ticketmaster at a glance
 
AccuWeather: Recasting API Experiences in a Developer-First World
AccuWeather: Recasting API Experiences in a Developer-First WorldAccuWeather: Recasting API Experiences in a Developer-First World
AccuWeather: Recasting API Experiences in a Developer-First World
 
Which Application Modernization Pattern Is Right For You?
Which Application Modernization Pattern Is Right For You?Which Application Modernization Pattern Is Right For You?
Which Application Modernization Pattern Is Right For You?
 
Apigee Product Roadmap Part 2
Apigee Product Roadmap Part 2Apigee Product Roadmap Part 2
Apigee Product Roadmap Part 2
 
The Four Transformative Forces of the API Management Market
The Four Transformative Forces of the API Management MarketThe Four Transformative Forces of the API Management Market
The Four Transformative Forces of the API Management Market
 
Walgreens at a glance
Walgreens at a glanceWalgreens at a glance
Walgreens at a glance
 
Apigee Edge: Intro to Microgateway
Apigee Edge: Intro to MicrogatewayApigee Edge: Intro to Microgateway
Apigee Edge: Intro to Microgateway
 
Managing the Complexity of Microservices Deployments
Managing the Complexity of Microservices DeploymentsManaging the Complexity of Microservices Deployments
Managing the Complexity of Microservices Deployments
 
Pitney Bowes at a glance
Pitney Bowes at a glancePitney Bowes at a glance
Pitney Bowes at a glance
 
Microservices Done Right: Key Ingredients for Microservices Success
Microservices Done Right: Key Ingredients for Microservices SuccessMicroservices Done Right: Key Ingredients for Microservices Success
Microservices Done Right: Key Ingredients for Microservices Success
 
Adapt or Die: Opening Keynote with Chet Kapoor
Adapt or Die: Opening Keynote with Chet KapoorAdapt or Die: Opening Keynote with Chet Kapoor
Adapt or Die: Opening Keynote with Chet Kapoor
 
Adapt or Die: Keynote with Greg Brail
Adapt or Die: Keynote with Greg BrailAdapt or Die: Keynote with Greg Brail
Adapt or Die: Keynote with Greg Brail
 
Adapt or Die: Keynote with Anant Jhingran
Adapt or Die: Keynote with Anant JhingranAdapt or Die: Keynote with Anant Jhingran
Adapt or Die: Keynote with Anant Jhingran
 
London Adapt or Die: Opening Keynot
London Adapt or Die: Opening KeynotLondon Adapt or Die: Opening Keynot
London Adapt or Die: Opening Keynot
 
London Adapt or Die: Lunch keynote
London Adapt or Die: Lunch keynoteLondon Adapt or Die: Lunch keynote
London Adapt or Die: Lunch keynote
 
London Adapt or Die: Closing Keynote — Adapt Now!
London Adapt or Die: Closing Keynote — Adapt Now!London Adapt or Die: Closing Keynote — Adapt Now!
London Adapt or Die: Closing Keynote — Adapt Now!
 

Dernier

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Dernier (20)

presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 

Pragmatic RESTful API Design: Apigee Webinar

Notes de l'éditeur

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. http://www.nordsc.com/ext/classification_of_http_based_apis.html\n
  8. \n
  9. Here&amp;#x2019;s an example SOAP request\n
  10. Via uzbeckistan and \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. let&amp;#x2019;s understand how developers build apps.\n\ndevelopers work in a development cycle (sometimes formally, more often informally) with four 4 phases:\n\nrequirements gathering\ndesign\ndevelopment \nand testing\n\n\n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. use facebook as versionless example being bad\n
  40. no dots\n\nversion required\n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. as they create applications, developers make hundreds or even thousands of simple decisions.\n\nthe faster they make decisions, the faster an app gets made.\n\nthe better the decisions they make, the better the app.\n\nHick&amp;#x2019;s law states that for simple stimulus-response tasks, the time it takes to make a decision is a function of the number of available options.\n\nThe more options we give our developers about our API the longer it will take them to build apps.\n\nlet&amp;#x2019;s take a look at an example where unnecessary complexity collides with Hick&amp;#x2019;s Law.\n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. use facebook as versionless example being bad\n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. use facebook as versionless example being bad\n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n