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
当配置遇到 Scala宏
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Lunfu Zhong
June 06, 2015
Programming
370
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
当配置遇到 Scala宏
一个 Internal DSL 的应用案例
Lunfu Zhong
June 06, 2015
More Decks by Lunfu Zhong
See All by Lunfu Zhong
spring-boot 在统一架构体系中的价值
zhongl
2
890
如何准备一场主题分享
zhongl
1
340
项目求生指南
zhongl
0
390
LEGO - let's build everything by scala
zhongl
1
300
Real-world Scala
zhongl
2
170
JVM运行时诊断工具 HouseMD
zhongl
0
510
Art of The Code
zhongl
1
270
Other Decks in Programming
See All in Programming
自動化したのに回らないテスト運用の壁ーAI時代の品質責任と生産性
mfunaki
0
120
Claude Code全社展開のためにやったことn選~プラグイン302個・コミッター271人を支えるために~
kenchan
4
1.3k
php-fpmのプロセスが枯渇した日-調査・対処・そして本当にやるべきだったこと-
shibuchaaaan
0
210
Detecting Compromised CI with eBPF and Cilium Tetragon
lizrice
0
130
アルゴリズムは何を圧縮しているのか ─ Haskell から育った「圧縮代数」というメンタルモデル
naoya
16
3.8k
為什麼你並不需要ViewModel / No, you don't need a ViewModel
lovee
1
480
Terraform標準の組織で AWS CDKをどう使うか
mu7889yoon
1
470
そこに3びきプロダクトがいるじゃろう——生成AI時代における“価値が届かない理由”の構造
kosuket
0
400
OpenSpecのproposalにbrainstormingを持たせてみた
tigertora7571
1
200
仕様駆動開発へのトライを機に チームに適合する手法を模索し続けている話
freee
PRO
0
390
VibeCodingからAgenticWorkflowへ
starfish719
0
190
「人を評価する AI」の設計と実装
ryoyanara
0
150
Featured
See All Featured
The Cult of Friendly URLs
andyhume
79
7k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
How Software Deployment tools have changed in the past 20 years
geshan
1
34k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
510
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
190
How to Ace a Technical Interview
jacobian
281
24k
My Coaching Mixtape
mlcsv
0
190
GitHub's CSS Performance
jonrohan
1033
470k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
290
Producing Creativity
orderedlist
PRO
348
40k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
210
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
Transcript
当配置遇到Scala宏 ⼜又⼀一个 Internal DSL 的应⽤用案例
关于我 Scala, Java, Big Data, Message Middleware
这些年我们⽤用过的配置 都有哪些?
.properties .yaml .conf .xml
相较⽽而⾔言...
醉⼈人的命名⻓长度 1 // application.properties 2 db1.jdbc.url = jdbc:mysql:10.0.0.1/demo 3 db1.jdbc.driver
= com.mysql.jdbc.Driver 4 db1.jdbc.username = jushi 5 db1.jdbc.password = ********
啰嗦的对称包围 1 <!-- logback.xml --> 2 <configuration scanscan="true" scanPeriod="3 seconds"
> 3 4 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 5 <encoder> 6 <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> 7 </encoder> 8 </appender> 9 10 <root level="INFO"> 11 <appender-ref ref="STDOUT" /> 12 </root> 13 </configuration>
优雅地近乎完美 1 #.travis.yml 2 language: scala 3 scala: 4 -
2.11.5 5 jdk: 6 - openjdk7 7 script: 8 - sbt ++$TRAVIS_SCALA_VERSION test 9 notifications: 10 email: 11 -
[email protected]
强⼤大到没有朋友 1 // kafka.conf 2 kafka { 3 server {
4 host = localhost 5 port = 9092 6 } 7 socket { 8 timeout = 5s 9 buffer = 64K 10 } 11 client = id 12 debug = false 13 delays = 2s 14 }
None
只是...
我 讨厌 G.E.T 1 // Consumer.scala 2 class Consumer extends
Actor { 3 @inline def conf = context.system.settings.config 4 5 val client = new SimpleConsumer( 6 conf.getString("kafka.server.host"), 7 conf.getInt("kafka.server.port"), 8 conf.getDuration("kafka.socket.timeout", SECOND), 9 conf.getLong("kafka.socket.buffer"), 10 conf.getString("kafka.client") 11 ) 12 13 ... 14 }
None
然后,我想到了宏
Method or Annotation
Method 1 def conf(key: String) = macro impl 2 3
def impl(c: Context)(key: c.Expr[String]) : c.Expr[Unit] = { 4 // TODO 5 } 6 7 8 val host = conf("kafka.server.host") 9 10 val host = conf.getString("kafka.server.host")
Method
Annotation 1 class conf extends StaticAnnotation { 2 def macroTransform(annottees:
Any*): Any = macro impl 3 4 private def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = { 5 import c.universe._ 6 7 annottees.map(_.tree) match { 8 case ClassDef(...) :: Nil => 9 // TODO 10 11 case _ => 12 c.abort(c.enclosingPosition, "Invalid annottee") 13 } 14 } 15 }
Annotation 1 @conf trait kafka { 2 val server =
new { 3 val host: String 4 } 5 } 6 7 trait kafka { 8 val server = new { 9 val host: String = conf.getString("kafka.server.host") 10 } 11 }
如果仅仅只是映射装载 就太 TYTSSN 了
由代码⽣生成配置 1 @conf trait kafka { 2 val server =
new { 3 val host = "wacai.com" 4 val port = 12306 5 } 6 7 val socket = new { 8 val timeout = 3 seconds 9 val buffer = 1024 * 64L 10 } 11 12 val client = "wacai" 13 } 1 kafka { 2 server { 3 host = wacai.com 4 port = 12306 5 } 6 7 socket { 8 timeout = 3s 9 buffer = 64K 10 } 11 12 client = wacai 13 }
之前提到的⼜又⼀一案例 1 import lego.dsl._ 2 3 new Server { 4
5 def name = "ping-pong" 6 7 tcp.bind(port = 12306) { 8 Codec() <=> Handle { 9 case Request(_, hs, _) => Response(200, hs) 10 } 11 } 12 }
参阅 github.com/wacai/config-annotation 使⽤用 Scala Macro Annotation 实现配置项绑定 ⾸首篇 续篇 终篇
What are macros good for ?
scala macro annotations real world example
[email protected]