Slide 1

Slide 1 text

FW と ライブラリ の考え方 Gunma.web #53 @kanayannet 15分

Slide 2

Slide 2 text

突然ですが SQLを初めて学ぶとします。 目的はデータへの問い合わせをスムーズに行う 今、使える言語はRuby

Slide 3

Slide 3 text

何から勉強する? ActiveRecord O/R mapper mysql2 素のSQL をひたすら書く

Slide 4

Slide 4 text

ActiveRecord class User < ActiveRecord::Base establish_connection( # connection 設定色々 ) validates :name, presence: { message: '名前を入力してください' } end # ここから実行コード u = User.new u.name = 'kanayannet' u.sex = 'man' u.like = 'jojo' u.save

Slide 5

Slide 5 text

mysql2 class User def initialize @cli = Mysql2::Client.new( # connection 設定色々... ) @name = '' @sex = '' @like = '' @errors = [] end attr_accesor :name, :sex, :like, :errors

Slide 6

Slide 6 text

def valid? if self.name.blank? @errors << '名前を入力してください' end return false if @errors.present? true end

Slide 7

Slide 7 text

def save return false if self.valid? sql = <<~SQL insert into users( name, sex, like, updated_at, created_at ) values(?, ?, ?, now(), now()) SQL sts = @cli.prepare(sql) sts.execute( @name, @sex, @like ) true end def close @cli.close end end

Slide 8

Slide 8 text

さて SQL 初学者にオススメの学び方 はどっち?

Slide 9

Slide 9 text

ここからは挙手方式でやろうと思います。

Slide 10

Slide 10 text

ActiveRecord ?

Slide 11

Slide 11 text

mysql2 ?

Slide 12

Slide 12 text

絶対はないですが... 自分は mysql2 をオススメします。

Slide 13

Slide 13 text

理由 基礎からガッツリと 接続, 切断, SQL文, transaction ...慣れる事ができるため 応用が効きます。(頭の中でイメージしやすい) 複数のtable があり 別sever いる 別scheme にいて join が必要である

Slide 14

Slide 14 text

NG な例 active_record でいきなりスタートすると... 例 正規化されている table A, B があります。 同じ server内に table はありません。 A の IDを含む B のデータを出す必要がある

Slide 15

Slide 15 text

NG1 1 接続しか考慮できなくて詰む 1 server 1 scheme に全部入ってないと頭が追いつかない joins method で繋げたいけど...同じServer内にいないし出 来ない A.joins(:b)

Slide 16

Slide 16 text

NG2 A を全件 loop してその中で都度都度 B にqueryを発行 数件ならいいけど... 100万件とかあるとServer負荷的にやさしくないよ

Slide 17

Slide 17 text

OK limit n, 1000 で切って where in を使えばいんじゃない? n は offset 下記は 1 - 1000 の例 MySQL を基礎からやった人は辿りつきやすい select id from A limit 1, 1000 ↓ select id from B where id in (AのID, AのID, ....)

Slide 18

Slide 18 text

心理学(人間の脳について) 感覚記憶 外界から入力された刺激情報 すぐ忘れる これのうち注意を向けられた情報だけが短期記憶 短期記憶 文字通り短期間の記憶 一度に保持される情報の容量の大きさにも限界がある 長期記憶 容量の大きさに制限はない 保持情報が長期記憶として安定化する過程がある 自転車に乗る方法やパズルの解き方などのように、 同じ経験を反復する

Slide 19

Slide 19 text

大事なことなので 自転車に乗る方法やパズルの解き方などのように、同じ 経験を反復する

Slide 20

Slide 20 text

慣れたら ActiveRecord

Slide 21

Slide 21 text

理由 コード量が少なく、開発効率が圧倒的

Slide 22

Slide 22 text

これの違いに似てるね プログラミングがとりあえず、できる データ設計 -> コード設計 -> 実装

Slide 23

Slide 23 text

オープニング終了!

Slide 24

Slide 24 text

今日のAgenda 勉強する場合の好み Front <-> Server の好み Server <-> RDB の好み lambda <-> DynamoDB の好み 画像処理 の好み

Slide 25

Slide 25 text

勉強する場合の好み Front <-> Server の好み Server <-> RDB の好み lambda <-> DynamoDB の好み 画像処理 の好み

Slide 26

Slide 26 text

Front <-> Server の好み

Slide 27

Slide 27 text

マイクロサービス 規模が小さいサービス同士を組み合わせて連係させるこ とで、ひとつの大きなアプリケーションやサイトの構築 を行う技法

Slide 28

Slide 28 text

よくある分離パターン データベースや全文検索エンジンといったミドルウェア からデータを取得、更新する ページを構築する それぞれ別サーバで処理して.... HTTPのインタフェースを利用してやりとりする

Slide 29

Slide 29 text

参考: @it https://atmarkit.itmedia.co.jp/ait/articles/1803/12/news012.h

Slide 30

Slide 30 text

BFF(Backends For Frontends) Front <-> Server これの事ですね。

Slide 31

Slide 31 text

Sinatra が推奨です。

Slide 32

Slide 32 text

理由 学習コストが少ない -> Ruby が解ってれば、大体できる 余計なパーツがない -> 比較対象: Rails memory, cpu が最低限で済みやすい 癖(作法) が少ない -> Frontend engineer が書いたものをそ のまま当てやすい 分業しやすい

Slide 33

Slide 33 text

Sample code app.rb require 'sinatra' class App < Sinatra::Base get "/" do "index" end post "/" do "create" end patch "/:id" do "edit #{params[:id]}" end delete "/:id" do "delete #{params[:id]}" end end

Slide 34

Slide 34 text

config.ru require "./app" run App

Slide 35

Slide 35 text

Gemfile # frozen_string_literal: true source "https://rubygems.org" gem 'sinatra' gem 'puma'

Slide 36

Slide 36 text

bundle config --local path vendor/bundle bundle i bundle exec pumactl start

Slide 37

Slide 37 text

frontend の人には 文字列の箇所を erb(テンプレート) に して 渡せばいいだけ

Slide 38

Slide 38 text

backend server Server <-> RDB lambda <-> DynamoDB

Slide 39

Slide 39 text

Server <-> RDB 役割: BFF のサーバからの input を保存, 抽出する 基本: html を返さず, json を返す

Slide 40

Slide 40 text

Ruby on Rails

Slide 41

Slide 41 text

特徴(メリット) 大体のよくある処理は短いコードで表現可能 ActiveRecord -> 特にこれがある事が大きい 同じ言語でこれを超えるFWがないので、迷いが少ない 他言語だと乱立してる感がある

Slide 42

Slide 42 text

特徴(デメリット) Frontの作法が独特...Frontend エンジニアがそのまま参加 しずらい事がある asset pipeline formタグ周りの独特な記法 <%= form_with model: @fruit, local: true do |form| %>

Slide 43

Slide 43 text

sinatra にActiveRecordでもいいのでは? activerecord は接続は1プロセスの中で1回のみ

Slide 44

Slide 44 text

Lost connection to MySQL server... 接続が長すぎて切れる事がある daemon process だし reconnect option は非推奨 -> 今後なくなる方向 trancation や SQLの変数を保持してくれないので Rails は http request 開始時にチェックして自動で接続し てくれる reconnect option いらない -> よしなにやってくれる 自分で実装する必要もない

Slide 45

Slide 45 text

注意: ディスってる訳じゃない 例: python orm でググる... どれ使えばええネン。 Ruby = ActiveRecord 1択 Rails とともに発展した感があり、優れてるし迷いがな い

Slide 46

Slide 46 text

Frontの作法が独特... backend Api にしておけば、目立たないね

Slide 47

Slide 47 text

利用企業 みんな大好きgithub も Rails だし 他: cookpad, 食べログ, note, Qiita, ラクスル

Slide 48

Slide 48 text

lambda <-> DynamoDB

Slide 49

Slide 49 text

どんな時にこれ? 大前提 トランザクションがいらない NoSQL だし リクエスト数が計算しやすい 使った分だけ課金される 読めないくらい多いものだと不向き

Slide 50

Slide 50 text

EC2, ECS, RDS あるけど? RDS 落としておいても...勝手に起動しちゃう ? 使ってなくとも起動してると課金される 料金が...

Slide 51

Slide 51 text

Lambda 側で何のFW ? Express.js 一言で表現すると... nodejs 版 sinatra

Slide 52

Slide 52 text

SampleCode const express = require('express'); const app = express(); const serverless = require('serverless-http'); app.get('/users', (req, res) => { res.json([1, 2, 3]); }); app.get('/users/:id', (req, res) => { res.json({ id: req.params.id }); }); app.post('/users', (req, res) => { res.json(req.body); }); app.delete('/users/:id', (req, res) => { res.json({ id: req.params.id }); });

Slide 53

Slide 53 text

app.put('/users/:id', (req, res) => { res.json({ id: req.params.id }); }); const handler = serverless(app); // ここ以降は local でテストするために必要 const startServer = async () => { app.listen(3000, () => { console.log("listening on port 3000!"); }); }

Slide 54

Slide 54 text

これと DynamoDB の組み合わせなら... フルマネージドでかつ、放っておいても課金がリクエス ト分

Slide 55

Slide 55 text

縁起でもないが... 使われなくなって放置されても課金されない

Slide 56

Slide 56 text

Lambda S3 event + Python + pillow 画像処理 の好み

Slide 57

Slide 57 text

画像処理周りの悩み事 画像よりも大きなメモリーを大量消費 middle ware の install -> 面倒臭い ImageMagick, opencv など

Slide 58

Slide 58 text

分離したいよね? アップロード先は静的ファイル だし S3 にまとめたい メモリーも 実運用サーバではなく 別に依存関係を切り たい

Slide 59

Slide 59 text

この時点で Lambda S3 event が確定したようなもの

Slide 60

Slide 60 text

参考: https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with- s3-example.html

Slide 61

Slide 61 text

middle ware の install 出来ればその言語だけで処理したい ゆくゆく拡張性持たせるにしても画像処理に向いてる言 語

Slide 62

Slide 62 text

Python + pillow この時点でこの二つが決まる

Slide 63

Slide 63 text

理由 pillow middle ware の install が不要 pure python で実装されてる という訳で言語は Python

Slide 64

Slide 64 text

SampleCode from PIL import Image import urllib.parse import boto3 import os QUALITY_IMAGE = 50 s3 = boto3.client('s3') def lambda_handler(event, context): bucket = event['Records'][0]['s3']['bucket']['name'] org_key = urllib.parse.unquote_plus( event['Records'][0]['s3']['object']['key'], encoding='utf-8' ) source_file = u'/tmp/' + os.path.basename(org_key) ext = 'jpg' dst_path = os.path.splitext( os.path.basename(source_key) )[0] + '.' + ext dst_key = os.path.splitext(org_key)[0] + '.' + ext

Slide 65

Slide 65 text

try: s3.download_file( Bucket=bucket, Key=org_key, Filename=source_file ) img = Image.open(source_file, 'r') img.save( dst_path, ext, quality = QUALITY_IMAGE ) s3.upload_file( Filename=dst_path, Bucket=bucket, Key=dst_key ) return dst_key except Exception as e: print(e)

Slide 66

Slide 66 text

画像は色々厄介 ちなみに ImageMagick を使って、3MB の画像を処理した ら 1GB 以上のメモリを使っていた経験があります。

Slide 67

Slide 67 text

まとめ

Slide 68

Slide 68 text

目的と手段 良いも悪いも表裏一体なところあります。 目的に沿って適切な手段を取ることを推奨します。

Slide 69

Slide 69 text

アンチパターン xx言語しか出来る人がいないから xx言語のFW ありがちだけど非推奨 理由: 結果的に後から見返した際にベストな選択ではな いため

Slide 70

Slide 70 text

学習期間 許されるのであれば、可能な限り 「学習」と「調査」期間を設けよう 言語やFWやライブラリは「道具=手段」であって 「目的」そのものではない

Slide 71

Slide 71 text

よくある Q & A Q: K澤さん一体、何言語覚えればいいんすか? A: 全部を覚える必要ないよ。 その代わりに出来る範囲を実装してください。 分担作業も手段の一つです。

Slide 72

Slide 72 text

よくある Q & A Q: 全部をやってみたいんですが? A: ガンバロウ! 覚えるしか...(ry

Slide 73

Slide 73 text

よくある Q & A Q: そんな事言ったって 一気に数言語も覚えられんすよ? A: 各個撃破です。 偉い人 も前回各個撃破と言ってました。 一気にやるのはオススメしません。 参考: https://speakerdeck.com/rtechkouhou/enziniatositekofalsexia sheng-kifalsekorutameni

Slide 74

Slide 74 text

ご清聴 ありがとう ございました。