Skip to content

Commit

Permalink
Merge pull request #15 from Flutterando/simplify_result
Browse files Browse the repository at this point in the history
Simplify result
  • Loading branch information
jacobaraujo7 authored Dec 11, 2024
2 parents 651113e + ad7a9fd commit 8e0aa2a
Show file tree
Hide file tree
Showing 13 changed files with 204 additions and 140 deletions.
45 changes: 45 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
## [2.0.0] - 2024-12-11

- This version aims to reduce the `Result` boilerplate by making the `Failure` type Exception by default. This will free the Result from having to type `Failure`, making the declaration smaller.

If there is a need to type `Failure`, use `ResultDart`.

### Added
- Introduced `typedef` for `Result<S>` and `AsyncResult<S>` to simplify usage:
- `Result<S>` is a simplified alias for `ResultDart<S, Exception>`.
- `AsyncResult<S>` is a simplified alias for `AsyncResultDart<S, Exception>`.

### Changed
- Replaced `Result` class with `ResultDart` as the base class for all results.
- Default failure type for `ResultDart` is now `Exception`.
- This change reduces boilerplate and improves usability by eliminating the need to specify the failure type explicitly in most cases.

### Removed

- Remove factories `Result.success` and `Result.failure`.


### Migration Guide
- In version >=2.0.0, the Failure typing is by default an `Exception`, but if there is a need to type it, use `ResultDart<Success, Failure>`.

only `Success` type:
```dart
// Old
Result<int, Exception> myResult = Success(42);
// NEW
Result<int> myResult = Success(42);
```

with `Success` and `Failure` types:
```dart
// Old
Result<int, String> myResult = Success(42);
// NEW
ResultDart<int, String> myResult = Success(42);
```


## [1.1.1] - 2023-07-05

* pump Dart version to 3.0.0
Expand Down
59 changes: 33 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<p align="center">
This package aims to create an implemetation of <b>Kotlin's and Swift's Result class and own operators</b>.
Inspired by Higor Lapa's <a href='https://pub.dev/packages/multiple_result'>multiple_result</a> package, the `dartz` package and the `fpdart` package.
Inspired by `multiple_result` package, the `dartz` package and the `fpdart` package.
<br />
<!-- Put the link for the documentation here -->
<a href="https://pub.dev/documentation/result_dart/latest/"><strong>Explore the docs »</strong></a>
Expand Down Expand Up @@ -46,8 +46,7 @@
<summary>Table of Contents</summary>
<ol>
<li><a href="#about-the-project">About The Project</a></li>
<li><a href="#sponsors">Sponsors</a></li>
<li><a href="#getting-started">Getting Started</a></li>
m <li><a href="#getting-started">Getting Started</a></li>
<li><a href="#how-to-use">How to Use</a></li>
<li><a href="#features">Features</a></li>
<li><a href="#contributing">Contributing</a></li>
Expand Down Expand Up @@ -85,25 +84,39 @@ But the other layers of code need to know about the two main values `[Success, F

<p align="right">(<a href="#readme-top">back to top</a>)</p>

<!-- SPONSORS -->
<!-- For now FTeam is the only sponsor for Flutterando packages. The community is open to more support for it's open source endeavors, so check it out and make contact with us through the links provided at the end -->
## Sponsors

<a href="https://fteam.dev">
<img src="https://raw.githubusercontent.com/Flutterando/README-Template/master/readme_assets/sponsor-logo.png" alt="Logo" width="120">
</a>
## Migrate 1.1.1 to 2.0.0

<p align="right">(<a href="#readme-top">back to top</a>)</p>
<br>
This version aims to reduce the `Result` boilerplate by making the `Failure` type Exception by default. This will free the Result from having to type `Failure`, making the declaration smaller.

```dart
// Old
Result<int, Exception> myResult = Success(42);
// NEW
Result<int> myResult = Success(42);
```

if there is a need to type it, use `ResultDart<Success, Failure>`:

```dart
// Old
Result<int, String> myResult = Success(42);
// NEW
ResultDart<int, String> myResult = Success(42);
```


<!-- GETTING STARTED -->
## Getting Started

<!---- The description provided below was aimed to show how to install a pub.dev package, change it as you see fit for your project ---->
To get result_dart working in your project follow either of the instructions below:
To get `result_dart` working in your project follow either of the instructions below:

a) Add result_dart as a dependency in your Pubspec.yaml:
a) Add `result_dart` as a dependency in your Pubspec.yaml:
```yaml
dependencies:
result_dart: x.x.x
Expand All @@ -129,7 +142,7 @@ Result getSomethingPretty();
then add the Success and the Failure types.

