BREAKING CHANGE: refactor labels with the new architecture - #1784
Conversation
| class LabelExchangeOrdersUsecase { | ||
| final LabelDatasource _labelDatasource; | ||
| final BatchLabelsUsecase _batchLabelsUsecase; | ||
| final LabelsFacade _labelsFacade; |
There was a problem hiding this comment.
You should not directly import a Facade here, as this tightly couples the "what" (adding a label) with the "how" (through the labels feature). A usecase should only get Ports injected, not concrete implementations, so you should create an ExchangeLabelsPort and implement that Port with the LabelsFacade. You could make the interface of the port something like addLabelsForOrder and then just pass the order to it, so in the concrete implementation of the ExchangeLabelsPort you can check the order type etc and decide which labels to add based on that. I would also move the system labels check and everything to it, as those are implementation details, the usecase just wants to make sure the order is labeled, it shouldn't know how exactly this is done.
There was a problem hiding this comment.
This usecase is out of the scope as it belongs to the exchange feature. This PR focus on refactoring the labels folder
There was a problem hiding this comment.
This usecase is out of the scope as it belongs to the exchange feature. This PR focus on refactoring the labels folder
There was a problem hiding this comment.
Oh ok, just wrote another comment saying the same and only now see you responded haha.
Will focus only on the labels feature code itself.
There was a problem hiding this comment.
We will refactor this usecase in when we attack the exchange feature
| import 'package:bb_mobile/core/utils/logger.dart'; | ||
| import 'package:bb_mobile/features/labels/labels_facade.dart'; | ||
|
|
||
| class LabelExchangeOrdersUsecase { |
There was a problem hiding this comment.
I think this is not a good usecase, this labeling should be part of the usecase that creates the orders.
But I don't know if we should refactor that when we apply the new architecture guidelines to the exchange features and we should focus on the labels feature here.
There was a problem hiding this comment.
The labeling is already part of the usecase that creates orders. This usecase is executed once the first time the user connect to the exchange to ensure it is labeling the orders that might have been created before the app was supporting the exchange.
The day we attack the exchange folder, let's rename it better!
LabelExistingExchangeOrdersUsecase ?
There was a problem hiding this comment.
I was thinking some more about this and I actually don't even think this should be done from the exchange feature. In the end it is the labels feature that needs a migration of the labels, or a seeding in some sense of missed values. So I was thinking that we should actually remove this usecase and let the labels feature use the core BBX api client directly to fetch the orders and seed the labels in a real db migration/seeding in the labels feature. It is a pure migration (framework) thing from the labels, no usecase needed and certainly not in exchange features.
…belsLocalDatasource across wallet and exchange modules
…ntralized interface
Remove singular/plural logic for export labels success message since we no longer track the exported count. Import success retains the count-based messaging. - Replace bip329LabelsExportSuccessSingular/Plural with bip329LabelsExportSuccess - Update all 10 language files (en, de, es, fi, fr, it, pt, ru, uk, zh) - Update page.dart to use the new translation key
e628aa0 to
fadd877
Compare
There was a problem hiding this comment.
This can just be moved to the domain folder. Primitives are part of the domain. No separate primitives folder needed.
There was a problem hiding this comment.
This can just be moved to the domain folder. Primitives are part of the domain. No separate primitives folder needed.
There was a problem hiding this comment.
The LabelEntity is too linked to bip329 specs still, it is also unclear if it is a system label or not. This is something crucial for our app, since it is the business that wants us to label things automatically. So this should reflect in the domain and be more explicit instead of needing to parse the label itself (which isn’t even clear from looking at the domain if that’s the way to know). Introducing the Provenance concept would help. I will add a general comment at the end or in another issue as to how we could model the domain better.
| import 'package:convert/convert.dart'; | ||
|
|
||
| class LabelEntity { | ||
| final int? id; |
There was a problem hiding this comment.
id should not be optional, one of the main characteristics of an entity is that it has an identity.
There was a problem hiding this comment.
I can not comment on a folder here, but the whole usecases folder should move to the application layer, since usecases are application logic, not domain logic.
There was a problem hiding this comment.
abel_error mixes UI build context with domain errors. This should be done in the UI layer. The domain errors should stay strictly domain related and shouldn’t even be the same errors exposed to the UI.
There was a problem hiding this comment.
Add page.dart into UI folder outside of presentation folder. We might create other screens and label related widgets that could be put in UI too then and pure UI is something that can be embedded in other features without problems, while the presentation folder should be more about the controllers (BLoC/Cubit) which I think shouldn't be used from other features.
| import 'package:convert/convert.dart'; | ||
|
|
||
| class LabelEntity { | ||
| final int? id; |
There was a problem hiding this comment.
Also, the id is now added here, but it is not used anywhere, so this addition doesn't add what it should be adding at the moment, everything is still by reference. We need the facade and use cases to use id, not the bip329 reference, otherwise there is still no way to edit a label cleanly and easily
| ); | ||
| } | ||
|
|
||
| StoreLabelModel toModel() { |
There was a problem hiding this comment.
This shouldn’t have a toModelbehavior since this is supposed to be a plain data object used by other features that never need this. Better to define a mapper class for it or if you really want to have a function like this somewhere and avoid an extra class, then I think it is better on the ApplicationLabel class since it is more internal at least. Otherwise you are leaking application related behaviour in the public object.
| required this.type, | ||
| required this.label, | ||
| required this.reference, | ||
| required this.origin, |
There was a problem hiding this comment.
Origin shouldn’t be required here since it is an optional field.
|
As a general comment, the domain is not modelled well, which leaks in the usecases and public api in the end too with things like it being impossible to edit an existing label. With a lot of unclarity and string manipulations for the system labels as well. This can be solved by better modelling of the domain by introducing custom types/classes that have meaning in our domain instead of using just native types. It helps with type safety and it makes polymorphism easier later as well since you can extend/implement these concepts. Here is an example of how the LabelEntity could be modeled by using value objects that give clear meanings to the fields of the entity independent of any external label specs: |
Schema Migration (v11 → v12)
Labels table changes:
idautoincrement primary keyref→referencespendablecolumn(label, reference)Key Changes
LabelEntitywith reference validators (tx, pubkey, input/output, xpub)StoreLabelEnvelopefor inputFiles
schema_11_to_12.dart- Migration preserving existing datalabel_entity.dart- Domain entity with validatorslabels_facade.dart- Public API*_port.dart/*_adapter.dart- Hexagonal boundaries