Custom object change tracking in Typescript - angularjs

I need to implement change tracking for state of any object.
How would I implement it?
For example:
let complexObject = {
/// ... mant many arrays and propertiess
}
let hash = convertToHash(complexObject)
let trackingArray = []
trackingArray.push(hash);
/// what from here and how to imlement it?

I would recommend you to use https://facebook.github.io/immutable-js/ when you change something you will get a new object. It will be much more efficient than creating a hash because you will not need to iterate the entire object graph.
Also it shares some memory internally so it will be more efficient than storing full clones in memory.

Assuming you are implementing change tracking for purpose of undo/redo functionality.
One way is to use immutable objects and store on stack old object each time when there is action invoked.
In order to capture change to objects you could use https://en.wikipedia.org/wiki/Command_pattern or redux (widely popular in react, implementation for angular).

Related

How do deal with nested Arrays/objects in BehaviorSubjects, Observables?

I generally have problems using rxjs with nested Objects or Arrays.
My current use-case is this:
{a: [
{b: 0, c:[{d:1}]},
{b: 1, e:[{f: 'someString'}]}
]
Task: Get and set the Observable or value of a,b,c,d,e,f. I also want to be able to subscribe to each property.
I had this Problem in a similar use-case with an Array of BehaviorSubjects:
Efficiently get Observable of an array BehaviorSubjects
I generally have problems to use the basic functionality of nested arrays/objects in rxjs.
The basic functionality I mean includes:
Array:
getting Element by Index
using for of/in on Arrays
setting an Element by Index
push, pop, shift, slice, splice, ...
Object:
getting Value by Property name
going into the nested tree: object.key1.key2.key3[3].key4 ...
setting Value by Property name
assign
for of/in loops
Generally:
Destructuring: e.g.: let [variable1, variable2] = someObject;
Maybe other stuff I forgot.
I dont know if and which functions are possible for which rxjs Objects and which make sense (for example you should be able to set values in an Observable directly). But coming from a background without rxjs, I have trouble to manage my rxjs Objects properly.
I think reason for this besides my lack of knowledge and understanding is, that
a. The rxjs Objects don't provide the functionality as I'm used to from normal arrays and objects. e.g.:
let variable1 = array[1].property;
//becomes this (see related stack-Question I mentioned earlier)
let variable2 = array.pipe(mergeMap(d=> d[index].pipe(map(d1 => d1[property]));
// -> what happens here? You first need to know what mergeMap,
// map is doing and you have 5 levels of nested inline functions.
b. To implement the those mentioned functionalities I need to go over the .pipe() function and use some function like mergeMap, map, pluck, ... Functions that aren't directly indicating that you can get the Observable of let's say 'e' in my example. Making something like object.a[1].e wierd to implement (at least I don't know how to do that yet)
EDIT:
I also want to note, that I still love the idea of rxjs which works well in angular. I just have problems using it to it's full extend, as I'm a bit new to angular and consequently rxjs.
I thin RX is mainly focus on dealing with async operations. Mutation of array and object we can perfectly use the methods comes natively with javascript if theres no existing operators. or you can create your own operator for mutation/iteration etc.
Will try to answer some of your question on array/objects mutation, they are actually very straight forward.
Array:
getting Element by Index
map(arr=>arr[index])
using for of/in on Arrays
map(arr=>arry.map(item=>....))
setting an Element by Index
tap(arr=>arr[index]=somevalue)
Object:
getting Value by Property name
pluck('name')
going into the nested tree: object.key1.key2.key3[3].key4 ...
pluck('key1','key2')
setting Value by Property name
map(obj=>({a:value,obj...}))
assign
lets say your really want some pick array index method as rxjs operator you can create something like, same as for..in operations.
const pluckIndex=(index)=>source=>source.pipe(map(arr=>arr[index]))
const source = of([2,3])
source.pipe(pluckIndex(1)).subscribe(x => console.log(x));

Can TypeScript's `readonly` fully replace Immutable.js?

I have worked on a couple of projects using React.js. Some of them have used Flux, some Redux and some were just plain React apps utilizing Context.
I really like the way how Redux is using functional patterns. However, there is a strong chance that developers unintentionally mutate the state. When searching for a solution, there is basically just one answer - Immutable.js. To be honest, I hate this library. It totally changes the way you use JavaScript. Moreover, it has to be implemented throughout the whole application, otherwise you end up having weird errors when some objects are plain JS and some are Immutable structures. Or you start using .toJS(), which is - again - very very bad.
Recently, a colleague of mine has suggested using TypeScript. Aside from the type safety, it has one interesting feature - you can define your own data structures, which have all their fields labeled as readonly. Such a structure would be essentially immutable.
I am not an expert on either Immutable.js or TypeScript. However, the promise of having immutable data structures inside Redux store and without using Immutable.js seems too good to be true. Is TypeScript's readonly a suitable replacement for Immutable.js? Or are there any hidden issues?
While it is true that the readonly modifier of TypeScript only exists at design type and does not affect runtime code, this is true of the entire type system. That is, nothing stops you at runtime from assigning a number to a variable of type string. So that answer is kind of a red herring... if you get warned at design time that you're trying to mutate something marked as const or readonly, then that would possibly eliminate the need for extensive runtime checking.
But there is a major reason why readonly is insufficient. There is an outstanding issue with readonly, which is that currently (as of TS3.4), types that differ only in their readonly attributes are mutually assignable. Which lets you easily bust through the protective readonly shell of any property and mess with the innards:
type Person = { name: string, age: number }
type ReadonlyPerson = Readonly<Person>;
const readonlyPerson: ReadonlyPerson = { name: "Peter Pan", age: 12 };
readonlyPerson.age = 40; // error, "I won't grow up!"
const writablePerson: Person = readonlyPerson; // no error?!?!
writablePerson.age = 40; // no error! Get a job, Peter.
console.log(readonlyPerson.age); // 40
This is pretty bad for readonly. Until that gets resolved, you might find yourself agreeing with a previous issue filer who had originally named the issue "readonly modifiers are a joke" 🤡.
Even if this does get resolved, readonly might not cover all use cases. You'd also need to walk through all interfaces and types in your libraries (or even the standard libraries) and remove methods that mutate state. So all uses of Array would need to be changed to ReadonlyArray and all uses of Map would need to be changed to ReadonlyMap, etc. Once you did this you'd have a fairly typesafe way to represent immutability. But it's a lot of work.
Anyway, hope that helps; good luck!
The purpose of Immutable.js is not to prevent a developer from doing an illegal mutation at compile time. It provides a convenient API to create copies of an object with some of its properties changed. The fact that you get type safeness on objects that you manage with immutable.js is basically just a side effect of using it.
Typescript is "just" a typing system. It does not implement any of the features Immutable.js does to make copies of immutable objects. All it does, when declaring a variable as readonly, is to check at compile time that you do not mutate it. How you design your code to handle immutability is not the scope of a typing system and you would still need a way of dealing with it.
React ensures immutability by providing a method setState instead of mutating the state object directly. It takes care of merging the changed properties for you. But if you e.g. use redux you may want a convenient solution to handle immutability too. That is what Immutable.js provides and typescript never will and it is independent of whether you like the api or not.
There are two issues with this:
1) You have to use readonly and/or things like ReadonlyArray all the way down, which is error-prone.
2) readonly exists solely at compile time, not runtime, unless backed by immutable data stores. Once your code is transpiled to JS your runtime code can do whatever it wants.
Immutable js distinguishing feature compared to readonly is structural sharing.
Here is general benefit:
Imagine nested JS object that have 16 properties across multiple levels of nesting.
With readonly the way to update a value is to copy old one, modify whatever data we want and then we have new value!
With JS the way to update a value is to keep all the properties that did not change and only copy those that did (and their parents untill we reach a root).
Thus Immutable js saves time on update (less copying), saves memory (less copying), saves time when deciding if we need to redo some related work (e.g. we know that some leafs didn't change so their DOM do not have to be changed by React!).
As you can see readonly is not even in the same league as Immutable js. One is mutation property, the other is efficient immutable data structure library.
Typescript is still rough around the edges with immutability - and they still (as of Typescript 3.7) haven't fixed the issue where you can mutate readonly objects by first assigning them to non-readonly objects.
But the usability is still pretty good because it covers almost all other use cases.
This definition which I've found in this comment works pretty well for me:
type ImmutablePrimitive = undefined | null | boolean | string | number | Function;
export type Immutable<T> =
T extends ImmutablePrimitive ? T :
T extends Array<infer U> ? ImmutableArray<U> :
T extends Map<infer K, infer V> ? ImmutableMap<K, V> :
T extends Set<infer M> ? ImmutableSet<M> : ImmutableObject<T>;
export type ImmutableArray<T> = ReadonlyArray<Immutable<T>>;
export type ImmutableMap<K, V> = ReadonlyMap<Immutable<K>, Immutable<V>>;
export type ImmutableSet<T> = ReadonlySet<Immutable<T>>;
export type ImmutableObject<T> = { readonly [K in keyof T]: Immutable<T[K]> };

What is the difference between ObservableMap and ObservableArray in mobx

As per the documentation,
observable.map(values?) creates a dynamic keyed observable map.
Observable maps are very useful if you don't want to react just to the
change of a specific entry, but also to the addition or removal of
entries.
I may be the only one who doesn't understand the difference between these two mobx observable types. Even the doc says map can track addition or removal, following array also notifies the console by autorun when a new value is pushed into the array. So what is the real difference between the two?
window.q = observable([1,2,3]);
autorun(()=>{console.log(q[0]);})
q.push(32)
The difference is in the methods you use to interact with them. Think of one as an array, and the other as a map. Arrays stores indices, maps store keys and values.

Using Array[Boolean] in Scala to find out progress of foreach

I have a class in Scala that has a method to perform a bunch of calculations sequentially using foreach on a list which is provided in the constructor. The class has a field val progress: Array[Boolean] = list.map(_ => false).toArray. Some of these calculations can take a long time so at the end of each one I set the appropriate index in progress to true. Then I can get progress to determine where I am in the calculations from outside the class.
This does not seem like the best approach in Scala (because I'm using a mutable data structure) so any advice to improve it would be much appreciated.
I don't think your approach is bad. The alternative is to use a var progress: List[Boolean] as an immutable data structure and have a long list of immutable lists pointed at by that variable. You don't really gain anything, you lose the ability to reserve the exact memory you will need in a single step and memory allocation is going to make this slower.
There is a reason why mutable data structures exist and that is because they are incredibly useful and very needed, same as why you can still define var instead of val, the important piece is not that one is "bad" and the other "good", it is a matter of knowing when you can use val and sacrifice mutability in exchange for security. In your example you just can't.
Side note: Instead of using
val progress: Array[Boolean] = list.map(_ => false).toArray
This is much clearer and faster IMHO:
val progress = Array.fill(list.size)(false)
Well, it depends on what you want to do with that information. If you are interested in specific events (e.g., 50% done or something like that), you could pass a listener into your foreach method and ask to be notified. But if you really need to inquire about the current state at any time, then ... well, if you need to know the state, then you have to keep the state, there is no way around that :)
Array of booleans seems to be an overkill (you could just keep the current index instead), but you mentioned that you were planning to keep se additional info around as well, so, it looks reasonable.

Immutable State - Propagating Changes to the GUI Efficiently

In a previous question I asked how to idiomatically implement an observer pattern for an F# application. My application now uses a MailboxProcessor as reccomended and I've created some helper functions to create sub-MailboxProcessor's etc. However, I'm at a mental block when it comes to specific case scenarios w.r.t. GUI binding.
Lets say I have a model as such:
type Document = {
Contents : seq<DocumentObject>
}
And the GUI (WPF, XAML) requires binding like so:
interface IMainWindowViewModel
{
IEnumerable<Control> ContentViews { get; }
}
Each ViewModel for each Control will require a DocumentObject (its underlying model) and a way of knowing if it has changed. I supply this as a sub-MailboxProcessor<DocumentObject> so that changes may be propagated correctly, I'm moderately confident this pattern works. Essentially, it maps the service outputs and wraps modification requests (outer interface example below):
let subSvc = generateSubSvc svc (fun doc -> doc.Contents[0]) (fun f -> fun oldDoc -> { oldDoc with Contents[0] = f Contents[0] })
let viewModel = new SomeDocObjViewModel(docObjSvc)
new DocObjView(viewModel)
Now, imagine a modification command now deletes a DocumentObject from MyDocument. The top-level MailboxProcessor now echoes the change to IMainWindowViewModel using it's IEvent<MyDocument>. And here's where my problems begin.
My IMainWindowViewModel doesn't really know which DocumentObject has been deleted. Only that there's a new Document and it has to deal with it. There may be ways of it figuring out but it never really knows directly. This can force me down the path of having to either re-create all the Control's for all DocumentObject's to be safe (inefficient). There are additional problems (such as dangling subSvc's) which I also haven't mentioned here for brevity.
Normally, these kind of dynamic changes would be dealt with something like an ObservableCollection<DocumentObject> which is then mapped into an ObservableCollection<Control>. This comes with all the caveats of shared mutable state and is a little 'hackish'; however, it does do the job.
Ideally, I'd like a 'pure' model, free from the trappings of PropertyChanged and ObservableCollections, what kind of patterns in F# would satisfy this need? Where is it appropriate to draw the line between idiomatic and realistic?
Have you considered using the Reactive Extensions (and Reactive UI further down the road) for the purpose of modelling mutable state (read: your model properties over time) in a functional way?
I don't see anything wrong technically to use an ObservableCollection in your model. After all, you need to track collection changes. You could do it on your own, but it looks like you can save yourself a lot of trouble reinventing the observable collection, unless you have a very specific reason to avoid the ObservableCollection class.
Also, using MailboxProcessor seems a bit overkill, since you could just use a Subject (from Rx) to publish and expose it as an IObservable to subscribe to 'messages':
type TheModel() =
let charactersCountSubject = new Subject()
let downloadDocument (* ... *) = async {
let! text = // ...
charactersCountSubject.OnNext(text.Length)
}
member val CharactersCount = charactersCountSubject.AsObservable() with get
type TheViewModel(model : TheModel) =
// ...
member val IsTooManyCharacters = model.CharactersCount.Select((>) 42)
Of course since we're talking about WPF, the view-model should implement INPC. There are different approaches, but whichever one you take, the ReactiveUI has a lot of convenient tools.
For example the CreateDerivedCollection extension method that solves one of the problems you've mentioned:
documents.CreateDerivedCollection(fun x -> (* ... map Document to Control ... *))
This will take your documents observable collection, and make another observable collection out of it (actually a ReactiveCollection) that will have documents mapped to controls.

Resources