SlideShare a Scribd company logo
Less is more
Do more with less code in a serverless world
Jerome Van Der Linden
Geneva Serverless Meetup - 26/05/2020
About me
• In a previous life, ”Mr Cut Cut” (M. Coupe coupe)
• Developer & software craftsman
• And now, Solutions Architect @ AWS
2
linkedin.com/in/jeromevdl/
Jerome Van Der Linden
Few principles
Clean Code
SOLID
4
S Single Responsibility Principle
O Open / closed Principle
L Liskov substitution Principle
I Interface segregation Principle
D Dependency Inversion Principle
Single Responsibility Principle
5
“A class or module should have one,
and only one, reason to be changed”
- Robert C. Martin, aka Uncle Bob
YAGNI (You Ain’t Gonna Need It)
6
Just because you can,
doesn’t mean you should…
KISS
7
8
And many more…
Clean Code
DRY
Don’t Repeat Yourself
Law of Demeter
Broken window
theory
Boy scout rule
Not invented here
How to apply those principles?
In the serverless world
Serverless World?
10
Serverless == FAASFunction As A Service
Serverless World?
11
Serverless ⊃ FAASFunction As A Service
AWS Serverless world
12
AWS
Lambda
AWS
Fargate
Amazon
API Gateway
Amazon
SNS
Amazon
SQS
COMPUTE
DATA STORES
INTEGRATION
Amazon Aurora
Serverless
Amazon
S3
Amazon
DynamoDB
Amazon
EventBridge
FAAS
AWS
Step Functions
AWS
AppSync
Single Responsibility Principle
ü Do’s ✘ Don’ts *
- Input validation
- Business logic /!
- Transform data
- Return result
- Event/Input Filtering
- Transport data
- Orchestration & long
transactions
- Retry/Failure handling
* Most of the time
Event Filtering
15
SNS
Topic
Publisher
if event_type == 'order_created’:
lambda_client.invoke('OrderCreation', ...)
elif event_type == 'order_placed’:
lambda_client.invoke('OrderPlacement', ...)
elif event_type == 'order_cancelled’:
lambda_client.invoke('OrderCancelation', ...)
OrderCreation
OrderPlacement
OrderCancellation
{
"event_type": "order_placed",
"order": {
"id": "232134",
"amount": "2341,45",
"stock_ref": "AMZN”
}
}
the wrong way
𝝺 function code
Input event
OrderFiltering
Event Filtering with SNS
16
OrderCreation
OrderPlacement
OrderCancellation
Publisher
OrderCreationEvent:
Type: AWS::SNS::Subscription
Properties:
TopicArn: 'arn:aws:sns:eu-central-1:123456789:OrdersTopic’
Protocol: lambda
Endpoint: 'arn:aws:lambda:eu-central-1:123456789:function:OrderCreation’
FilterPolicy:
event_type:
- order_created
SNS
Topic
https://docs.aws.amazon.com/sns/latest/dg/sns-subscription-filter-policies.html
Cloudformation template
{
"event_type": [
"order_created"
]
}
Filter policy
Event Filtering with SNS
17
OrderCreation
OrderPlacement
OrderCancellation
Publisher
OrderPlacementEvent:
Type: AWS::SNS::Subscription
Properties:
TopicArn: 'arn:aws:sns:eu-central-1:123456789:OrdersTopic’
Protocol: lambda
Endpoint: 'arn:aws:lambda:eu-central-1:123456789:function:OrderPlacement’
FilterPolicy:
event_type:
- order_placed
SNS
Topic
Cloudformation template
Event Filtering with SNS
18
OrderCreation
OrderPlacement
OrderCancellation
Publisher
OrderCancellationEvent:
Type: AWS::SNS::Subscription
Properties:
TopicArn: 'arn:aws:sns:eu-central-1:123456789:OrdersTopic’
Protocol: lambda
Endpoint: 'arn:aws:lambda:eu-central-1:123456789:function:OrderCancellation’
FilterPolicy:
event_type:
- order_cancelled
SNS
Topic
Cloudformation template
Event Filtering with EventBridge
19
https://aws.amazon.com/blogs/compute/reducing-custom-code-by-using-advanced-rules-in-amazon-eventbridge/
{
"Source": "custom.myATMapp",
"EventBusName": "default",
"DetailType": "transaction",
"Time": "Wed Jan 29 2020 08:03:18 GMT-0500",
"Detail":{
"action": "withdrawal",
"location": "NY-NYC-001",
"amount": 300,
"result": "approved",
"transactionId": "123456",
"cardPresent": true,
"partnerBank": "Example Bank",
"remainingFunds": 722.34
}
}
{
"source": [ "custom.myATMapp" ],
"detail-type": [ "transaction" ],
"detail": {
"amount": [ { "numeric": [ ">", 300 ] } ]
}
}
{
"source": [ "custom.myATMapp" ],
"detail-type": [ "transaction" ],
"detail": {
"location": [ { "prefix": "NY-NYC-" } ]
}
}
{
"source": [ "custom.myATMapp" ],
"detail-type": [ "transaction" ],
"detail": {
"partnerBank": [ { "exists": true } ]
}
}
{
"source": [ "custom.myATMapp" ],
"detail-type": [ "transaction" ],
"detail": {
"result": [ "approved" ],
"partnerBank": [ { "exists": false } ],
"location": [ { "anything-but": "NY-NYC-002" }]
}
}
Orchestration
20
the wrong way
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
Simple orchestration with Lambda destinations
21
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
Lambda Destinations
Simple orchestration with Lambda destinations
22
Amazon SNS
Amazon
EventBridge
Amazon
Cloudwatch Logs
Amazon S3
Amazon SES
AWS Config
Amazon
CloudFormation
AWS
CodeCommit
A
S
Y
N
C
"DestinationConfig": {
"onSuccess": {
"Destination": "arn:aws:lambda:..."
},
"onFailure": {
"Destination": "arn:aws:sqs:..."
}
}
Cloudformation template
Amazon SNS
Amazon
EventBridge
Amazon
SQS
AWS Lambda
if success:
return {...}
else:
raise Exception(‘Failure', {...})
𝝺 function code
Lambda function
A
S
Y
N
C
Advanced orchestration with Step Functions
23
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
Advanced orchestration with Step Functions
24
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
{
"StartAt": "SimpleInvocation",
"States": {
"SimpleInvocation": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-central-
1:123456789012:function:HelloFunction",
"Next": "Choose1or2"
},
Advanced orchestration with Step Functions
25
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"Choose1or2": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.foo”,
"NumericEquals": 1,
"Next": "Lambda1"
},
{
"Variable": "$.foo",
"NumericEquals": 2,
"Next": "ParallelInvocation"
}
],
"Default": "Unmatched"
},
Advanced orchestration with Step Functions
26
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"Lambda1": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-
central-1:123456789012:function:Lambda1",
"Next": "SuccessOrFailure"
},
Advanced orchestration with Step Functions
27
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"SuccessOrFailure": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.status",
"StringEquals": "SUCCESS",
"Next": "SendNotification"
},
{
"Variable": "$.status",
"StringEquals": "FAILURE",
"Next": "QueueError"
}
],
"Default": "Unmatched"
}
Advanced orchestration with Step Functions
28
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"SendNotification": {
"Type": "Succeed"
},
"QueueError": {
"Type": "Fail"
},
Advanced orchestration with Step Functions
29
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"ParallelInvocation": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "SendApprovalRequest",
"States": {
"SendApprovalRequest": {
// ...
}
},
{
"StartAt": "Loop",
"States": {
"Loop": {
// ...
}
}
}
Advanced orchestration with Step Functions
30
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"SendApprovalRequest": {
"Type": "Task",
"Resource":
"arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters": {
"FunctionName": "sendMailForApprovalFunction",
"Payload": {
"step.$": "$$.State.Name",
"model.$": "$.data",
"token.$": "$$.Task.Token"
}
},
"ResultPath": "$.output",
"Next": "Approved",
"Catch": [
{
"ErrorEquals": [ "rejected" ],
"ResultPath": "$.reason",
"Next": "Rejected"
}
]
}
SendTaskSuccess
SendTaskFailure
Advanced orchestration with Step Functions
31
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"Loop": {
"Type": "Map",
"ItemsPath": "$.loopItems",
"Iterator": {
"StartAt": "LoopLambda",
"States": {
"LoopLambda": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-
1:123456789012:function:LoopFunction",
"End": true
}
}
},
"End": true
}
Advanced orchestration with Step Functions
32
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
TL;DR Single Responsibility Principle
33
èKeep your 𝝺 code focused on the business
This is not the responsibility of a 𝝺 to do orchestration
You ain’t gonna need it
34
Welcome in the “functionless” world !
API Gateway Service Proxy
35
Ex: insert data in DynamoDB
36
Resource: /comments
HTTP Method: POST
HTTP Request Body: {
"pageId": "example-page-id",
"userName": "ExampleUserName",
"message": "Example comment to be added."
}
Table: Comments
commentId: String
userName: String
message: String
pageId: String
PK: commentIdAPI Gateway DynamoDBLambda
var AWS = require('aws-sdk');
var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
exports.handler = async function(event, context) {
var params = {
TableName: 'Comments’,
Item: {
'commentId' : {
S: 'randomid’
},
'pageId' : {
S: event.pageId
},
'userName' : {
S: event.userName
},
'message' : {
S: event.message
}
}
};
ddb.putItem(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
}
});
}
Ex: insert data in DynamoDB
37
Resource: /comments
HTTP Method: POST
HTTP Request Body: {
"pageId": "example-page-id",
"userName": "ExampleUserName",
"message": "Example comment to be added."
}
Table: Comments
commentId: String
userName: String
message: String
pageId: String
PK: commentIdAPI Gateway DynamoDB
Ex: insert data in DynamoDB
38
Resource: /comments
HTTP Method: POST
HTTP Request Body: {
"pageId": "example-page-id",
"userName": "ExampleUserName",
"message": "Example comment to be added."
}
Table: Comments
commentId: String
userName: String
message: String
pageId: String
PK: commentIdAPI Gateway DynamoDB
Ex: insert data in DynamoDB
39
Resource: /comments
HTTP Method: POST
HTTP Request Body: {
"pageId": "example-page-id",
"userName": "ExampleUserName",
"message": "Example comment to be added."
}
Table: Comments
commentId: String
userName: String
message: String
pageId: String
PK: commentIdAPI Gateway DynamoDB
Ex: insert data in DynamoDB
40
Resource: /comments
HTTP Method: POST
HTTP Request Body: {
"pageId": "example-page-id",
"userName": "ExampleUserName",
"message": "Example comment to be added."
}
Table: Comments
commentId: String
userName: String
message: String
pageId: String
PK: commentIdAPI Gateway DynamoDB
Ex: insert data in DynamoDB
41
Resource: /comments
HTTP Method: POST
HTTP Request Body: {
"pageId": "example-page-id",
"userName": "ExampleUserName",
"message": "Example comment to be added."
}
Table: Comments
commentId: String
userName: String
message: String
pageId: String
PK: commentIdAPI Gateway DynamoDB
Use with caution
42
• Not a generic design pattern, not
always applicable
• Apply when the lambda is a
passthrough (no business code, just
mapping)
• Mapping can sometimes be complex
(Velocity Template Language)
Step Function integrations
43
"QueueError": {
"Type": "Task",
"Resource": "arn:aws:states:::sqs:sendMessage",
"Parameters": {
"QueueUrl": "https://sqs.eu-central-1.amazonaws.com/123456789012/myQueue",
"MessageBody.$": "$.input.message"
},
"End": true
},
"SendNotification": {
"Type": "Task",
"Resource": "arn:aws:states:::sns:publish",
"Parameters": {
"TopicARN": "arn:aws:sns:eu-central-
1:123456789012:myTopic",
"Subject": "Lambda1 has successfully finish its job",
"Message.$" : "$.input.message"
},
"End": true
},
SQS
SNS
Step Function integrations
44
AWS Batch Amazon DynamoDB Amazon ECS / Fargate Amazon EMR AWS Glue
Amazon SageMaker Amazon SNS Amazon SQS AWS Step Functions
AWS Lambda
AWS CodeBuild
TL;DR You Ain’t Gonna Need It
45
è 𝝺 is not always needed
You can save costs and
optimize performance
when functions are just passthrough/mapping
Keep it simple stupid
46
Lighten your functions
Keep your functions simple & stupid
nano functions
API GW
/res1
/res2
/res3
= 1 handler (1 function)
= 1 file
Not that stupid
so they need
sisters to do the job !
Keep your functions simple & stupid
nano functions
API GW
/res1
/res2
/res3
= 1 handler (1 function)
= 1 file
function-lith
API GW
/{proxy}
/res1
/res2
/res3
That’s really not simple & stupid!
= 1 handler (1 function)
= 1 file
Keep your functions simple & stupid
nano functions
API GW
/res1
/res2
/res3
function-lith
API GW
/{proxy}
/res1
/res2
/res3
= 1 handler (1 function)
= 1 file
fat functions
API GW
/res1
/res2
/res3
= 3 handlers (3 functions)
= 1 file
= 1 handler (1 function)
= 1 file
Keep your functions simple & stupid
50
nano functions
API GW
/res1
/res2
/res3
function-lith
API GW
/{proxy}
/res1
/res2
/res3
fat functions
= 1 handler (1 function)
= 1 file
API GW
= 3 handler (3 functions)
= 1 file
micro functions
API GW
/res1
/res2
/res3
/res1
/res2
/res3
= 1 handler (1 function)
= 1 file
= 1 handler (1 function)
= 1 file
Keep your functions simple & stupid
https://github.com/cdk-patterns/serverless/tree/master/the-lambda-trilogy
Potential duplicated code ++
Cognitive burden ++
Coupled functions
Coupled deployments
nano functions
API GW
/res1
/res2
/res3
function-lith
API GW
/{proxy}
/res1
/res2
/res3
fat functions
= 1 handler (1 function)
= 1 file
API GW
= 3 handler (3 functions)
= 1 file
micro functions
/res1
/res2
/res3
= 1 handler (1 function)
= 1 file
API GW
/res1
/res2
/res3
= 1 handler (1 function)
= 1 file
Stupidity Complexity
FAAS?
Longer cold starts ++
Risk of blast radius
Framework dependent
Longer cold starts
Risk of blast radius
Potential duplicated code
Cognitive burden
TL;DR Keep it simple stupid
52
Lighter functions
=
Easier to test and maintain
Faster to start: less cold start
More scalable: higher throughput
More secure: less permission needed
Conclusion
No function is easier to manage
than ‘no function’
– me
è If you can do better without a
function, just do it
è Else, apply software
craftsmanship principles
(clean code, tests, code reviews…)
“No server is easier to
manage than ‘no server’”
– Werner Vogels
Thank You @jeromevdl
https://tinyurl.com/ydeowzut
2-minutes survey:
Appendix
AWSTemplateFormatVersion: 2010-09-09
Resources:
API:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Sub ${AWS::StackName}-api-
${AWS::AccountId}
APIDeployment:
Type: AWS::ApiGateway::Deployment
Properties:
RestApiId: !Ref API
StageName: prod
DependsOn:
- ListBucketAPI
APIBucketResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !GetAtt API.RootResourceId
PathPart: "{bucket}"
RestApiId: !Ref API
ListBucketAPI:
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: GET
ResourceId: !Ref APIBucketResource
RestApiId: !Ref API
AuthorizationType: NONE
Integration:
Credentials: 'arn:aws:iam::1234567890:role/role-demo-api-gw-s3-integration’
IntegrationHttpMethod: GET
IntegrationResponses:
- StatusCode: "200"
PassthroughBehavior: WHEN_NO_MATCH
RequestParameters:
integration.request.header.Content-Type: method.request.header.Content-Type
integration.request.header.x-amz-acl: "'authenticated-read’”
integration.request.path.bucket: method.request.path.bucket
Type: AWS
Uri: !Sub arn:aws:apigateway:${AWS::Region}:s3:path/{bucket}
MethodResponses:
- StatusCode: "200"
RequestParameters:
method.request.path.bucket: true
method.request.header.Content-Type: false
API Gateway & S3 sample
https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html
57
Advanced orchestration with Step Functions{
"StartAt": "SimpleInvocation",
"States": {
"SimpleInvocation": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-central-1:123456789012:function:HelloFunction",
"Next": "Choose1or2"
},
"Choose1or2": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.foo",
"NumericEquals": 1,
"Next": "Lambda1"
},
{
"Variable": "$.foo",
"NumericEquals": 2,
"Next": "ParallelInvocation"
}
],
"Default": "Unmatched"
},
"Lambda1": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-central-1:123456789012:function:Lambda1",
"Next": "SuccessOrFailure"
},
"SuccessOrFailure": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.status",
"StringEquals": "SUCCESS",
"Next": "SendNotification"
},
{
"Variable": "$.status",
"StringEquals": "FAILURE",
"Next": "QueueError"
}
],
"Default": "Unmatched"
},
"SendNotification": {
"Type": "Succeed"
},
"QueueError": {
"Type": "Fail"
},
"ParallelInvocation": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "SendApprovalRequest",
"States": {
"SendApprovalRequest": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters": {
"FunctionName": "sendMailForApprovalFunction",
"Payload": {
"step.$": "$$.State.Name",
"model.$": "$.data",
"token.$": "$$.Task.Token"
}
},
"ResultPath": "$.output",
"Next": "Approved",
"Catch": [
{
"ErrorEquals": [ "rejected" ],
"ResultPath": "$.reason",
"Next": "Rejected"
}
]
},
"Approved": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-central-1:123456789012:function:Lambda1",
"End": true
},
"Rejected": {
"Type": "Fail"
}
}
},
{
"StartAt": "Loop",
"States": {
"Loop": {
"Type": "Map",
"ItemsPath": "$.loopItems",
"Iterator": {
"StartAt": "LoopLambda",
"States": {
"LoopLambda": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:LoopFunction",
"End": true
}
}
},
"End": true
}
}
}
],
"End": true
},
"Unmatched": {
"Type": "Fail",
"Error": "DefaultStateError",
"Cause": "No Matches!"
}
}
}

