Is it possible to create inheritance between two mobx stores? - mobx

I'm building two widgets with mobx/react, where all the logic sits inside the stores. Both share most of the design rules, so their stores are 95% identical.
Is there a smart way to handle this situation?
For example, is it possible to create inheritance such as this?
class Animal {
#observable name = "";
constructor(name) {
this.name = name;
}
#computed get sentence() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
#observable isBarking = false;
#computed get bark() {
if (this.isBarking){
console.log('The dog is barking');
}
}
#action
setIsBarking(isBarking) {
this.isBarking = isBarking;
}
}

Yes you can, but you have to structure it like this, using the new Mobx pattern which does not use decorators:
(Using Typescript)
import {observable, action, computed, makeObservable} from "mobx";
const animalProps = {
name: observable,
sentence: computed
};
class abstract Animal {
name = "";
constructor(name) {
this.name = name;
}
get sentence() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
isBarking = false;
constructor(){
makeObservable(this, {
...animalProps,
isBarking: observable,
bark: computed,
setIsBarking: action
});
}
get bark() {
if (this.isBarking){
console.log('The dog is barking');
}
}
setIsBarking(isBarking) {
this.isBarking = isBarking;
}
}
If you need an instance of Animal in your app, then Mobx-State-Tree is a better option. Because making a prop observable/actionable/computable twice (the parent class and the subclass) will throw an error.

I know this was asked a long time ago at this point, but per the docs here you can override as you wrote. There are limitations though:
Only action, computed, flow, action.bound defined on prototype can be overriden by subclass.
Field can't be re-annotated in subclass, except with override.
makeAutoObservable does not support subclassing.
Extending builtins (ObservableMap, ObservableArray, etc) is not supported.
You can't provide different options to makeObservable in subclass.
You can't mix annotations/decorators in single inheritance chain.
All their standard limitations apply as well which I won't list here.
This works with the non-annotation syntax as well (e.g., makeObservable).

