public interface IResult<T> { void Handle(IResultHandler<T> handler); TResult Match<TResult>(Func<T, TResult> onSuccess, Func<string, TResult> onFailure); IResult<TResult> Map<TResult>(Func<T, TResult> map);}
public sealed record Success<T>(T Value) : IResult<T> { public void Handle(IResultHandler<T> handler) => handler.OnSuccess(Value); public TResult Match<TResult>(Func<T, TResult> onSuccess, Func<string, TResult> onFailure) => onSuccess(Value); public IResult<TResult> Map<TResult>(Func<T, TResult> map) => new Success<TResult>(map(Value));}
public sealed record Failure<T>(string Reason) : IResult<T> { public void Handle(IResultHandler<T> handler) => handler.OnFailure(Reason); public TResult Match<TResult>(Func<T, TResult> onSuccess, Func<string, TResult> onFailure) => onFailure(Reason); public IResult<TResult> Map<TResult>(Func<T, TResult> map) => new Failure<TResult>(Reason);}
public interface IResultHandler<T> { void OnSuccess(T value); void OnFailure(string reason);}
Result
dưới dạng ADT giúp xử lý lỗi hiệu quả hơn và tránh các ngoại lệ gây mất kiểm soát.public interface ValidationPolicy { Result<String> validate(String input);}
public class AllowAllPolicy implements ValidationPolicy { public Result<String> validate(String input) { return new Success<>(input); }}
public class EmailPolicy implements ValidationPolicy { public Result<String> validate(String input) { return input.contains("@") ? new Success<>(input) : new Failure<>("Invalid email"); }}
public interface IValidationPolicy { IResult<string> Validate(string input);}
public sealed class AllowAllPolicy : IValidationPolicy { public IResult<string> Validate(string input) => new Success<string>(input);}
public sealed class EmailPolicy : IValidationPolicy { public IResult<string> Validate(string input) => input.Contains("@") ? new Success<string>(input) : new Failure<string>("Invalid email");}
public static Result<String> getUser(String id) { return id.length() > 0 ? new Success<>("User-" + id) : new Failure<>("Empty ID");}
public static Result<Integer> getAge(String username) { return new Success<>(username.length() + 20);}
public static String pipeline(String id) { return getUser(id) .map(name -> name.toUpperCase()) .map(name -> name + "_Validated") .match(val -> "Success: " + val, err -> "Error: " + err);}
public static IResult<string> GetUser(string id) => id.Length > 0 ? new Success<string>("User-" + id) : new Failure<string>("Empty ID");
public static IResult<int> GetAge(string username) => new Success<int>(username.Length + 20);
public static string Pipeline(string id) => GetUser(id) .Map(name => name.ToUpper()) .Map(name => name + "_VALIDATED") .Match(success => $"Success: {success}", error => $"Error: {error}");
public interface UserRepository { Result<User> findById(String id);}
public class InMemoryUserRepository implements UserRepository { private final Map<String, User> users = Map.of("1", new User("1", "Alice"));
public Result<User> findById(String id) { return Optional.ofNullable(users.get(id)) .<Result<User>>map(Success::new) .orElse(new Failure<>("User not found")); }}
public interface IUserRepository { IResult<User> FindById(string id);}
public sealed class InMemoryUserRepository : IUserRepository { private readonly Dictionary<string, User> _users = new() { { "1", new User("1", "Alice") } }; public IResult<User> FindById(string id) => _users.TryGetValue(id, out var user) ? new Success<User>(user) : new Failure<User>("User not found");}
public record CreateUserCommand(String id, String name) {}
public interface CommandHandler<TCommand, TResult> { Result<TResult> handle(TCommand command);}
public class CreateUserHandler implements CommandHandler<CreateUserCommand, User> { private final UserRepository repo;
public CreateUserHandler(UserRepository repo) { this.repo = repo; }
public Result<User> handle(CreateUserCommand command) { return new Success<>(new User(command.id(), command.name())); }}
public record CreateUserCommand(string Id, string Name);
public interface ICommandHandler<TCommand, TResult> { IResult<TResult> Handle(TCommand command);}
public sealed class CreateUserHandler : ICommandHandler<CreateUserCommand, User> { public IResult<User> Handle(CreateUserCommand command) => new Success<User>(new User(command.Id, command.Name));}
Trường hợp sử dụng | Đánh giá |
---|---|
Thiết kế theo Domain-Driven Design | ✅ Rất phù hợp |
Event Sourcing / CQRS | ✅ Rất tốt |
Pipeline ETL / Dòng xử lý | ✅ Biểu đạt tốt |
Ứng dụng Web MVC đơn giản | ❌ Quá phức tạp, không cần thiết |
Hệ thống có tương tác ngoài | ✅ Tốt để cô lập hiệu ứng phụ |