<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lucas Fugisawa</title>
    <description>The latest articles on DEV Community by Lucas Fugisawa (@lucasfugisawa).</description>
    <link>https://dev.to/lucasfugisawa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F999579%2F42b11784-d360-44e7-8d9f-247ba730913e.png</url>
      <title>DEV Community: Lucas Fugisawa</title>
      <link>https://dev.to/lucasfugisawa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucasfugisawa"/>
    <language>en</language>
    <item>
      <title>Kotlin + gRPC: Tooling, CI/CD, and Architectural Practices</title>
      <dc:creator>Lucas Fugisawa</dc:creator>
      <pubDate>Wed, 07 May 2025 22:00:00 +0000</pubDate>
      <link>https://dev.to/lucasfugisawa/kotlin-grpc-tooling-cicd-and-architectural-practices-4a2k</link>
      <guid>https://dev.to/lucasfugisawa/kotlin-grpc-tooling-cicd-and-architectural-practices-4a2k</guid>
      <description>&lt;p&gt;In the previous articles of this series, we explored how to build idiomatic gRPC APIs with Kotlin from schema design using Protobuf to leveraging streams, coroutines, and Kotlin DSL builders. Now it's time to look beyond the application code.&lt;/p&gt;

&lt;p&gt;In this article, we'll have a sneak peek on what it takes to prepare your gRPC service for production. This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Observability and traceability&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security and authentication&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing tools and diagnostics&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best practices for repository structure&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD automation&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;And how this fits into a &lt;strong&gt;DDD-oriented architecture&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This fifth article is more of a bonus and a point of attention that you should focus on if you need to implement gRPC for a production environment. Each topic mentioned here is very broad, and it is up to you to delve into each of them as needed. Also, for this reason, I will not cover code changes for the content of this article specifically.&lt;/p&gt;

&lt;p&gt;Our focus is on &lt;strong&gt;scalability and maintainability&lt;/strong&gt;. Let's explore how to structure your environment so your gRPC APIs thrive in the real world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observability
&lt;/h2&gt;

&lt;p&gt;In REST APIs, it's common to use reverse proxies, access logs, or APM tools for insights. In the gRPC world, you need to be more intentional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interceptors
&lt;/h2&gt;

&lt;p&gt;Interceptors allow you to intercept gRPC calls and inject cross-cutting concerns like logging, metrics, or authentication. They work similarly to middleware in web frameworks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoggingInterceptor&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ServerInterceptor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReqT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RespT&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;interceptCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ServerCall&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReqT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RespT&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ServerCallHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReqT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RespT&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ServerCall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Listener&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReqT&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;method&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;methodDescriptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullMethodName&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[gRPC] Call to method: $method"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also hook into libraries like &lt;code&gt;micrometer&lt;/code&gt; to expose metrics (latency, counters, histograms) to your monitoring tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distributed tracing and OpenTelemetry
&lt;/h2&gt;

&lt;p&gt;With multiple services interacting via gRPC, tracing request flows is crucial. &lt;strong&gt;OpenTelemetry&lt;/strong&gt; is the open standard for collecting traces, metrics, and logs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tracer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GlobalOpenTelemetry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTracer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"note-service"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;span&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spanBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"createNote"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;startSpan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// request logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use OTLP exporters to send data to Jaeger, Zipkin, Grafana Tempo, NewRelic, DataDog etc. and visualize the full call path across services.&lt;/p&gt;

&lt;p&gt;If you don't have very complex tracing requirements, I recommend that you use the &lt;a href="https://opentelemetry.io/docs/zero-code/java/agent/" rel="noopener noreferrer"&gt;OpenTelemetry Java Agent&lt;/a&gt; instead of instrumenting through code. And if you need some tracing customization, you can use an &lt;a href="https://opentelemetry.io/docs/collector/" rel="noopener noreferrer"&gt;OpenTelemetry Collector&lt;/a&gt; to process the data before sending it to your monitoring tool. By avoiding instrumentation through code, you end up with a simpler, more scalable, and less intrusive solution to observe what's happening with your application.&lt;/p&gt;

&lt;h1&gt;
  
  
  Security: encryption and authentication
&lt;/h1&gt;

&lt;p&gt;By default, gRPC does not enforce TLS or authentication. You must explicitly configure it.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLS: encrypting transport
&lt;/h2&gt;

&lt;p&gt;gRPC uses HTTP/2 under the hood, which supports TLS natively. In production, you can use managed certificates (e.g., via ingress or cert-manager). For local development, you can configure it manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;creds&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TlsServerCredentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;certChain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;server&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Grpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newServerBuilderForPort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NoteServiceImpl&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Authentication: via metadata headers
&lt;/h2&gt;

&lt;p&gt;gRPC supports custom headers via &lt;code&gt;Metadata&lt;/code&gt;. The common pattern is to pass a token (e.g., JWT) through the &lt;code&gt;Authorization&lt;/code&gt; header.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthInterceptor&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ServerInterceptor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReqT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RespT&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;interceptCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.):&lt;/span&gt; &lt;span class="nc"&gt;ServerCall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Listener&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReqT&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ASCII_STRING_MARSHALLER&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="nf"&gt;validateToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UNAUTHENTICATED&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid token"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="err"&gt;: &lt;/span&gt;&lt;span class="nc"&gt;ServerCall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Listener&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReqT&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the interceptor, validate the token, extract claims, and inject user context for downstream logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repository Structure: where do &lt;code&gt;.proto&lt;/code&gt; files go?
&lt;/h2&gt;

&lt;p&gt;In systems with multiple services, &lt;code&gt;.proto&lt;/code&gt; file sharing becomes a real concern. You typically choose between two options:&lt;/p&gt;

&lt;h2&gt;
  
  
  Monorepo (app + proto together)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Everything in one place; simple for small teams.&lt;/li&gt;
&lt;li&gt;Easy co-evolution of contracts and services.&lt;/li&gt;
&lt;li&gt;Harder to share across languages or services.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dedicated proto repository
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Store &lt;code&gt;.proto&lt;/code&gt; files separately with versions and changelogs.&lt;/li&gt;
&lt;li&gt;Services import generated artifacts or raw definitions.&lt;/li&gt;
&lt;li&gt;Publish as binary artifacts (e.g., JAR, NPM package).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This second pattern usually promotes decoupling, better versioning, and clean reuse across the organization.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tools for testing gRPC APIs
&lt;/h1&gt;

&lt;p&gt;Testing gRPC locally doesn't have to be difficult. These tools make it straightforward:&lt;/p&gt;

&lt;h2&gt;
  
  
  grpcurl
&lt;/h2&gt;

&lt;p&gt;Think of it as &lt;code&gt;curl&lt;/code&gt; for gRPC. Make calls from the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grpcurl -plaintext -d '{"title":"Hello"}' localhost:50051 com.fugisawa.NoteService/CreateNote
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Postman
&lt;/h2&gt;

&lt;p&gt;Postman now supports gRPC. You can import your &lt;code&gt;.proto&lt;/code&gt; files or use server introspection, and test methods via a graphical interface.&lt;/p&gt;

&lt;h1&gt;
  
  
  CI/CD: artifact generation and compatibility guarantees
&lt;/h1&gt;

&lt;p&gt;You should automate the generation and publication of your Protobuf contracts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build + publish
&lt;/h2&gt;

&lt;p&gt;In your CI pipeline, generate and publish a reusable artifact:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew generateProto build publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This artifact can be published to Maven, GitHub Packages, or Artifactory and consumed by other services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compatibility checks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://buf.build/docs/breaking/overview/" rel="noopener noreferrer"&gt;buf&lt;/a&gt; is a powerful tool that checks for breaking changes in your &lt;code&gt;.proto&lt;/code&gt; definitions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;buf breaking --against ./previous-version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run this in CI to prevent merges that would break existing consumers.&lt;/p&gt;

&lt;h1&gt;
  
  
  Domain models and Protobuf: avoiding contract leakage
&lt;/h1&gt;

&lt;p&gt;The types generated by Protobuf (like &lt;code&gt;Note&lt;/code&gt;) are transport-level DTOs. They should &lt;strong&gt;not&lt;/strong&gt; be used as your domain model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate domain from transport
&lt;/h2&gt;

&lt;p&gt;Design rich domain types with business semantics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data class Note(val id: NoteId, val title: Title, val content: Content)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then map between transport and domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fun Note.toProto(): NoteProto = note {
    id = this@toProto.id.value
    title = this@toProto.title.value
    content = this@toProto.content.value
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps your domain clean, testable, decoupled and independent of gRPC or any other transport layer.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final thoughts
&lt;/h1&gt;

&lt;p&gt;In this article, we explored:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to add observability with interceptors and tracing.&lt;/li&gt;
&lt;li&gt;How to secure gRPC with TLS and token-based authentication.&lt;/li&gt;
&lt;li&gt;How to test APIs with &lt;code&gt;grpcurl&lt;/code&gt; and Postman.&lt;/li&gt;
&lt;li&gt;How to structure your repositories and CI/CD pipelines.&lt;/li&gt;
&lt;li&gt;How to keep your domain model decoupled from your transport layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These practices are essential for building resilient, maintainable, and scalable gRPC APIs in real-world environments.&lt;/p&gt;




&lt;p&gt;This is the last article in the Kotlin + gRPC series. If you want to talk and exchange experiences on this subject, contact me, and I will be happy to talk.&lt;/p&gt;

&lt;p&gt;To explore more about Kotlin-related topics, subscribe to my newsletter at  &lt;a href="https://fugisawa.com/" rel="noopener noreferrer"&gt;https://fugisawa.com/&lt;/a&gt;  and stay tuned for more insights and updates.&lt;/p&gt;

</description>
      <category>kotlinserverside</category>
      <category>kotlin</category>
      <category>backend</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Kotlin + gRPC: Streaming, Deadlines, and Structured Error Handling</title>
      <dc:creator>Lucas Fugisawa</dc:creator>
      <pubDate>Wed, 30 Apr 2025 22:00:00 +0000</pubDate>
      <link>https://dev.to/lucasfugisawa/kotlin-grpc-streaming-deadlines-and-structured-error-handling-5e9k</link>
      <guid>https://dev.to/lucasfugisawa/kotlin-grpc-streaming-deadlines-and-structured-error-handling-5e9k</guid>
      <description>&lt;p&gt;In the previous articles of this series, we built a solid foundation: from setting up a gRPC service in Kotlin, to mastering schema design, and writing idiomatic, expressive code with Protobuf and Kotlin DSLs.&lt;/p&gt;

&lt;p&gt;Now, we're ready to go beyond the basics into features that power real-time, reactive, and resilient APIs.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How &lt;strong&gt;gRPC streaming&lt;/strong&gt; works, and how to use &lt;strong&gt;Kotlin coroutines and Flow&lt;/strong&gt; idiomatically.&lt;/li&gt;
&lt;li&gt;How to handle &lt;strong&gt;deadlines and cancellations&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;How to return and interpret &lt;strong&gt;structured errors&lt;/strong&gt; using gRPC status codes and custom metadata.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These features are essential when building robust and production-grade services.&lt;/p&gt;

&lt;h1&gt;
  
  
  When request/response isn't enough
&lt;/h1&gt;

&lt;p&gt;Until now, our gRPC calls have all followed a &lt;strong&gt;unary&lt;/strong&gt; pattern, where the client sends a single request and the server replies with a single response.&lt;/p&gt;

&lt;p&gt;But gRPC supports more than that. With &lt;strong&gt;streaming&lt;/strong&gt;, you can build APIs that push data continuously, handle long-lived connections, or send multiple requests and responses within a single call.&lt;/p&gt;

&lt;p&gt;There are three types of gRPC streaming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server streaming&lt;/strong&gt;: the client sends one request and receives a stream of responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client streaming&lt;/strong&gt;: the client sends a stream of requests and gets a single response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bidirectional streaming&lt;/strong&gt;: both client and server send streams of messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see how each one works in practice using &lt;strong&gt;Kotlin's &lt;code&gt;Flow&lt;/code&gt;&lt;/strong&gt; and coroutines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server Streaming: one request, many responses
&lt;/h2&gt;

&lt;p&gt;Imagine we want to support &lt;strong&gt;live updates&lt;/strong&gt;: the client subscribes to notes with a certain tag, and the server streams back matching notes as they're created.&lt;/p&gt;

&lt;p&gt;First, let's update our &lt;code&gt;.proto&lt;/code&gt; file and add that new RPC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;NoteService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;StreamNotesByTag&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NoteTagFilter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="n"&gt;Note&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;NoteTagFilter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember that when you update the Protobuf definitions, you also need to regenerate the Kotlin code by running the &lt;code&gt;generateProto&lt;/code&gt; Gradle task, or the &lt;code&gt;protoc&lt;/code&gt; command we saw in the first article of this series.&lt;/p&gt;

&lt;p&gt;In Kotlin, this generates a suspending &lt;code&gt;Flow&lt;/code&gt;-based method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;streamNotesByTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;NoteTagFilter&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Note&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Example: mock stream of notes tagged with 'kotlin'  &lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;notes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Note 1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"kotlin"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Note 2"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"kotlin"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; 
        &lt;span class="n"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// simulate async delivery &lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The client can collect the stream:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tagFilter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;noteTagFilter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"kotlin"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;responseFlow&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;streamNotesByTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tagFilter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;responseFlow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received note: ${note.title}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a powerful pattern for pushing real-time updates to clients, and thanks to Kotlin &lt;code&gt;Flow&lt;/code&gt;, it integrates naturally with your coroutine pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Client Streaming: multiple requests, one response
&lt;/h2&gt;

&lt;p&gt;Let's say a client wants to &lt;strong&gt;send a batch of notes&lt;/strong&gt; in a single stream, and the server replies with a summary (e.g., how many were saved).&lt;/p&gt;

&lt;p&gt;Let's add the &lt;code&gt;.proto&lt;/code&gt; definitions for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;NoteService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;CreateNotes&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="n"&gt;Note&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NoteBatchSummary&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;NoteBatchSummary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int32&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server receives a &lt;code&gt;Flow&amp;lt;Note&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;suspend&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createNotes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Note&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;):&lt;/span&gt; &lt;span class="nc"&gt;NoteBatchSummary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; 
    &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Saving note: ${note.title}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;++&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;noteBatchSummary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And on the client side, you can send a stream using &lt;code&gt;flow { ... }&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;notesFlow&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Streamed Note 1"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Streamed Note 2"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;summary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createNotes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notesFlow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server stored ${summary.count} notes"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is great for bulk uploads or scenarios where messages arrive incrementally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bidirectional Streaming: send and receive concurrently
&lt;/h2&gt;

&lt;p&gt;Bidirectional streaming gives you full duplex communication, which is perfect for chat apps, collaborative editing, or real-time sync.&lt;/p&gt;

&lt;p&gt;Let's suppose we want a functionality to share notes in real time with other users in the same group.&lt;/p&gt;

&lt;p&gt;We'll start by defining the Protobufs for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;NoteService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;NoteCollab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="n"&gt;Note&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="n"&gt;Note&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can use that new definition to implement the logic. To keep this simple, we won't implement a complete logic for collaborative group notes. Instead, we'll implement this RPC to simply echo back each note received.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;
&lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;noteCollab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Note&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;):&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Note&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;receivedNote&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received from ${receivedNote.title}: ${receivedNote.content}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"From server: ${receivedNote.title}"&lt;/span&gt;
                &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"${receivedNote.content}"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And on the client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;noteFlow&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Note 1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Content 1"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Note 2"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Content 2"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;responses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;noteCollab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;noteFlow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received: ${note.title} - ${note.content}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each side can send and receive notes independently, and all backed by non-blocking, coroutine-friendly flows.&lt;/p&gt;

