Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
サーバサイドDartを試してみた
Search
ANDPAD inc
February 25, 2021
Programming
3
4.3k
サーバサイドDartを試してみた
2021/02/24 ANDPAD TechLive #2 Flutterって実際どうなの?設計からテストまで
ANDPAD inc
February 25, 2021
Tweet
Share
More Decks by ANDPAD inc
See All by ANDPAD inc
読もう! Android build ドキュメント
andpad
1
370
アンドパッドにおける CocoaPods ライブラリ群の SwiftPackageManager への移行戦略
andpad
0
170
Flutter は DCM が 9 割
andpad
1
250
Amplify で SPA をホスティングする際の注意点
andpad
1
220
マルチプロダクト開発の現場でAWS Security Hubを1年以上運用して得た教訓
andpad
0
98
rails stats で紐解く ANDPAD のイマを支える技術たち
andpad
1
500
本編では話さない Zig の話
andpad
2
330
"noncopyable types" の使いどころについて考えてみた
andpad
0
480
ANDPAD黒板のオフラインモード機能 リリースまでの軌跡
andpad
0
560
Other Decks in Programming
See All in Programming
當開發遇上包裝:AI 如何讓產品從想法變成商品
clonn
0
2.5k
AIエージェントによるテストフレームワーク Arbigent
takahirom
0
270
がんばりすぎないコーディングルール運用術
tsukakei
1
180
JVM の仕組みを理解して PHP で実装してみよう
m3m0r7
PRO
1
250
コードに語らせよう――自己ドキュメント化が内包する楽しさについて / Let the Code Speak
nrslib
5
990
型付け力を強化するための Hoogle のすゝめ / Boosting Your Type Mastery with Hoogle
guvalif
1
230
鯛変だったRubyKaigi 2025 ── それでも楽しかった!
pndcat
0
130
Babylon.js 8.0のアプデ情報を 軽率にキャッチアップ / catch-up-babylonjs-8
drumath2237
0
110
CQRS/ESのクラスとシステムフロー ~ RailsでフルスクラッチでCQRSESを組んで みたことから得た学び~
suzukimar
0
190
衛星の軌道をWeb地図上に表示する
sankichi92
0
250
DevTalks 25 - Create your own AI-infused Java apps with ease
kdubois
2
120
Investigating Multithreaded PostgreSQL
macdice
0
150
Featured
See All Featured
StorybookのUI Testing Handbookを読んだ
zakiyama
30
5.8k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
1
78
What's in a price? How to price your products and services
michaelherold
245
12k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
19
1.2k
Imperfection Machines: The Place of Print at Facebook
scottboms
267
13k
A better future with KSS
kneath
239
17k
Code Reviewing Like a Champion
maltzj
523
40k
Navigating Team Friction
lara
186
15k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Fireside Chat
paigeccino
37
3.5k
Optimizing for Happiness
mojombo
378
70k
Transcript
サーバサイドDartを試してみた バベルの塔以前の世界へ ANDPAD Tech Live #2
1. 動機 2. なぜDartでサーバを実装するのか 3. サンプルの構成 4. サンプルのポイント解説 5. 感想
6. 実戦投入のはじめの一歩 目次 ※ FlutterやgRPCの基礎知識があることを前提にしている。本資料では、これらの詳細には触れない。
• サーバ、Webフロント、モバイルアプリで言語がばら ばらのせいか、相乗効果がない ◦ バベルの塔の建設現場っぽい • サーバのコードを読まないと、Web APIの仕様が分か らないことがある ◦
モバイルアプリエンジニアからすると、サーバの言語とツー ルに馴染みがないのでつらい 1. 動機(問題意識) 主は、人の子らが作ろうとしていた街と塔とを見ようとしてお下りになり、そして仰せられた、「なるほど、彼らは一つの民で、同じ言葉を話して いる。この業は彼らの行いの始まりだが、おそらくこのこともやり遂げられないこともあるまい。それなら、我々は下って、彼らの言葉を乱して やろう。彼らが互いに相手の言葉を理解できなくなるように」。 — 「創世記」11章1-9節
• サーバ、Webフロント、モバイルアプリで言語を統一 する ◦ ノウハウの共有ができる ◦ 担当外のコードも読みやすい ◦ フルスタック開発もできる 1.
動機(解決案)
• フルスタック開発ができる言語は2つ ◦ Javascript(Typescript込み) ◦ Dart • モバイルアプリ開発では、Javascript(ReactNative)よ りも、Dart(Flutter)の方が勢いがある 2.
なぜDartでサーバを実装するのか ※厳密にいえばGoなどでも全部開発できるが、この 2つの言語以外はロマンだと思う。
• サーバをDartで実装してみました ◦ サンプルコード ▪ https://github.com/KamikazeZirou/dart-ser ver-sample ◦ おなじみのTodoアプリ ▪
バックエンドのAPIのみ 3.サンプルの構成(概要)
3.サンプルの構成(アーキテクチャ) Repository MySQL Domain Model Service gRPC Handler API Client
Handler:APIのエントリポイント。データ形式の変換をして、 gRPCを隠蔽する。 Service:ビジネスロジックを担当。ロジックが単純すぎるので Repositoryのメソッド呼ぶだけ。 DomainModel:データとビジネスロジックを持つ。サンプルは単純すぎるので単なる構造体。 Repository:データのCRUD機能などを提供。データの保存方法を隠蔽する。 円の外から内の依存関係は良いが、逆は NG。 Dart Server
ライブラリ バージョン 備考 Flutter 1.26.0.17.6.pre beta channel, Dart 2.12。 grpc
3.0.0 このバージョンではDart 2.12以上が必要。 protoファイルからのコード生成は割愛。 公式の説明をお勧めします。 https://grpc.io/docs/languages/dart/ mysql1 0.17.1 MySQLドライバ。 riverpod 0.13.0-nullsafety.3 DIに使う。 3.サンプルの構成(利用ライブラリ) mysql1以外は、モバイルアプリ開発でも珍しくはない
3.サンプルの構成(開発環境) ツール 説明 Docker MySQLサーバとDartサーバを動かす用。 Dockerを使わなくてもサーバは起動できるが、実務ではコンテナとしてデプロイ することが多いので Dockerを使う。 protoc gRPCのAPIを定義するprotoファイルから各言語のコードを生成するツール。
protoc_plugin protoファイルからDartのクライントコードとサーバコードを生成するツール。 Dart のプラグイン。 Android Studio コードエディタ。サーバ独自の設定は不要。 もちろん、InteliJやVSCodeでもOK。
3.サンプルの構成(開発環境) service TodoService { rpc CreateTodo (CreateTodoRequest) returns (CreateTodoResponse) {}
} message Todo { int32 id = 1; string title = 2; string description = 3; } message CreateTodoRequest { // 作成するTodo Todo todo = 1; } message CreateTodoResponse { // 作成したTodo Todo todo = 1; } 補足:gRPCのコード生成 protoファイル Dart コード Go コード JS コード protocで 生成
4.サンプルのポイント解説(main) void main(List<String> arguments) async { final container = ProviderContainer();
var listener = container.listen(todoServiceHandlerProvider); // 1. serviceHandler の作成 final serviceHandler = await listener.read(); // 2. serviceHandler をgRPCのServerに登録 final server = Server( [serviceHandler], const <Interceptor>[], CodecRegistry(codecs: const [GzipCodec(), IdentityCodec()]), ); // 3. サーバ起動 await server.serve(port: 5001); ... }
4.サンプルのポイント解説(Handler) // 1. Handlerにはprotocが生成したAPIサーバ用の基底クラスを継承させる class TodoServiceHandler extends TodoServiceBase { //
2. APIに対応するメソッドがあるのでoverrideする @override Future<grpc.CreateTodoResponse> createTodo(ServiceCall call, grpc.CreateTodoRequest request) async { // 3. データをgRPC -> domain形式に変換 // 4. Serviceのメソッドを呼ぶ final newTodo = await _todoService.create(domain.Todo( title: request.todo.title, description: request.todo.description, )); // 5. Serviceの処理結果をgRPC形式に変換して返す return CreateTodoResponse( todo: grpc.Todo( id: newTodo.id, title: newTodo.title, description: newTodo.description, )); } } 形式変換をするのは、 Service がgRPCに依存しないようにす るため。
• Service ◦ サンプルではRepositoryのAPI呼ぶだけ • Repository ◦ モバイルアプリの時と同じように実装すればOK 4.サンプルのポイント解説(Service/Repository)
riverpodを使用。 Handler、Service、 Repositoryのオブジェクト のProviderを実装。 // MySQLConnection のプロバイダ final dbConnectionProvider =
Provider.autoDispose((ref) async { ... final connection = await MySqlConnection.connect(settings); ... return connection; }); // Repository のプロバイダ。 // ref.watch で依存オブジェクトを取得する。 // ここでは、MySQLConnection を取得している。 final todoRepositoryProvider = Provider.autoDispose((ref) => ref.watch(dbConnectionProvider).then((conn) => MySQLTodoRepository(conn))); final todoServiceProvider = Provider.autoDispose((ref) => ref .watch(todoRepositoryProvider) .then((repository) => TodoServiceImpl(repository))); final todoServiceHandlerProvider = Provider.autoDispose((ref) => ref .watch(todoServiceProvider) .then((service) => TodoServiceHandler(service))); 4.サンプルのポイント解説(DI)
マルチステージビルドを使う。 ビルド用と実行用でイメージを分け ることで、実行イメージのサイズを 抑える手法。 ビルドに使うDockerイメージのサイ ズは約250MBある。Dart SDKなど が含まれるため。 実行用のDockerイメージは、開発 用のツールが一切入っていないの
でサイズは約2.2MB。 (ビルドしたバイナリファイルのサイ ズは約8.7MB) 4.サンプルのポイント解説(Docker) # ランタイムなしで実行可能なサーバのバイナリファイルをビルドするイメージ FROM google/dart:2.12-beta as builder WORKDIR /app ADD pubspec.* /app/ RUN pub get ADD . /app RUN pub get --offline RUN dart compile exe bin/server.dart -o bin/server # ビルドしたバイナリを実行するイメージ FROM subfuzion/dart:slim WORKDIR /app COPY --from=builder /app/bin/server . CMD [] ENTRYPOINT ["./server"]
4.サンプルのポイント解説(docker-compose) • Docker単独よりもサーバの実行が簡単にできる ◦ サーバの起動時のコマンドがDockerコマンドよりも簡潔に なる ◦ コンテナ間の依存関係を設定できる ▪ DBのコンテナをDartサーバのコンテナより先に実行できる
4.サンプルのポイント解説(client) Future<void> main(List<String> args) async { // 1. gRPC接続チャンネルを作る final
channel = ClientChannel( 'localhost', port: 50051, options: ChannelOptions( credentials: ChannelCredentials.insecure(), codecRegistry: CodecRegistry(codecs: const [GzipCodec(), IdentityCodec()]), ), ); // 2. protoファイルから生成したClientのオブジェクトを作る final stub = TodoServiceClient(channel); // 3. gRPCのAPIを呼ぶ。 try { final response = await stub.createTodo( CreateTodoRequest( todo: Todo(title: 'title3', description: 'description3')), options: CallOptions(compression: const GzipCodec()), ); } catch (e) { ... } await channel.shutdown(); }
• 良かったこと ◦ アプリ開発とノウハウは共有できる ▪ riverpodは初めて使ったが、モバイルアプリ開発にも知見を転用でき る ◦ Dartの書き方をほぼ忘れていたが、Goよりは書きやすい ▪
並列処理が出てきたら、感想は変わりそう • 懸念 ◦ サーバ向けライブラリが充実していない ▪ 有力なORMが少ない • Web Framework Aqueductの一部としてならORMあるが・・・ ▪ AWSの公式SDKはなさそう・・・ 5.感想
• モバイルアプリ用のAPI Gatewayで採用する 6.実戦投入のはじめの一歩 BFFでは、API GatewayはAPIクライアント ごとの要件に沿って実装する。 開発の担当は、APIクライアント開発者が 良いらしい。クライアントの要件に詳しいの は、クライアントの開発者のため。
モバイルアプリ開発者が慣れている Dart をAPI Gatewayに採用すると、開発効率 は上がるはず。 ※今のANDPADにはAPI Gatewayなし
ANDPADでは、マイクロサービスを開発する メンバーを募集しています! こんな方におすすめです。 • アプリ開発以外もやってみたい • ユーザの業務を考えつつ開発をしたい • サービスの基盤を考えたい 最後に
番外 言語 MSにたとえると 補足 Kotlin ゲルググ Dart リック・ドムⅡ C# ドワッジ
Java ドム Go イフリート グフとドムの中間。 Rust グフ ゲームだと格闘が強い。使ったことはない。 C++ ザク C 旧ザク GCの壁