dwyl / statuses

📝 A collection of statuses for use in our various apps.
GNU General Public License v2.0
5 stars 1 forks source link

Question: How are we going to use statuses in `Dart`/`Flutter`? #10

Closed nelsonic closed 1 year ago

nelsonic commented 1 year ago

As noted in https://github.com/dwyl/statuses/issues/4#issuecomment-1179609113 I feel that JSON is a more versatile format for storing the statuses list than a List of Elixir Map or Struct ...

As per https://github.com/dwyl/product-roadmap/issues/40 we are building a Flutter (Native Mobile App) version of the MVP that will be offline first. We need statuses in Dart-land so that it can be included in the compiled Native App.

We could either create a Struct in Dart and duplicate the statuses and thus have to maintain them in multiple places ... !DRY

or

use JSON.

nelsonic commented 1 year ago

@LuchoTurtle the reason I assigned this to you is that you can help us understand the best way of using the statuses in Flutter-land. Ideally we would only manage a single source of truth for this. i.e. we don't want to create a separate Dart package ... 💭

LuchoTurtle commented 1 year ago

Dart, being quite close to Typescript when it comes to syntax, I wager having a JSON format is suitable to this use case, as you've stated. Parsing json files remain the best option for data exchange and parsing it comes out of the box with the language.

No need to go for formats like json-dl, there's no official support so let's keep it to the basics.

In Flutter, parsing local json files is as simple as

final String response = await rootBundle.loadString('assets/sample.json');
final data = await json.decode(response);

and declaring its location in the pubspec.yaml file.

flutter:
assets:
- assets/sample.json

However, I have a question regarding the DRY principle and how having a json file detailing each status will affect this repo. It's clear you don't want to have yet another package for Dart to have these statuses. By having a single json file that is parsable, will it deprecate the Elixir library in this repo?

Does it make sense to have a Dart and Elixir package in this repo that makes use of this json file, both of which simply parse it? Does it make sense for us to do the same for the Elixir library and basically have this repo as an aggregate of different packages for each language we need?

nelsonic commented 1 year ago

The parse a JSON file and use it is exactly the approach taken in https://github.com/dwyl/quotes which is a basic showcase of a module/package available in two languages/ecosystems JavaScript (NPM) and Elixir (Hex.pm).

My question stems from the fact that we did have JSON in this repo before ... and it was removed int: https://github.com/dwyl/statuses/pull/3/files 💭 As much as I'd like to have a Struct that would allow type-checking But think that can be achieved in a statically-typed language even with the JSON approach ...

In Elixir this appears to be the approach: https://elixirforum.com/t/how-to-decode-a-json-into-a-struct-safely/14331 And in Dart we can define a class: https://www.technicalfeeder.com/2022/02/parse-json-into-a-dart-class-object/?utm_content=cmp-true ⚠️ don't open that without an Ad Blocker!

What I would like to have is a compile-time check that a given status int is defined. i.e. we cannot accidentally have status: 5000 if it's not in the JSON file. 🚫

LuchoTurtle commented 1 year ago

What I would like to have is a compile-time check that a given status int is defined. i.e. we cannot accidentally have status: 5000 if it's not in the JSON file. 🚫

I think you can have simple type definitions that check if a given status int is defined or not. However, what you've stated, is that you want to have a value validation at compile-time, which is something I've never tried in Dart (and actually thought it wasn't doable).

This type of feature was actually requested before at https://github.com/dart-lang/language/issues/1294.

There are some ways to do this, apparently:

However, I fail how this would be helpful to the end user. If we're doing this similarly to https://github.com/dwyl/quotes, they will just use the parsed struct. There's no chance there's a status: 5000 in it because the json was already parsed by the library and there's no chance a status with value 5000 is in it (unless we intentionally put it there).

Am I missing something? Is this object value compile-time validation only useful for us? How is it needed?

nelsonic commented 1 year ago

Ok. If we aren't able to do compile-time checking of the status int then ignore that "nice-to-have". 👌 But the discussion above regarding how to use the same set of statuses in both Dart and Elixir remains. 💭

LuchoTurtle commented 1 year ago

To have the same set of statuses is to follow the same methodology you previously mentioned with https://github.com/dwyl/quotes - parse the JSON file and export it as objects. You use the same quotes.json file for both index.js and quotes.ex.

I wager we could do the same thing with dart: serialize the JSON and just provide the class object from the package. People will use the objects and you will still have the benefits of static types. For example, for quotes...

class Quote {
  String? author;
  String? text;

  Quote({this.author, this.text});

  Quote.fromJson(Map<String, dynamic> json) {
    author = json['author'];
    text = json['text'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['author'] = this.author;
    data['text'] = this.text;
    return data;
  }
}

You could try using global_assert from the parsed JSON class to add more compile-time constraints. However, I don't exactly know how, as of now.

nelsonic commented 1 year ago

@LuchoTurtle this looks good. 👌 Perhaps we can do a trial run of this in quotes: https://github.com/dwyl/quotes/issues/96 💭

nelsonic commented 1 year ago

@LuchoTurtle now that https://github.com/dwyl/quotes/pull/97 is merged, how confident do you feel in doing something similar for this project so that we can use statuses in Dart/Flutter? 💭