Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Python, Ruby, dan Golang:Perbandingan Aplikasi Layanan Web

Setelah perbandingan Python, Ruby, dan Golang baru-baru ini untuk aplikasi baris perintah, saya memutuskan untuk menggunakan pola yang sama untuk membandingkan membangun layanan web sederhana. Saya telah memilih Flask (Python), Sinatra (Ruby), dan Martini (Golang) untuk perbandingan ini. Ya, ada banyak opsi lain untuk pustaka aplikasi web dalam setiap bahasa, tetapi saya merasa ketiganya cocok untuk perbandingan.


Ikhtisar Perpustakaan

Berikut adalah perbandingan tingkat tinggi perpustakaan oleh Stackshare.


Flask (Python)

Flask adalah kerangka kerja mikro untuk Python berdasarkan Werkzeug, Jinja2 dan niat baik.

Untuk aplikasi yang sangat sederhana, seperti yang ditunjukkan dalam demo ini, Flask adalah pilihan yang tepat. Aplikasi Flask dasar hanya 7 baris kode (LOC) dalam satu file sumber Python. Keunggulan Flask dibandingkan pustaka web Python lainnya (seperti Django atau Pyramid) adalah bahwa Anda dapat memulai dari yang kecil dan membangun aplikasi yang lebih kompleks sesuai kebutuhan.

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()


Sinatra (Ruby)

Sinatra adalah DSL untuk membuat aplikasi web dengan cepat di Ruby dengan sedikit usaha.

Sama seperti Flask, Sinatra sangat bagus untuk aplikasi sederhana. Aplikasi dasar Sinatra hanya 4 LOC dalam satu file sumber Ruby. Sinatra digunakan sebagai pengganti library seperti Ruby on Rails untuk alasan yang sama seperti Flask - Anda dapat memulai dari yang kecil dan memperluas aplikasi sesuai kebutuhan.

require 'sinatra'

get '/hi' do
  "Hello World!"
end


Martini (Golang)

Martini adalah paket yang kuat untuk menulis aplikasi/layanan web modular dengan cepat di Golang.

Martini hadir dengan beberapa baterai yang disertakan daripada Sinatra dan Flask tetapi masih sangat ringan untuk memulai - hanya 9 LOC untuk aplikasi dasar. Martini mendapat beberapa kritik dari komunitas Golang tetapi masih memiliki salah satu proyek Github berperingkat tertinggi dari semua kerangka web Golang. Penulis Martini menanggapi langsung kritik di sini. Beberapa kerangka kerja lain termasuk Revel, Gin, dan bahkan perpustakaan net/http bawaan.

package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hello world!"
  })
  m.Run()
}

Tanpa dasar-dasarnya, mari buat aplikasi!




Deskripsi Layanan

Layanan yang dibuat menyediakan aplikasi blog yang sangat mendasar. Rute berikut dibuat:

  • GET / :Mengembalikan blog (menggunakan template untuk merender).
  • GET /json :Mengembalikan konten blog dalam format JSON.
  • POST /new :Menambahkan postingan baru (judul, ringkasan, konten) ke blog.

Antarmuka eksternal ke layanan blog persis sama untuk setiap bahasa. Untuk kesederhanaan MongoDB akan digunakan sebagai penyimpanan data untuk contoh ini karena ini adalah yang paling sederhana untuk diatur dan kita tidak perlu khawatir tentang skema sama sekali. Dalam aplikasi "seperti blog" normal, database relasional mungkin diperlukan.


Tambahkan Pos

POST /new

$ curl --form title='Test Post 1' \
     --form summary='The First Test Post' \
     --form content='Lorem ipsum dolor sit amet, consectetur ...' \
     http://[IP]:[PORT]/new


Melihat HTML

GET /



Lihat JSON

GET /json

[
   {
      content:"Lorem ipsum dolor sit amet, consectetur ...",
      title:"Test Post 1",
      _id:{
         $oid:"558329927315660001550970"
      },
      summary:"The First Test Post"
   }
]



Struktur Aplikasi

Setiap aplikasi dapat dipecah menjadi komponen-komponen berikut:


Pengaturan Aplikasi

  • Inisialisasi aplikasi
  • Jalankan aplikasi


