Exploring the Scala Macro System for Compile Time Model-Based Generation of Statically Type-Safe REST Services Filipe R. R. Oliveira ei10038@fe.up.pt July 20, 2015 Supervisor Hugo Sereno Ferreira Co-supervisor Tiago Boldt Sousa
Context Growth of web services 2
Context How is complexity handled? REST 3
Context Resource A GET POST Resource B ... GET POST ... Traditional 4
Context Resource A GET POST Resource B ... GET POST ... Traditional Model-driven CRUD 5
Model-Driven Engineering 6
Model-Driven Frameworks - Python - Highly customizable - Python - Only supports MongoDB - JavaScript (Node.js) - Model definition via terminal - JavaScript (Node.js) - Scaffolding via terminal 7
Motivation Runtime Reflection Less Performance 8
Motivation Runtime Dynamically Reflection Typed Less Longer Performance Debugging 9
Research Problem Considering a statically type-safe programming language that enables generation of REST services in compile time . Can a model-driven REST framework written in this language improve the development process and execution performance when compared to current ones? 10
Research Process 1. Review a. REST frameworks b. Model-driven development 2. Develop a proof of concept a. In Scala b. Using macros 3. Validate a. Benchmarks b. Academic quasi-experiment 11
Scala Macros def macros printf("Hello, %s!", "World") print("Hello, World!") 12
Scala Macros def macros printf("Hello, %s!", "World") print("Hello, World!") macro annotations @json case class Category(name: String, description: String) case class Category(name: String, description: String) { def toJson: String = "{" + "name:" + name + "," + "description:" + description + "}" } 13
Proof of Concept - Capture models - Customizable operations - Configurable 14
Metamorphic Application Architecture Either synchronous or asynchronous 15
Metamorphic Application Architecture Create | GetAll | Get | Replace | Delete 16
Metamorphic Application Architecture metamorphic { host = "111.111.111.111" // default "localhost" port = 9000 // default 8080 databases.default.name = "file.db" } 17
Metamorphic Process Representation UML 18
Metamorphic Process @entity class Category { def name = StringField() def description = StringField() } Representation Specification UML Internal DSL 19
Metamorphic Process @entity class Category { def name = StringField() def description = StringField() } Specification Internal DSL 20
Metamorphic Process @entity class Category { Entity("Category", List( Property("name", String, … ), def name = StringField() Property("description", String, … ) def description = StringField() } ) Specification Matching Internal DSL Macro expansion 21
Metamorphic Process @entity class Category { Entity("Category", List( Property("name", String, … ), def name = StringField() Property("description", String, … ) def description = StringField() } ) Specification Matching Internal DSL Macro expansion 22
Metamorphic Process @entity class Category { Entity("Category", List( Property("name", String, … ), def name = StringField() Property("description", String, … ) def description = StringField() } ) Specification Matching Internal DSL Macro expansion 23
Metamorphic Process Entity("Category", List( Property("name", String, … ), Property("description", String, … ) ) Matching Macro expansion 24
Metamorphic Process Application( Service("CategoryService", List( Entity("Category", List( Operation(Get, Property("name", String, … ), Path("categories", … ), … ), Property("description", String, … ) Operation(Post, ) Path("categories", … ), … ), … ) Matching Transformation ) Macro expansion Macro expansion 25
Metamorphic Process Application( Service("CategoryService", List( Entity("Category", List( Operation(Get, Property("name", String, … ), Path("categories", … ), … ), Property("description", String, … ) Operation(Post, ) Path("categories", … ), … ), … ) Matching Transformation ) Macro expansion Macro expansion 26
Metamorphic Process Application( Service("CategoryService", List( Entity("Category", List( Operation(Get, Property("name", String, … ), Path("categories", … ), … ), Property("description", String, … ) Operation(Post, ) Path("categories", … ), … ), … ) Matching Transformation ) Macro expansion Macro expansion 27
Metamorphic Process Application( Service("CategoryService", List( Operation(Get, Path("categories", … ), … ), Operation(Post, Path("categories", … ), … ), … ) Transformation ) Macro expansion 28
Metamorphic Process object MyApp extends App { case class Category( Application( id: Option[Int], Service("CategoryService", List( name: String, Operation(Get, description: String Path("categories", … ), … ), ) Operation(Post, Path("categories", … ), … ), // Repository[Category] … // CategoryService ) } Transformation Generation ) Macro expansion Macro result 29
Metamorphic Process object MyApp extends App { case class Category( id: Option[Int], name: String, description: String ) // Repository[Category] // CategoryService } Generation Macro result 30
Metamorphic Process object MyApp extends App { POST http://localhost:8080/categories/ GET http://localhost:8080/categories/ case class Category( PUT http://localhost:8080/categories/1/ id: Option[Int], DELETE http://localhost:8080/categories/1/ name: String, description: String GET http://localhost:8080/categories/1/ ) { "id": 1, // Repository[Category] "name": "Cameras", // CategoryService "description": "High quality cameras." } } Generation Client App Macro result 31
Metamorphic Internal DSL import metamorphic.dsl._ @app object RESTApp { @entity class Category { def name = StringField() def description = StringField() } class CategoryService extends EntityService[Category] { def create(category: Category) = { if (category.name.length < 5) Response("Name is too short.", BadRequest) else super.create(category) } } } 32
Benchmarks Does Metamorphic has better execution performance? 33
Benchmarks Implementations 1. Metamorphic sync 2. Metamorphic async PostgreSQL 9.3.8 3. LoopBack *MongoDB 4. Sails 5. Django REST Python 2.7 Production environments 6. Django REST Python 3.4 7. Eve* 34
Benchmarks Execution Operation type Entity type Create | GetAll | Get | Replace | Delete Simple | Has Object | Has List 35
Benchmarks Execution Operation type Entity type Create | GetAll | Get | Replace | Delete Simple | Has Object | Has List Concurrency Executed up to 10 5000 requests Discarded the first 1000 requests 36
Benchmarks Results GetAll 37
Benchmarks Results Framework Create GetAll Get Replace Delete Sum LoopBack 1 | 1 | 1 3 | 2 | 1 1 | 1 | 1 2 | 2 | 2 1 | 1 | 1 21 Metamorphic Async 2 | 2 | 2 1 | 1 | 2 3 | 2 | 2 . 1 | 1 | 1 . 2 | 2 | 2 26 Sails 3 | 3 | 6 2 | 6 | 4 2 | 3 | 3 3 | 3 | 6 3 | 3 | 5 55 Django REST 3.4 5 | 5 | 4 5 | 4 | 5 6 | 5 | 5 5 | 4 | 3 4 | 4 | 4 68 Django REST 4 | 4 | 3 6 | 5 | 6 5 | 6 | 6 4 | 5 | 4 5 | 5 | 3 71 Metamorphic 6 | 6 | 5 4 | 3 | 3 4 | 4 | 4 6 | 6 | 5 6 | 6 | 6 74 Eve* 1 | 1 | 1 4 | 3 | 2 4 | 3 | 3 1 | 1 | 2 3 | 3 | 3 35 38
Academic Quasi-Experiment Is Metamorphic quick and easy to use, and error preventive? 39
Experiment Design 8 students (5th year) sync Baseline treatment Experimental treatment 40
Experiment Description Tasks Online shop application 1. Modeling 5 entities 2. Creation of services 3. Customization 41
Experiment Questionnaires The goal Analysis - Statistical validity - Wilcoxon-Mann-Whitney test - Features evaluation - 5% significance level 42
Experiment Questionnaires Results Are functionalities easier and more intuitive to use? Functionality ρ - Round 1 ρ - Round 2 Modeling 0.043 0.200 Creation of services 0.014 0.014 Customization 0.014 0.100 43
Experiment Questionnaires Results Rapid prototyping Production-level 44
Experiment Time Measurement Measurement Round x ̅ E σ E x ̅ B σ B x ̅ B − x ̅ E ( x ̅ B − x ̅ E ) / x ̅ B 1 11.44 03.11 20.13 09.18 08.69 43.2% Task 1: Modeling 2 07.94 01.48 08.81 03.06 00.87 09.9% 1 08.31 06.46 22.94 13.73 14.63 63.8% Task 2: Services 2 10.69 05.76 17.25 01.49 06.56 38.0% 1 05.06 02.12 03.92 02.67 -1.14 -29.1% Task 3: Customization 2 05.31 01.91 03.44 00.97 -1.87 -54.4% 1 45.81 08.19 70.56 12.14 24.75 35.1% Total 2 31.50 01.86 51.38 08.29 19.88 38.7% 45
Recommend
More recommend