```dart
Result<String, Exception> getSomethingPretty() {
Result<String> getSomethingPretty() {
}
Expand All @@ -140,9 +153,6 @@ In the return of the above function, you just need to use:
// Using Normal instance
return Success('Something Pretty');
// Using Result factory
return Result.success('Something Pretty');
// import 'package:result_dart/functions.dart'
return successOf('Something Pretty');
Expand All @@ -156,9 +166,6 @@ or
// Using Normal instance
return Failure(Exception('something ugly happened...'));
// Using Result factory
return Result.failure('something ugly happened...');
// import 'package:result_dart/functions.dart'
return failureOf('Something Pretty');
Expand All @@ -170,7 +177,7 @@ The function should look something like this:

```dart
Result<String, Exception> getSomethingPretty() {
Result<String> getSomethingPretty() {
if(isOk) {
return Success('OK!');
} else {
Expand All @@ -183,7 +190,7 @@ or when using extensions, like this:

```dart
Result<String, Exception> getSomethingPretty() {
Result<String> getSomethingPretty() {
if(isOk) {
return 'OK!'.toSuccess();
} else {
Expand Down Expand Up @@ -412,7 +419,7 @@ void main() {
Some results do not need a specific return. Use the Unit type to signal an **empty** return.

```dart
Result<Unit, Exception>
Result<Unit>
```

### Help with functions that return their parameter:
Expand All @@ -423,7 +430,7 @@ NOTE: use import 'package:result_dart/functions.dart'
Sometimes it is necessary to return the parameter of the function as in this example:

```dart
final result = Success<int, String>(0);
final result = Success(0);
String value = result.when((s) => '$s', (e) => e);
print(string) // "0";
Expand All @@ -432,7 +439,7 @@ print(string) // "0";
We can use the `identity` function or its acronym `id` to facilitate the declaration of this type of function that returns its own parameter and does nothing else:

```dart
final result = Success<int, String>(0);
final result = Success(0);
// changed `(e) => e` by `id`
String value = result.when((s) => '$s', id);
Expand All @@ -452,7 +459,7 @@ All **Result** operators is available in **AsyncResult**

```dart
AsyncResult<String, Exception> fetchProducts() async {
AsyncResult<String> fetchProducts() async {
try {
final response = await dio.get('/products');
final products = ProductModel.fromList(response.data);
Expand Down
20 changes: 10 additions & 10 deletions example/cpf_validator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,42 @@ void main(List<String> args) {
print('CPF Validator: ${result.isSuccess()}');
}

Result<String, ValidatorException> getTerminalInput() {
Result<String> getTerminalInput() {
final text = stdin.readLineSync();
if (text == null || text.isEmpty) {
return const Result.failure(ValidatorException('Incorrect input'));
return const Failure(ValidatorException('Incorrect input'));
}

return Result.success(text);
return Success(text);
}

String removeSpecialCharacteres(String input) {
final reg = RegExp(r'(\D)');
return input.replaceAll(reg, '');
}

Result<List<int>, ValidatorException> parseNumbers(String input) {
Result<List<int>> parseNumbers(String input) {
if (input.isEmpty) {
return const Result.failure(ValidatorException('Input is Empty'));
return const Failure(ValidatorException('Input is Empty'));
}

try {
final list = input.split('').map((e) => int.parse(e)).toList();
return Result.success(list);
final list = input.split('').map(int.parse).toList();
return Success(list);
} catch (e) {
return const Result.failure(ValidatorException('Parse error'));
return const Failure(ValidatorException('Parse error'));
}
}

bool validateCPF(List<int> numberDigits) {
final secondRef = numberDigits.removeLast();
final int secondDigit = calculateDigit(numberDigits);
final secondDigit = calculateDigit(numberDigits);
if (secondRef != secondDigit) {
return false;
}

final firstRef = numberDigits.removeLast();
final int firstDigit = calculateDigit(numberDigits);
final firstDigit = calculateDigit(numberDigits);
return firstRef == firstDigit;
}

Expand Down
8 changes: 4 additions & 4 deletions lib/functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ T identity<T>(T a) => a;
T id<T>(T a) => a;

/// Build a [Result] that returns a [Failure].
Result<S, F> successOf<S extends Object, F extends Object>(S success) {
return Result<S, F>.success(success);
ResultDart<S, F> successOf<S extends Object, F extends Object>(S success) {
return Success<S, F>(success);
}

/// Build a [Result] that returns a [Failure].
Result<S, F> failureOf<S extends Object, F extends Object>(F failure) {
return Result<S, F>.failure(failure);
ResultDart<S, F> failureOf<S extends Object, F extends Object>(F failure) {
return Failure<S, F>(failure);
}
3 changes: 2 additions & 1 deletion lib/result_dart.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
library result_dart;

export 'src/async_result.dart';
export 'src/result.dart';
export 'src/result_dart_base.dart';
export 'src/result_extension.dart';
export 'src/types.dart';
export 'src/unit.dart';
40 changes: 20 additions & 20 deletions lib/src/async_result.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,31 @@ import 'dart:async';

import '../result_dart.dart';

/// `AsyncResult<S, E>` represents an asynchronous computation.
typedef AsyncResult<S extends Object, F extends Object> = Future<Result<S, F>>;
/// `AsyncResultDart<S, E>` represents an asynchronous computation.
typedef AsyncResultDart<S extends Object, F extends Object> = Future<ResultDart<S, F>>;

/// `AsyncResult<S, E>` represents an asynchronous computation.
extension AsyncResultExtension<S extends Object, F extends Object> //
on AsyncResult<S, F> {
/// `AsyncResultDart<S, E>` represents an asynchronous computation.
extension AsyncResultDartExtension<S extends Object, F extends Object> //
on AsyncResultDart<S, F> {
/// Returns a new `Result`, mapping any `Success` value
/// using the given transformation and unwrapping the produced `Result`.
AsyncResult<W, F> flatMap<W extends Object>(
FutureOr<Result<W, F>> Function(S success) fn,
AsyncResultDart<W, F> flatMap<W extends Object>(
FutureOr<ResultDart<W, F>> Function(S success) fn,
) {
return then((result) => result.fold(fn, Failure.new));
}

/// Returns a new `Result`, mapping any `Error` value
/// using the given transformation and unwrapping the produced `Result`.
AsyncResult<S, W> flatMapError<W extends Object>(
FutureOr<Result<S, W>> Function(F error) fn,
AsyncResultDart<S, W> flatMapError<W extends Object>(
FutureOr<ResultDart<S, W>> Function(F error) fn,
) {
return then((result) => result.fold(Success.new, fn));
}

/// Returns a new `AsyncResult`, mapping any `Success` value
/// Returns a new `AsyncResultDart`, mapping any `Success` value
/// using the given transformation.
AsyncResult<W, F> map<W extends Object>(
AsyncResultDart<W, F> map<W extends Object>(
FutureOr<W> Function(S success) fn,
) {
return then(
Expand All @@ -43,7 +43,7 @@ extension AsyncResultExtension<S extends Object, F extends Object> //

/// Returns a new `Result`, mapping any `Error` value
/// using the given transformation.
AsyncResult<S, W> mapError<W extends Object>(
AsyncResultDart<S, W> mapError<W extends Object>(
FutureOr<W> Function(F error) fn,
) {
return then(
Expand All @@ -59,18 +59,18 @@ extension AsyncResultExtension<S extends Object, F extends Object> //
}

/// Change a [Success] value.
AsyncResult<W, F> pure<W extends Object>(W success) {
AsyncResultDart<W, F> pure<W extends Object>(W success) {
return then((result) => result.pure(success));
}

/// Change the [Failure] value.
AsyncResult<S, W> pureError<W extends Object>(W error) {
AsyncResultDart<S, W> pureError<W extends Object>(W error) {
return mapError((_) => error);
}

/// Swap the values contained inside the [Success] and [Failure]
/// of this [AsyncResult].
AsyncResult<F, S> swap() {
/// of this [AsyncResultDart].
AsyncResultDart<F, S> swap() {
return then((result) => result.swap());
}

Expand Down Expand Up @@ -125,22 +125,22 @@ extension AsyncResultExtension<S extends Object, F extends Object> //
/// Returns the encapsulated `Result` of the given transform function
/// applied to the encapsulated a `Failure` or the original
/// encapsulated value if it is success.
AsyncResult<S, R> recover<R extends Object>(
FutureOr<Result<S, R>> Function(F failure) onFailure,
AsyncResultDart<S, R> recover<R extends Object>(
FutureOr<ResultDart<S, R>> Function(F failure) onFailure,
) {
return then((result) => result.fold(Success.new, onFailure));
}

/// Performs the given action on the encapsulated Throwable
/// exception if this instance represents failure.
/// Returns the original Result unchanged.
AsyncResult<S, F> onFailure(void Function(F failure) onFailure) {
AsyncResultDart<S, F> onFailure(void Function(F failure) onFailure) {
return then((result) => result.onFailure(onFailure));
}

/// Performs the given action on the encapsulated value if this
/// instance represents success. Returns the original Result unchanged.
AsyncResult<S, F> onSuccess(void Function(S success) onSuccess) {
AsyncResultDart<S, F> onSuccess(void Function(S success) onSuccess) {
return then((result) => result.onSuccess(onSuccess));
}
}
Loading

0 comments on commit 8e0aa2a

Please sign in to comment.