Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Polyglot copy

Many people understand the very basics of several languages, all the way to Hello World. However, this isn’t a full fledged application and it’s challenging to make the translations in your head between all the different dialects (interpreted languages aren’t really different from each other like different languages – they work very much the same and the only difference is in the structure of the language). Out in our community are many people who firmly believe that moving from Ruby to Perl is not possible, that it’s very difficult to learn a new language, that it makes no sense to try to understand what “foreign” code might be doing.

In this talk I will cover the example in 5 different languages (Perl, Ruby, PHP, Python, Node) and show how to map the exact same functionality to different languages.

The code can be found on Github at http://www.github.com/synedra/polyglot

  • Inicia sesión para ver los comentarios

Polyglot copy

  1. 1. Becoming a Polyglot Simple API Engines in 5 Languages Kirsten Hunter @synedra http://www.princesspolymath.com
  2. 2. Kirsten Hunter @synedra http://www.princesspolymath.com Introduction Kirsten Hunter Kirsten Hunter @synedra http://www.princesspolymath.com
  3. 3. Kirsten Hunter @synedra http://www.princesspolymath.com The Challenge Siloed Communities Poor Understanding of Language Differences Fear of the Unknown Exclusivity
  4. 4. Kirsten Hunter @synedra http://www.princesspolymath.com The Solution • Simple API Project • Mongo Backend • Single Page Application Front End • Identically functioning API Engines in 5 Languages
  5. 5. Kirsten Hunter @synedra http://www.princesspolymath.com Fortune Cookie Server Engines use data from mongo db Each engine presents full API capability * GET * PUT * POST * DELETE Github / Docker synedra/polyglot c9.io python image clone github repo
  6. 6. Kirsten Hunter @synedra http://www.princesspolymath.com Single Page Application
  7. 7. Kirsten Hunter @synedra http://www.princesspolymath.com Mongo Setup load quoteid.jsonStartup mongo /etc/init.d/mongodb start { "content": "Boredom: the desire for desires.", "index": 1998, "author": "Leo Tolstoy" }, mongoimport --collection quotes --file quoteid.json --type json --jsonArray
  8. 8. Kirsten Hunter @synedra http://www.princesspolymath.com Schema Modeling RAML OpenAPI
  9. 9. Kirsten Hunter @synedra http://www.princesspolymath.com RAML 0.8 title: Fortune Cookie version: V1 baseUri: http://www.fortunecookieserver.com/api/v1 /quotes: displayName: Quotes get: description: Get a list of quotes queryParameters: random: description: Retrieve a random quote required: false default: false type: boolean responses: 200: body: application/json: example: | [ {"content":"That which does not kill us makes us stronger.", "author":"Sun Yi", "id":1 } ]
  10. 10. Kirsten Hunter @synedra http://www.princesspolymath.com RAML 0.8 title: Fortune Cookie version: V1 baseUri: http://www.fortunecookieserver.com/api/v1 /quotes: displayName: Quotes get: description: Get a list of quotes queryParameters: random: description: Retrieve a random quote required: false default: false type: boolean responses: 200: body: application/json: example: | [ {"content":"That which does not kill us makes us stronger.", "author":"Sun Yi", "id":1 } ]
  11. 11. Kirsten Hunter @synedra http://www.princesspolymath.com RAML 0.8 title: Fortune Cookie version: V1 baseUri: http://www.fortunecookieserver.com/api/v1 /quotes: displayName: Quotes get: description: Get a list of quotes queryParameters: random: description: Retrieve a random quote required: false default: false type: boolean responses: 200: body: application/json: example: | [ {"content":"That which does not kill us makes us stronger.", "author":"Sun Yi", "id":1 } ]
  12. 12. Kirsten Hunter @synedra http://www.princesspolymath.com { "swagger": "2.0", "info": { "title": "Fortune Cookie API", "description": "Random quote of the day", "version": "1.0.0" }, "host": "api.fortunecookieserver.com", "schemes": [ "http" ], "basePath": "/v1", "produces": [ "application/json" ], "paths": { "/quotes": { "get": { "summary": "Quotes", "description": "This is a quote server.n", "tags": [ "Quotes" ], "responses": { "200": { "description": "An array of products", "schema": { "type": "array", "items": { "$ref": "#/definitions/Quote" } } },
  13. 13. Kirsten Hunter @synedra http://www.princesspolymath.com { "swagger": "2.0", "info": { "title": "Fortune Cookie API", "description": "Random quote of the day", "version": "1.0.0" }, "host": "api.fortunecookieserver.com", "schemes": [ "http" ], "basePath": "/v1", "produces": [ "application/json" ], "paths": { "/quotes": { "get": { "summary": "Quotes", "description": "This is a quote server.n", "tags": [ "Quotes" ], "responses": { "200": { "description": "An array of products", "schema": { "type": "array", "items": { "$ref": "#/definitions/Quote" } } },
  14. 14. Kirsten Hunter @synedra http://www.princesspolymath.com { "swagger": "2.0", "info": { "title": "Fortune Cookie API", "description": "Random quote of the day", "version": "1.0.0" }, "host": "api.fortunecookieserver.com", "schemes": [ "http" ], "basePath": "/v1", "produces": [ "application/json" ], "paths": { "/quotes": { "get": { "summary": "Quotes", "description": "This is a quote server.n", "tags": [ "Quotes" ], "responses": { "200": { "description": "An array of products", "schema": { "type": "array", "items": { "$ref": "#/definitions/Quote" } } },
  15. 15. Kirsten Hunter @synedra http://www.princesspolymath.com Quick Schema Editor Demo
  16. 16. Kirsten Hunter @synedra http://www.princesspolymath.com PHP - Mongo Setup// Routes $app->group('/api/quotes', function () { // Setup DB connection $mongo = new MongoClient('mongodb://localhost:27017'); $mongo->connect(); $db = $mongo->test; $quotes = $db->selectCollection('quotes'); $this->get('', function (Request $request, Response $response, array $args) use ($quotes) { $this->logger->info("Fetching 10 records…n"); $results = []; foreach ($quotes->find([], ['_id' => 0])->sort(['index' => -1])->limit(10) as $quote) { $results[] = $quote; } $response ->getBody()->write(json_encode($results, JSON_PRETTY_PRINT)); $newResponse = $response->withHeader( 'Content-type', 'application/json; charset=utf-8' ); return $newResponse; });
  17. 17. Kirsten Hunter @synedra http://www.princesspolymath.com PHP - Route// Routes $app->group('/api/quotes', function () { // Setup DB connection $mongo = new MongoClient('mongodb://localhost:27017'); $mongo->connect(); $db = $mongo->test; $quotes = $db->selectCollection('quotes'); $this->get('', function (Request $request, Response $response, array $args) use ($quotes) { $this->logger->info("Fetching 10 records…n"); $results = []; foreach ($quotes->find([], ['_id' => 0])->sort(['index' => -1])->limit(10) as $quote) { $results[] = $quote; } $response ->getBody()->write(json_encode($results, JSON_PRETTY_PRINT)); $newResponse = $response->withHeader( 'Content-type', 'application/json; charset=utf-8' ); return $newResponse; });
  18. 18. Kirsten Hunter @synedra http://www.princesspolymath.com PHP - Static $app->get('/', function(Request $request, Response $response, $args) { return $response->getBody()->write('Hello World from PHP Slim'); }); $app->get('/demo', function(Request $request, Response $response, $args) { $content = file_get_contents('../static/index.html'); return $response->getBody()->write($content); });
  19. 19. Kirsten Hunter @synedra http://www.princesspolymath.com Perl - Mongo Setupuse Dancer; use Dancer::Plugin::CRUD; use MongoDB; my $client = MongoDB->connect(); my $db = $client->get_database('test'); my $quotes = $db->get_collection('quotes'); my $json = JSON->new->allow_nonref; set content_type => 'application/json'; get '/' => sub{ return {message => "Hello from Perl and Dancer"}; }; set public => path(dirname(__FILE__), '..', 'static'); get "/demo/?" => sub { send_file '/index.html' }; get '/api/quotes' => sub { my $response = $quotes->find()->sort({'index' => -1})->limit(10); my @results = (); while(my $quote = $response->next) { push (@results,
  20. 20. Kirsten Hunter @synedra http://www.princesspolymath.com Perl - Static Files use Dancer; use Dancer::Plugin::CRUD; use MongoDB; my $client = MongoDB->connect(); my $db = $client->get_database('test'); my $quotes = $db->get_collection('quotes'); my $json = JSON->new->allow_nonref; set content_type => 'application/json'; get '/' => sub{ return {message => "Hello from Perl and Dancer"}; }; set public => path(dirname(__FILE__), '..', 'static'); get "/demo/?" => sub { send_file '/index.html' }; get '/api/quotes' => sub { my $response = $quotes->find()->sort({'index' => -1})->limit(10); my @results = (); while(my $quote = $response->next) { push (@results,
  21. 21. Kirsten Hunter @synedra http://www.princesspolymath.com Perl - Routes get '/api/quotes' => sub { my $response = $quotes->find()->sort({'index' => -1})->limit(10); my @results = (); while(my $quote = $response->next) { push (@results, {"content" => $quote->{'content'}, "index" => $quote->{'index'}, "author" => $quote->{'author'} } ); } if (! scalar (@results)) { status 404; return; } return @results; };
  22. 22. Kirsten Hunter @synedra http://www.princesspolymath.com Python - Mongo Setup app = Flask("test",static_folder='') api = Api(app) mongo = PyMongo(app) parser = reqparse.RequestParser() parser.add_argument('author') parser.add_argument('content', required=True, help="Content cannot be blank!") APP_ROOT = os.path.dirname(os.path.abspath(__file__)) STATIC_ROOT = os.path.join(APP_ROOT, "..", "static") class Quote(Resource): def get(self, quote_id): if quote_id == "random": print "Random is random" quotes = mongo.db.quotes.find().sort("index", -1).limit(1) max_number = int(quotes[0]["index"]) rand_quote = randint(0, max_number) quotes = mongo.db.quotes.find_one({"index": int(rand_quote)}) else: quotes = mongo.db.quotes.find_one({"index": int(quote_id)}) resp = Response(dumps(quotes, default=default), mimetype='application/json') return resp def delete(self, quote_id):
  23. 23. Kirsten Hunter @synedra http://www.princesspolymath.com Python - Static APP_ROOT = os.path.dirname(os.path.abspath(__file__)) STATIC_ROOT = os.path.join(APP_ROOT, "..", "static") class Quote(Resource): def get(self, quote_id): if quote_id == "random": print "Random is random" quotes = mongo.db.quotes.find().sort("index", -1).limit(1) max_number = int(quotes[0]["index"]) rand_quote = randint(0, max_number) quotes = mongo.db.quotes.find_one({"index": int(rand_quote)}) else: quotes = mongo.db.quotes.find_one({"index": int(quote_id)}) resp = Response(dumps(quotes, default=default), mimetype='application/json') return resp … @app.route('/') def hello_world(): return 'Hello from Flask!' @app.route('/demo') def serve_page(): return send_from_directory(STATIC_ROOT, "index.html")
  24. 24. Kirsten Hunter @synedra http://www.princesspolymath.com Python - Route # shows a list of all quotes, and lets you POST to add new quotes class QuoteList(Resource): def get(self): quotes = mongo.db.quotes.find().sort("index", -1).limit(10) resp = Response(dumps(quotes, default=default), mimetype='application/json') return resp def post(self): args = parser.parse_args() quotes = mongo.db.quotes.find().sort("index", -1).limit(1) print quotes[0] args["index"] = int(quotes[0]["index"]) + 1 print args try: mongo.db.quotes.insert(args) except Error as ve: abort(400, str(ve)) return 201 api.add_resource(QuoteList, '/api/quotes') api.add_resource(Quote, '/api/quotes/<quote_id>')
  25. 25. Kirsten Hunter @synedra http://www.princesspolymath.com Ruby - Mongo Setup class Quote include Mongoid::Document field :index field :author field :content end Mongoid.load!("mongoid.yml", :development) set :port, 3000 set :bind, '0.0.0.0' get '/demo*' do content_type :html File.read(File.join('../static', 'index.html')) end get '/' do content_type :html "Hello World from Sinatra" end before do content_type 'application/json' end
  26. 26. Kirsten Hunter @synedra http://www.princesspolymath.com class Quote include Mongoid::Document field :index field :author field :content end Mongoid.load!("mongoid.yml", :development) set :port, 3000 set :bind, '0.0.0.0' get '/demo*' do content_type :html File.read(File.join('../static', 'index.html')) end get '/' do content_type :html "Hello World from Sinatra" end before do content_type 'application/json' end Ruby - Static
  27. 27. Kirsten Hunter @synedra http://www.princesspolymath.com before do content_type 'application/json' end namespace "/api" do # list all get '/quotes' do Quote.all.desc(:index).limit(10).to_json end get '/quotes/random' do newnumber = Quote.count random_num = rand(newnumber) quote = Quote.find_by(index: random_num.to_i) return status 404 if quote.nil? quote.to_json end # view one get '/quotes/:index' do quote = Quote.find_by(index: params[:index].to_i) return status 404 if quote.nil? quote.to_json end Ruby - Route
  28. 28. Kirsten Hunter @synedra http://www.princesspolymath.com var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/test'); var db = mongoose.connection; var quoteSchema = mongoose.Schema({ content: String, author: String, index: Number }); var Quote = mongoose.model('Quote', quoteSchema) Quote.count().exec(function(err, count){ quotecount = count; }); var express = require('express'); var app = express(); var router = express.Router(); var path = require('path'); var bodyParser = require('body-parser'); app.use('/demo', express.static(path.join(__dirname, '..', 'static'))); app.use(bodyParser.json()); // index Node - Mongo Setup
  29. 29. Kirsten Hunter @synedra http://www.princesspolymath.com var express = require('express'); var app = express(); var router = express.Router(); var path = require('path'); var bodyParser = require('body-parser'); app.use('/demo', express.static(path.join(__dirname, '..', 'static'))); app.use(bodyParser.json()); // index app.get('/', function(req, res) { res.send('Hello world from express'); }); app.use('/api', router); // REST API router.route('/quotes/random') .get(function(req, res, next) { var random = Math.floor(Math.random() * quotecount); Quote.findOne({"index":random}, function (err, result) { if (err) { console.log(err); res.redirect('/quotes/random'); } res.send(result); Node - Express Static
  30. 30. Kirsten Hunter @synedra http://www.princesspolymath.com var express = require('express'); var app = express(); var router = express.Router(); var path = require('path'); var bodyParser = require('body-parser'); app.use('/demo', express.static(path.join(__dirname, '..', 'static'))); app.use(bodyParser.json()); // index app.get('/', function(req, res) { res.send('Hello world from express'); }); app.use('/api', router); // REST API router.route('/quotes/random') .get(function(req, res, next) { var random = Math.floor(Math.random() * quotecount); Quote.findOne({"index":random}, function (err, result) { if (err) { console.log(err); res.redirect('/quotes/random'); } res.send(result); Node - Express Routes
  31. 31. Kirsten Hunter @synedra http://www.princesspolymath.com Node - Hapi Static server.route({ method : 'GET', path : '/demo/{path*}', handler : { directory : { path : '../static', listing : false, index : true }}})}); server.route([ { method: 'GET', path: '/', handler: function(request, reply) { reply('Hello world from hapi'); }}]);
  32. 32. Kirsten Hunter @synedra http://www.princesspolymath.com Node - Hapi Routes server.route([ { method: 'GET', path: '/api/quotes/random', handler: function(request, reply) { var random = Math.floor(Math.random() * quotecount); Quote.findOne({"index":random}, function (err, result) { reply(result); }) } },
  33. 33. Kirsten Hunter @synedra http://www.princesspolymath.com Questions? http://www.princesspolymath.com Kirsten Hunter @synedra http://www.princesspolymath.com

×