I previously had the following code, it works fine. (note that Card, SearchResults, Quiz all extend Persistable, and Persistable contains the constructor .fromMap.
Persistable fromString(String value){
Map<String, dynamic> m = parse(value);
switch(m['type']){
case 'card':
return new Card.fromMap(m);
case 'searchresults':
return new SearchResults.fromMap(m);
case 'quiz':
return new Quiz.fromMap(m);
}
}
It was a bit wordy, so I thought I would break it down into two parts. I first have this:
static final Map<String, Persistable> lookup =
{'card': Card,
'searchresults': SearchResults,
'quiz': Quiz };
Seems reasonable, but then when I try to redefine the method, I get confused.
Persistable fromString(String value){
Map<String, dynamic> m = parse(value);
String type = m['type'];
Persistable p = lookup[type];
... Confused, this can't be right
... ultimately want to "return new p.fromMap(m)";
}
Persistable p really means a instance of class Persistable. How do I type my lookup map so that its values are of the class Persistable, so that I can call their .fromMap constructors?
First of all I think your initial approach is perfectly valid and should not be cast away owing simply to its verbosity.
I believe alternative approaches introduce additional complexity and are justified only if you are really in need of dynamic dispatch. (For example if you write library for persistency and you wish to add ability to register arbitrary class for persistency for clients of library)
If dynamic dispatch is a must for you I believe there is two main possibility:
- Reflection API. Recently reflection library got sync API, so this way is now much more affordable then before. I believe there always will be some cost incurred by reflection anyway.
- Use core DART functionality.
With the second approach you may use some sort of trick to imitate constructor call dynamically.
For instance you may store in map not Type variable but function which returns instance of required class:
So your code may look something like
static final Map<String, Function> lookup = new Map<String, Function>
static void registerClass(String className, factory) {
lookup[className] = factory;
}
static Persistable getInstance(String className, Map map){
return lookup[className](map);
}
And on client side:
....
registerClass('quiz', (map)=> new Quiz.fromMap(map));
registerClass('card', (map)=> new Card.fromMap(map));
(Attention - I did not test this)
You may look for working sample code for that approach in https://github.com/vadimtsushko/objectory
Related
I see the factory constructor factory IMap.fromPairs(FoldableOps<dynamic, Tuple2<K, V>> foldableOps, Order<K> kOrder), but how do you use FoldableOps to be able to pass an Iterable<Tuple2<X,Y>> into it?
After consulting the aforementioned art installation (you know, in lieu of official documentation) as well as some sample code in the repo, I believe this is the way to do it:
iList<Tuple<K, T>> tuples = ...;
IMap<K, T> map = IMap.fromPairs(tuples, Order<K>);
Where what you pass for Order<K> depends on the key type in the tuples. If it's a native type like int or String, you can pass IntOrder or StringOrder. Otherwise, you will need to create an Order implementation for that type, e.g.:
class Foo extends Comparable {
...
}
Order<Foo> fooOrder = ComparableOrder<Foo>();
iList<Tuple<Foo, dynamic>> tuples = ...;
iMap<Foo, dynamic> map = iMap.fromPairs(tuples, fooOrder);
In Java, we can serial any object like this:
Object anyObj = new Object();
String json = JSON.tostring(anyObj);
but in Dart, we must define toJson method like this in every single Object:
import 'dart:convert';
String toJson() => json.encode(toMap());
and define toMap:
Map<String, dynamic> toMap() => {}
any simple way? Image if the system has 10000+ objects, are we write toJson function for every object? Is it possible to serial object to json like Java way in Dart?
Most Java libraries that provide serialization of arbitrary objects rely on runtime reflection to know what fields are present on an object (and their types, etc).
Runtime reflection is technically possible in Dart (using dart:mirrors) but the library is unstable and is not available on all platforms (notably runtime reflection is disabled in Flutter).
The idiomatic Dart way to do this is with code generation. In general, you add the required annotations/etc, then run flutter pub run build_runner build to use the build_runner package to generate extra code.
A couple of popular libraries are:
json_serializable is useful if you have a model class that you want to add toJson() and fromJson() methods to:
#JsonSerializable // marks the class for json code generation
class Dog {
final String name;
final int age;
Dog(this.name, this.age);
// boilerplate for generated implementations
Map<String, dynamic> toJson() => _$DogToJson(this);
factory Dog.fromJson(Map<String, dynamic> json) => _$DogFromJson(json);
}
built_value is a more all-encompassing approach. The main purpose of the library is to provide deep immutability for model classes, similar to Kotlin's data class. However, it also provides good serialization support out of the box. There is a fair amount of boilerplate, but it can definitely be worth it (especially if you use the vscode plugin to write it for you):
abstract class Dog extends Built<Dog, DogBuilder> {
Dog._();
factory Dog([void Function(DogBuilder) updates]) = _$Dog;
String get name;
int get age;
}
You can then use this code like:
final dog = Dog((b) {
b.name = 'name';
b.age = 123;
});
final helloDog = dog.rebuild((b) => b.name = 'hello');
This blog post goes through serialization in detail: https://medium.com/dartlang/darts-built-value-for-serialization-f5db9d0f4159#.h12y94wu7
Both libraries are maintained by Google
Coming back to C++ after a hiatus in Java. Attempting to create an immutable object and after working in Java, a public const variable seems the most sensible (like Java final).
public:
const int A;
All well and good, but if I want to defensive check this value, how might I go about it. The code below seems strange to me, but unlike Java final members, I can't seem to set A in the constructor after defensive checks (compiler error).
MyObj::MyObj(int a) : A(a) {
if (a < 0)
throw invalid_argument("must be positive");
}
A public const variable for A seems like a clearer, cleaner solution than a getter only with a non const int behind it, but open to that or other ideas if this is bad practice.
Your example as it stands should work fine:
class MyObj {
public:
const int var;
MyObj(int var) : var(var) {
if (var < 0)
throw std::invalid_argument("must be positive");
}
};
(Live example, or with out-of-line constructor)
If you intend that MyObj will always be immutable, then a const member is
probably fine. If you want the variable to be immutable in general, but still have the possibility to overwrite the entire object with an assignment, then better to have a private variable with a getter:
class MyObj {
int var;
public:
MyObj(int var) : var(var) {
if (var < 0)
throw std::invalid_argument("must be positive");
}
int getVar() const { return var; }
};
// now allows
MyObj a(5);
MyObj b(10);
a = b;
Edit
Apparently, what you want to do is something like
MyObj(int var) {
if (var < 0)
throw std::invalid_argument("must be positive");
this->var = var;
}
This is not possible; once a const variable has a value it cannot be changed. Once the body ({} bit) of the constructor starts, const variables already have a value, though in this case the value is "undefined" since you're not setting it (and the compiler is throwing an error because of it).
Moreover, there's actually no point to this. There is no efficiency difference in setting the variable after the checks or before them, and it's not like any external observers will be able to see the difference regardless since the throw statement will unroll the stack, deconstructing the object straight away.
Generally the answer by N. Shead is the regular practice - but you can also consider:
Create domain-specific types and use them instead of general primitives. E.g., if your field is a telephone number, have a type TelephoneNumber which, in its constructor (or factory), taking a string, does all the telephone number validation you'd like (and throws on invalid). Then you write something like:
class Contact {
const TelephoneNumber phone_;
public:
Contact(string phone) : phone_(phone) { ... }
...
When you do this the constructor for TelephoneNumber taking a string argument will be called when initializing the field phone_ and the validation will happen.
Using domain-specific types this way is discussed on the web under the name "primitive obsession" as a "code smell".
(The problem with this approach IMO is that you pretty much have to use it everywhere, and from the start of your project, otherwise you start having to have explicit (or implicit) casting all over the place and your code looks like crap and you can never be sure if the value you have has been validated or not. If you're working with an existing codebase it is nearly impossible to retrofit it completely though you might just start using it for particularly important/ubiquitous types.)
Create validation methods that take and return some value, and which perform the validation necessary - throwing when invalid otherwise returning its argument. Here's an example validator:
string ValidatePhoneNumber(string v) {
<some kind of validation throwing on invalid...>
return v;
}
And use it as follows:
class Contact {
const string phone_;
public:
Contact(string phone) : phone_(ValidatePhoneNumber(phone)) { ... }
I've seen this used when an application or library is doing so much validation of domain-specific types that a small library of these domain-specific validator methods has been built up and code readers are used to them. I wouldn't really consider it idiomatic, but it does have the advantage that the validation is right out there in the open where you can see it.
Whenever I need to pass data down the reactive chain I end up doing something like this:
public Mono<String> doFooAndPassDtoAsMono(Dto dto) {
return Mono.just(dto)
.flatMap(dtoMono -> {
Mono<String> result = // remote call returning a Mono
return Mono.zip(Mono.just(dtoMono), result);
})
.flatMap(tup2 -> {
return doSomething(tup2.getT1().getFoo(), tup2.getT2()); // do something that requires foo and result and returns a Mono
});
}
Given the below sample Dto class:
class Dto {
private String foo;
public String getFoo() {
return this.foo;
}
}
Because it often gets tedious to zip the data all the time to pass it down the chain (especially a few levels down) I was wondering if it's ok to simply reference the dto directly like so:
public Mono<String> doFooAndReferenceParam(Dto dto) {
Mono<String> result = // remote call returning a Mono
return result.flatMap(result -> {
return doSomething(dto.getFoo(), result); // do something that requires foo and result and returns a Mono
});
}
My concern about the second approach is that assuming a subscriber subscribes to this Mono on a thread pool would I need to guarantee that Dto is thread safe (the above example is simple because it just carries a String but what if it's not)?
Also, which one is considered "best practice"?
Based on what you have shared, you can simply do following:
public Mono<String> doFooAndPassDtoAsMono(Dto dto) {
return Mono.just(dto.getFoo());
}
The way you are using zip in the first option doesn't solve any purpose. Similarly, the 2nd option will not work either as once the mono is empty then the next flat map will not be triggered.
The case is simple if
The reference data is available from the beginning (i.e. before the creation of the chain), and
The chain is created for processing at most one event (i.e. starts with a Mono), and
The reference data is immutable.
Then you can simple refer to the reference data in a parameter or local variable – just like in your second solution. This is completely okay, and there are no concurrency issues.
Using mutable data in reactive flows is strongly discouraged. If you had a mutable Dto class, you might still be able to use it (assuming proper synchronization) – but this will be very surprising to readers of your code.
I have a class that serves as a model for some data I get from a server. This data starts as an unwieldy xml object where text nodes have attributes so the json format I convert it into does not have simple string values. Instead I have:
#Injectable()
export class FooString {
_attr: string;
value: string;
isReadOnly(): boolean {
return this._attr && this._attr === 'ReadOnly';
}
isHidden(): boolean {
return this._attr && this._attr === 'Hid';
}
}
Then my model is like:
#Injectable()
export class Payment {
constructor(
public FooId: FooString,
public FooStat: FooString,
public FooName: FooString ) { }
}
Everything ends up with the same instance of FooString. How do I get discrete instances for each of them?
I have tried a factory, but it still only creates a single instance:
export let fooStringProvider = provide(FooString, {
useFactory: (): FooString => {
console.log('in foostring factory');
return new FooString();
}
});
new FooString();
new Payment();
;-)
Why using DI when they don't have dependencies and you don't want to maintain single instances per provider. Therefore, just use new.
When to use DI
There are a few criterias when using DI instead of new the right thing:
If you want Angular to maintain and share instances
If you want to work with an interface or base class but then you want to configure from the outside what implementation should actually be used at runtime - like the MockBackend for Http during testing.
If you class has dependencies to instances and/or values provided by DI
If you want to be able to easily test classes in isolation (https://en.wikipedia.org/wiki/Inversion_of_control)
probably others ...
If there are good arguments to use DI, but you also want new instances then you can just provide a factory.
This answer https://stackoverflow.com/a/36046754/217408 contains a concrete example how to do that.
Using DI is usually a good idea. There are IMHO no strong arguments against using DI. Only when none of the above arguments apply and providing factories is too cumbersome, use new Xxx() instead.