More Related Content

What's hot

Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)
danwrong
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
guest9bcef2f
 
Zend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarZend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinar
Yonni Mendes
 
Micro app-framework
Micro app-frameworkMicro app-framework
Micro app-framework
Michael Dawson
 
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
Codemotion
 
Prototype UI
Prototype UIPrototype UI
Prototype UI
Sébastien Gruhier
 
Elixir Paris Meetup
Elixir Paris MeetupElixir Paris Meetup
Elixir Paris Meetup
Joan Zapata
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous php
Wim Godden
 
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQUA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
Michelangelo van Dam
 
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Ivan Čukić
 
Bhanu Pratap Singh Shekhawat, BCA Third Year
Bhanu Pratap Singh Shekhawat, BCA Third YearBhanu Pratap Singh Shekhawat, BCA Third Year
Bhanu Pratap Singh Shekhawat, BCA Third Year
Dezyneecole
 
the 5 layers of web accessibility - Open Web Camp II
the 5 layers of web accessibility - Open Web Camp IIthe 5 layers of web accessibility - Open Web Camp II
the 5 layers of web accessibility - Open Web Camp II
Dirk Ginader
 
Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009
Fabio Akita
 
2013-06-25 - HTML5 & JavaScript Security
2013-06-25 - HTML5 & JavaScript Security2013-06-25 - HTML5 & JavaScript Security
2013-06-25 - HTML5 & JavaScript Security
Johannes Hoppe
 
AngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesAngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile Services
Rainer Stropek
 
GDayX - Advanced Angular.JS
GDayX - Advanced Angular.JSGDayX - Advanced Angular.JS
GDayX - Advanced Angular.JS
Nicolas Embleton
 
AngularJS Animations
AngularJS AnimationsAngularJS Animations
AngularJS Animations
Eyal Vardi
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMR
Javier Abadía
 
HTML5 Web Messaging
HTML5 Web MessagingHTML5 Web Messaging
HTML5 Web Messaging
Mike Taylor
 

What's hot (19)

Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
 
Zend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarZend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinar
 
Micro app-framework
Micro app-frameworkMicro app-framework
Micro app-framework
 
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
 
Prototype UI
Prototype UIPrototype UI
Prototype UI
 
Elixir Paris Meetup
Elixir Paris MeetupElixir Paris Meetup
Elixir Paris Meetup
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous php
 
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQUA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
 
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
 
Bhanu Pratap Singh Shekhawat, BCA Third Year
Bhanu Pratap Singh Shekhawat, BCA Third YearBhanu Pratap Singh Shekhawat, BCA Third Year
Bhanu Pratap Singh Shekhawat, BCA Third Year
 
the 5 layers of web accessibility - Open Web Camp II
the 5 layers of web accessibility - Open Web Camp IIthe 5 layers of web accessibility - Open Web Camp II
the 5 layers of web accessibility - Open Web Camp II
 
Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009
 
