見出し画像

プログラミング言語なんでもできますが伝わらない問題2

もう10年ぐらい同じことで悩んでいる気がするのは、業務に差し障るようなことがないからなんですが、やっぱりバシッと説明できるようになりたい。

そんな思いから前回の記事を書いてみて、反響もあるようなないような感じでひまなので、続編を書いてみようと思いました。


アンドロイドアプリの通信最適化

これは非技術者の営業の方に説明したら、身近なものでイメージしやすいし、できそうって思われるんじゃないだろうかという提案。

1. HTTP通信の最適化

HTTP通信は、モバイルアプリで一般的に使用される通信方法です。

最適化のための方法としては、以下の点が挙げられます。

  • キャッシュの使用: サーバーから頻繁に取得するデータをローカルにキャッシュし、ネットワークの使用を減らす。

  • 圧縮: サーバーとクライアント間のデータを圧縮して送受信することで、データ転送量を削減する。

  • バッチリクエスト: 複数のリクエストをまとめて送信することで、ネットワークオーバーヘッドを減らす。

// 依存関係にOkHttpを追加します。
// implementation 'com.squareup.okhttp3:okhttp:4.9.3'

import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.File

fun setupHttpClient(context: Context): OkHttpClient {
    // キャッシュサイズを設定(例: 10MB)
    val cacheSize = 10 * 1024 * 1024L // 10MB
    val cacheDir = File(context.cacheDir, "http_cache")
    val cache = Cache(cacheDir, cacheSize)

    return OkHttpClient.Builder()
        .cache(cache)
        .addInterceptor { chain ->
            var request = chain.request()
            request = if (hasNetwork(context))
                request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build()
            else
                request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24).build()
            chain.proceed(request)
        }
        .build()
}

fun hasNetwork(context: Context): Boolean {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val activeNetwork = connectivityManager.activeNetworkInfo
    return activeNetwork != null && activeNetwork.isConnected
}

fun fetchData(client: OkHttpClient, url: String): String? {
    val request = Request.Builder()
        .url(url)
        .build()

    val response: Response = client.newCall(request).execute()
    return if (response.isSuccessful) {
        response.body?.string()
    } else {
        null
    }
}
  • setupHttpClient: OkHttpクライアントを設定し、キャッシュを設定します。ネットワーク接続がある場合はキャッシュ時間を設定し、ない場合はキャッシュされたデータを使用します。

  • hasNetwork: ネットワークの有無をチェックします。

  • fetchData: 指定したURLからデータを取得する関数です。

2. データの圧縮

データ圧縮を使用することで、送受信するデータ量を減らし、通信コストを削減できます。

一般的には、サーバー側でgzip圧縮を使用し、クライアントで自動的に解凍します。

OkHttpを使用してgzip圧縮を有効にするには、リクエストヘッダーに設定を追加します。

fun fetchCompressedData(client: OkHttpClient, url: String): String? {
    val request = Request.Builder()
        .url(url)
        .header("Accept-Encoding", "gzip")
        .build()

    val response: Response = client.newCall(request).execute()
    return if (response.isSuccessful) {
        response.body?.string()
    } else {
        null
    }
}

3. バッチリクエスト

複数のリクエストをまとめて1つのリクエストとして送信することで、ネットワークのオーバーヘッドを削減できます。

具体的な実装はバックエンドとクライアントの設計に依存しますが、バッチリクエストを送ることで通信回数を減らすことができます。

// バッチリクエストのためのJSONオブジェクトを作成
val batchRequestBody = """
{
    "requests": [
        { "url": "https://api.example.com/data1" },
        { "url": "https://api.example.com/data2" },
        { "url": "https://api.example.com/data3" }
    ]
}
"""

// バッチリクエストを送信
fun sendBatchRequest(client: OkHttpClient, url: String, batchRequestBody: String): String? {
    val requestBody = batchRequestBody.toRequestBody("application/json".toMediaTypeOrNull())
    val request = Request.Builder()
        .url(url)
        .post(requestBody)
        .build()

    val response: Response = client.newCall(request).execute()
    return if (response.isSuccessful) {
        response.body?.string()
    } else {
        null
    }
}

4. 非同期処理とリトライ

通信の失敗時にリトライを行い、ユーザーに不便を感じさせないための非同期処理が重要です。

fun fetchDataAsync(client: OkHttpClient, url: String, retries: Int = 3, callback: (String?) -> Unit) {
    val request = Request.Builder()
        .url(url)
        .build()

    client.newCall(request).enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            if (retries > 0) {
                fetchDataAsync(client, url, retries - 1, callback) // リトライ
            } else {
                callback(null) // 失敗
            }
        }

        override fun onResponse(call: Call, response: Response) {
            if (response.isSuccessful) {
                callback(response.body?.string())
            } else {
                callback(null)
            }
        }
    })
}

非同期でデータを取得し、失敗した場合はリトライを行います。

リトライ回数を設定することで、通信失敗時のユーザー体験を向上させます。

説明のしかた

完全に理解はしていないけど、こういうことをちょっと聞いたら「あーね」って感じで理解できます。

そんなことを言ったらまた疑われるので、ぐっとその言葉は言うのを我慢して、下記のように説明します。

スマホアプリを使うときって、アプリがインターネットを通じて情報をやり取りしますよね。でも、アプリがたくさんデータを使うと、ユーザーのデータ通信量が増えたり、アプリが遅くなったり、スマホの電池が早く減ったりするんです。これって、ユーザーにとってはストレスになっちゃうこともあります。だから、私たちはアプリが使うデータ量をできるだけ減らして、より効率的にする工夫をしています。たとえば、よく使う情報はスマホの中に一時的に保存しておいて、インターネットにつなぐ回数を減らすようにしています。これを『キャッシュ』って呼んでいます。また、一度に大量の情報を送るんじゃなくて、必要な情報だけを少しずつ送るようにしたり、データを圧縮して小さくしてから送ることもあります。これをすると、アプリがサクサク動いて、ユーザーも快適に使えますよね。さらに、アプリがエラーでデータを取得できなかったときに自動で何度か再試行する仕組みも入れていて、ユーザーが失敗したように感じることを減らす工夫もしています。要するに、アプリの裏側で効率よくデータをやり取りすることで、ユーザーの負担を減らし、より快適な使い心地を提供しようとしているんです。

※ChatGPT4o作

まとめ

給料は安く良い人を使いたいというのは多くの経営者の方が思っていることだと思いますが、上手に説明をして認めてもらえたら、それはお互いに価値のあることだと思います。

口下手な技術者の方も多いと思いますが、上手な自分の売り込み方や交渉力だけじゃなく技術もチームワークもコミュ力も高いレベルで身につけて、稼げる技術者になっていきたいものですね。

この記事が気に入ったらサポートをしてみませんか?