&lt;h1&gt;
  
  
  Deadlines and cancellations
&lt;/h1&gt;

&lt;p&gt;Every gRPC call can be bounded by a &lt;strong&gt;deadline&lt;/strong&gt; — a time limit for how long the client is willing to wait.&lt;/p&gt;

&lt;p&gt;In Kotlin, deadlines are passed using &lt;strong&gt;call options&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;stubWithDeadline&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withDeadlineAfter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;TimeUnit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SECONDS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;note&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stubWithDeadline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createNote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;createNoteRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Timeout?"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;StatusRuntimeException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DEADLINE_EXCEEDED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Request timed out!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the server side, when the deadline is exceeded or the client cancels, &lt;code&gt;collect&lt;/code&gt; or &lt;code&gt;emit&lt;/code&gt; will throw a cancellation exception.&lt;/p&gt;

&lt;p&gt;To handle this cleanly, we just need to catch potential &lt;code&gt;CancellationException&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;streamNotesByTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;NoteTagFilter&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Note&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;generateNote&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CancellationException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Client cancelled the stream"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it easier to free up resources when clients disconnect.&lt;/p&gt;

&lt;h1&gt;
  
  
  Structured error handling
&lt;/h1&gt;

&lt;p&gt;By default, when something goes wrong in gRPC, you'll get a &lt;code&gt;StatusRuntimeException&lt;/code&gt; with a gRPC status code. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NOT_FOUND&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Note not found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asRuntimeException&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The client can catch it and inspect the code and message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getNoteById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getNoteRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"missing"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;StatusRuntimeException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: ${e.status.code} - ${e.status.description}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But for production systems, you'll often want &lt;strong&gt;structured error responses&lt;/strong&gt;, with application-level codes, details, or even localized messages. To achieve this, use &lt;strong&gt;gRPC error metadata&lt;/strong&gt; with &lt;code&gt;StatusProto&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, let's define an error details message in &lt;code&gt;.proto&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"google/rpc/status.proto"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"google/rpc/error_details.proto"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, then, build structured errors on the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;errorDetail&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ErrorInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setReason&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NOT_FOUND"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setDomain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"noteservice.fugisawa.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;statusProto&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NOT_FOUND_VALUE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Note not found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errorDetail&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;StatusProto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toStatusRuntimeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statusProto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally extract it on the client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StatusProto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromThrowable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;errorInfo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;detailsList&lt;/span&gt;
    &lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;mapNotNull&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unpack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ErrorInfo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;firstOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Reason: ${errorInfo?.reason}, Domain: ${errorInfo?.domain}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Machine-readable error codes.&lt;/li&gt;
&lt;li&gt;Human-readable messages.&lt;/li&gt;
&lt;li&gt;Extensibility with metadata.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Implementation summary: what changed from the previous article?
&lt;/h1&gt;

&lt;p&gt;As in the previous articles, all code is available in individual branches of the &lt;a href="https://github.com/lucasfugisawa/note-service-kotlin-gprc" rel="noopener noreferrer"&gt;note-service-kotlin-gprc&lt;/a&gt; repository. For this article, you can check the &lt;a href="https://github.com/lucasfugisawa/note-service-kotlin-gprc/tree/article4-streaming" rel="noopener noreferrer"&gt;&lt;code&gt;article4-streaming&lt;/code&gt;&lt;/a&gt; branch. &lt;em&gt;The error handling code is not yet available in the provided source code, and should be added soon.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here's a quick summary of what's new:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Protobuf schema&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Added &lt;code&gt;StreamNotesByTag&lt;/code&gt;, &lt;code&gt;CreateNotes&lt;/code&gt;, and &lt;code&gt;NoteCollab&lt;/code&gt; RPCs for server, client, and bidirectional streaming.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Server implementation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Implemented all three streaming methods using Kotlin &lt;code&gt;Flow&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Client implementation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Demonstrated how to collect streams using &lt;code&gt;Flow&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Final thoughts
&lt;/h1&gt;

&lt;p&gt;In this article, we explored:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How gRPC streaming works and how to use it idiomatically with Kotlin coroutines.&lt;/li&gt;
&lt;li&gt;How to build real-time and interactive APIs using server, client, and bidirectional streaming.&lt;/li&gt;
&lt;li&gt;How to use deadlines and cancellation to build responsive and efficient services.&lt;/li&gt;
&lt;li&gt;How to model structured, expressive error responses that go beyond raw status codes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools give you the building blocks to write modern, responsive, and production-ready gRPC services in Kotlin.&lt;/p&gt;




&lt;p&gt;To explore more about Kotlin-related topics, subscribe to my newsletter at  &lt;a href="https://fugisawa.com/" rel="noopener noreferrer"&gt;https://fugisawa.com/&lt;/a&gt;  and stay tuned for more insights and updates.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>kotlinserverside</category>
      <category>backend</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Kotlin + gRPC: Nesting, Composition, Validations, and Idiomatic Builder DSL</title>
      <dc:creator>Lucas Fugisawa</dc:creator>
      <pubDate>Wed, 23 Apr 2025 00:47:03 +0000</pubDate>
      <link>https://dev.to/lucasfugisawa/kotlin-grpc-nesting-composition-validations-and-idiomatic-builder-dsl-cap</link>
      <guid>https://dev.to/lucasfugisawa/kotlin-grpc-nesting-composition-validations-and-idiomatic-builder-dsl-cap</guid>
      <description>&lt;p&gt;In the first two articles of this series, we built our first gRPC service in Kotlin and explored the essentials of Protobuf schema design from optional and repeated fields to enums, oneof, maps, and how to evolve your schema safely.&lt;/p&gt;

&lt;p&gt;In this article, we'll level up again and explore how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compose more &lt;strong&gt;expressive data models&lt;/strong&gt; using &lt;strong&gt;nested messages&lt;/strong&gt; and &lt;strong&gt;message composition&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Write &lt;strong&gt;idiomatic Kotlin code&lt;/strong&gt; using the Protobuf-generated &lt;strong&gt;DSL builders&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Understand what types of &lt;strong&gt;validations&lt;/strong&gt; belong in your schema, and which should be handled at the application level.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get into it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Designing composite schemas
&lt;/h1&gt;

&lt;p&gt;As your service grows, you'll likely need to model increasingly complex data structures. Instead of dumping all fields into a single message, Protobuf encourages a &lt;strong&gt;compositional approach&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's say we want to enrich our &lt;code&gt;Note&lt;/code&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;author&lt;/strong&gt; (id, name, email),&lt;/li&gt;
&lt;li&gt;And &lt;strong&gt;timestamps&lt;/strong&gt; (created/updated).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a great chance to encapsulate those concerns into separate messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Author&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Timestamps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;created_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;updated_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;optional&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;repeated&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="na"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;NoteStatus&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Author&lt;/span&gt; &lt;span class="na"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Timestamps&lt;/span&gt; &lt;span class="na"&gt;timestamps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This brings several benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better &lt;strong&gt;modularity&lt;/strong&gt;: you can reuse &lt;code&gt;Author&lt;/code&gt; or &lt;code&gt;Timestamps&lt;/code&gt; elsewhere.&lt;/li&gt;
&lt;li&gt;Clearer &lt;strong&gt;separation of concerns&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Cleaner and more readable &lt;code&gt;.proto&lt;/code&gt; files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From a Kotlin perspective, this also maps nicely into structured types that you can build and test independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nesting messages (inline or not)
&lt;/h2&gt;

&lt;p&gt;Sometimes, if a message is only used inside a parent, it can be convenient to nest it directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Attachment&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;oneof&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Attachment&lt;/span&gt; &lt;span class="na"&gt;attachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps your schema scoped and avoids polluting the top-level namespace with types that are internal to &lt;code&gt;Note&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Kotlin, the generated class will be accessible as &lt;code&gt;Note.Attachment&lt;/code&gt;, fully usable and composable like any other message.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing idiomatic Kotlin with the builder DSL
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;protobuf-kotlin&lt;/code&gt; library generates &lt;strong&gt;Kotlin-style DSL builders&lt;/strong&gt; for your messages. We've used these before, but now we'll dive into &lt;strong&gt;more advanced and idiomatic usage patterns&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can compose nested messages with the gRPC builders DSL in a very concise and expressive way. Take a look at this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;note&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"My composed note"&lt;/span&gt; 
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"This note uses nested messages and DSL composition"&lt;/span&gt; 
    &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;author&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"user-123"&lt;/span&gt; 
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Lucas Fugisawa"&lt;/span&gt; 
        &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"lucas@fugisawa.com"&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;timestamps&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;timestamps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;createdAt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;updatedAt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;note&lt;/code&gt; is composed using a natural composition language enabled by the gRPC builders Kotlin DSLs.&lt;/p&gt;

&lt;p&gt;This is clean, readable, and can leverage Kotlin's scope functions (&lt;code&gt;apply&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt;, &lt;code&gt;run&lt;/code&gt;) to make your code more concise and expressive. For example, let's say some fields should only be set when they're available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;maybeContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetchContent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;note&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Conditional note"&lt;/span&gt; 
    &lt;span class="n"&gt;maybeContent&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;includeTags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"grpc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"kotlin"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; 

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;metadataMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;putAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeated and map fields in Protobuf are always initialized (empty by default), and Kotlin gives you a nice collection interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"protos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"modeling"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;metadataMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"imported"&lt;/span&gt; 
    &lt;span class="n"&gt;metadataMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"high"&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also clear them when needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;clearTags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;clearMetadataMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, these APIs are idiomatic and safe, and you never need to worry about &lt;code&gt;null&lt;/code&gt; collections.&lt;/p&gt;

&lt;h1&gt;
  
  
  Validation: should I validate on schema or application?
&lt;/h1&gt;

&lt;p&gt;A recurring design question is: &lt;em&gt;what types of validation should live in the Protobuf schema, and which ones should be handled in the application code?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The answer is about separating &lt;strong&gt;structural&lt;/strong&gt; vs. &lt;strong&gt;business&lt;/strong&gt; validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Schema-level validation: enforce structure
&lt;/h2&gt;

&lt;p&gt;When we want to enforce structure, we handle validations by the schema itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is a field required or optional? → use &lt;code&gt;optional&lt;/code&gt;, &lt;code&gt;oneof&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;Should only one of multiple fields be set? → use &lt;code&gt;oneof&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Should a field be a list? → use &lt;code&gt;repeated&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Is the value restricted to a fixed set? → use &lt;code&gt;enum&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are enforced during Protobuf message parsing and ensure that the wire format is well-formed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;optional&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;oneof&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;folder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures structural correctness before your business logic even runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  ❗ Application-level validation: enforce business rules
&lt;/h2&gt;

&lt;p&gt;These rules depend on your domain logic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Title must be at least 5 characters.&lt;/li&gt;
&lt;li&gt;Author email must be valid.&lt;/li&gt;
&lt;li&gt;Updated timestamp must not precede created timestamp.&lt;/li&gt;
&lt;li&gt;Content length must not exceed 500 words.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These should be handled in your server (and possibly client) code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Title must be at least 5 characters"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;updatedAt&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"updatedAt cannot be before createdAt"&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you try to push business rules into the Protobuf schema, you'll quickly hit limitations and possibly hurt your API's flexibility.&lt;/p&gt;

&lt;h1&gt;
  
  
  Implementation summary: what changed from the previous article?
&lt;/h1&gt;

&lt;p&gt;As I mentioned in the previous article, the source code for the scope of each article will be made available in individual branches at the  &lt;a href="https://github.com/lucasfugisawa/note-service-kotlin-gprc" rel="noopener noreferrer"&gt;note-service-kotlin-gprc&lt;/a&gt;  repository, while  &lt;code&gt;HEAD&lt;/code&gt;  on the  &lt;code&gt;main&lt;/code&gt;  branch will accommodate the latest working version.&lt;/p&gt;