2013-06-25 - HTML5 & JavaScript Security
2013-06-25 - HTML5 & JavaScript Security2013-06-25 - HTML5 & JavaScript Security
2013-06-25 - HTML5 & JavaScript Security
 
AngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesAngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile Services
 
GDayX - Advanced Angular.JS
GDayX - Advanced Angular.JSGDayX - Advanced Angular.JS
GDayX - Advanced Angular.JS
 
AngularJS Animations
AngularJS AnimationsAngularJS Animations
AngularJS Animations
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMR
 
HTML5 Web Messaging
HTML5 Web MessagingHTML5 Web Messaging
HTML5 Web Messaging
 

Similar to Do more with less code in a serverless world

Building Awesome API with Spring
Building Awesome API with SpringBuilding Awesome API with Spring
Building Awesome API with Spring
Vladimir Tsukur
 
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
DataStax Academy
 
Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for Cassandra
Edward Capriolo
 
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry PiMonitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
InfluxData
 
Do more with less code in serverless
Do more with less code in serverlessDo more with less code in serverless
Do more with less code in serverless
jeromevdl
 
Clean Code Development
Clean Code DevelopmentClean Code Development
Clean Code Development
Peter Gfader
 
Deliver Business Value Faster with AWS Step Functions
Deliver Business Value Faster with AWS Step FunctionsDeliver Business Value Faster with AWS Step Functions
Deliver Business Value Faster with AWS Step Functions
Daniel Zivkovic
 
How to ship customer value faster with step functions
How to ship customer value faster with step functionsHow to ship customer value faster with step functions
How to ship customer value faster with step functions
Yan Cui
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 
Stuff I Learned About Performance
Stuff I Learned About PerformanceStuff I Learned About Performance
Stuff I Learned About Performance
Michael Barker
 
Health Monitoring
Health MonitoringHealth Monitoring
Health Monitoring
Milan Negovan
 
Delightful steps to becoming a functioning user of Step Functions
Delightful steps to becoming a functioning user of Step FunctionsDelightful steps to becoming a functioning user of Step Functions
Delightful steps to becoming a functioning user of Step Functions
Yan Cui
 
Surviving javascript.pptx
Surviving javascript.pptxSurviving javascript.pptx
Surviving javascript.pptx
Tamas Rev
 
Serverless Swift with Apache OpenWhisk. UA Mobile 2017.
Serverless Swift with Apache OpenWhisk. UA Mobile 2017.Serverless Swift with Apache OpenWhisk. UA Mobile 2017.
Serverless Swift with Apache OpenWhisk. UA Mobile 2017.
UA Mobile
 
Webauthn Tutorial
Webauthn TutorialWebauthn Tutorial
Webauthn Tutorial
FIDO Alliance
 
.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#
Bertrand Le Roy
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)
Scott Wlaschin
 
E.D.D.I - Open Source Chatbot Platform
E.D.D.I - Open Source Chatbot PlatformE.D.D.I - Open Source Chatbot Platform
E.D.D.I - Open Source Chatbot Platform
Gregor Jarisch
 
Real-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampReal-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @Moldcamp
Alexei Gorobets
 
A miało być tak... bez wycieków
A miało być tak... bez wyciekówA miało być tak... bez wycieków
A miało być tak... bez wycieków
Konrad Kokosa
 

Similar to Do more with less code in a serverless world (20)

Building Awesome API with Spring
Building Awesome API with SpringBuilding Awesome API with Spring
Building Awesome API with Spring
 
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
 
Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for Cassandra
 
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry PiMonitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
 
Do more with less code in serverless
Do more with less code in serverlessDo more with less code in serverless
Do more with less code in serverless
 
Clean Code Development
Clean Code DevelopmentClean Code Development
Clean Code Development
 
Deliver Business Value Faster with AWS Step Functions
Deliver Business Value Faster with AWS Step FunctionsDeliver Business Value Faster with AWS Step Functions
Deliver Business Value Faster with AWS Step Functions
 
How to ship customer value faster with step functions
How to ship customer value faster with step functionsHow to ship customer value faster with step functions
How to ship customer value faster with step functions
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
 
Stuff I Learned About Performance
Stuff I Learned About PerformanceStuff I Learned About Performance
Stuff I Learned About Performance
 
Health Monitoring
Health MonitoringHealth Monitoring
Health Monitoring
 
Delightful steps to becoming a functioning user of Step Functions
Delightful steps to becoming a functioning user of Step FunctionsDelightful steps to becoming a functioning user of Step Functions
Delightful steps to becoming a functioning user of Step Functions
 
Surviving javascript.pptx
Surviving javascript.pptxSurviving javascript.pptx
Surviving javascript.pptx
 
Serverless Swift with Apache OpenWhisk. UA Mobile 2017.
Serverless Swift with Apache OpenWhisk. UA Mobile 2017.Serverless Swift with Apache OpenWhisk. UA Mobile 2017.
Serverless Swift with Apache OpenWhisk. UA Mobile 2017.
 
Webauthn Tutorial
Webauthn TutorialWebauthn Tutorial
Webauthn Tutorial
 
.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)
 
E.D.D.I - Open Source Chatbot Platform
E.D.D.I - Open Source Chatbot PlatformE.D.D.I - Open Source Chatbot Platform
E.D.D.I - Open Source Chatbot Platform
 
Real-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampReal-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @Moldcamp
 
A miało być tak... bez wycieków
A miało być tak... bez wyciekówA miało być tak... bez wycieków
A miało być tak... bez wycieków
 

More from jeromevdl

Message-Driven Architecture on AWS
Message-Driven Architecture on AWSMessage-Driven Architecture on AWS
Message-Driven Architecture on AWS
jeromevdl
 
