그런 throw 괜찮아요?(호루라기 발생에 대한 예외적인 시비)

괜찮아요, 괜찮아요.프라하 CEO의
이전에 나는 내가 쓴 코드를 다시 읽었는데 이런 코드가 있다는 것을 발견했다.
class Item {
    constructor(private name: string) {
        if (name.length < 4 ) {
            throw new Error('名前は四文字以上じゃないとダメだよ!')
        }
    }
}

const item1 = new Item('okなアイテム')
const item2 = new Item('ng') // throwする
가볍게 throw가 됐지만 그런 throw는 괜찮을까요?

그럼 무슨 일이 일어날까요?


초기화에 실패했을 때 어떤 논리를 실행해야 한다면, 아까 같은 코드는 호출자catch에서
class HogeUsecase {
    public do(input: string) {
        try {
            const item1 = new Item(input)
        } catch(e) {
            // ここで例外を処理する
        }
        
    }
}
그러나 "Item류는throw의 가능성이 있다"는 것은 인터페이스만 보면 모른다(TypeScript를 전제로 고려).throw에 대해 알기 위해서는 Item 코드를 이해해야 해요. 이번처럼 짧은 코드는 괜찮은데 Item이 3000줄 정도의 괴물 코드라면 무시하기 쉬워요.
Item throw를 무시한 사람을 가정하면 이러한 용례에서 Item을 초기화합니다
// このユースケースは結構大事なので失敗したら必ずメール通知する必要がある
class HogeUsecase {
    public do(input: string) {
        const item1 = new Item(input) // new: throwしないと思い込んでtry-catchの外に追加したコード

        try {
	    someNewAction(item1) // new: item1を使用する新たな処理
	    throwableImportantAction(input)
        } catch(e) {
	    // このユースケースが正常に完了しなかったらメール通知するようになっている
        }
    }
초기화에 실패하여 용례가 정상적으로 끝나지 않아도 메일 알림이 전달되지 않는 코드가 간단하게 완성되었습니다.
만약 호출자가 코드의 사용 방법에 대해 반드시 많은 것을 알아야 한다면 (예외가 발생한 것을 모르면 적절하게 사용할 수 없다), 코드를 대량으로 생산한다면, 이렇게 원래의 논리 (정상적으로 끝나지 않으면 반드시 메일 알림을 보내야 한다) 를 삭제한 코드를 잘못 쓸 위험이 증가할 것이다.
이는'정상 시스템의 처리를 모두 배제하고 즉시 이상 시스템의 지점으로 들어간다'는 예외적 특성 때문에 발생한 것으로, 이 특성이 효과가 있는 경우도 있고 효과가 없는 경우도 있기 때문에 무조건 사용하는 것은 고려할 가치가 있지 않겠는가?이런 문제를 제기하는 것이 이번 보도의 요지이다

모나드는 예외를 대신했다


예외 발생 외에 또 어떤 대책을 고려할 수 있을까?
함수형 언어를 사용하는 익숙함モナド 모델을 먼저 소개하고 싶습니다.예를 들어, Result 또는 Maybe에서 자주 나타나는 모드를 사용하면 다음과 같은 코드를 작성할 수 있습니다.
class HogeUsecase {
    public do(input: string) {
        const item1: Maybe<Item> = new Item(input) // ItemではなくMaybe<Item>型を返す
	
        try {
	    someNewAction(item1) // Itemではなく Maybe<Item> 型なのでビルドできず、実行もできない
	    throwableImportantAction(input)
        }
    }
방금 전까지만 해도 Item형이었기 때문에 썸뉴액션에 직접 맡길 수 없습니다.메이브는'아이템일 수도 있지만 그렇지 않을 수도 있으니 확인해 주세요'라는 의미를 부여한 새로운 장르로 기억된다.Maybe<Item>Maybe<Item>로 변환하려면 다음과 같은 코드를 한 번 끼워야 합니다.
if (item1.isOk()) {
  item1.value // isOk(結果)を一度チェックしないとItem型は取り出せない
}
형의 존재로 인해 컴파일러는 Item 클래스를 읽지 않아도 Item이 초기화되지 않을 가능성이 있기 때문에 예외적인 경우처럼 "에이, Item이 초기화되지 않을 때가 있나!?"이런 고려가 누락되면 발생하기 매우 어려울 것이다.물론 이런 문법이라면 이상 시스템 처리를 잊어버릴 가능성이 있기 때문에 완전히 방지하는 것은 아니지만 의외의 예외로 발생한 코드보다 이상 시스템에 존재하는 코드 위험이 줄어들 수 있음을 미리 암시하는 것이 좋다고 생각합니다.
비교해 보다
  • 예외 모드: 코드를 읽지 않으면 예외가 생길지 모르고, 예외를 포착하지 않아도 컴파일러가 알림을 주지 않는다(개인적으로는 최고다)try-catch의 끼워넣기도 깊어진다(이것도 힘들다)포착되지 않으면 예외적으로 예상치 못한 처리에 전파되고 들어갈 수 있다(이것도...)
  • 모나드의 모드: 컴파일러는 이상 시스템의 가능성을 알려줄 수 있고 검사하지 않으면 구축할 수 없다
  • 물론 예외적인 경우도 많다. 예를 들어 정상적인 시스템의 처리를 모두 패스트로 건너뛰는 것이 좋지만, 자신이 관리하는 응용 프로그램의 논리를 쓸 때 예외를 순진무구하게 사용하는 것은 더 고려할 여지가 있을 수 있다.
    "그런 throw 괜찮을까요?"
    "제일 e로 주세요."
    이런 느낌.안 그래?
    성닉스의 출현으로 성닉스 주변에 대한 불안이 있다면 이쪽 기사도 봐주세요
    https://zenn.dev/dowanna6/articles/63fdebe8dd167f

    보태다


    일반적으로 구조기로 자신의 클래스와 다른 클래스를 되돌릴 수 없기 때문에 모나도를 초기화할 때 구조기는 먼저 privte를 사용한 다음public의static 방법으로 Item을 생성한다.이런 느낌:
        const item1 = Item.instantiate()
    
    그래서 이번 예에서 코드ItemMaybe<Item>답장) 좀 이상한 코드인데 설명을 위해 간단하게 용서해 주세요.

    좋은 웹페이지 즐겨찾기