&lt;p&gt;In the article, I highlighted only parts of the code that were relevant to understanding the concepts. So, here is a summary of what changed in the code, which can be checked in detail in the &lt;a href="https://github.com/lucasfugisawa/note-service-kotlin-gprc/tree/article3-composition-validation" rel="noopener noreferrer"&gt;article3-composition-validation&lt;/a&gt; repository branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Protobuf implementation:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Added &lt;code&gt;Author&lt;/code&gt; and &lt;code&gt;Timestamps&lt;/code&gt; message types.&lt;/li&gt;
&lt;li&gt;Included &lt;code&gt;author&lt;/code&gt; and &lt;code&gt;timestamps&lt;/code&gt; fields inside &lt;code&gt;Note&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Moved &lt;code&gt;Attachment&lt;/code&gt; inside &lt;code&gt;Note&lt;/code&gt; as a nested message using &lt;code&gt;oneof&lt;/code&gt; for mutually exclusive fields (&lt;code&gt;url&lt;/code&gt; vs &lt;code&gt;file_path&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Updated &lt;code&gt;CreateNoteRequest&lt;/code&gt; to allow clients to pass an &lt;code&gt;Author&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ✅ Server-side logic:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Dynamically sets &lt;code&gt;timestamps&lt;/code&gt; on note creation using &lt;code&gt;Clock.System.now()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Calculates and includes word count in &lt;code&gt;metadataDetails&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Composes the full &lt;code&gt;Note&lt;/code&gt; using nested builders (&lt;code&gt;author { ... }&lt;/code&gt;, &lt;code&gt;timestamps { ... }&lt;/code&gt;) idiomatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ✅ Client-side logic:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Demonstrates how to build nested structures using Kotlin's builder DSL (&lt;code&gt;createNoteRequest { ... }&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Uses conditional composition (&lt;code&gt;tags +=&lt;/code&gt;, &lt;code&gt;metadata["key"] = value&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;Prints nested fields clearly: timestamps, author info, oneof handling for attachments.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Final thoughts
&lt;/h1&gt;

&lt;p&gt;In this article, we covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to build richer and more structured Protobuf schemas with composition and nesting.&lt;/li&gt;
&lt;li&gt;How to write idiomatic Kotlin using the DSL builders generated by &lt;code&gt;protobuf-kotlin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;How to compose messages conditionally and fluently.&lt;/li&gt;
&lt;li&gt;When to validate at the schema level, and when to leave it to your app logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are foundational skills for writing maintainable, expressive, and production-ready gRPC services.&lt;/p&gt;

&lt;p&gt;Next up, we'll explore a new dimension: &lt;strong&gt;gRPC Streaming in Kotlin&lt;/strong&gt;, including how to build reactive APIs with &lt;strong&gt;coroutines&lt;/strong&gt; and &lt;strong&gt;Flows&lt;/strong&gt; — perfect for real-time updates and sync.&lt;/p&gt;




&lt;p&gt;To explore more about Kotlin-related topics, subscribe to my newsletter at  &lt;a href="https://fugisawa.com/" rel="noopener noreferrer"&gt;https://fugisawa.com/&lt;/a&gt;  and stay tuned for more insights and updates.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>kotlinserverside</category>
      <category>backend</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Kotlin + gRPC: Enhance Protobuf schema design with Optional, Repeated, Maps, Enums, Oneof and backwards compatibility</title>
      <dc:creator>Lucas Fugisawa</dc:creator>
      <pubDate>Wed, 16 Apr 2025 12:03:13 +0000</pubDate>
      <link>https://dev.to/lucasfugisawa/kotlin-grpc-enhance-protobuf-schema-design-with-optional-repeated-maps-enums-oneof-and-30kd</link>
      <guid>https://dev.to/lucasfugisawa/kotlin-grpc-enhance-protobuf-schema-design-with-optional-repeated-maps-enums-oneof-and-30kd</guid>
      <description>&lt;p&gt;In the previous (first) article of this series, we introduced gRPC and Protocol Buffers by building a minimal Kotlin gRPC service: a simple NoteService that allowed creating and retrieving notes.&lt;/p&gt;

&lt;p&gt;Now that we've covered the fundamentals and the codebase setup, it's time to dig a bit deeper into the backbone of any gRPC application: your schema.&lt;/p&gt;

&lt;p&gt;Protobuf is a schema-first system. Every API you design begins with a &lt;code&gt;.proto&lt;/code&gt; file, and that file &lt;em&gt;is&lt;/em&gt; your contract. The way you design your fields (how you think about presence, defaults, repetition, optionality, maps, enums, and even deletions) will determine how flexible and resilient your API is as it evolves. &lt;em&gt;Other more architecture-level aspects (such as security, decoupling the domain model from the transport model, etc.) also affect your gRPC API resilience. However, we'll look at these later.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This article focuses on the essential building blocks of schema design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding field presence and default values.&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;optional&lt;/code&gt;, &lt;code&gt;repeated&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;enum&lt;/code&gt;, and &lt;code&gt;oneof&lt;/code&gt; effectively.&lt;/li&gt;
&lt;li&gt;Applying best practices for evolving your Protobuf definitions without breaking clients.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Along the way, we'll evolve our NoteService use case with new requirements, applying these concepts in a real-world context.&lt;/p&gt;

&lt;h1&gt;
  
  
  Evolving our use case: Notes with metadata and updates
&lt;/h1&gt;

&lt;p&gt;In the previous article, a note had only a &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt;, and a unique &lt;code&gt;id&lt;/code&gt; assigned on creation. That was fine as a starting point, but real-world applications rarely stay that simple.&lt;/p&gt;

&lt;p&gt;Let's say our team now needs the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notes should support optional &lt;strong&gt;tags&lt;/strong&gt;, stored as a list.&lt;/li&gt;
&lt;li&gt;Users should be able to attach &lt;strong&gt;custom metadata&lt;/strong&gt; (like a map of key/value labels).&lt;/li&gt;
&lt;li&gt;A note can optionally be marked as &lt;strong&gt;archived&lt;/strong&gt;, and later we may add more status values.&lt;/li&gt;
&lt;li&gt;We want to support &lt;strong&gt;partial updates&lt;/strong&gt;, where clients can update only specific fields.&lt;/li&gt;
&lt;li&gt;Notes may support &lt;strong&gt;multiple attachment types&lt;/strong&gt;, but only one per note.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't just scope creep. It's a chance to apply schema design best practices and show how to evolve your API safely and clearly.&lt;/p&gt;

&lt;h1&gt;
  
  
  Understanding field presence and default values
&lt;/h1&gt;

&lt;p&gt;One of the developers' first challenges when using Protobuf is grasping how it handles missing vs. default values.&lt;/p&gt;

&lt;p&gt;In Protobuf, every field has a default value based on its type. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;int32&lt;/code&gt; defaults to &lt;code&gt;0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;string&lt;/code&gt; defaults to &lt;code&gt;""&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bool&lt;/code&gt; defaults to &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But here's the tricky part: &lt;strong&gt;unless you explicitly tell Protobuf to track field presence, you cannot distinguish between "unset" and "default"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine this field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a client omits this field entirely when calling a RPC, and another client sends an empty string (&lt;code&gt;""&lt;/code&gt;), you won't be able to tell them apart. This matters in scenarios like PATCH operations, where &lt;em&gt;"clear the content"&lt;/em&gt; (or change it to zero) and &lt;em&gt;"leave it untouched"&lt;/em&gt; are very different instructions. To fix this, we have a few tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;optional&lt;/code&gt; in proto3 (since v3.15) to enable presence tracking
&lt;/h2&gt;

&lt;p&gt;As of version 3.15, proto3 reintroduces the &lt;code&gt;optional&lt;/code&gt; keyword to track whether a &lt;a href="https://squidfunk.github.io/protobluff/guide/scalar-types/" rel="noopener noreferrer"&gt;scalar&lt;/a&gt; (i.e., numbers, enums and strings) field was explicitly set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;optional&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enables Kotlin code like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasContent&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="c1"&gt;// Client explicitly set the field  val content = note.content&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="c1"&gt;// Field was not set &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is particularly useful for implementing update operations where presence matters. For instance, distinguishing between &lt;em&gt;"remove the content"&lt;/em&gt; (or change it to zero) and &lt;em&gt;"leave it unchanged"&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using wrapper types to enable presence tracking for scalars
&lt;/h2&gt;

&lt;p&gt;Protobuf &amp;lt; 3.15 doesn't support presence tracking on primitive fields (like &lt;code&gt;int32&lt;/code&gt;, &lt;code&gt;bool&lt;/code&gt;, etc.) by default. To track presence for those, you can use &lt;strong&gt;Google's wrapper types&lt;/strong&gt;, which wrap a primitive inside a message.&lt;/p&gt;

&lt;p&gt;Here's how you define them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"google/protobuf/wrappers.proto"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;NoteMetadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;google.protobuf.Int32Value&lt;/span&gt; &lt;span class="na"&gt;word_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This introduces a layer of indirection: the &lt;code&gt;word_count&lt;/code&gt; is now a message with a single field, &lt;code&gt;value&lt;/code&gt;. But this indirection lets you test for presence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasWordCount&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wordCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can do this for all scalar types: &lt;code&gt;StringValue&lt;/code&gt;, &lt;code&gt;Int32Value&lt;/code&gt;, &lt;code&gt;BoolValue&lt;/code&gt;, and so on.&lt;/p&gt;

&lt;p&gt;Because optional was reintroduced to Protobuf 3.15+, wrappers are generally obsolete, and you shouldn't need them unless you're using messages that already use them. It's a good idea to check the &lt;a href="https://protobuf.dev/best-practices/" rel="noopener noreferrer"&gt;Proto Best Practices&lt;/a&gt; when designing Protobuf APIs.&lt;/p&gt;

&lt;h1&gt;
  
  
  Repeated fields: modeling lists
&lt;/h1&gt;

&lt;p&gt;Let's say we want to support tags for a note. This is a perfect use case for &lt;code&gt;repeated&lt;/code&gt; fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;repeated&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeated fields always default to empty lists. On the Kotlin side, you'll work with them as immutable lists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tagsList&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use the Kotlin builder DSL to set them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;note&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"kotlin"&lt;/span&gt; 
    &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"grpc"&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeated fields are safe to evolve, so you can add them any time without breaking clients.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using &lt;code&gt;map&lt;/code&gt; for representing arbitrary key-value metadata
&lt;/h1&gt;

&lt;p&gt;Let's say we want to support storing user-defined metadata on a note. Think of labels like &lt;code&gt;"project" -&amp;gt; "gRPC"&lt;/code&gt; or &lt;code&gt;"priority" -&amp;gt; "high"&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="na"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This defines a map field that becomes a &lt;code&gt;Map&amp;lt;String, String&amp;gt;&lt;/code&gt; in Kotlin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadataMap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood, a &lt;code&gt;map&lt;/code&gt; is just a &lt;code&gt;repeated&lt;/code&gt; field of key/value pairs, but Protobuf provides syntactic sugar for it.&lt;/p&gt;

&lt;p&gt;Some caveats you should consider when using maps are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Map keys must be scalars (string, int, etc.).&lt;/li&gt;
&lt;li&gt;You can't track presence of individual keys — you either have the key or you don't.&lt;/li&gt;
&lt;li&gt;Map order is not guaranteed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Modeling finite sets with &lt;code&gt;enum&lt;/code&gt;:
&lt;/h1&gt;

&lt;p&gt;Let's model a note's status. We might want to distinguish between active and archived notes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;NoteStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;UNKNOWN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="na"&gt;ACTIVE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="na"&gt;ARCHIVED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;NoteStatus&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two rules here are crucial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always define &lt;code&gt;0&lt;/code&gt; as a meaningful default, usually &lt;code&gt;UNKNOWN&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Avoid changing enum numeric values, since clients may have them hardcoded.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Kotlin, Protobuf generates an enum with a fallback for unrecognized values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;NoteStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ACTIVE&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nc"&gt;NoteStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ARCHIVED&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nc"&gt;NoteStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UNRECOGNIZED&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is critical for &lt;strong&gt;forward compatibility&lt;/strong&gt;: if a newer server adds a new status (&lt;code&gt;DELETED = 3&lt;/code&gt;), older clients won't crash — they'll get &lt;code&gt;UNRECOGNIZED&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Handling mutually exclusive fields with &lt;code&gt;oneof&lt;/code&gt;:
&lt;/h1&gt;

&lt;p&gt;Let's say users can attach either a file or a URL to a note, but never both.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Attachment&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;oneof&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enforces exclusivity: only one of the fields can be set at a time.&lt;/p&gt;

&lt;p&gt;Kotlin gives you a &lt;code&gt;.sourceCase&lt;/code&gt; field to inspect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sourceCase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Attachment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SourceCase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FILE_PATH&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nc"&gt;Attachment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SourceCase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;URL&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nc"&gt;Attachment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SourceCase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SOURCE_NOT_SET&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a powerful modeling tool when you want a field to be &lt;em&gt;either-or&lt;/em&gt;, such as &lt;em&gt;“use X or use Y, but not both”&lt;/em&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Safe schema evolution
&lt;/h1&gt;

&lt;p&gt;As your service evolves, you'll need to change your schema, but not all changes are safe. Protobuf allows some flexibility, but you must follow a few rules to avoid breaking existing clients or corrupting data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safe changes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Adding new fields (with new tags)&lt;/strong&gt;: This is safe and common. Clients that don't know the new field simply ignore it. Just be sure to use a unique tag that hasn't been used before.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Adding new enum values (with new tags)&lt;/strong&gt;: This is also safe. Clients that don't recognize the new value will treat it as &lt;code&gt;UNRECOGNIZED&lt;/code&gt;, allowing fallback handling.&lt;/li&gt;
&lt;li&gt;⚠️ &lt;strong&gt;Changing field names&lt;/strong&gt;: The name of the field doesn't affect the wire format. Only the tag matters. However, generated code will change, which may break client code unless they recompile. Safe for the protocol, but not always for your code.&lt;/li&gt;
&lt;li&gt;⚠️ &lt;strong&gt;Changing default behavior&lt;/strong&gt;: While proto3 does not support custom default values in &lt;code&gt;.proto&lt;/code&gt; files, you can change how your app behaves when a field is unset. This is safe as long as you don't rely on transmitted defaults.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Breaking changes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🚫 &lt;strong&gt;Removing fields&lt;/strong&gt;: Old clients may still send these fields. If the tag is not handled properly, the data may be dropped or misinterpreted. Always &lt;strong&gt;&lt;a href="https://protobuf.dev/programming-guides/proto3/#reserved" rel="noopener noreferrer"&gt;reserve&lt;/a&gt;&lt;/strong&gt; the tag and field name to avoid future reuse.&lt;/li&gt;
&lt;li&gt;🚫 &lt;strong&gt;Changing field tags&lt;/strong&gt;: Tags define the wire format. Changing a tag effectively creates a new field, breaking compatibility with all existing clients and servers.&lt;/li&gt;
&lt;li&gt;🚫 &lt;strong&gt;Changing field types&lt;/strong&gt;: Even similar types like &lt;code&gt;int32&lt;/code&gt; to &lt;code&gt;int64&lt;/code&gt; are encoded differently and may not deserialize correctly. Never change a field type without also changing its tag.&lt;/li&gt;
&lt;li&gt;🚫 &lt;strong&gt;Reusing tag numbers&lt;/strong&gt;: A reused tag can be misinterpreted as an old field. This is dangerous and can silently corrupt data. Always mark removed tags as &lt;code&gt;reserved&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When breaking changes are truly necessary, consider versioning your messages (e.g., &lt;code&gt;NoteV2&lt;/code&gt;) and methods (&lt;code&gt;CreateNoteV2&lt;/code&gt;) to introduce changes without affecting existing consumers.&lt;/p&gt;

&lt;h1&gt;
  
  
  Type Mapping Reference
&lt;/h1&gt;

&lt;p&gt;Here is a quick summary of how Protobuf types map to Kotlin:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Protobuf Type&lt;/th&gt;
&lt;th&gt;Kotlin Type&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;String&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Defaults to &lt;code&gt;""&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;int32&lt;/code&gt;, &lt;code&gt;int64&lt;/code&gt;, &lt;code&gt;uint32&lt;/code&gt;...&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Int&lt;/code&gt;, &lt;code&gt;Long&lt;/code&gt;, &lt;code&gt;UInt&lt;/code&gt;, etc.&lt;/td&gt;
&lt;td&gt;Defaults to 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Defaults to false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;optional string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;String&lt;/code&gt; + &lt;code&gt;.hasField()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Presence tracked explicitly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;google.protobuf.StringValue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;String?&lt;/code&gt; + &lt;code&gt;.hasField()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Wrapper, allows presence detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;repeated string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;List&amp;lt;String&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Always present, default = emptyList&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;map&amp;lt;string, string&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Map&amp;lt;String, String&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Always present, default = emptyMap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enum&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Enum&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Has &lt;code&gt;UNRECOGNIZED&lt;/code&gt; fallback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;oneof&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Field + &lt;code&gt;.case&lt;/code&gt; enum&lt;/td&gt;
&lt;td&gt;Only one field set at a time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Implementation summary: What changed from the previous article?
&lt;/h1&gt;

&lt;p&gt;As I mentioned in the previous article, the source code for the scope of each article will be made available in individual branches at the  &lt;a href="https://github.com/lucasfugisawa/note-service-kotlin-gprc" rel="noopener noreferrer"&gt;note-service-kotlin-gprc&lt;/a&gt;  repository, while  &lt;code&gt;HEAD&lt;/code&gt;  on the  &lt;code&gt;main&lt;/code&gt;  branch will accommodate the latest working version.&lt;/p&gt;

&lt;p&gt;In the article, I highlighted only parts of the code that were relevant to understanding the concepts. So, here is a summary of what changed in the code, which can be checked in detail in the &lt;a href="https://github.com/lucasfugisawa/note-service-kotlin-gprc/tree/article2-schema-design" rel="noopener noreferrer"&gt;article2-schema-design&lt;/a&gt; repository branch.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Protobuf schema&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduced &lt;code&gt;optional&lt;/code&gt; keyword for tracking field presence (e.g., &lt;code&gt;content&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Added a &lt;code&gt;repeated string tags&lt;/code&gt; field to allow multiple tags per note.&lt;/li&gt;
&lt;li&gt;Added &lt;code&gt;map&amp;lt;string, string&amp;gt; metadata&lt;/code&gt; to store arbitrary key-value annotations.&lt;/li&gt;
&lt;li&gt;Introduced a &lt;code&gt;NoteStatus&lt;/code&gt; enum with values &lt;code&gt;UNKNOWN&lt;/code&gt;, &lt;code&gt;ACTIVE&lt;/code&gt;, and &lt;code&gt;ARCHIVED&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Added a &lt;code&gt;NoteMetadata&lt;/code&gt; message that includes &lt;code&gt;word_count&lt;/code&gt;, using a wrapper type (&lt;code&gt;Int32Value&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Introduced a &lt;code&gt;oneof&lt;/code&gt; field in &lt;code&gt;Attachment&lt;/code&gt; to allow attaching either a URL or file path — but never both.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Server implementation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now checks for presence using &lt;code&gt;hasContent()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Dynamically computes and returns word count in &lt;code&gt;metadataDetails&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Maps all new fields from the request into the response.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Client implementation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Demonstrates how to build a request with optional fields, tags, metadata, attachment, and enum values.&lt;/li&gt;
&lt;li&gt;Shows how to check presence, handle &lt;code&gt;oneof&lt;/code&gt;, and interpret server responses idiomatically in Kotlin.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Final thoughts
&lt;/h1&gt;

&lt;p&gt;Designing Protobuf schemas is more than just writing &lt;code&gt;.proto&lt;/code&gt; files. It's about thinking deeply about how your API will evolve, how your data behaves over the wire, and how clients will interpret what they receive.&lt;/p&gt;

&lt;p&gt;In this article, we've explored:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why field presence matters, and how to track it.&lt;/li&gt;
&lt;li&gt;How to use optional fields, wrapper types, repeated values, maps, and enums effectively.&lt;/li&gt;
&lt;li&gt;How to model exclusive choices using &lt;code&gt;oneof&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;How to evolve your schema safely, without breaking existing clients.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools and techniques are foundational for any team using gRPC in production. Schema design &lt;em&gt;is&lt;/em&gt; API design, and mastering it gives you a long-term edge in building reliable services.&lt;/p&gt;




&lt;p&gt;To explore more about Kotlin-related topics, subscribe to my newsletter at  &lt;a href="https://fugisawa.com/" rel="noopener noreferrer"&gt;https://fugisawa.com/&lt;/a&gt;  and stay tuned for more insights and updates.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>kotlinserverside</category>
      <category>backend</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Kotlin + gRPC: Build your first service in four steps</title>
      <dc:creator>Lucas Fugisawa</dc:creator>
      <pubDate>Fri, 11 Apr 2025 01:20:31 +0000</pubDate>
      <link>https://dev.to/lucasfugisawa/kotlin-grpc-build-your-first-service-in-four-steps-3pff</link>
      <guid>https://dev.to/lucasfugisawa/kotlin-grpc-build-your-first-service-in-four-steps-3pff</guid>
      <description>&lt;p&gt;This is the first article in a hands-on series where we'll explore how to build &lt;strong&gt;gRPC&lt;/strong&gt; services using &lt;strong&gt;Kotlin&lt;/strong&gt;. The series is designed to help you understand not only the technical how-to, but also the design choices behind &lt;strong&gt;Protocol Buffers&lt;/strong&gt; and &lt;strong&gt;gRPC&lt;/strong&gt;. We'll start simple and gradually introduce more advanced concepts as we go.&lt;/p&gt;

&lt;p&gt;Here is what you can expect from the upcoming articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the next article, we will explore field presence, repeated, maps, enums, oneOf, and how to evolve your API safely.&lt;/li&gt;
&lt;li&gt;Then, we will expand our model to cover nesting, composition, validations, and idiomatic builder DSL.&lt;/li&gt;
&lt;li&gt;Later, we will explore gRPC streaming to build APIs that go beyond request/response, using Kotlin coroutines and flows. We'll also explore deadlines and error handling.&lt;/li&gt;
&lt;li&gt;Finally, as a bonus, we'll go over topics you should focus on if you need to implement gRPC for a production environment, like tooling, CI/CD and Architectural Practices.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end of the series, you will have a solid understanding of gRPC in Kotlin, and a real working service you can build upon.&lt;/p&gt;

&lt;p&gt;If you've worked with REST APIs, you know they've become the standard way to build and expose web services. They're simple, flexible, and have broad tooling support. But when services need to communicate with each other efficiently, especially in a distributed or high-performance system, gRPC is often a better choice.&lt;/p&gt;

&lt;p&gt;In this first article, we will talk about what gRPC is, how it fits into a Kotlin ecosystem, and how to build a simple gRPC service and client from scratch. We will also compare it to REST and JSON, discuss its tradeoffs, and walk you through the tools and structure needed to get started.&lt;/p&gt;

&lt;p&gt;By the end, you'll understand how gRPC works, why it matters, and how to implement a basic service using Kotlin, Protocol Buffers, and gRPC.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is gRPC and why use it?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://grpc.io/" rel="noopener noreferrer"&gt;gRPC&lt;/a&gt;&lt;/strong&gt; is a framework created by Google for making remote procedure calls (RPC). It allows you to call methods on a service running on another machine as if they were local. Under the hood, it uses HTTP/2 and &lt;strong&gt;&lt;a href="https://protobuf.dev/" rel="noopener noreferrer"&gt;Protocol Buffers (Protobuf)&lt;/a&gt;&lt;/strong&gt; for communication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Protocol Buffers&lt;/strong&gt; are a language-neutral, platform-neutral mechanism for serializing structured data. You define your messages and services in a &lt;code&gt;.proto&lt;/code&gt; file, and code is generated from that file in your target language.&lt;/p&gt;

&lt;p&gt;This allows for benefits such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strongly typed contracts&lt;/strong&gt; between services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code generation&lt;/strong&gt; avoids boilerplate and reduces errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Binary serialization&lt;/strong&gt; for performance and smaller payloads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/2&lt;/strong&gt; enables multiplexing, streaming, and low latency.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  REST vs. gRPC: Tradeoffs
&lt;/h3&gt;

&lt;p&gt;It's important to understand that gRPC is not always "better" than REST. It's different. Choosing between REST and gRPC depends on your context, constraints, and goals.&lt;/p&gt;

&lt;h4&gt;
  
  
  gRPC strengths:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;More efficient data transmission (Protobuf is binary, smaller than JSON).&lt;/li&gt;
&lt;li&gt;Strong typing and codegen reduce runtime errors.&lt;/li&gt;
&lt;li&gt;Supports streaming (one-way and bidirectional).&lt;/li&gt;
&lt;li&gt;Easier evolution with schema compatibility rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  REST strengths:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Human-readable and debug-friendly (JSON over HTTP).&lt;/li&gt;
&lt;li&gt;Better support for web clients and public APIs.&lt;/li&gt;
&lt;li&gt;Mature ecosystem, including caching, proxies, and tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Our Use Case: A simple Note service
&lt;/h2&gt;

&lt;p&gt;In this series, we will build a Note Service — something like a backend for a basic note-taking app. Over time, we will introduce complexity gradually.&lt;/p&gt;

&lt;p&gt;Here's what you'll see in future articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add support for &lt;strong&gt;tags&lt;/strong&gt;, &lt;strong&gt;users&lt;/strong&gt;, and &lt;strong&gt;note metadata&lt;/strong&gt; (nested fields, repeated fields).&lt;/li&gt;
&lt;li&gt;Handle optional fields and versioning concerns as the schema evolves.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;streaming&lt;/strong&gt; for features like syncing or watching updates in real-time.&lt;/li&gt;
&lt;li&gt;Learn about Protobuf features like &lt;code&gt;oneof&lt;/code&gt;, field presence, and default values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start small: a service to create a new note with a title and content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project structure and tools
&lt;/h3&gt;

&lt;p&gt;To build our Kotlin gRPC service, we'll use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kotlinlang.org/docs/jvm-get-started.html" rel="noopener noreferrer"&gt;Kotlin/JVM&lt;/a&gt;&lt;/strong&gt; as our programming language on the JVM platform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kotlinlang.org/docs/gradle.html" rel="noopener noreferrer"&gt;Gradle&lt;/a&gt; (Kotlin DSL)&lt;/strong&gt; — dependency and build management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kotlinlang.org/docs/gradle.html" rel="noopener noreferrer"&gt;Protocol Buffers&lt;/a&gt; (&lt;code&gt;.proto&lt;/code&gt;)&lt;/strong&gt; — our API schema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://protobuf.dev/installation/" rel="noopener noreferrer"&gt;protoc&lt;/a&gt;&lt;/strong&gt; — the Protobuf compiler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://grpc.io/docs/languages/kotlin/quickstart/" rel="noopener noreferrer"&gt;gRPC Kotlin&lt;/a&gt;&lt;/strong&gt; — gRPC support for Kotlin and coroutines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our folder structure will start with something like this (a very basic Kotlin + Gradle project), but might evolve as we expand our project scope:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;note-service-kotlin-gprc/
├── build.gradle.kts
├── settings.gradle.kts
├── src/
│   ├── main/
│   │   ├── kotlin/            # Kotlin code (server + client)
│   │   └── proto/             # Protobuf files (.proto)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The source code for the scope of each article will be made available in individual branches at the &lt;a href="https://github.com/lucasfugisawa/note-service-kotlin-gprc" rel="noopener noreferrer"&gt;note-service-kotlin-gprc&lt;/a&gt; repository, while &lt;code&gt;HEAD&lt;/code&gt; on the &lt;code&gt;main&lt;/code&gt; branch will accommodate the latest working version.&lt;/p&gt;

&lt;p&gt;The specific branch for this article is &lt;a href="https://github.com/lucasfugisawa/note-service-kotlin-gprc/tree/article1-first-service" rel="noopener noreferrer"&gt;article1-first-service&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Writing your first &lt;code&gt;.proto&lt;/code&gt; file
&lt;/h2&gt;

&lt;p&gt;Let's define the initial structure of our Note Service using Protocol Buffers. This file describes the types and service methods that gRPC will generate for us.&lt;/p&gt;

&lt;p&gt;Create a file at &lt;code&gt;src/main/proto/note_service.proto&lt;/code&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="na"&gt;syntax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"proto3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fugisawa.grpc.noteservice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="na"&gt;java_package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"com.fugisawa.grpc.noteservice"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="na"&gt;java_multiple_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;NoteService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;CreateNote&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateNoteRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Note&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;CreateNoteRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break this down:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;syntax = "proto3";&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This declares that we're using &lt;strong&gt;&lt;a href="https://protobuf.dev/programming-guides/proto3/" rel="noopener noreferrer"&gt;proto3&lt;/a&gt;&lt;/strong&gt;, the most recent version of 'the Protocol Buffers language. It simplifies the syntax and sets some defaults (like making fields optional).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;package note;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is the &lt;strong&gt;Protobuf package name&lt;/strong&gt;. It groups related messages and services under a common namespace to avoid naming conflicts.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;option java_package&lt;/code&gt; and &lt;code&gt;java_multiple_files&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;These are used by the code generator for JVM languages (like Kotlin or Java):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;java_package = "com.fugisawa.noteservice"&lt;/code&gt;: sets the package name in the generated Kotlin/Java code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;java_multiple_files = true&lt;/code&gt;: instead of placing all generated types into a single file, this generates one file per message/service, which is cleaner and more modular.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;service&lt;/code&gt; block
&lt;/h3&gt;

&lt;p&gt;This defines the &lt;strong&gt;gRPC service&lt;/strong&gt; and its RPC methods. In our case...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;NoteService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;CreateNote&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateNoteRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Note&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... defines a service named &lt;code&gt;NoteService&lt;/code&gt; with one RPC method &lt;code&gt;CreateNote&lt;/code&gt;, which accepts a message of type &lt;code&gt;CreateNoteRequest&lt;/code&gt; and returns a &lt;code&gt;Note&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;gRPC will generate both a base server class and a client stub for us, based on this.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;message&lt;/code&gt; blocks
&lt;/h3&gt;

&lt;p&gt;These define structured data for the request and response types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;CreateNoteRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This defines the input type for our &lt;code&gt;CreateNote&lt;/code&gt; method. It has two fields: &lt;code&gt;title&lt;/code&gt; (a string field with &lt;strong&gt;tag 1&lt;/strong&gt;) and &lt;code&gt;content&lt;/code&gt; (another string field with &lt;strong&gt;tag 2&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;And this...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... is the response type, which includes &lt;code&gt;id&lt;/code&gt; (a string representing the unique note ID, with &lt;strong&gt;tag 1&lt;/strong&gt;), &lt;code&gt;title&lt;/code&gt; (for the note title with &lt;strong&gt;tag 2&lt;/strong&gt;) and &lt;code&gt;content&lt;/code&gt; (for the note content with &lt;strong&gt;tag 3&lt;/strong&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  But what are those numbered tags?
&lt;/h3&gt;

&lt;p&gt;Each field in a Protobuf message has a &lt;strong&gt;unique number&lt;/strong&gt;. These numbers are used in the binary encoding of the message, not the field names. They matter a lot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Must not change&lt;/strong&gt; once published — they define the wire format.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can't reuse deleted field numbers&lt;/strong&gt; — unless you're absolutely sure they won't be interpreted by old clients.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Field order doesn't matter&lt;/strong&gt; in the source, but tags must be unique.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Protobuf tags must be between 1 and (2&lt;sup&gt;29&lt;/sup&gt; - 1), but you should use 1–15 for frequently-used fields, since they encode more efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Generating Kotlin code from Protobuf definitions
&lt;/h2&gt;

&lt;p&gt;The next step is to generate Kotlin code from our &lt;code&gt;.proto&lt;/code&gt; file. There are two main ways to do this:&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: Using Gradle
&lt;/h3&gt;

&lt;p&gt;For compiling our Protobuf definitions to Kotlin code, we can use a Gradle plugin, which makes our life easier. Add the Protobuf plugin and dependencies to your &lt;code&gt;build.gradle.kts&lt;/code&gt;. Remember we also need to add the Kotlin Coroutines dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jvm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"1.9.22"&lt;/span&gt; 
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.google.protobuf"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"0.9.4"&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;repositories&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;mavenCentral&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"io.grpc:grpc-kotlin-stub:1.4.1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"io.grpc:grpc-netty-shaded:1.71.0"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"io.grpc:grpc-protobuf:1.71.0"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.google.protobuf:protobuf-kotlin:4.30.2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;protobuf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nf"&gt;protoc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="n"&gt;artifact&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"com.google.protobuf:protoc:4.30.2"&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"grpc"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="n"&gt;artifact&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"io.grpc:protoc-gen-grpc-java:1.71.0"&lt;/span&gt;  
        &lt;span class="p"&gt;}&lt;/span&gt;  
        &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"grpckt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="n"&gt;artifact&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"io.grpc:protoc-gen-grpc-kotlin:1.4.1:jdk8@jar"&lt;/span&gt;  
        &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="nf"&gt;generateProtoTasks&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;builtins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"kotlin"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="p"&gt;}&lt;/span&gt;  
            &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"grpc"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
                &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"grpckt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="p"&gt;}&lt;/span&gt;  
        &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(Consider using local String variables for dependency version numbers. I didn't do it here for simplicity.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew generateProto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates Kotlin and gRPC code under &lt;code&gt;build/generated&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Option 2: Manual compilation using &lt;code&gt;protoc&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;You can also generate code manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;protoc  
    &lt;span class="nt"&gt;--proto_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src/main/proto  
    &lt;span class="nt"&gt;--kotlin_out&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;build/generated/source/proto/main/kotlin  
    &lt;span class="nt"&gt;--grpc-kotlin_out&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;build/generated/source/proto/main/kotlin  
    note_service.proto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll need the &lt;code&gt;protoc&lt;/code&gt; binary and the &lt;code&gt;protoc-gen-grpc-kotlin&lt;/code&gt; plugin &lt;a href="https://protobuf.dev/installation/" rel="noopener noreferrer"&gt;installed&lt;/a&gt; on your system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Implementing the gRPC Server
&lt;/h2&gt;

&lt;p&gt;Now that we have the Kotlin stub code generated, the next step is to write the backend logic that will handle incoming gRPC calls. This is where we implement the &lt;code&gt;NoteService&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.fugisawa.noteservice&lt;/span&gt;  

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.fugisawa.grpc.noteservice.CreateNoteRequest&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.fugisawa.grpc.noteservice.Note&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.fugisawa.grpc.noteservice.NoteServiceGrpcKt&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.fugisawa.grpc.noteservice.note&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.*&lt;/span&gt;  

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NoteServiceImpl&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;NoteServiceGrpcKt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NoteServiceCoroutineImplBase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;suspend&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createNote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CreateNoteRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="c1"&gt;// Here, you will implement your note creation logic, persist the new note etc.  &lt;/span&gt;
        &lt;span class="c1"&gt;// Let's just generate dummy note, for this example:  &lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;newNoteId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;   
            &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newNoteId&lt;/span&gt;  
            &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;  
            &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;  
        &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, what we are doing is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We are extending the &lt;code&gt;NoteServiceCoroutineImplBase&lt;/code&gt; (generated by the Protobuf compilation).&lt;/li&gt;
&lt;li&gt;We are implementing the &lt;code&gt;createNote()&lt;/code&gt; function with our own logic for creating notes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also need to start our gRPC server, register the service, and block the main thread (which, for simplicity, we'll do in the main application entry point function):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.fugisawa.noteservice&lt;/span&gt;  

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.grpc.Server&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.grpc.ServerBuilder&lt;/span&gt;  

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Server&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ServerBuilder&lt;/span&gt;  
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forPort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50051&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NoteServiceImpl&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  

      &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
      &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server started on port 50051"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
      &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;awaitTermination&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all we need to get a Kotlin gRPC server running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Creating a gRPC Client in Kotlin
&lt;/h2&gt;

&lt;p&gt;Now, let's now write a client that connects to the server and sends a &lt;code&gt;CreateNote&lt;/code&gt; request.&lt;/p&gt;

&lt;p&gt;Typically, we will not implement a gRPC client for a gRPC service available in the same application. We will do this in this article just to keep things simple and avoid having to create a new application to act as the client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.fugisawa.noteservice&lt;/span&gt;  

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.fugisawa.grpc.noteservice.NoteServiceGrpcKt.NoteServiceCoroutineStub&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.fugisawa.grpc.noteservice.createNoteRequest&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.grpc.ManagedChannelBuilder&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.runBlocking&lt;/span&gt;  

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;runBlocking&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;  
        &lt;span class="nc"&gt;ManagedChannelBuilder&lt;/span&gt;  
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50051&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;usePlaintext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;stub&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NoteServiceCoroutineStub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createNoteRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"My first note"&lt;/span&gt;  
        &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"This is my first note created with gRPC!"&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;note&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createNote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Note created: ${note.id} - ${note.title}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This small program connects to our gRPC server and calls the &lt;code&gt;CreateNote&lt;/code&gt; method, just like a real client would. Let's walk through what each part is doing.&lt;/p&gt;

&lt;p&gt;We wrap our &lt;code&gt;main&lt;/code&gt; function in &lt;code&gt;runBlocking&lt;/code&gt; because gRPC Kotlin uses &lt;strong&gt;suspend functions&lt;/strong&gt; for all RPC calls, which means we need a coroutine scope to call them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;runBlocking&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we create a &lt;strong&gt;gRPC channel&lt;/strong&gt; (which is a connection to the server). We are connecting to &lt;code&gt;localhost:50051&lt;/code&gt;, which is where our server is running. We are using &lt;code&gt;.usePlaintext()&lt;/code&gt; to disable TLS (which is fine for local development), as we didn't configure TLS for the server.&lt;/p&gt;

&lt;p&gt;Then we create a stub. A &lt;strong&gt;stub&lt;/strong&gt; is a client-side object that lets you call remote methods as if they were local. We're using the &lt;strong&gt;coroutine-based version&lt;/strong&gt;, auto-generated by the gRPC Kotlin plugin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;stub&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NoteServiceCoroutineStub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This stub exposes &lt;code&gt;suspend&lt;/code&gt; functions like &lt;code&gt;createNote()&lt;/code&gt; that we can call directly.&lt;/p&gt;

&lt;p&gt;The next thing we do is create a &lt;code&gt;CreateNoteRequest&lt;/code&gt; object using the &lt;strong&gt;Kotlin DSL builder&lt;/strong&gt; generated from the &lt;code&gt;.proto&lt;/code&gt; file. This DSL-style builder only works because you're using the &lt;code&gt;protobuf-kotlin&lt;/code&gt; library and configured our Gradle setup to generate &lt;code&gt;kotlin&lt;/code&gt; output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createNoteRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"My first note"&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"This is my first note created with gRPC!"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, here is where the actual &lt;strong&gt;RPC call&lt;/strong&gt; happens. We call &lt;code&gt;createNote()&lt;/code&gt; on the stub, passing the request. It suspends while the request is sent and response is received from the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;note&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createNote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how simple and idiomatic calling a gRPC service can be in Kotlin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All calls are suspending functions — no callbacks, no threads to manage.&lt;/li&gt;
&lt;li&gt;Messages are constructed using type-safe Kotlin builders.&lt;/li&gt;
&lt;li&gt;Communication is binary, efficient, and strongly typed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to run the Server and the Client
&lt;/h2&gt;

&lt;p&gt;We're building both server and client in the same Gradle project, but typically they would be two separate applications. In this article, we will use them by starting our application with different entry points.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To run the server, execute &lt;code&gt;Server.main()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In a second terminal (or a new IntelliJ run configuration), run &lt;code&gt;Client.main()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;In this article, we covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What gRPC and Protobuf are, and why they matter.&lt;/li&gt;
&lt;li&gt;When to use gRPC vs REST.&lt;/li&gt;
&lt;li&gt;How to define an API using a &lt;code&gt;.proto&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;How to generate Kotlin code using Gradle and &lt;code&gt;protoc&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;How to implement and run a gRPC server and client in Kotlin.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the upcoming articles, we'll dig deeper into &lt;code&gt;optional&lt;/code&gt; fields, field/argument presence detection, &lt;code&gt;repeat&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;oneof&lt;/code&gt; fields, and the subtle but important differences in how Protocol Buffers handle missing or default values. That's where things get interesting and real-world.&lt;/p&gt;




&lt;p&gt;To explore more about Kotlin-related topics, subscribe to my newsletter at  &lt;a href="https://fugisawa.com/" rel="noopener noreferrer"&gt;https://fugisawa.com/&lt;/a&gt;  and stay tuned for more insights and updates.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>kotlinserverside</category>
      <category>backend</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Scope Isolation in Kotlin DSLs with @DslMarker</title>
      <dc:creator>Lucas Fugisawa</dc:creator>
      <pubDate>Sat, 05 Apr 2025 14:32:32 +0000</pubDate>
      <link>https://dev.to/lucasfugisawa/scope-isolation-in-kotlin-dsls-with-dslmarker-44j</link>
      <guid>https://dev.to/lucasfugisawa/scope-isolation-in-kotlin-dsls-with-dslmarker-44j</guid>
      <description>&lt;p&gt;In the previous article &lt;a href="https://dev.to/lucasfugisawa/taking-kotlin-builders-to-the-next-level-a-type-safe-dsl-approach-3g8a"&gt;Taking Kotlin Builders to the Next Level: A Type-Safe DSL Approach&lt;/a&gt;, we explored how Kotlin's type-safe builders allow you to build expressive and concise DSLs. But as soon as your DSL starts nesting structures, something sneaky can happen: &lt;strong&gt;receiver conflicts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's take a deeper look at this problem and how Kotlin's &lt;code&gt;@DslMarker&lt;/code&gt; annotation solves it, making your DSLs safer and more robust.&lt;/p&gt;

&lt;p&gt;But if you haven't read that previous article yet, I strongly recommend you to pause here for a while and do it first.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what's the problem, in fact?
&lt;/h2&gt;

&lt;p&gt;When you nest multiple DSL blocks, like this...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;car&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Honda"&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Civic"&lt;/span&gt;
    &lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt;
        &lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;..., you're creating &lt;strong&gt;nested lambdas with receivers&lt;/strong&gt;, which are also &lt;strong&gt;closures&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In Kotlin, lambdas &lt;em&gt;are&lt;/em&gt; closures: they carry with them access to everything in the outer scope, including the outer receiver (&lt;code&gt;CarBuilder&lt;/code&gt;). So inside the &lt;code&gt;localDate { ... }&lt;/code&gt; block, the compiler sees both &lt;code&gt;LocalDateBuilder&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; &lt;code&gt;CarBuilder&lt;/code&gt; in scope. That means inside the &lt;code&gt;localDate { ... }&lt;/code&gt; block, you still have access to the outer &lt;code&gt;CarBuilder&lt;/code&gt;, even though you're writing in the context of &lt;code&gt;LocalDateBuilder&lt;/code&gt;. And that can get dangerous fast.&lt;/p&gt;

&lt;p&gt;This can lead to subtle and unintended behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Oops"&lt;/span&gt; &lt;span class="c1"&gt;// Refers to CarBuilder, not LocalDateBuilder&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;make&lt;/code&gt; property is not part of &lt;code&gt;LocalDateBuilder&lt;/code&gt;, but since the lambda captures the outer receiver (&lt;code&gt;CarBuilder&lt;/code&gt;), it's still accessible. That’s a classic receiver conflict.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if both builders have some properties with the same name?
&lt;/h3&gt;

&lt;p&gt;Let's say, hypothetically, that both &lt;code&gt;CarBuilder&lt;/code&gt; and &lt;code&gt;LocalDateBuilder&lt;/code&gt; define a property called &lt;code&gt;year&lt;/code&gt;. This is &lt;em&gt;not unrealistic&lt;/em&gt; — maybe &lt;code&gt;CarBuilder&lt;/code&gt; tracks the model year, while &lt;code&gt;LocalDateBuilder&lt;/code&gt; builds the date when that car model was first announced.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CarBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"N/A"&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"N/A"&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;// Model year!&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;announcementDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LocalDateBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1970&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's write a nested DSL block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;car&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Toyota"&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Corolla"&lt;/span&gt;
    &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2023&lt;/span&gt; &lt;span class="c1"&gt;// OK: CarBuilder.year&lt;/span&gt;

    &lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt; &lt;span class="c1"&gt;// Is this LocalDateBuilder.year or CarBuilder.year?&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Surprisingly, both &lt;code&gt;year&lt;/code&gt; properties are accessible inside the &lt;code&gt;localDate&lt;/code&gt; block. This makes the code &lt;strong&gt;ambiguous and error-prone&lt;/strong&gt;, because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If &lt;code&gt;year = 2025&lt;/code&gt; targets the &lt;strong&gt;outer receiver&lt;/strong&gt;, the &lt;code&gt;LocalDate&lt;/code&gt; may be built with a default year (1970), leading to silent bugs.&lt;/li&gt;
&lt;li&gt;  The code &lt;em&gt;looks&lt;/em&gt; correct, and it &lt;em&gt;compiles&lt;/em&gt; - but it does an unexpected thing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to be sure you're writing to the intended scope, you can always disambiguate manually using &lt;code&gt;this&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt; &lt;span class="c1"&gt;// Clearly refers to LocalDateBuilder.year&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="nd"&gt;@car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2023&lt;/span&gt; &lt;span class="c1"&gt;// Explicitly refers to CarBuilder.year&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But of course, this adds verbosity and cognitive overhead. Using &lt;code&gt;@DslMarker&lt;/code&gt; gives you a safer default: the compiler protects you from accidental access.&lt;/p&gt;

&lt;h2&gt;
  
  
  How &lt;code&gt;@DslMarker&lt;/code&gt; solves this?
&lt;/h2&gt;

&lt;p&gt;By annotating both &lt;code&gt;CarBuilder&lt;/code&gt; and &lt;code&gt;LocalDateBuilder&lt;/code&gt; with the same &lt;code&gt;@CarDsl&lt;/code&gt;, Kotlin will restrict visibility to &lt;strong&gt;only the closest receiver&lt;/strong&gt; within each block. That marker tells the compiler: &lt;em&gt;these receivers belong to the same DSL, don't mix them up&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;First, we need to define a DSL marker annotation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@DslMarker&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AnnotationTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CLASS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AnnotationTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TYPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;annotation&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CarDsl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we need to annotate our builders using our new DSL marker annotation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@CarDsl&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CarBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"N/A"&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"N/A"&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;announcementDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;announcementDate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@CarDsl&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LocalDateBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1970&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we accidentally try this...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Oops"&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Error: model is from CarBuilder, not in scope here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;..., Kotlin will &lt;strong&gt;refuse to compile&lt;/strong&gt;, forcing you to stay inside the intended builder scope. This helps eliminate bugs &lt;strong&gt;before they happen&lt;/strong&gt;,&lt;/p&gt;

&lt;h3&gt;
  
  
  But… what if I &lt;em&gt;really&lt;/em&gt; need to access the outer scope?
&lt;/h3&gt;

&lt;p&gt;While &lt;code&gt;@DslMarker&lt;/code&gt; intentionally hides outer receivers to avoid accidental misuse, Kotlin still gives you an escape hatch: &lt;strong&gt;you can explicitly reference outer receivers using labeled lambdas&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is helpful in advanced use cases where you genuinely need access to both scopes, but want to do it &lt;em&gt;on purpose&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let's say you want to configure both the &lt;code&gt;LocalDateBuilder&lt;/code&gt; &lt;strong&gt;and&lt;/strong&gt; the outer &lt;code&gt;CarBuilder&lt;/code&gt; inside the same nested block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;car&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Toyota"&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Corolla"&lt;/span&gt;
    &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2023&lt;/span&gt;

    &lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt;
        &lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;

        &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Oops"&lt;/span&gt; &lt;span class="c1"&gt;// not allowed due to @DslMarker&lt;/span&gt;
        &lt;span class="c1"&gt;// To access the CarBuilder.make, use  the labeled receiver explicitly&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="nd"&gt;@car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Toyota (revised)"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, if you have nested builders of the same type, which can cause confusion when using the default labels, you can use custom labels to make it clearer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;car&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;outerCar@&lt;/span&gt;&lt;span class="nf"&gt;car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="nd"&gt;@outerCar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Toyota (revised)"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Here's what's happening:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;  We've labeled the outer &lt;code&gt;car&lt;/code&gt; block with &lt;code&gt;outerCar@&lt;/code&gt; (or used the implicit default &lt;code&gt;@car&lt;/code&gt; label name)&lt;/li&gt;
&lt;li&gt;  Inside &lt;code&gt;localDate { ... }&lt;/code&gt;, the &lt;code&gt;CarBuilder&lt;/code&gt; is no longer directly visible (because of &lt;code&gt;@DslMarker&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;  But we can still access it with &lt;code&gt;this@outerCar&lt;/code&gt; (or with the default &lt;code&gt;@car&lt;/code&gt;) explicitly referring to the outer receiver.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Using the Kotlin DSL markers lets you maintain safe defaults (no accidental access), but still gives you full control when needed. It's the best of both worlds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Safety by default&lt;/strong&gt; with &lt;code&gt;@DslMarker&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Escape hatch&lt;/strong&gt; with labeled receivers when necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a good idea to use this sparingly — reaching across DSL scopes often indicates the logic might be better separated — but it's great to know the tool is there when you need it.&lt;/p&gt;




&lt;p&gt;To explore more about Kotlin-related topics, subscribe to my newsletter at &lt;a href="https://fugisawa.com/" rel="noopener noreferrer"&gt;https://fugisawa.com/&lt;/a&gt; and stay tuned for more insights and updates.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>backend</category>
      <category>kotlinserverside</category>
    </item>
    <item>
      <title>Taking Kotlin Builders to the Next Level: A Type-Safe DSL Approach</title>
      <dc:creator>Lucas Fugisawa</dc:creator>
      <pubDate>Sat, 15 Feb 2025 15:39:35 +0000</pubDate>
      <link>https://dev.to/lucasfugisawa/taking-kotlin-builders-to-the-next-level-a-type-safe-dsl-approach-3g8a</link>
      <guid>https://dev.to/lucasfugisawa/taking-kotlin-builders-to-the-next-level-a-type-safe-dsl-approach-3g8a</guid>
      <description>&lt;p&gt;You might recall my &lt;a href="https://dev.to/lucasfugisawa/kotlin-design-patterns-simplifying-the-builder-pattern-3e7g"&gt;Simplifying the Builder Pattern&lt;/a&gt; article about using Kotlin Data Classes as a simpler version of the Builder pattern. You saw how named parameters and default values removed much of the ceremony you see in a traditional Builder. Now, I want to guide you further.&lt;/p&gt;

&lt;p&gt;In this article, we will explore Kotlin type-safe builders (DSLs). You will learn how to create code for object construction that feels more expressive. Think of it like reading small sentences.&lt;/p&gt;

&lt;p&gt;If you want to build objects in a clear and flexible way, this piece will walk you step by step. You will see how to write DSLs in Kotlin. Then you will create objects with code like &lt;code&gt;car { ... }&lt;/code&gt;, which is both concise and readable.&lt;/p&gt;

&lt;p&gt;Take what you already know about Kotlin and extend it. Let's begin and see how to go beyond data classes while keeping the same clarity.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are function types with a receiver?
&lt;/h2&gt;

&lt;p&gt;Before we build our DSL, we need a quick look at one Kotlin feature: &lt;strong&gt;function types with a receiver&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A function type with a receiver allows you to define a block of code that acts as if it's inside an object's scope. That means you can access the object's methods and properties without extra qualifiers. Here's a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Printer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Function type with a receiver: Printer.() -&amp;gt; Unit&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;usePrinter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Printer&lt;/span&gt;&lt;span class="p"&gt;.()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;printer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Printer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;printer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;usePrinter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello from inside the Printer scope"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;code&gt;usePrinter { ... }&lt;/code&gt;, you call &lt;code&gt;show()&lt;/code&gt; directly. That's because the block is defined as &lt;code&gt;Printer.() -&amp;gt; Unit&lt;/code&gt;, so it behaves like a method on &lt;code&gt;Printer&lt;/code&gt;. More precisely, it represents an &lt;em&gt;extension function type&lt;/em&gt;. We'll use this idea to write our DSL for building objects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building on data classes with a type-safe builder
&lt;/h2&gt;

&lt;p&gt;In my &lt;a href="https://dev.to/lucasfugisawa/kotlin-design-patterns-simplifying-the-builder-pattern-3e7g"&gt;earlier article&lt;/a&gt;, we had a &lt;code&gt;Car&lt;/code&gt; data class with properties like &lt;code&gt;make&lt;/code&gt;, &lt;code&gt;model&lt;/code&gt;, and &lt;code&gt;year&lt;/code&gt;. Now we will replace &lt;code&gt;year&lt;/code&gt; with &lt;code&gt;announcementDate&lt;/code&gt; of type &lt;code&gt;LocalDate&lt;/code&gt;. We will create a DSL so you can write &lt;code&gt;car { ... }&lt;/code&gt; blocks to build &lt;code&gt;Car&lt;/code&gt; objects. Let's start with a simple &lt;code&gt;Car&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"N/A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"N/A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;announcementDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A type-safe builder, or a DSL, will allow us to create cars like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;honda&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Honda"&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Civic"&lt;/span&gt;
    &lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt;
        &lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the nested &lt;code&gt;localDate { ... }&lt;/code&gt;. That's a mini-DSL for creating a &lt;code&gt;LocalDate&lt;/code&gt;. Let's walk through the steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Write a builder class for LocalDate
&lt;/h3&gt;

&lt;p&gt;Define a builder for &lt;code&gt;LocalDate&lt;/code&gt;. Store &lt;code&gt;year&lt;/code&gt;, &lt;code&gt;month&lt;/code&gt;, and &lt;code&gt;day&lt;/code&gt;, then build a &lt;code&gt;LocalDate&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LocalDateBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1970&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LocalDateBuilder&lt;/span&gt;&lt;span class="p"&gt;.()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDateBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you call &lt;code&gt;localDate { ... }&lt;/code&gt; and set the date parts in a small block.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;LocalDateBuilder&lt;/code&gt;, each property (&lt;code&gt;year&lt;/code&gt;, &lt;code&gt;month&lt;/code&gt;, &lt;code&gt;day&lt;/code&gt;) is a mutable field. You set them in the block passed to &lt;code&gt;localDate&lt;/code&gt;. The &lt;code&gt;build()&lt;/code&gt; function then transforms those fields into a &lt;code&gt;LocalDate&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This pattern is flexible. You could add validation or adjust default values if you need stricter control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Write a builder class for Car
&lt;/h3&gt;

&lt;p&gt;Next, create a builder for &lt;code&gt;Car&lt;/code&gt;. You will keep &lt;code&gt;make&lt;/code&gt;, &lt;code&gt;model&lt;/code&gt;, and &lt;code&gt;announcementDate&lt;/code&gt; as mutable fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CarBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"N/A"&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"N/A"&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;announcementDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;announcementDate&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;CarBuilder&lt;/code&gt; holds properties that match the data class fields. In your &lt;code&gt;car&lt;/code&gt; block, you assign values to &lt;code&gt;make&lt;/code&gt;, &lt;code&gt;model&lt;/code&gt;, or &lt;code&gt;announcementDate&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;When you call &lt;code&gt;build()&lt;/code&gt;, it creates a &lt;code&gt;Car&lt;/code&gt; object with whatever state you defined. This separation lets you add checks or transformations if you want more than just copying values.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Write the DSL entry function
&lt;/h3&gt;

&lt;p&gt;Lastly, define a helper function to create a &lt;code&gt;CarBuilder&lt;/code&gt;, run the block, and return the final &lt;code&gt;Car&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CarBuilder&lt;/span&gt;&lt;span class="p"&gt;.()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CarBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;civic&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Honda"&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Civic"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;car(block: CarBuilder.() -&amp;gt; Unit)&lt;/code&gt; function is the entry point to your DSL. It creates a &lt;code&gt;CarBuilder&lt;/code&gt;, then runs the given block in that builder's scope. Finally, it calls &lt;code&gt;build()&lt;/code&gt; to return the finished &lt;code&gt;Car&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;You can return different implementations if needed. For example, you could add logic to decide if certain fields are valid or required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing approaches: traditional builders, data classes, and DSLs
&lt;/h2&gt;

&lt;p&gt;Let's compare how you might build a &lt;code&gt;Car&lt;/code&gt; with three different patterns:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Traditional builder
&lt;/h3&gt;

&lt;p&gt;This often appears in Java or Kotlin code that mimics the same style.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;announcementDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Builder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"N/A"&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"N/A"&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;announcementDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1970&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;withMake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;withModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;withAnnouncementDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;announcementDate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;carWithBuilder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Honda"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Civic"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withAnnouncementDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2025&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern is clear about each property you set, but it requires a separate builder class and methods like &lt;code&gt;withMake&lt;/code&gt;, &lt;code&gt;withModel&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Kotlin data classes with named parameters
&lt;/h3&gt;

&lt;p&gt;Kotlin's data classes can replace many builder use cases thanks to named parameters and default arguments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"N/A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"N/A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;announcementDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1970&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;carWithDataClass&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Honda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Civic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2025&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't need extra builder methods. You can skip arguments you don't need, thanks to default values.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. DSL (type-safe builder)
&lt;/h3&gt;

&lt;p&gt;When your object or configuration gets deeper, you might want a more expressive way to nest properties. DSLs allow you to build objects within code blocks, making them easy to read or extend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;carWithDSL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Honda"&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Civic"&lt;/span&gt;
    &lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt;
        &lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each block runs with the appropriate builder scope. You don’t repeat object names, and you can nest DSL calls for related objects like LocalDate.&lt;/p&gt;

&lt;p&gt;When your object or configuration becomes more complex, you might want a more expressive way to nest properties. DSLs let you build objects in code blocks, making them easier to read and extend. Each block runs in the correct builder scope. You don’t repeat object names, and you can nest DSL calls for related objects like &lt;code&gt;LocalDate&lt;/code&gt;. You also gain extra flexibility because a DSL block is actual Kotlin code. That means you can do more than simple assignments. For example, you can perform validations, logging, or other conditional logic inside the builder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Suppose you have a function that fetches or reads car data from some file.&lt;/span&gt;
&lt;span class="c1"&gt;// This can be a placeholder for actual file IO and parsing.&lt;/span&gt;
&lt;span class="c1"&gt;// For example, you might parse JSON into a CarData object.&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;loadCarData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;CarData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CarData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Nissan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Leaf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;isElectric&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// A simple data class to represent the loaded car data.&lt;/span&gt;
&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;CarData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;isElectric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// DSL-based creation of a Car with integrated IO/data loading.&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;carWithDSL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting the car creation process..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;loadCarData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"car_config.json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isElectric&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt;
            &lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
            &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt;
            &lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
            &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;31&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isNotBlank&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Model must not be blank."&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Car creation block finished. Building the Car object now."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  What’s Happening Here:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Loading External Data:&lt;/strong&gt; The first action inside the block is to load data using &lt;code&gt;loadCarData(…)&lt;/code&gt;. You might read from a file, fetch from an API, or query a database. Since this is just a Kotlin function call, you can do this I/O inline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Assigning Properties Dynamically:&lt;/strong&gt; The DSL remains flexible. After reading the external data, you use the result to decide which fields to set. This gives you a huge advantage when your configuration depends on external information or user preferences.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Domain Logic:&lt;/strong&gt; You can branch your code and change behavior based on conditions (e.g., an electric car gets a different announcement date). Everything stays in one place, inside the DSL block, which avoids scattered logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validation:&lt;/strong&gt; Because you’re using Kotlin code, you can enforce rules and constraints (require(…)) at build time. This helps keep your final object valid, all within the DSL’s context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logging or Feedback:&lt;/strong&gt; Notice that you can print logs or run other side effects. This is possible because your DSL block is just a function body. You can integrate other statements, error handling, or detailed logging as needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Kotlin's features enabling DSLs / type-safe builders
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Named and Default Parameters&lt;/strong&gt;:  These let you call constructors in a flexible way. They also reduce the need for multiple constructors.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Function Types with a Receiver&lt;/strong&gt;: This feature drives DSL creation. You define blocks that operate in the context of a specific object. That means you access properties and methods directly, which improves readability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros of the DSLs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Natural Nesting:&lt;/strong&gt; You can nest objects that relate to each other. For example, a &lt;code&gt;car { engine { ... } }&lt;/code&gt; DSL can clarify how parts fit together. This nesting helps you keep code organized and shows logical groupings right inside the builder.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Readability:&lt;/strong&gt; Each block reads like a small sentence about the object you are constructing. Instead of calling many methods in a row, you see a structured layout. Future readers can follow your logic like reading a short story about how the object is built.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Less Boilerplate:&lt;/strong&gt; You don’t repeat the same method calls or property assignments. You only define your builder classes once. Then you write short blocks that do the configuration. This saves time, especially as your objects grow in complexity.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Type-Safe:&lt;/strong&gt; The DSL ensures you only set valid properties. The compiler checks everything. You also get IDE support, like auto-completion. This reduces mistakes and helps you see what options are available at a glance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use cases examples
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;User profile setup&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You can nest parts of a user profile:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;profile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;userProfile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Alice"&lt;/span&gt; 
    &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; 
    &lt;span class="nf"&gt;address&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="n"&gt;street&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Main Street"&lt;/span&gt; 
        &lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Springfield"&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;UI configuration&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You might build a layout tree in a natural way:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mainPanel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;panel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;panel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="nf"&gt;field&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Email"&lt;/span&gt;
            &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TEXT&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="nf"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Cancel"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Emails or reports&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You can add sections or attachments in blocks:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;weeklyReportEmail&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;email&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Weekly Report"&lt;/span&gt; 
    &lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"manager@company.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"team@company.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Here is our weekly progress..."&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;    
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Complex file generation&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For XML or JSON, DSLs let you organize nested tags and fields with clarity.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;document&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;xml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"catalog"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"book"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="nf"&gt;element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
        &lt;span class="nf"&gt;element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="nf"&gt;element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"book"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="nf"&gt;element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
        &lt;span class="nf"&gt;element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This article was originally posted to my Lucas Fugisawa on Kotlin blog, at: &lt;a href="https://fugisawa.com/taking-kotlin-builders-to-the-next-level-a-type-safe-dsl-approach/" rel="noopener noreferrer"&gt;https://fugisawa.com/taking-kotlin-builders-to-the-next-level-a-type-safe-dsl-approach/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In each of these scenarios, DSLs help you avoid confusion when building complex structures.&lt;/p&gt;

&lt;h2&gt;
  
  
  A word of caution: nested builders and receiver conflicts
&lt;/h2&gt;

&lt;p&gt;As your DSL grows and starts to nest deeper, you might run into a subtle issue known as receiver conflict. In Kotlin, when you define multiple builder blocks, each with its own receiver (like &lt;code&gt;car { ... }&lt;/code&gt; and &lt;code&gt;localDate { ... }&lt;/code&gt;), the compiler allows access to all visible receivers. That can be dangerous.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;car&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Honda"&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Civic"&lt;/span&gt;
    &lt;span class="n"&gt;announcementDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt;
        &lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;

        &lt;span class="c1"&gt;// Oops — this is from the outer CarBuilder, not LocalDateBuilder!&lt;/span&gt;
        &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"This will, but maybe shouldn't compile..."&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since both builders are in scope, &lt;code&gt;make = ...&lt;/code&gt; refers to the outer &lt;code&gt;CarBuilder&lt;/code&gt;, not the inner &lt;code&gt;LocalDateBuilder&lt;/code&gt;. This can lead to surprising bugs and unintended assignments.&lt;/p&gt;

&lt;p&gt;Thankfully, Kotlin provides a solution to isolate DSL scopes and prevent this kind of issue. In the next article, we'll dive into Kotlin's &lt;code&gt;@DslMarker&lt;/code&gt; feature, what it is, why it exists, and how to use it effectively to keep your DSLs clean, safe, and predictable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Type-safe builders (DSLs) bring a new layer of readability to your code. You maintain the simplicity of data classes, then add a more expressive syntax for your objects. You write &lt;code&gt;car { ... }&lt;/code&gt; blocks and set properties in a natural way. Test them in your next project, and see how they simplify your object creation logic.&lt;/p&gt;




&lt;p&gt;To explore more about Kotlin-related topics, subscribe to my newsletter at  &lt;a href="https://fugisawa.com/" rel="noopener noreferrer"&gt;https://fugisawa.com/&lt;/a&gt; and stay tuned for more insights and updates.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>designpatterns</category>
      <category>backend</category>
      <category>kotlinserverside</category>
    </item>
    <item>
      <title>Kotlin Devs Brasil: Fortalecendo a Comunidade Kotlin no Brasil 🚀</title>
      <dc:creator>Lucas Fugisawa</dc:creator>
      <pubDate>Tue, 27 Feb 2024 02:16:49 +0000</pubDate>
      <link>https://dev.to/lucasfugisawa/kotlin-devs-brasil-fortalecendo-a-comunidade-kotlin-no-brasil-4e4c</link>
      <guid>https://dev.to/lucasfugisawa/kotlin-devs-brasil-fortalecendo-a-comunidade-kotlin-no-brasil-4e4c</guid>
      <description>&lt;p&gt;Hoje, quero compartilhar com vocês algo que tem ocupado minha mente e coração nos últimos tempos: a criação da Kotlin Devs Brasil, uma comunidade dedicada aos desenvolvedores Kotlin no Brasil.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que uma comunidade Kotlin?
&lt;/h2&gt;

&lt;p&gt;A pergunta que pode estar passando pela sua cabeça é: &lt;em&gt;"Por que criar uma comunidade Kotlin agora?"&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Bem, Kotlin tem se tornado uma linguagem cada vez mais popular. Apesar disso, percebemos uma lacuna significativa no Brasil: a falta de um espaço onde possamos nos conectar, compartilhar e crescer juntos como desenvolvedores Kotlin.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que esperar da Kotlin Devs Brasil?
&lt;/h2&gt;

&lt;p&gt;A Kotlin Devs Brasil não é apenas mais um grupo ou fórum. É um espaço para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Colaboração: Um espaço para pessoas trabalharem juntas em projetos, compartilhando conhecimento e melhores práticas.&lt;/li&gt;
&lt;li&gt;Aprendizado: Desde iniciantes até veteranos, todos têm algo a aprender ou ensinar.&lt;/li&gt;
&lt;li&gt;Oportunidades: Seja você em busca de uma nova oportunidade de carreira ou alguém procurando talentos, vem com a gente!&lt;/li&gt;
&lt;li&gt;Eventos e Workshops: Organizaremos encontros online e, eventualmente, presenciais para fortalecer nossa comunidade.&lt;/li&gt;
&lt;li&gt;Discussões: Um lugar para tirar dúvidas, discutir tendências e muito mais.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Por que participar?
&lt;/h2&gt;

&lt;p&gt;Participar de uma comunidade como a Kotlin Devs Brasil é sobre fazer parte de algo maior, contribuir para o crescimento coletivo e encontrar pessoas que compartilham dos mesmos interesses e paixões que você.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Crescimento Pessoal e Profissional&lt;/strong&gt;: A troca de experiências e conhecimento nos torna melhores desenvolvedores e pessoas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Networking&lt;/strong&gt;: Conecte-se com profissionais de todo o Brasil, abrindo portas para novas oportunidades.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contribuição&lt;/strong&gt;: Contribua com o crescimento da comunidade Kotlin no Brasil, ajudando a moldar o futuro da tecnologia no país.&lt;/p&gt;

&lt;p&gt;Junte-se a nós!&lt;/p&gt;

&lt;p&gt;Estamos apenas começando, e sua participação é fundamental para construirmos uma comunidade sólida e acolhedora. Se você ama Kotlin ou está curioso sobre a linguagem, este é o seu lugar.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://kotlinbr.dev/" rel="noopener noreferrer"&gt;https://kotlinbr.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Estamos ansiosos para recebê-lo(a) e crescermos juntos. Vamos fortalecer a presença de Kotlin no Brasil e mostrar o talento incrível que temos aqui. Junte-se a nós nessa jornada!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>programming</category>
      <category>community</category>
      <category>discord</category>
    </item>
    <item>
      <title>Kotlin Design Patterns: Simplifying the Observer Pattern</title>
      <dc:creator>Lucas Fugisawa</dc:creator>
      <pubDate>Mon, 26 Feb 2024 10:54:21 +0000</pubDate>
      <link>https://dev.to/lucasfugisawa/kotlin-design-patterns-simplifying-the-observer-pattern-1bc3</link>
      <guid>https://dev.to/lucasfugisawa/kotlin-design-patterns-simplifying-the-observer-pattern-1bc3</guid>
      <description>&lt;p&gt;The Observer Pattern is a behavioral design pattern where an object (the subject) maintains a list of its dependents (observers), and notifies them automatically of any state changes.&lt;/p&gt;

&lt;p&gt;This pattern ensures that multiple objects are notified when certain state changes occur. It's widely used in implementing distributed event handling systems.&lt;/p&gt;

&lt;p&gt;The Observer Pattern decouples the subject from its observers and allows for dynamic addition or removal of observers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approaches in Java
&lt;/h2&gt;

&lt;p&gt;Let’s consider a weather station that notifies displays when the temperature changes. Check this &lt;strong&gt;Java&lt;/strong&gt; example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Observer Interface:&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Observer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Subject Interface:&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Subject&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;registerObserver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Observer&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;removeObserver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Observer&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;notifyObservers&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Concrete Subject:&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherStation&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Subject&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Observer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;observers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setTemperature&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;notifyObservers&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;registerObserver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Observer&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;observers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;removeObserver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Observer&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;observers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;notifyObservers&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Observer&lt;/span&gt; &lt;span class="n"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;observers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;observer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Concrete Observer:&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Display&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Observer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;displayId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Display&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;displayId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayId&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;": Temperature updated: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Client:&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherApp&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;WeatherStation&lt;/span&gt; &lt;span class="n"&gt;station&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WeatherStation&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Display&lt;/span&gt; &lt;span class="n"&gt;display1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Display&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Display 1"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Display&lt;/span&gt; &lt;span class="n"&gt;display2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Display&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Display 2"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;registerObserver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;display1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;registerObserver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;display2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setTemperature&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this &lt;strong&gt;Java&lt;/strong&gt; example, &lt;code&gt;WeatherStation&lt;/code&gt; is the subject, and &lt;code&gt;Display&lt;/code&gt; is an observer that updates when the temperature changes. Both displays &lt;code&gt;display1&lt;/code&gt; and &lt;code&gt;display2&lt;/code&gt; are notified (&lt;code&gt;update(float temperature)&lt;/code&gt;) when the station temperature changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functional approach in Java 8+
&lt;/h3&gt;

&lt;p&gt;You can use &lt;strong&gt;Java 8+&lt;/strong&gt; functional features to simplify the Observer pattern and achive a very similar approach using functional interfaces and Java's lambda expressions.&lt;/p&gt;

&lt;p&gt;Here’s how you can adapt the Weather Station example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.ArrayList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.function.Consumer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherStation&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Consumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Float&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;onTemperatureChangeListeners&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setTemperature&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;notifyTemperatureChange&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;notifyTemperatureChange&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;newTemperature&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;onTemperatureChangeListeners&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newTemperature&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onTemperatureChange&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Consumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Float&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;onTemperatureChangeListeners&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage:&lt;/span&gt;
&lt;span class="nc"&gt;WeatherStation&lt;/span&gt; &lt;span class="n"&gt;station&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WeatherStation&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Registering listeners using lambda expressions:&lt;/span&gt;
&lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onTemperatureChange&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Display 1: Temperature updated to "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onTemperatureChange&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Display 2: Temperature updated to "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Simulating a temperature change:&lt;/span&gt;
&lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setTemperature&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this &lt;strong&gt;Java&lt;/strong&gt; example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The &lt;code&gt;WeatherStation&lt;/code&gt; class maintains a list of &lt;code&gt;Consumer&amp;lt;Float&amp;gt;&lt;/code&gt; objects, which are functional interfaces in Java that can be used with lambda expressions.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;onTemperatureChange&lt;/code&gt; method allows registering &lt;code&gt;Consumer&lt;/code&gt; lambda expressions that will be called when the temperature changes.&lt;/li&gt;
&lt;li&gt;  When &lt;code&gt;setTemperature&lt;/code&gt; is called, it triggers &lt;code&gt;notifyTemperatureChange&lt;/code&gt;, which executes all registered lambda expressions with the new temperature.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Kotlin's Approach:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Kotlin&lt;/strong&gt; provides observer delegates feature. &lt;code&gt;Delegates.observable()&lt;/code&gt; simplifies the observer pattern implementation for objects properties changes:&lt;/p&gt;

&lt;p&gt;You can combine observer delegates to observe property changes and higher-order functions to register callbacks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlin.properties.Delegates&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherStation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Observable property with callbacks:&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Float&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nc"&gt;Delegates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newValue&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;onTemperatureChangeListeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// List of callbacks:&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;onTemperatureChangeListeners&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;(&lt;/span&gt;&lt;span class="nc"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// Function to add callbacks:&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onTemperatureChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;onTemperatureChangeListeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Client:&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;station&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WeatherStation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// Registering callbacks:&lt;/span&gt;
    &lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onTemperatureChange&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Display 1: Temperature updated to $it"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onTemperatureChange&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Display 2: Temperature updated to $it"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Simulating temperature change:&lt;/span&gt;
    &lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;30f&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this &lt;strong&gt;Kotlin&lt;/strong&gt; implementation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The &lt;code&gt;temperature&lt;/code&gt; property in &lt;code&gt;WeatherStation&lt;/code&gt; is an observable property. When it changes, all registered callbacks in &lt;code&gt;onTemperatureChangeListeners&lt;/code&gt; are invoked.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;onTemperatureChange&lt;/code&gt; method allows registration of lambda expressions (callbacks) that react to temperature changes.&lt;/li&gt;
&lt;li&gt;  Clients register callbacks to &lt;code&gt;WeatherStation&lt;/code&gt; which get executed whenever the &lt;code&gt;temperature&lt;/code&gt; property changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Benefits of This Approach:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Simplicity:&lt;/strong&gt; This approach simplifies the observer pattern by eliminating the need for interfaces and concrete observer classes.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Flexibility:&lt;/strong&gt; It's easy to add or remove behaviors (callbacks) dynamically at runtime.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Expressiveness:&lt;/strong&gt; Leveraging Kotlin's language features results in more readable and maintainable code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kotlin Features Simplifying the Observer Pattern
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Higher-Order Functions and Lambdas:&lt;/strong&gt; Enables concise observer implementation using functions (behavior) as parameters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delegated Properties (&lt;code&gt;Delegates.observable()&lt;/code&gt;):&lt;/strong&gt; Simplifies property change observation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Kotlin’s &lt;code&gt;Delegates.observable()&lt;/code&gt; offers a concise and powerful alternative to the traditional observer pattern, especially for simple use cases. For more complex scenarios, the standard implementation is still useful and can be implemented concisely.&lt;/p&gt;

&lt;p&gt;--&lt;br&gt;
This article was originally posted to my Lucas Fugisawa on Kotlin blog, at: &lt;a href="https://fugisawa.com/kotlin-design-patterns-simplifying-the-observer-pattern/" rel="noopener noreferrer"&gt;https://fugisawa.com/kotlin-design-patterns-simplifying-the-observer-pattern/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To explore more about design patterns and other Kotlin-related topics, subscribe to my newsletter on &lt;a href="https://fugisawa.com/" rel="noopener noreferrer"&gt;https://fugisawa.com/&lt;/a&gt; and stay tuned for more insights and updates.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>backend</category>
      <category>designpatterns</category>
      <category>kotlinserverside</category>
    </item>
    <item>
      <title>Kotlin Design Patterns: Simplifying the Proxy Pattern</title>
      <dc:creator>Lucas Fugisawa</dc:creator>
      <pubDate>Tue, 20 Feb 2024 15:45:49 +0000</pubDate>
      <link>https://dev.to/lucasfugisawa/kotlin-design-patterns-simplifying-the-proxy-pattern-52o</link>
      <guid>https://dev.to/lucasfugisawa/kotlin-design-patterns-simplifying-the-proxy-pattern-52o</guid>
      <description>&lt;p&gt;The Proxy Pattern is a structural design pattern in object-oriented programming. It provides a surrogate or placeholder for another object to control access to it. This pattern creates a 'proxy' object that acts as an intermediary between the client and the real object.&lt;/p&gt;

&lt;p&gt;This pattern is useful when direct access to an object is impractical or impossible. For example: when an object is remote, expensive to create, or needs additional security.&lt;/p&gt;

&lt;p&gt;It's widely used in software development for several key purposes. The main use cases are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lazy Initialization (Virtual Proxy):&lt;/strong&gt; Delays the creation of expensive objects until necessary, saving resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access Control (Protection Proxy):&lt;/strong&gt; Manages access to an object, allowing or denying operations based on permission checks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Remote Object Access (Remote Proxy):&lt;/strong&gt; Represents an object in a different location, handling communication in networked applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logging Requests (Logging Proxy):&lt;/strong&gt; Records operations on an object, useful for debugging and monitoring.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Caching:&lt;/strong&gt; Stores results of operations, returning cached data for repeated requests to enhance performance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's dive into two of those use cases. In these examples, we will not consider coupling, orthogonality and best practices because we want to focus on the pattern itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy Initialization (Virtual Proxy) example
&lt;/h3&gt;

&lt;h4&gt;
  
  
  The base classes:
&lt;/h4&gt;

&lt;p&gt;Let's consider a very simple and hypothetic &lt;code&gt;DatabaseQuery&lt;/code&gt; interface and its implementation. &lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Java&lt;/strong&gt; solution is usually like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;DatabaseQuery&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RealDatabaseQuery&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DatabaseQuery&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Query Result"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;strong&gt;Kotlin&lt;/strong&gt;, we would have this equivalent code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;DatabaseQuery&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RealDatabaseQuery&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;DatabaseQuery&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Query Result"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  The proxy class:
&lt;/h4&gt;

&lt;p&gt;The following &lt;strong&gt;Java&lt;/strong&gt; class allows for a lazy &lt;code&gt;DatabaseQuery&lt;/code&gt; that will instantiate the &lt;code&gt;RealDatabaseQuery&lt;/code&gt; only when (and if) needed - that is: when &lt;code&gt;execute()&lt;/code&gt; is called.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LazyDatabaseQuery&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DatabaseQuery&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;RealDatabaseQuery&lt;/span&gt; &lt;span class="n"&gt;realQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;realQuery&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;realQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RealDatabaseQuery&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;realQuery&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;strong&gt;Kotlin&lt;/strong&gt;, you can use lazy initialization feature to simplify the implementation of the Lazy Initialization Proxy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LazyDatabaseQuery&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;DatabaseQuery&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;realQuery&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;lazy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;RealDatabaseQuery&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;realQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;lazy&lt;/code&gt; keyword is used for lazy initialization of &lt;code&gt;RealDatabaseQuery&lt;/code&gt;. This ensures that &lt;code&gt;RealDatabaseQuery&lt;/code&gt; is only created when it's first needed, adhering to the principles of the Lazy Initialization Proxy pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging Requests (Logging Proxy) example
&lt;/h3&gt;

&lt;p&gt;This proxy logs each action performed on an object. It's useful for monitoring activities, debugging, or auditing system usage.&lt;/p&gt;

&lt;h4&gt;
  
  
  The base classes:
&lt;/h4&gt;

&lt;p&gt;Let's define an interface &lt;code&gt;DataService&lt;/code&gt; with a method &lt;code&gt;fetchData()&lt;/code&gt;. Wel'll also define &lt;code&gt;RealDataService&lt;/code&gt;, a class implementing this interface, where &lt;code&gt;fetchData()&lt;/code&gt; would fetch and return data from a data source.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;DataService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;fetchStatistics&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RealDataService&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DataService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Data from service"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;fetchStatistics&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"999"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;strong&gt;Kotlin&lt;/strong&gt;, we would have this equivalent code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;DataService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fetchStatistics&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RealDataService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;DataService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Data from service"&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fetchStatistics&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"999"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  The proxy class:
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;LoggingDataServiceProxy&lt;/code&gt; &lt;strong&gt;Java&lt;/strong&gt; class in implements a proxy for &lt;code&gt;DataService&lt;/code&gt;. It logs a message each time its &lt;code&gt;fetchData&lt;/code&gt; method is called, then delegates the actual data fetching to the encapsulated &lt;code&gt;DataService&lt;/code&gt; instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoggingDataServiceProxy&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DataService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;DataService&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;LoggingDataServiceProxy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DataService&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt; 

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fetching data..."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fetchData&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;fetchStatistics&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fetchData&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;strong&gt;Kotlin&lt;/strong&gt;, we can make use of class delegation to easily intercept and log only the desired methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoggingDataServiceProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;realService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;DataService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;DataService&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;realService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LOG: Fetching data..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;realService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kotlin's class delegation (&lt;code&gt;by realService&lt;/code&gt;) simplifies forwarding calls while allowing override for logging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;In Kotlin, the Proxy Pattern is enhanced (or even made unnecessary) by language features like class delegation, delegated properties and lazy initialization. These features allow for more concise and expressive implementations.&lt;/p&gt;

&lt;p&gt;--&lt;br&gt;
This article was originally posted to my Lucas Fugisawa on Kotlin blog, at: &lt;a href="https://fugisawa.com/kotlin-design-patterns-simplifying-the-proxy-pattern/" rel="noopener noreferrer"&gt;https://fugisawa.com/kotlin-design-patterns-simplifying-the-proxy-pattern/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To explore more about design patterns and other Kotlin-related topics, subscribe to my newsletter on &lt;a href="https://fugisawa.com/" rel="noopener noreferrer"&gt;https://fugisawa.com/&lt;/a&gt; and stay tuned for more insights and updates.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>backend</category>
      <category>designpatterns</category>
      <category>kotlinserverside</category>
    </item>
    <item>
      <title>Kotlin Design Patterns: Simplifying the Decorator Pattern</title>
      <dc:creator>Lucas Fugisawa</dc:creator>
      <pubDate>Thu, 15 Feb 2024 15:11:11 +0000</pubDate>
      <link>https://dev.to/lucasfugisawa/kotlin-design-patterns-simplifying-the-decorator-pattern-42n9</link>
      <guid>https://dev.to/lucasfugisawa/kotlin-design-patterns-simplifying-the-decorator-pattern-42n9</guid>
      <description>&lt;p&gt;The Decorator Pattern is a flexible alternative to subclassing for extending functionality. It allows behavior to be added to individual objects without affecting the other objects from the same class.&lt;/p&gt;

&lt;p&gt;It is particularly useful when changes are needed during runtime. Also, it's useful when subclassing would result in an exponential rise of new classes.&lt;/p&gt;

&lt;p&gt;The pattern involves an interface, concrete implementations of this interface, and decorator classes that 'wrap' the original classes. The decorators implement the same interface and forward calls to the wrapped object, optionally adding their own behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Traditional Approach in Java:
&lt;/h2&gt;

&lt;p&gt;Let's consider a &lt;code&gt;UserRepository&lt;/code&gt; interface and its implementation. We'll also have a &lt;code&gt;UsernameValidator&lt;/code&gt; as a decorator to add validation logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Interface:&lt;/span&gt;
&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt;  

&lt;span class="c1"&gt;// Concrete Implementation:&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRepositoryImpl&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;userList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;  

    &lt;span class="nd"&gt;@Override&lt;/span&gt;  
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;userList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt;  

    &lt;span class="nd"&gt;@Override&lt;/span&gt;  
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="n"&gt;userList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt;  

&lt;span class="c1"&gt;// Decorator:&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsernameValidator&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;MAX_NAME_LENGTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;MIN_NAME_LENGTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UsernameValidator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt;  

    &lt;span class="nd"&gt;@Override&lt;/span&gt;  
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt;  

    &lt;span class="nd"&gt;@Override&lt;/span&gt;  
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MIN_NAME_LENGTH&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;MAX_NAME_LENGTH&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"User name is not of valid length"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
        &lt;span class="o"&gt;}&lt;/span&gt;  
        &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this Java example, &lt;code&gt;UsernameValidator&lt;/code&gt; adds a validation layer to &lt;code&gt;UserRepositoryImpl&lt;/code&gt; without modifying its original code.&lt;/p&gt;

&lt;p&gt;Notice that the method &lt;code&gt;get(String userName)&lt;/code&gt; simply delegates to the target &lt;code&gt;repository&lt;/code&gt;, while &lt;code&gt;set(String userName, String user)&lt;/code&gt; first decorates (adds new functionality) and then delegates to the target &lt;code&gt;repository&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This pattern allows &lt;code&gt;UsernameValidator&lt;/code&gt; to control how and when it calls into the composed &lt;code&gt;UserRepository&lt;/code&gt;, providing a clear structure for adding or modifying behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kotlin's Approach:
&lt;/h2&gt;

&lt;p&gt;In Kotlin, we actually have two usual implementations. The first one uses composition and is similar to the Java solution. The second one uses Kotlin class delegation features that allow a simpler and more concise solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decorating by Composition (like the Java solution)
&lt;/h3&gt;

&lt;p&gt;Decoration by composition involves explicitly composing a class with another class it wishes to decorate, rather than using class delegation. Here's the Kotlin implementation of the UserRepository example using decoration by composition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Interface:&lt;/span&gt;
&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Concrete Implementation:&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRepositoryImpl&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;userList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableMapOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;userList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Decorator using Composition:&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsernameValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nc"&gt;MIN_NAME_LENGTH&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="nc"&gt;MAX_NAME_LENGTH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"User name is not of valid length"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;MAX_NAME_LENGTH&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;MIN_NAME_LENGTH&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this composition-based approach, the &lt;code&gt;UsernameValidator&lt;/code&gt; class explicitly contains a &lt;code&gt;UserRepository&lt;/code&gt; instance (&lt;code&gt;repository&lt;/code&gt;) and uses this instance to perform the actual work. It overrides the &lt;code&gt;set&lt;/code&gt; method to add validation logic before delegating the setting of the user to the composed &lt;code&gt;UserRepository&lt;/code&gt; object.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decorating by Delegation (using Kotlin class delegation)
&lt;/h3&gt;

&lt;p&gt;Kotlin's features, such as class delegation, make implementing the Decorator Pattern simpler and more concise.&lt;/p&gt;

&lt;p&gt;Using the same &lt;code&gt;UserRepository&lt;/code&gt; example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Interface:&lt;/span&gt;
&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Concrete Implementation:&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRepositoryImpl&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;userList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableMapOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;userList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Decorator with Class Delegation:&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsernameValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;repository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nc"&gt;MIN_NAME_LENGTH&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="nc"&gt;MAX_NAME_LENGTH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"User name is not of valid length"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;MAX_NAME_LENGTH&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;MIN_NAME_LENGTH&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Kotlin, the &lt;code&gt;UsernameValidator&lt;/code&gt; class uses class delegation (&lt;code&gt;by repository&lt;/code&gt;) to implement &lt;code&gt;UserRepository&lt;/code&gt;. This delegates all calls to the provided &lt;code&gt;UserRepository&lt;/code&gt; instance, except for the overridden &lt;code&gt;set&lt;/code&gt; method.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kotlin Features Simplifying the Decorator Pattern
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Class Delegation:&lt;/strong&gt; Kotlin simplifies the Decorator Pattern by allowing delegation of the interface's implementation to another object. This removes the need for explicit forwarding of undecorated methods calls.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Final Thougths
&lt;/h2&gt;

&lt;p&gt;In Kotlin, the Decorator Pattern is simplified through features like class delegation, enhancing readability and reducing boilerplate code. Understanding these features allows Kotlin developers to implement design patterns in a more efficient and effective manner.&lt;/p&gt;

&lt;p&gt;--&lt;br&gt;
This article was originally posted to my Lucas Fugisawa on Kotlin blog, at: &lt;a href="https://fugisawa.com/kotlin-design-patterns-simplifying-the-decorator-pattern/" rel="noopener noreferrer"&gt;https://fugisawa.com/kotlin-design-patterns-simplifying-the-decorator-pattern/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To explore more about design patterns and other Kotlin-related topics, subscribe to my newsletter on &lt;a href="https://fugisawa.com/" rel="noopener noreferrer"&gt;https://fugisawa.com/&lt;/a&gt; and stay tuned for more insights and updates.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>designpatterns</category>
      <category>backend</category>
      <category>kotlinserverside</category>
    </item>
    <item>
      <title>Kotlin Design Patterns: Simplifying the Prototype Pattern</title>
      <dc:creator>Lucas Fugisawa</dc:creator>
      <pubDate>Mon, 12 Feb 2024 12:30:15 +0000</pubDate>
      <link>https://dev.to/lucasfugisawa/kotlin-design-patterns-simplifying-the-prototype-pattern-2p72</link>
      <guid>https://dev.to/lucasfugisawa/kotlin-design-patterns-simplifying-the-prototype-pattern-2p72</guid>
      <description>&lt;p&gt;We use the Prototype Pattern when creating new instances from scratch is more expensive than copying existing ones.&lt;/p&gt;

&lt;p&gt;So, instead of instantiating new objects, you can have a prototype from which clones / copies are made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Traditional Approach in Java:
&lt;/h2&gt;

&lt;p&gt;In this Java example, &lt;code&gt;GraphicElement&lt;/code&gt; represents a complex graphic element with complex initialization logic, such as loading textures, calculating geometry, etc.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PrototypeCapable&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Cloneable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
    &lt;span class="nc"&gt;PrototypeCapable&lt;/span&gt; &lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;CloneNotSupportedException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt;  

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GraphicElement&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PrototypeCapable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Represents complex geometry  &lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
    &lt;span class="c1"&gt;// Getters and setters ommited.  &lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;GraphicElement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;texture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;texture&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;texture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Some complex initialization logic here (loading textures, calculating geometry, etc.)"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;  

  &lt;span class="nd"&gt;@Override&lt;/span&gt;  
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;GraphicElement&lt;/span&gt; &lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;CloneNotSupportedException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GraphicElement&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clone&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="c1"&gt;// Usage:  &lt;/span&gt;
&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;initialPoints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"y1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"x2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"y2"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
&lt;span class="nc"&gt;GraphicElement&lt;/span&gt; &lt;span class="n"&gt;originalElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GraphicElement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Red"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;initialPoints&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"BrickTexture"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
&lt;span class="nc"&gt;GraphicElement&lt;/span&gt; &lt;span class="n"&gt;clonedElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;originalElement&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clone&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;  
&lt;span class="n"&gt;clonedElement&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setColor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Blue"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cloned Element Color: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;clonedElement&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getColor&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Output: Blue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, you can see cloning is used to create a new element &lt;code&gt;clonedElement&lt;/code&gt; based on the existing &lt;code&gt;originalElement&lt;/code&gt;, instead of instatiating a new object from scratch. Also, the &lt;code&gt;color&lt;/code&gt; is changed from red to blue on the &lt;code&gt;clonedElement&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kotlin's Approach:
&lt;/h2&gt;

&lt;p&gt;Kotlin allows for an efficient and concise way to implement cloning of complex objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;GraphicElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;points&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;init&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texture&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;texture&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Some complex initialization logic here (loading textures, calculating geometry, etc.)"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage:&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;initialPoints&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"y1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"x2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"y2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;originalElement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GraphicElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Red"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;initialPoints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;clonedElement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;originalElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Blue"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Modifying color while cloning&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this Kotlin example, &lt;code&gt;GraphicElement&lt;/code&gt; is a data class used for creating complex graphic elements. The &lt;code&gt;copy&lt;/code&gt; method simplifies the process of cloning and modifying these elements.&lt;br&gt;
Notice that the &lt;code&gt;color&lt;/code&gt; for the &lt;code&gt;clonedElement&lt;/code&gt; can be set / changed earlier, while copying the &lt;code&gt;originalElement&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kotlin Features Simplifying the Prototype Pattern
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Data Classes&lt;/strong&gt;: Offer an inbuilt &lt;code&gt;copy&lt;/code&gt; method, streamlining the creation of prototype instances.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;&lt;code&gt;copy&lt;/code&gt; method&lt;/strong&gt;: Allows changing specific properties while copying, allowing for more concise and expressive code.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Final Thougths
&lt;/h2&gt;

&lt;p&gt;Kotlin's approach to the Prototype pattern showcases its efficiency and simplicity. Data classes and their built-in &lt;code&gt;copy&lt;/code&gt; method make the cloning process straightforward, simplifying the pattern implementation while maintaining functionality.&lt;/p&gt;

&lt;p&gt;--&lt;br&gt;
This article was originally posted to my Lucas Fugisawa on Kotlin blog, at: &lt;a href="https://fugisawa.com/kotlin-design-patterns-simplifying-the-prototype-pattern/" rel="noopener noreferrer"&gt;https://fugisawa.com/kotlin-design-patterns-simplifying-the-prototype-pattern/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To explore more about design patterns and other Kotlin-related topics, subscribe to my newsletter on &lt;a href="https://fugisawa.com/" rel="noopener noreferrer"&gt;https://fugisawa.com/&lt;/a&gt; and stay tuned for more insights and updates.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>designpatterns</category>
      <category>backend</category>
      <category>kotlinserverside</category>
    </item>
  </channel>
</rss>