DevopsDays Geneva 2020 - Compliance & Governance as Code
DevopsDays Geneva 2020 - Compliance & Governance as CodeDevopsDays Geneva 2020 - Compliance & Governance as Code
DevopsDays Geneva 2020 - Compliance & Governance as Code
jeromevdl
 
Softshake 2017 - Développer un chatbot Alexa
Softshake 2017 - Développer un chatbot AlexaSoftshake 2017 - Développer un chatbot Alexa
Softshake 2017 - Développer un chatbot Alexa
jeromevdl
 
Chatbots buzzword ou nouvel eldorado
Chatbots   buzzword ou nouvel eldoradoChatbots   buzzword ou nouvel eldorado
Chatbots buzzword ou nouvel eldorado
jeromevdl
 
Management projet vs management produit
Management projet vs management produitManagement projet vs management produit
Management projet vs management produit
jeromevdl
 
Softshake - Offline applications
Softshake - Offline applicationsSoftshake - Offline applications
Softshake - Offline applications
jeromevdl
 
My Android is not an iPhone like any others (Mdevcon 2014)
My Android is not an iPhone like any others (Mdevcon 2014)My Android is not an iPhone like any others (Mdevcon 2014)
My Android is not an iPhone like any others (Mdevcon 2014)
jeromevdl
 
DroidconUK 2013 : Beef up android apps with java tools
DroidconUK 2013 : Beef up android apps with java toolsDroidconUK 2013 : Beef up android apps with java tools
DroidconUK 2013 : Beef up android apps with java tools
jeromevdl
 
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
jeromevdl
 
Devoxx France 2013 : Musclez vos apps android avec les outils du monde java
Devoxx France 2013 : Musclez vos apps android avec les outils du monde javaDevoxx France 2013 : Musclez vos apps android avec les outils du monde java
Devoxx France 2013 : Musclez vos apps android avec les outils du monde java
jeromevdl
 
Jug Lausanne Android Janvier2013
Jug Lausanne Android Janvier2013Jug Lausanne Android Janvier2013
Jug Lausanne Android Janvier2013
jeromevdl
 
Metroide
MetroideMetroide
Metroide
jeromevdl
 

More from jeromevdl (12)

Message-Driven Architecture on AWS
Message-Driven Architecture on AWSMessage-Driven Architecture on AWS
Message-Driven Architecture on AWS
 
DevopsDays Geneva 2020 - Compliance & Governance as Code
DevopsDays Geneva 2020 - Compliance & Governance as CodeDevopsDays Geneva 2020 - Compliance & Governance as Code
DevopsDays Geneva 2020 - Compliance & Governance as Code
 
Softshake 2017 - Développer un chatbot Alexa
Softshake 2017 - Développer un chatbot AlexaSoftshake 2017 - Développer un chatbot Alexa
Softshake 2017 - Développer un chatbot Alexa
 
Chatbots buzzword ou nouvel eldorado
Chatbots   buzzword ou nouvel eldoradoChatbots   buzzword ou nouvel eldorado
Chatbots buzzword ou nouvel eldorado
 
Management projet vs management produit
Management projet vs management produitManagement projet vs management produit
Management projet vs management produit
 
Softshake - Offline applications
Softshake - Offline applicationsSoftshake - Offline applications
Softshake - Offline applications
 
My Android is not an iPhone like any others (Mdevcon 2014)
My Android is not an iPhone like any others (Mdevcon 2014)My Android is not an iPhone like any others (Mdevcon 2014)
My Android is not an iPhone like any others (Mdevcon 2014)
 
DroidconUK 2013 : Beef up android apps with java tools
DroidconUK 2013 : Beef up android apps with java toolsDroidconUK 2013 : Beef up android apps with java tools
DroidconUK 2013 : Beef up android apps with java tools
 
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
 
Devoxx France 2013 : Musclez vos apps android avec les outils du monde java
Devoxx France 2013 : Musclez vos apps android avec les outils du monde javaDevoxx France 2013 : Musclez vos apps android avec les outils du monde java
Devoxx France 2013 : Musclez vos apps android avec les outils du monde java
 
Jug Lausanne Android Janvier2013
Jug Lausanne Android Janvier2013Jug Lausanne Android Janvier2013
Jug Lausanne Android Janvier2013
 
Metroide
MetroideMetroide
Metroide
 

Recently uploaded

[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
Jason Yip
 
Must Know Postgres Extension for DBA and Developer during Migration
Must Know Postgres Extension for DBA and Developer during MigrationMust Know Postgres Extension for DBA and Developer during Migration
Must Know Postgres Extension for DBA and Developer during Migration
Mydbops
 
Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving | Nameplate Manufacturing Process - 2024Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving
 
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge GraphGraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
Neo4j
 
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin..."$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
Fwdays
 
From Natural Language to Structured Solr Queries using LLMs
From Natural Language to Structured Solr Queries using LLMsFrom Natural Language to Structured Solr Queries using LLMs
From Natural Language to Structured Solr Queries using LLMs
Sease
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
AstuteBusiness
 
JavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green MasterplanJavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green Masterplan
Miro Wengner
 
AI in the Workplace Reskilling, Upskilling, and Future Work.pptx
AI in the Workplace Reskilling, Upskilling, and Future Work.pptxAI in the Workplace Reskilling, Upskilling, and Future Work.pptx
AI in the Workplace Reskilling, Upskilling, and Future Work.pptx
Sunil Jagani
 
Discover the Unseen: Tailored Recommendation of Unwatched Content
Discover the Unseen: Tailored Recommendation of Unwatched ContentDiscover the Unseen: Tailored Recommendation of Unwatched Content
Discover the Unseen: Tailored Recommendation of Unwatched Content
ScyllaDB
 
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
Fwdays
 
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
DanBrown980551
 
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdfLee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
leebarnesutopia
 
Christine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptxChristine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptx
christinelarrosa
 
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
Fwdays
 
What is an RPA CoE? Session 1 – CoE Vision
What is an RPA CoE?  Session 1 – CoE VisionWhat is an RPA CoE?  Session 1 – CoE Vision
What is an RPA CoE? Session 1 – CoE Vision
DianaGray10
 
AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)
HarpalGohil4
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
Pablo Gómez Abajo
 
Introducing BoxLang : A new JVM language for productivity and modularity!
Introducing BoxLang : A new JVM language for productivity and modularity!Introducing BoxLang : A new JVM language for productivity and modularity!
Introducing BoxLang : A new JVM language for productivity and modularity!
Ortus Solutions, Corp
 
Christine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptxChristine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptx
christinelarrosa
 

Recently uploaded (20)

