인터페이스에 대한 작은 메모

클라이언트는 현재 모놀리식 애플리케이션을 상호 연결된 일련의 서비스로 분할하기를 원했습니다. 그들은 Service Oriented Archicture (SOA) 길을 가고 싶었지만 API에서 노출하고 싶은 것과 관련하여 몇 가지 흥미로운 선택을 했습니다.

그래서 내 딸인 릴리-로즈에 대해 생각하게 되었습니다. 그녀가 꽤 어렸을 때 나는 안드로이드 폰을 가지고 있었고 그녀는 우리가 차를 탈 때 가지고 노는 것을 좋아했습니다. 어느 날 우리는 운전을 하다가 그녀가 전화에 새 아이콘이 있는 것을 발견했습니다. 그것은 그녀의 얼굴을 가지고 있었다. 그리고 그녀의 이름.

"아빠, 그게 뭔데요?"

"모르겠어요. 클릭하지 않으시겠습니까?”

그래서 그녀는 했다. 그리고 이것이 그녀가 본 것입니다.



그녀는 미소를 지었지만 혼란스러워 보였고 나에게 전화를 보여주었다(나는 그녀와 함께 뒤에 있었다). "그냥 '나를 클릭하세요'라고 되어 있습니다."

"그래서 왜 안돼?"

그래서 그녀는 그것을 클릭했고 다음과 같은 것을 보았습니다.



그런 다음 그녀는 그것을 다시 클릭했고 다음과 같은 것을 보았습니다.



그녀는 "고양이들이 우리가 실수하기를 기다리고 있다"또는 "변호사는 법정에서 무엇을 입나요?"와 같은 이상한 말을 계속 듣습니다. 소송.” (나는 그것을 설명해야 했다) 그리고 그녀는 웃고 폭발했다. 그녀가 버튼을 누를 때마다 임의의 배경색에 임의의 농담이 표시됩니다. 그것을 아빠의 승리로 생각하십시오.

그렇다면 이것이 API와 어떤 관련이 있습니까? 다른 소프트웨어가 아니라 내 딸을 위한 애플리케이션이지만 API로 생각할 수 있습니다. 어린 딸도 사용법을 알 수 있도록 만들었습니다. 나는 심지어 그녀에게서 버그 보고서를 받았습니다! (“아빠, 안 돼요!”) 때때로 그녀가 같은 농담과 같은 배경색을 두 번 받는다는 것을 깨닫는 데 시간이 좀 걸렸습니다. 그래서 나는 그녀가 같은 농담을 두 번 연속으로 듣지 않도록 했습니다.

이제 소프트웨어 개발자로서 "Ovid는 어떤 프로그래밍 언어를 사용했습니까?"또는 "농담이 데이터베이스에 저장되어 있습니까?"내 딸은 신경 쓰지 않았고 당신도 마찬가지입니다. 사용된 기술은 애플리케이션을 구축하기 위한 스캐폴딩이었습니다. 애플리케이션의 인터페이스는 스캐폴딩을 숨겨야 합니다.

비계를 노출하는 것은 신뢰할 수 있다는 암묵적인 약속을 하는 것입니다. 당신이 그 약속을 어기면 사람들은 불행해질 것입니다.

솔직히 너무 사소해서 글을 쓴다는게 우스꽝스럽게 느껴지지만 위반하는 경우를 너무 많이 봐서 글을 쓰게 되었습니다. 나는 어떤 언어를 사용했는가? 무슨 상관이야? 앱이 동일하다면 제 딸은 여전히 ​​웃을 것입니다. 농담이 하드 코딩되어 데이터베이스에 저장되고 원격 서비스에서 가져왔습니까? 다시 말하지만 그것은 중요하지 않습니다. 그리고 인터페이스에 노출되어서는 안됩니다.

이러한 기술적 결정이 중요하지 않다는 것은 아닙니다. 최종 소비자가 알 필요가 없다는 것입니다. 숨길 때 변경하거나 수정할 수 있습니다. 애플리케이션에 있든 API에 있든 정보를 노출하면 귀하가 제공하는 것의 소비자는 이러한 세부 정보에 의존하는 법을 배우게 됩니다. 그러지 마세요.


기술적 세부 사항을 알아야 하는 사람들을 위해 Kotlin으로 작성된 앱의 핵심은 다음과 같습니다.

package io.github.ovid.lilly_roserules

import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import kotlin.random.Random
import androidx.constraintlayout.widget.ConstraintLayout

class MainActivity : AppCompatActivity() {
    internal lateinit var layout: ConstraintLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        layout = findViewById(R.id.mainlayout)

        val rollButton    = findViewById<Button>(R.id.rollButton)
        val quoteTextView = findViewById<TextView>(R.id.quoteTextView)

        val messages      = getMessages()
        val colors        = getColors()
        var lastChoice    = 0

        rollButton.setOnClickListener {
            var thisChoice = 0

            // make sure we never get the same message twice in a row
            while (thisChoice == lastChoice) {
                thisChoice = Random.nextInt(messages.size)
            }
            lastChoice = thisChoice

            // picks a random message
            quoteTextView.text = messages[thisChoice]

            // picks a random background color
            val randColor = Random.nextInt(colors.size)
            layout.setBackgroundColor(Color.parseColor(colors[randColor]))
        }
    }

    fun getColors():Array<String> {
        val colors = arrayOf(
            // list of colors
        )
        return colors
    }

    fun getMessages():Array<String> {
        val messages = arrayOf(
            // list of jokes
        )
        return messages
    }
}


그것은 매우 간단했고 딸을 즐겁게하기 위해 빠르게 함께 던져졌습니다. 하지만 "생산 준비"상태로 만들어야 하는 경우 모든 중요한 부분이 숨겨져 있었습니다. 이것은 API가 아니라 스마트폰의 애플리케이션이었기 때문에 어리석은 소리로 들릴 수 있지만 제가 본 이 실수를 반복해서 설명하는 더 나은 비유를 찾기가 어렵습니다.

좋은 웹페이지 즐겨찾기