Have you consider MobX State Tree (https://github.com/mobxjs/mobx-state-tree) for managing your two classes Animal and Dog ?
This will give you the powerfull compose functionality, that could be used instead of inheritance.
Here's the probably most useful part for you: "Simulate inheritance by using type composition" https://github.com/mobxjs/mobx-state-tree#simulate-inheritance-by-using-type-composition

Related

Overriding an internal method with Decorator Design Pattern

I am writing an object-oriented code in which I am trying to use Decorator pattern to implement a variety of optimizations to be applied on a family of core classes at runtime. The main behaviour of core classes is a complex behaviour that is fully implemented in those classes, which indeed calls other internal methods to fulfill pieces of the task.
The decorators will only customize the internal methods which are called by the complex behaviour in core class.
Here is a pseudo-code of what I'm trying to reach:
interface I{
complex();
step1();
step2();
}
class C implements I{
complex(){
...
this.step1();
...
this.step2();
}
step1(){
...
}
step2(){
...
}
}
abstract class Decorator implements I{
I wrapped;
constructor(I obj){
this.wrapped = obj;
}
complex(){
this.wrapped.complex();
}
step1(){
this.wrapped.step1();
}
step2(){
this.wrapped.step2();
}
}
class ConcreteDecorator extends Decorator{
constructor(I obj){
super(obj);
}
step2(){
... // customizing step2()
}
}
There are a variety of customizations possible which could be combined together, and that is the main reason I'm using decorator pattern. otherwise I'll get to create dozens to hundred subtypes for each possible combination of customizations.
Now if I try to create object of the decorated class:
x = new C();
y = new ConcreteDecorator(x);
y.complex();
I expect the complex() method to be executed form the wrapped core object, while using the overridden step2() method from decorator. But it does not work this way as the complex() method in abstract decorator directly calls the method on core object which indeed skips the overridden step2() in decorator.
My overall goal is to enable the decorators only overriding one or few of the stepx() methods and that would be invoked by the complex() method which is already implemented in the core object and invokes all the steps.
Could this functionality be implemented using Decorator design pattern at all? If yes how, and if not what is the appropriate design pattern for tackling this problem.
Thanks.
I guess you could resolve that problem with Strategy pattern, where the Strategy interface includes the methods that are vary from class to class. Strategy interface may include as only one method as well as several depending on their nature.
interface IStrategy {
step1(IData data);
step2(IData data);
}
interface I {
complex();
}
class C implements I {
IData data
constructor(IStrategy strategy) {}
complex() {
...
this.strategy.step1(this.data);
...
this.strategy.step2(this.data);
}
}
class S1 implements IStrategy {
constructor(IStrategy strategy)
step1(IData data) {
}
step2(IData data) {
}
}
strategy1 = new S1();
c = new C(strategy1)
The issue you are facing is that in your application of the Decorator design pattern, because you are not decorating complex(), the call to complex() on a decorator object will be delegated to the decorated object, which has "normal" version of step2.
I think a more appropriate design pattern to solve your problem would be the Template Method design pattern.
In your case complex() would play the role of the template method, whose steps can be customized by subclasses. Instead of using composition, you use inheritance, and the rest stays more or less the same.
Here is a sample application of the Template Method design pattern to your context:
public interface I {
void complex();
void step1(); // Better to remove from the interface if possible
void step2(); // Better to remove from the interface if possible
}
// Does not need to be abstract, but can be
class DefaultBehavior implements I {
// Note how this is final to avoid having subclass
// change the algorithm.
public final void complex() {
this.step1();
this.step2();
}
public void step1() { // Default step 1
System.out.println("Default step 1");
}
public void step2() { // Default step 2
System.out.println("Default step 1");
}
}
class CustomizedStep2 extends DefaultBehavior {
public void step2() { // Customized step 2
System.out.println("Customized step 2");
}
}

How to handle private state in functional programming?

I have a feature in my application which has some private state information and some public state to share. How can I get rid of the mutable private state variable? How do I get the private state into the chain?
I just recently learned about functional programming and wanted to transform this feature to a more fp-like approach.
This is my approach so far as a simple example.
sealed class PublicState {
data class Data(val a:Int, val b:Int):PublicState()
object Pending : PublicState()
}
data class PrivateState(val a:Int, val b:Int, val x:Int)
sealed class Action {
data class InputC(val c:Int):Action()
data class InputD(val d:Int):Action()
}
sealed class Update {
data class A(val a:Int):Update()
data class B(val b:Int):Update()
object Working : Update()
}
class Feature {
val actions = PublishSubject.create<Action>()
val state = BehaviorSubject.create<PublicState>()
private var privateState = PrivateState(0,0,1)
init {
val startState = privateState.toPublicState()
actions.flatMap {action ->
when (action) {
is Action.InputC -> handleC(action)
is Action.InputD -> handleD(action)
}
}.scan(startState, ::reduce)
.subscribe(state)
}
fun reduce(previousState:PublicState, update: Update):PublicState {
// can't use previousState because Pending has not all information
// I don't want to add the information to pending because state is undefined while pending
return when (update) {
is Update.A -> privateState.copy(a = update.a).toPublicState()
is Update.B -> privateState.copy(b = update.b).toPublicState()
Update.Working -> PublicState.Pending
}
}
fun doAction(action: Action) {
actions.onNext(action)
}
private fun handleC(action:Action.InputC):Observable<Update> {
return Observable.fromCallable {
// time consuming work which uses x
val result = privateState.x + privateState.a + action.c
Update.A(result) as Update
}.startWith(Update.Working)
}
private fun handleD(action:Action.InputD):Observable<Update> {
return Observable.fromCallable {
// time consuming work which uses x
val result = privateState.x + privateState.b + action.d
Update.B(result) as Update
}.startWith(Update.Working)
}
}
private fun PrivateState.toPublicState(): PublicState {
return PublicState.Data(a, b)
}
In reality there are a lot more state variables than a, b and x. But if I want them in the chain, I have a gigantic State variable and all of it gets exposed. It feels easier with the mutable variable.
Do you have any suggestion how to solve this? I am also open for other patterns, if you think this is a wrong approach.
My goal is to keep some private state and expose just the PublicState.
FP does not deal with private states. Why would you care about keeping something private? Because someone else, from an outer world, could intentionally or not mutate that one and bring entire object into disrepair, right? But there are no mutations in the FP. So you're safe.
Thus your quesiton reduces to the "how to handle state". Well, let me know if you want me to answer.

TableView and Fragment to edit Details with tornadofx

I use kotlinx.serialization for my models.
I'd like the idea of them to not depend on JavaFX, so they do not expose properties.
Given a model, I want a tableview for a quick representation of a list of instances, and additionally a more detailed Fragment as an editor.
consider the following model:
#Serializable
data class Person(
var name: String,
var firstname: String,
var complex: Stuff)
the view containing the tableview contains
private val personlist = mutableListOf<Person>().observable()
with a tableview that opens an instance of PersonEditor for the selected row when Enter is pressed:
tableview(personlist) {
column("name", Person::name)
column("first name", Person::firstname)
setOnKeyPressed { ev ->
selectedItem?.apply {
when (ev.code) {
KeyCode.ENTER -> PersonEditor(this).openModal()
}
}
}
}
I followed this gitbook section (but do not want the modelview to be rebound on selection of another row within the tableview)
The editor looks about like this:
class PersonEditor(person: Person) : ItemFragment<Person>() {
val model: Model = Model()
override val root = form {
fieldset("Personal information") {
field("Name") {
textfield(model.name)
}
field("Vorname") {
textfield(model.firstname)
}
}
fieldset("complex stuff") {
//... more complex stuff here
}
fieldset {
button("Save") {
enableWhen(model.dirty)
action { model.commit() }
}
button("Reset") { action { model.rollback() } }
}
}
class Model : ItemViewModel<Person>() {
val name = bind(Person::name)
val firstname = bind(Person::firstname)
//... complex stuff
}
init {
itemProperty.value = mieter
model.bindTo(this)
}
}
When I save the edited values in the detail view, the tableview is not updated.
Whats the best practize to solve this?
Also I'm unsure, if what I'm doing can be considered good practize, so i'd be happy for some advice on that too.
The best practice in a JavaFX application is to use observable properties. Not doing so is an uphill battle. You can keep your lean domain objects, but add a JavaFX/TornadoFX specific version with observable properties. This object can know how to copy data to/from your "lean" domain objects.
With this approach, especially in combination with ItemViewModel wrappers will make sure that your data is always updated.
The setOnKeyPressed code you posted can be changed to:
setOnUserSelect {
PersonEditor(it).openModal()
}
Notice though, that you are not supposed to instantiate Views and Fragments directly, as doing so skips certain steps in the TornadoFX life cycle. Instead you should pass the person as a parameter, or create a new scope and inject a PersonModel into that scope before opening the editor in that scope:
setOnUserSelect {
find<PersonEditor>(Scope(PersonEditor(it)))
}

Specialized Singleton implementation

I am looking for specialized singleton implementation, probably I might be using wrong terminology and hence looking for expert suggestion. Here is my scenario:
There is common code which can be called by ComponentA or ComponentB. I need to push telemetry data from the common code. Telemetry needs to have information that whether this common code get called by ComponentA or ComponentB.
So common code will have just this line of code:
telemetry.pushData(this._area, data);
where this._area tells the telemetry data is getting pushed for which component
I need to push telemetry data from multiple places so it would be good if object got created once and used through out the code lifetime
One option I can think of passing component context to the common code which in mind doesn't look right, hence looking for suggestion what kind of pattern one should use in this case?
This is what I am thinking
// Telemetry.ts file present in shared code
export class Telemetry extends Singleton {
public constructor() {
super();
}
public static instance(): Telemetry {
return super.instance<Telemetry>(Telemetry);
}
public publishEvent(data): void {
if (!this.area) {
throw new Error("Error: Initialize telemetry class with right area");
}
pushtelemetryData(this.area, data);
}
public area: string;
}
// Create Telemetry object from component A
Telemetry.instance().area = "ComponentA";
// Shared code will call telemetry publishEvent
Telemetry.instance().publishEvent(data);
Thanks
It's not a good pattern to use in TypeScript where you would generally inject dependencies.
If you must absolutely do it then you can do it by faking it somewhat:
namespace Telemetry {
var instance : SingletonSomething;
export function push(data: Any) : void {
if (instance == null) {
instance = new SingletonSomething();
}
instance.push(data);
}
class SingletonSomething() { ... }
}
and then you could call
Telemetry.push(data);
You can imitate the singleton pattern in typescript easily:
class Telemetry {
private static instance: Telemetry;
public static getInstance(): Telemetry {
if (Telemetry.instance == null) {
Telemetry.instance = new Telemetry();
}
return Telemetry.instance;
}
...
}
If you have your code in some sort of closure (module, namespace, etc) then you can replace the static member with:
let telemetryInstance: Telemetry;
export class Telemetry {
public static getInstance(): Telemetry {
if (telemetryInstance == null) {
telemetryInstance = new Telemetry();
}
return telemetryInstance;
}
...
}
But then you can also replace the static method with:
let telemetryInstance: Telemetry;
export function getTelemetryInstance(): Telemetry {
if (telemetryInstance == null) {
telemetryInstance = new Telemetry();
}
return telemetryInstance;
}
export class Telemetry {
...
}
At this point, in case you are using some sort of closure, you might ask yourself if you really need the class at all?
If you use this as a module:
// telemetry.ts
export interface TelemetryData {
...
}
export function pushData(data: TelemetryData): void {
...
}
Then you get exactly what you're looking for, and this is more of the "javascript way" of doing it.
Edit
In the telemetry module there's no need to know the users of it.
If the Telemetry.pushData function needs to have information about the object that called it then define an interface for it:
// telemetry.ts
export interface TelemetryData {
...
}
export interface TelemetryComponent {
name: string;
...
}
export function pushData(data: TelemetryData, component: TelemetryComponent): void {
...
}
Then in the other modules, where you use it:
// someModule.ts
import * as Telemetry from "./telemetry";
class MyComponent implement Telemetry.TelemetryComponent {
// can also be a simple string property
public get name() {
return "MyComponent";
}
fn() {
...
Telemetry.pushData({ ... }, this);
}
}
2nd Edit
Because you are using a module system, your module files are enough to make singletons, there's no need for a class to achieve that.
You can do this:
// telemetry.ts
let area: string;
export interface TelemetryData {
...
}
export function setArea(usedArea: string) {
area = usedArea;
}
export function pushData(data: TelemetryData): void {
...
}
Then:
Telemetry.setArea("ComponentA");
...
Telemetry.publishEvent(data);
The telemetry module will be created only once per page, so you can treat the entire module as a singleton.
Export only the functions that are needed.

Information Hiding the "Swifter" way?

I have a question regarding object oriented design principles and Swift. I am pretty familiar with Java and I am currently taking a udacity course to get a first hands on in Swift.
In the Java community (basically in every community that follows OOP) it is very common to use information hiding techniques such as hiding or encapsulating data within classes to make sure it cannot be manipulated from outside. A common principle is to declare all attributes of a class as being private and use getters for retrieving an attribute's value and setters for manipulation.
I tried to follow this approach when writing a class that was part of the course and it looks like this:
//
// RecordedAudio.swift
// Pitch Perfect
//
import Foundation
class RecordedAudio: NSObject {
private let filePathUrl: NSURL!
private let title: String?
init(filePathUrl: NSURL, title: String?)
{
self.filePathUrl = filePathUrl
self.title = title
}
func getFilePathUrl() -> NSURL
{
return filePathUrl
}
func getTitle() -> String
{
if title != nil
{
return title!
}
else
{
return "none"
}
}
}
The code works and my private attributes cannot be accessed from outside my class, which is exactly the behavior I wanted to achieve. However, the following questions came to my mind:
1.) The course instructor decided to leave the attributes' access control level at the default "internal" and not use getters/setters but rather access the attributes directly from outside. Any thoughts on why developers might do that in swift? Is my approach not "swift" enough???
2.) In conclusion: Is there a "swifter" way to implement encapsulation when writing your own class? What are swift's native techniques to achieve the information hiding I am aiming for?
You can restrict external property manipulation, by marking the property public for reading and private for writing, as described in the documentation:
class RecordedAudio: NSObject {
public private(set) let filePathUrl: NSURL!
public private(set) let title: String?
init(filePathUrl: NSURL, title: String?) {
self.filePathUrl = filePathUrl
self.title = title
}
}
// in another file
let audio = RecordedAudio(filePathUrl: myUrl, title: myTitle)
let url = audio.filePathUrl // works, returns the url
audio.filePathUrl = newUrl // doesn't compile
I do it a bit like in Obj-C:
class MyClass
private var _something:Int
var something:Int {
get {return _something}
// optional: set { _something = newValue }
}
init() { _something = 99 }
}
...
let c = MyClass()
let v = c.something
Above is a primitive example, but handled stringent it works as a good pattern.