[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
 
Must Know Postgres Extension for DBA and Developer during Migration
Must Know Postgres Extension for DBA and Developer during MigrationMust Know Postgres Extension for DBA and Developer during Migration
Must Know Postgres Extension for DBA and Developer during Migration
 
Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving | Nameplate Manufacturing Process - 2024Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving | Nameplate Manufacturing Process - 2024
 
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge GraphGraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
 
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin..."$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
 
From Natural Language to Structured Solr Queries using LLMs
From Natural Language to Structured Solr Queries using LLMsFrom Natural Language to Structured Solr Queries using LLMs
From Natural Language to Structured Solr Queries using LLMs
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
 
JavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green MasterplanJavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green Masterplan
 
AI in the Workplace Reskilling, Upskilling, and Future Work.pptx
AI in the Workplace Reskilling, Upskilling, and Future Work.pptxAI in the Workplace Reskilling, Upskilling, and Future Work.pptx
AI in the Workplace Reskilling, Upskilling, and Future Work.pptx
 
Discover the Unseen: Tailored Recommendation of Unwatched Content
Discover the Unseen: Tailored Recommendation of Unwatched ContentDiscover the Unseen: Tailored Recommendation of Unwatched Content
Discover the Unseen: Tailored Recommendation of Unwatched Content
 
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
 
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
 
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdfLee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
 
Christine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptxChristine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptx
 
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
 
What is an RPA CoE? Session 1 – CoE Vision
What is an RPA CoE?  Session 1 – CoE VisionWhat is an RPA CoE?  Session 1 – CoE Vision
What is an RPA CoE? Session 1 – CoE Vision
 
AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
 
Introducing BoxLang : A new JVM language for productivity and modularity!
Introducing BoxLang : A new JVM language for productivity and modularity!Introducing BoxLang : A new JVM language for productivity and modularity!
Introducing BoxLang : A new JVM language for productivity and modularity!
 
Christine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptxChristine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptx
 

Do more with less code in a serverless world

  • 1. Less is more Do more with less code in a serverless world Jerome Van Der Linden Geneva Serverless Meetup - 26/05/2020
  • 2. About me • In a previous life, ”Mr Cut Cut” (M. Coupe coupe) • Developer & software craftsman • And now, Solutions Architect @ AWS 2 linkedin.com/in/jeromevdl/ Jerome Van Der Linden
  • 4. SOLID 4 S Single Responsibility Principle O Open / closed Principle L Liskov substitution Principle I Interface segregation Principle D Dependency Inversion Principle
  • 5. Single Responsibility Principle 5 “A class or module should have one, and only one, reason to be changed” - Robert C. Martin, aka Uncle Bob
  • 6. YAGNI (You Ain’t Gonna Need It) 6 Just because you can, doesn’t mean you should…
  • 8. 8 And many more… Clean Code DRY Don’t Repeat Yourself Law of Demeter Broken window theory Boy scout rule Not invented here
  • 9. How to apply those principles? In the serverless world
  • 10. Serverless World? 10 Serverless == FAASFunction As A Service
  • 11. Serverless World? 11 Serverless ⊃ FAASFunction As A Service
  • 12. AWS Serverless world 12 AWS Lambda AWS Fargate Amazon API Gateway Amazon SNS Amazon SQS COMPUTE DATA STORES INTEGRATION Amazon Aurora Serverless Amazon S3 Amazon DynamoDB Amazon EventBridge FAAS AWS Step Functions AWS AppSync
  • 13. Single Responsibility Principle ü Do’s ✘ Don’ts * - Input validation - Business logic /! - Transform data - Return result - Event/Input Filtering - Transport data - Orchestration & long transactions - Retry/Failure handling * Most of the time
  • 14. Event Filtering 15 SNS Topic Publisher if event_type == 'order_created’: lambda_client.invoke('OrderCreation', ...) elif event_type == 'order_placed’: lambda_client.invoke('OrderPlacement', ...) elif event_type == 'order_cancelled’: lambda_client.invoke('OrderCancelation', ...) OrderCreation OrderPlacement OrderCancellation { "event_type": "order_placed", "order": { "id": "232134", "amount": "2341,45", "stock_ref": "AMZN” } } the wrong way 𝝺 function code Input event OrderFiltering
  • 15. Event Filtering with SNS 16 OrderCreation OrderPlacement OrderCancellation Publisher OrderCreationEvent: Type: AWS::SNS::Subscription Properties: TopicArn: 'arn:aws:sns:eu-central-1:123456789:OrdersTopic’ Protocol: lambda Endpoint: 'arn:aws:lambda:eu-central-1:123456789:function:OrderCreation’ FilterPolicy: event_type: - order_created SNS Topic https://docs.aws.amazon.com/sns/latest/dg/sns-subscription-filter-policies.html Cloudformation template { "event_type": [ "order_created" ] } Filter policy
  • 16. Event Filtering with SNS 17 OrderCreation OrderPlacement OrderCancellation Publisher OrderPlacementEvent: Type: AWS::SNS::Subscription Properties: TopicArn: 'arn:aws:sns:eu-central-1:123456789:OrdersTopic’ Protocol: lambda Endpoint: 'arn:aws:lambda:eu-central-1:123456789:function:OrderPlacement’ FilterPolicy: event_type: - order_placed SNS Topic Cloudformation template
  • 17. Event Filtering with SNS 18 OrderCreation OrderPlacement OrderCancellation Publisher OrderCancellationEvent: Type: AWS::SNS::Subscription Properties: TopicArn: 'arn:aws:sns:eu-central-1:123456789:OrdersTopic’ Protocol: lambda Endpoint: 'arn:aws:lambda:eu-central-1:123456789:function:OrderCancellation’ FilterPolicy: event_type: - order_cancelled SNS Topic Cloudformation template
  • 18. Event Filtering with EventBridge 19 https://aws.amazon.com/blogs/compute/reducing-custom-code-by-using-advanced-rules-in-amazon-eventbridge/ { "Source": "custom.myATMapp", "EventBusName": "default", "DetailType": "transaction", "Time": "Wed Jan 29 2020 08:03:18 GMT-0500", "Detail":{ "action": "withdrawal", "location": "NY-NYC-001", "amount": 300, "result": "approved", "transactionId": "123456", "cardPresent": true, "partnerBank": "Example Bank", "remainingFunds": 722.34 } } { "source": [ "custom.myATMapp" ], "detail-type": [ "transaction" ], "detail": { "amount": [ { "numeric": [ ">", 300 ] } ] } } { "source": [ "custom.myATMapp" ], "detail-type": [ "transaction" ], "detail": { "location": [ { "prefix": "NY-NYC-" } ] } } { "source": [ "custom.myATMapp" ], "detail-type": [ "transaction" ], "detail": { "partnerBank": [ { "exists": true } ] } } { "source": [ "custom.myATMapp" ], "detail-type": [ "transaction" ], "detail": { "result": [ "approved" ], "partnerBank": [ { "exists": false } ], "location": [ { "anything-but": "NY-NYC-002" }] } }
  • 19. Orchestration 20 the wrong way invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App…
  • 20. Simple orchestration with Lambda destinations 21 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… Lambda Destinations
  • 21. Simple orchestration with Lambda destinations 22 Amazon SNS Amazon EventBridge Amazon Cloudwatch Logs Amazon S3 Amazon SES AWS Config Amazon CloudFormation AWS CodeCommit A S Y N C "DestinationConfig": { "onSuccess": { "Destination": "arn:aws:lambda:..." }, "onFailure": { "Destination": "arn:aws:sqs:..." } } Cloudformation template Amazon SNS Amazon EventBridge Amazon SQS AWS Lambda if success: return {...} else: raise Exception(‘Failure', {...}) 𝝺 function code Lambda function A S Y N C
  • 22. Advanced orchestration with Step Functions 23 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App…
  • 23. Advanced orchestration with Step Functions 24 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… { "StartAt": "SimpleInvocation", "States": { "SimpleInvocation": { "Type": "Task", "Resource": "arn:aws:lambda:eu-central- 1:123456789012:function:HelloFunction", "Next": "Choose1or2" },
  • 24. Advanced orchestration with Step Functions 25 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "Choose1or2": { "Type": "Choice", "Choices": [ { "Variable": "$.foo”, "NumericEquals": 1, "Next": "Lambda1" }, { "Variable": "$.foo", "NumericEquals": 2, "Next": "ParallelInvocation" } ], "Default": "Unmatched" },
  • 25. Advanced orchestration with Step Functions 26 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "Lambda1": { "Type": "Task", "Resource": "arn:aws:lambda:eu- central-1:123456789012:function:Lambda1", "Next": "SuccessOrFailure" },
  • 26. Advanced orchestration with Step Functions 27 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "SuccessOrFailure": { "Type": "Choice", "Choices": [ { "Variable": "$.status", "StringEquals": "SUCCESS", "Next": "SendNotification" }, { "Variable": "$.status", "StringEquals": "FAILURE", "Next": "QueueError" } ], "Default": "Unmatched" }
  • 27. Advanced orchestration with Step Functions 28 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "SendNotification": { "Type": "Succeed" }, "QueueError": { "Type": "Fail" },
  • 28. Advanced orchestration with Step Functions 29 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "ParallelInvocation": { "Type": "Parallel", "Branches": [ { "StartAt": "SendApprovalRequest", "States": { "SendApprovalRequest": { // ... } }, { "StartAt": "Loop", "States": { "Loop": { // ... } } }
  • 29. Advanced orchestration with Step Functions 30 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "SendApprovalRequest": { "Type": "Task", "Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken", "Parameters": { "FunctionName": "sendMailForApprovalFunction", "Payload": { "step.$": "$$.State.Name", "model.$": "$.data", "token.$": "$$.Task.Token" } }, "ResultPath": "$.output", "Next": "Approved", "Catch": [ { "ErrorEquals": [ "rejected" ], "ResultPath": "$.reason", "Next": "Rejected" } ] } SendTaskSuccess SendTaskFailure
  • 30. Advanced orchestration with Step Functions 31 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "Loop": { "Type": "Map", "ItemsPath": "$.loopItems", "Iterator": { "StartAt": "LoopLambda", "States": { "LoopLambda": { "Type": "Task", "Resource": "arn:aws:lambda:us-east- 1:123456789012:function:LoopFunction", "End": true } } }, "End": true }
  • 31. Advanced orchestration with Step Functions 32 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App…
  • 32. TL;DR Single Responsibility Principle 33 èKeep your 𝝺 code focused on the business This is not the responsibility of a 𝝺 to do orchestration
  • 33. You ain’t gonna need it 34 Welcome in the “functionless” world !
  • 35. Ex: insert data in DynamoDB 36 Resource: /comments HTTP Method: POST HTTP Request Body: { "pageId": "example-page-id", "userName": "ExampleUserName", "message": "Example comment to be added." } Table: Comments commentId: String userName: String message: String pageId: String PK: commentIdAPI Gateway DynamoDBLambda var AWS = require('aws-sdk'); var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'}); exports.handler = async function(event, context) { var params = { TableName: 'Comments’, Item: { 'commentId' : { S: 'randomid’ }, 'pageId' : { S: event.pageId }, 'userName' : { S: event.userName }, 'message' : { S: event.message } } }; ddb.putItem(params, function(err, data) { if (err) { console.log("Error", err); } else { console.log("Success", data); } }); }
  • 36. Ex: insert data in DynamoDB 37 Resource: /comments HTTP Method: POST HTTP Request Body: { "pageId": "example-page-id", "userName": "ExampleUserName", "message": "Example comment to be added." } Table: Comments commentId: String userName: String message: String pageId: String PK: commentIdAPI Gateway DynamoDB
  • 37. Ex: insert data in DynamoDB 38 Resource: /comments HTTP Method: POST HTTP Request Body: { "pageId": "example-page-id", "userName": "ExampleUserName", "message": "Example comment to be added." } Table: Comments commentId: String userName: String message: String pageId: String PK: commentIdAPI Gateway DynamoDB
  • 38. Ex: insert data in DynamoDB 39 Resource: /comments HTTP Method: POST HTTP Request Body: { "pageId": "example-page-id", "userName": "ExampleUserName", "message": "Example comment to be added." } Table: Comments commentId: String userName: String message: String pageId: String PK: commentIdAPI Gateway DynamoDB
  • 39. Ex: insert data in DynamoDB 40 Resource: /comments HTTP Method: POST HTTP Request Body: { "pageId": "example-page-id", "userName": "ExampleUserName", "message": "Example comment to be added." } Table: Comments commentId: String userName: String message: String pageId: String PK: commentIdAPI Gateway DynamoDB
  • 40. Ex: insert data in DynamoDB 41 Resource: /comments HTTP Method: POST HTTP Request Body: { "pageId": "example-page-id", "userName": "ExampleUserName", "message": "Example comment to be added." } Table: Comments commentId: String userName: String message: String pageId: String PK: commentIdAPI Gateway DynamoDB
  • 41. Use with caution 42 • Not a generic design pattern, not always applicable • Apply when the lambda is a passthrough (no business code, just mapping) • Mapping can sometimes be complex (Velocity Template Language)
  • 42. Step Function integrations 43 "QueueError": { "Type": "Task", "Resource": "arn:aws:states:::sqs:sendMessage", "Parameters": { "QueueUrl": "https://sqs.eu-central-1.amazonaws.com/123456789012/myQueue", "MessageBody.$": "$.input.message" }, "End": true }, "SendNotification": { "Type": "Task", "Resource": "arn:aws:states:::sns:publish", "Parameters": { "TopicARN": "arn:aws:sns:eu-central- 1:123456789012:myTopic", "Subject": "Lambda1 has successfully finish its job", "Message.$" : "$.input.message" }, "End": true }, SQS SNS
  • 43. Step Function integrations 44 AWS Batch Amazon DynamoDB Amazon ECS / Fargate Amazon EMR AWS Glue Amazon SageMaker Amazon SNS Amazon SQS AWS Step Functions AWS Lambda AWS CodeBuild
  • 44. TL;DR You Ain’t Gonna Need It 45 è 𝝺 is not always needed You can save costs and optimize performance when functions are just passthrough/mapping
  • 45. Keep it simple stupid 46 Lighten your functions
  • 46. Keep your functions simple & stupid nano functions API GW /res1 /res2 /res3 = 1 handler (1 function) = 1 file Not that stupid so they need sisters to do the job !
  • 47. Keep your functions simple & stupid nano functions API GW /res1 /res2 /res3 = 1 handler (1 function) = 1 file function-lith API GW /{proxy} /res1 /res2 /res3 That’s really not simple & stupid! = 1 handler (1 function) = 1 file
  • 48. Keep your functions simple & stupid nano functions API GW /res1 /res2 /res3 function-lith API GW /{proxy} /res1 /res2 /res3 = 1 handler (1 function) = 1 file fat functions API GW /res1 /res2 /res3 = 3 handlers (3 functions) = 1 file = 1 handler (1 function) = 1 file
  • 49. Keep your functions simple & stupid 50 nano functions API GW /res1 /res2 /res3 function-lith API GW /{proxy} /res1 /res2 /res3 fat functions = 1 handler (1 function) = 1 file API GW = 3 handler (3 functions) = 1 file micro functions API GW /res1 /res2 /res3 /res1 /res2 /res3 = 1 handler (1 function) = 1 file = 1 handler (1 function) = 1 file
  • 50. Keep your functions simple & stupid https://github.com/cdk-patterns/serverless/tree/master/the-lambda-trilogy Potential duplicated code ++ Cognitive burden ++ Coupled functions Coupled deployments nano functions API GW /res1 /res2 /res3 function-lith API GW /{proxy} /res1 /res2 /res3 fat functions = 1 handler (1 function) = 1 file API GW = 3 handler (3 functions) = 1 file micro functions /res1 /res2 /res3 = 1 handler (1 function) = 1 file API GW /res1 /res2 /res3 = 1 handler (1 function) = 1 file Stupidity Complexity FAAS? Longer cold starts ++ Risk of blast radius Framework dependent Longer cold starts Risk of blast radius Potential duplicated code Cognitive burden
  • 51. TL;DR Keep it simple stupid 52 Lighter functions = Easier to test and maintain Faster to start: less cold start More scalable: higher throughput More secure: less permission needed
  • 52. Conclusion No function is easier to manage than ‘no function’ – me è If you can do better without a function, just do it è Else, apply software craftsmanship principles (clean code, tests, code reviews…) “No server is easier to manage than ‘no server’” – Werner Vogels
  • 55. AWSTemplateFormatVersion: 2010-09-09 Resources: API: Type: AWS::ApiGateway::RestApi Properties: Name: !Sub ${AWS::StackName}-api- ${AWS::AccountId} APIDeployment: Type: AWS::ApiGateway::Deployment Properties: RestApiId: !Ref API StageName: prod DependsOn: - ListBucketAPI APIBucketResource: Type: AWS::ApiGateway::Resource Properties: ParentId: !GetAtt API.RootResourceId PathPart: "{bucket}" RestApiId: !Ref API ListBucketAPI: Type: AWS::ApiGateway::Method Properties: HttpMethod: GET ResourceId: !Ref APIBucketResource RestApiId: !Ref API AuthorizationType: NONE Integration: Credentials: 'arn:aws:iam::1234567890:role/role-demo-api-gw-s3-integration’ IntegrationHttpMethod: GET IntegrationResponses: - StatusCode: "200" PassthroughBehavior: WHEN_NO_MATCH RequestParameters: integration.request.header.Content-Type: method.request.header.Content-Type integration.request.header.x-amz-acl: "'authenticated-read’” integration.request.path.bucket: method.request.path.bucket Type: AWS Uri: !Sub arn:aws:apigateway:${AWS::Region}:s3:path/{bucket} MethodResponses: - StatusCode: "200" RequestParameters: method.request.path.bucket: true method.request.header.Content-Type: false API Gateway & S3 sample https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html
  • 56. 57 Advanced orchestration with Step Functions{ "StartAt": "SimpleInvocation", "States": { "SimpleInvocation": { "Type": "Task", "Resource": "arn:aws:lambda:eu-central-1:123456789012:function:HelloFunction", "Next": "Choose1or2" }, "Choose1or2": { "Type": "Choice", "Choices": [ { "Variable": "$.foo", "NumericEquals": 1, "Next": "Lambda1" }, { "Variable": "$.foo", "NumericEquals": 2, "Next": "ParallelInvocation" } ], "Default": "Unmatched" }, "Lambda1": { "Type": "Task", "Resource": "arn:aws:lambda:eu-central-1:123456789012:function:Lambda1", "Next": "SuccessOrFailure" }, "SuccessOrFailure": { "Type": "Choice", "Choices": [ { "Variable": "$.status", "StringEquals": "SUCCESS", "Next": "SendNotification" }, { "Variable": "$.status", "StringEquals": "FAILURE", "Next": "QueueError" } ], "Default": "Unmatched" }, "SendNotification": { "Type": "Succeed" }, "QueueError": { "Type": "Fail" }, "ParallelInvocation": { "Type": "Parallel", "Branches": [ { "StartAt": "SendApprovalRequest", "States": { "SendApprovalRequest": { "Type": "Task", "Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken", "Parameters": { "FunctionName": "sendMailForApprovalFunction", "Payload": { "step.$": "$$.State.Name", "model.$": "$.data", "token.$": "$$.Task.Token" } }, "ResultPath": "$.output", "Next": "Approved", "Catch": [ { "ErrorEquals": [ "rejected" ], "ResultPath": "$.reason", "Next": "Rejected" } ] }, "Approved": { "Type": "Task", "Resource": "arn:aws:lambda:eu-central-1:123456789012:function:Lambda1", "End": true }, "Rejected": { "Type": "Fail" } } }, { "StartAt": "Loop", "States": { "Loop": { "Type": "Map", "ItemsPath": "$.loopItems", "Iterator": { "StartAt": "LoopLambda", "States": { "LoopLambda": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:LoopFunction", "End": true } } }, "End": true } } } ], "End": true }, "Unmatched": { "Type": "Fail", "Error": "DefaultStateError", "Cause": "No Matches!" } } }