Permintaan

  • Tentukan rute di mana pengguna dapat meminta data (GET)
  • Tentukan rute tempat pengguna dapat mengirimkan data (POST)


Tanggapan

  • Render JSON (GET /json )
  • Membuat template (GET / )


Basis Data

  • Inisialisasi koneksi
  • Masukkan data
  • Ambil data


Penerapan Aplikasi

  • Pekerja Buruh!

Selebihnya dari artikel ini akan membandingkan setiap komponen ini untuk setiap perpustakaan. Tujuannya bukan untuk menyarankan bahwa salah satu perpustakaan ini lebih baik daripada yang lain - ini untuk memberikan perbandingan khusus antara ketiga alat:

  • Flask (Python)
  • Sinatra (Ruby)
  • Martini (Golang)



Penyiapan Proyek

Semua proyek di-bootstrap menggunakan docker dan docker-compose. Sebelum menyelami bagaimana setiap aplikasi di-bootstrap di bawah tenda, kita bisa menggunakan buruh pelabuhan untuk menjalankan dan menjalankan masing-masing dengan cara yang persis sama - docker-compose up

Serius, itu dia! Sekarang untuk setiap aplikasi ada Dockerfile dan docker-compose.yml file yang menentukan apa yang terjadi ketika Anda menjalankan perintah di atas.

Python (flask) - Dockerfile

FROM python:3.4

ADD . /app
WORKDIR /app

RUN pip install -r requirements.txt

Dockerfile ini mengatakan bahwa kita memulai dari gambar dasar dengan Python 3.4 terinstal, menambahkan aplikasi kita ke /app direktori dan menggunakan pip untuk menginstal persyaratan aplikasi kami yang ditentukan dalam requirements.txt .

Ruby (sinatra)

FROM ruby:2.2

ADD . /app
WORKDIR /app

RUN bundle install

Dockerfile ini mengatakan bahwa kita memulai dari gambar dasar dengan Ruby 2.2 terinstal, menambahkan aplikasi kita ke /app direktori dan menggunakan bundler untuk menginstal persyaratan aplikasi kami yang ditentukan dalam Gemfile .

Golang (martini)

FROM golang:1.3

ADD . /go/src/github.com/kpurdon/go-blog
WORKDIR /go/src/github.com/kpurdon/go-blog

RUN go get github.com/go-martini/martini && \
    go get github.com/martini-contrib/render && \
    go get gopkg.in/mgo.v2 && \
    go get github.com/martini-contrib/binding

Dockerfile ini mengatakan bahwa kita memulai dari gambar dasar dengan Golang 1.3 terinstal, menambahkan aplikasi kita ke /go/src/github.com/kpurdon/go-blog direktori dan mendapatkan semua dependensi yang diperlukan menggunakan go get perintah.



Inisialisasi/Jalankan Aplikasi

Python (Flask) - app.py

# initialize application
from flask import Flask
app = Flask(__name__)

# run application
if __name__ == '__main__':
    app.run(host='0.0.0.0')
$ python app.py

Ruby (Sinatra) - app.rb

# initialize application
require 'sinatra'
$ ruby app.rb

Golang (Martini) - app.go

// initialize application
package main
import "github.com/go-martini/martini"
import "github.com/martini-contrib/render"

func main() {
    app := martini.Classic()
    app.Use(render.Renderer())

    // run application
    app.Run()
}
$ go run app.go


Tentukan Rute (GET/POST)

Python (Flask)

# get
@app.route('/')  # the default is GET only
def blog():
    # ...

#post
@app.route('/new', methods=['POST'])
def new():
    # ...

Ruby (Sinatra)

# get
get '/' do
  # ...
end

# post
post '/new' do
  # ...
end

Golang (Martini)

// define data struct
type Post struct {
  Title   string `form:"title" json:"title"`
  Summary string `form:"summary" json:"summary"`
  Content string `form:"content" json:"content"`
}

