class Result {
public float data;
public string error;
public Result(float data, string error) ...
}
Result Depth3(int i)
{
if (i == 42)
return Result(13.0, null);
return Result(-1, "not match!!");
}
Result Depth2(int i)
{
var res = Depth3(i);
if (res.data == -1)
return res;
Console.WriteLine(res.data);
return res;
}
다음과 같은 단점이 있을 수 있겠다.
Result를 개발자가 직접 구현 해야 한다. 유지 보수에 대한 비용이 발생한다.
구현 하는것은 어렵지 않겠지만 개발자의 주관적인 OOP 관점에 의해 다양한 구현이 발생할 수 있다. 다른 개발자가 이를 이해하기 위한 비용이 발생한다.
fn depth_3(i: i32) -> Result<f32, String> {
if i == 42 {
Ok(13.0)
} else {
Err(String::from("Not match!"))
}
}
fn depth_2(i: i32) -> Result<f32, String> {
match depth_3(i) {
Ok(v) => {
println!("depth_2 sucess ... use {v}");
Ok(v)
},
Err(e) => return Err(e), // 에러 처리는 이 함수 호출한 곳에서 처리
}
}
fn depth_1(i: i32) -> Result<f32, String> {
match depth_2(i) {
Ok(v) => {
println!("depth_1 sucess ... use {v}");
Ok(v)
},
Err(e) => return Err(e), // 에러 처리는 이 함수 호출한 곳에서 처리
}
}
fn main() {
let res = depth_1(1);
match res {
Ok(v) => println!("process is ok ... {}", v),
Err(e) => () // 에러 처리 수행
}
}
enum Result를 제공하여 개발자가 직접 구현할 필요를 제거하였다. 그리고 Rust 만의 강력한 컴파일 검사 기능으로 버그 발생 가능성이 낮아진다.
enum Result<T, E> {
OK(T),
Err(E),
}
해당 코드는
match some_function(i) {
Ok(v) => v,
Err(e) => return Err(e),//역시 이 함수를 호출한 곳에서 처리하라고 반환
}
? 연산자를 사용하여 축약 가능하다
some_function(i)?
? 를 이용하여 코드를 개선하면 다음과 같다.
fn depth_3(i: i32) -> Result<f32, String> {
if i == 42 {
Ok(13.0)
} else {
Err(String::from("Not match!"))
}
}
fn depth_2(i: i32) -> Result<f32, String> {
let v = depth_3(i)?;// 개선
println!("depth_2 sucess ... use {v}");
Ok(v)
}
fn depth_1(i: i32) -> Result<f32, String> {
let v = depth_2(i)?;// 개선
println!("depth_1 sucess ... use {v}");
Ok(v)
}
fn main() {
let res = depth_1(1);
match res {
Ok(v) => println!("process is ok ... {}", v),
Err(e) => ()
}
}