// get
app.Get("/", func(r render.Render) {
  // ...
}

// post
import "github.com/martini-contrib/binding"
app.Post("/new", binding.Bind(Post{}), func(r render.Render, post Post) {
  // ...
}


Render Respons JSON

Python (Flask)

Flask menyediakan metode jsonify() tetapi karena layanan menggunakan MongoDB, utilitas mongodb bson digunakan.

from bson.json_util import dumps
return dumps(posts) # posts is a list of dicts [{}, {}]

Ruby (Sinatra)

require 'json'
content_type :json
posts.to_json # posts is an array (from mongodb)

Golang (Martini)

r.JSON(200, posts) // posts is an array of Post{} structs


Merender Respons HTML (Templat)

Python (Flask)

return render_template('blog.html', posts=posts)
<!doctype HTML>
<html>
  <head>
    <title>Python Flask Example</title>
  </head>
  <body>
    {% for post in posts %}
      <h1> {{ post.title }} </h1>
      <h3> {{ post.summary }} </h3>
      <p> {{ post.content }} </p>
      <hr>
    {% endfor %}
  </body>
</html>

Ruby (Sinatra)

erb :blog
<!doctype HTML>
<html>
  <head>
    <title>Ruby Sinatra Example</title>
  </head>
  <body>
    <% @posts.each do |post| %>
      <h1><%= post['title'] %></h1>
      <h3><%= post['summary'] %></h3>
      <p><%= post['content'] %></p>
      <hr>
    <% end %>
  </body>
</html>

Golang (Martini)

r.HTML(200, "blog", posts)
<!doctype HTML>
<html>
  <head>
    <title>Golang Martini Example</title>
  </head>
  <body>
    {{range . }}
      <h1>{{.Title}}</h1>
      <h3>{{.Summary}}</h3>
      <p>{{.Content}}</p>
      <hr>
    {{ end }}
  </body>
</html>


Koneksi Basis Data

Semua aplikasi menggunakan driver mongodb khusus untuk bahasa tersebut. Variabel lingkungan DB_PORT_27017_TCP_ADDR adalah IP dari wadah buruh pelabuhan yang ditautkan (ip basis data).

Python (Flask)

from pymongo import MongoClient
client = MongoClient(os.environ['DB_PORT_27017_TCP_ADDR'], 27017)
db = client.blog

Ruby (Sinatra)

require 'mongo'
db_ip = [ENV['DB_PORT_27017_TCP_ADDR']]
client = Mongo::Client.new(db_ip, database: 'blog')

Golang (Martini)

import "gopkg.in/mgo.v2"
session, _ := mgo.Dial(os.Getenv("DB_PORT_27017_TCP_ADDR"))
db := session.DB("blog")
defer session.Close()


Menyisipkan Data Dari POST

Python (Flask)

from flask import request
post = {
    'title': request.form['title'],
    'summary': request.form['summary'],
    'content': request.form['content']
}
db.blog.insert_one(post)

Ruby (Sinatra)

client[:posts].insert_one(params) # params is a hash generated by sinatra

Golang (Martini)

db.C("posts").Insert(post) // post is an instance of the Post{} struct


Ambil Data

Python (Flask)

posts = db.blog.find()

Ruby (Sinatra)

@posts = client[:posts].find.to_a

Golang (Martini)

var posts []Post
db.C("posts").Find(nil).All(&posts)


Penerapan Aplikasi (Docker!)

Solusi hebat untuk menerapkan semua aplikasi ini adalah dengan menggunakan docker dan docker-compose.

Python (Flask)

Dockerfile

FROM python:3.4

ADD . /app
WORKDIR /app

RUN pip install -r requirements.txt

docker-compose.yml

web:
  build: .
  command: python -u app.py
  ports:
    - "5000:5000"
  volumes:
    - .:/app
  links:
    - db
db:
  image: mongo:3.0.4
  command: mongod --quiet --logpath=/dev/null

Ruby (Sinatra)

Dockerfile

FROM ruby:2.2

ADD . /app
WORKDIR /app

RUN bundle install

docker-compose.yml

web:
  build: .
  command: bundle exec ruby app.rb
  ports:
    - "4567:4567"
  volumes:
    - .:/app
  links:
    - db
db:
  image: mongo:3.0.4
  command: mongod --quiet --logpath=/dev/null

Golang (Martini)

Dockerfile

FROM golang:1.3

ADD . /go/src/github.com/kpurdon/go-todo
WORKDIR /go/src/github.com/kpurdon/go-todo

RUN go get github.com/go-martini/martini && go get github.com/martini-contrib/render && go get gopkg.in/mgo.v2 && go get github.com/martini-contrib/binding

docker-compose.yml

web:
  build: .
  command: go run app.go
  ports:
    - "3000:3000"
  volumes: # look into volumes v. "ADD"
    - .:/go/src/github.com/kpurdon/go-todo
  links:
    - db
db:
  image: mongo:3.0.4
  command: mongod --quiet --logpath=/dev/null


Kesimpulan

Untuk menyimpulkan, mari kita lihat apa yang saya yakini sebagai beberapa kategori di mana perpustakaan yang disajikan terpisah satu sama lain.


Kesederhanaan

Sementara Flask sangat ringan dan membaca dengan jelas, aplikasi Sinatra adalah yang paling sederhana dari ketiganya di 23 LOC (dibandingkan dengan 46 untuk Flask dan 42 untuk Martini). Untuk alasan ini Sinatra adalah pemenang dalam kategori ini. Namun perlu dicatat bahwa kesederhanaan Sinatra disebabkan oleh "keajaiban" yang lebih default - misalnya, pekerjaan implisit yang terjadi di belakang layar. Bagi pengguna baru, hal ini sering kali menyebabkan kebingungan.

Berikut adalah contoh spesifik dari “sihir” di Sinatra:

params # the "request.form" logic in python is done "magically" behind the scenes in Sinatra.

Dan kode Flask yang setara:

from flask import request
params = {
    'title': request.form['title'],
    'summary': request.form['summary'],
    'content': request.form['content']
}

Untuk pemula dalam memprogram Flask dan Sinatra tentu saja lebih sederhana, tetapi untuk programmer berpengalaman dengan waktu yang dihabiskan dalam bahasa lain yang diketik secara statis, Martini menyediakan antarmuka yang cukup sederhana.



Dokumentasi

Dokumentasi Flask adalah yang paling sederhana untuk dicari dan paling mudah didekati. Sementara Sinatra dan Martini didokumentasikan dengan baik, dokumentasi itu sendiri tidak begitu mudah didekati. Untuk itulah Flask adalah pemenang dalam kategori ini.



Komunitas

Flask adalah pemenang dalam kategori ini. Komunitas Ruby lebih sering dogmatis tentang Rails sebagai satu-satunya pilihan yang baik jika Anda membutuhkan sesuatu yang lebih dari layanan dasar (meskipun Padrino menawarkan ini di atas Sinatra). Komunitas Golang masih belum mencapai kesepakatan tentang satu (atau bahkan beberapa) kerangka kerja web, yang diharapkan karena bahasanya sendiri masih sangat muda. Namun Python telah merangkul sejumlah pendekatan untuk pengembangan web termasuk Django untuk aplikasi web berfitur lengkap dan Flask, Botol, CheryPy, dan Tornado untuk pendekatan kerangka mikro.




Penentuan Akhir

Perhatikan bahwa inti dari artikel ini bukanlah untuk mempromosikan satu alat, melainkan untuk memberikan perbandingan yang tidak memihak dari Flask, Sinatra, dan Martini. Dengan itu, saya akan memilih Flask (Python) atau Sinatra (Ruby). Jika Anda berasal dari bahasa seperti C atau Java, mungkin sifat Golang yang diketik secara statis mungkin menarik bagi Anda. Jika Anda seorang pemula, Flask mungkin menjadi pilihan terbaik karena sangat mudah untuk digunakan dan hanya ada sedikit "keajaiban" default. Rekomendasi saya adalah Anda fleksibel dalam mengambil keputusan saat memilih perpustakaan untuk proyek Anda.

pertanyaan? Masukan? Silakan komentar di bawah. Terima kasih!

Selain itu, beri tahu kami jika Anda tertarik untuk melihat beberapa tolok ukur.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Pelajari Analisis Data Dasar dengan Fungsi SQL Window

  2. Mengambil pendekatan manusia untuk tata kelola data

  3. Seberapa mahalkah Konversi Implisit sisi kolom?

  4. Pandas:Cara Membaca dan Menulis File

  5. SQL AS:Penggunaan, Contoh, dan Bagaimana Ini Dapat Bermanfaat Bagi Anda