State Management and Global Variables - flutter

I'm teaching myself Flutter, having previously studied traditional object oriented languages. I'm still a beginner, but it's clear state management is a key issue in Flutter, so I'm learning about it (mostly with Providers).
Much of what I'm learning seems like using global variables, set and called from other classes (with notifyListener() calls in the latter case). But when I learned about OOP I was taught this was a "bad" thing. One object may inadvertently change a variable's value, breaking another object. In other words, encapsulation is good, global variables are bad--they violate the encapsulation idea.
What am I missing?

The provider model (or more generally, the subscriber-listener model) does not break encapsulation. For encapsulation to be broken, changes in one object directly result in the mutation of another object. For example, if you had these two classes:
class A {
int x;
B b;
}
class B {
String s;
A a;
}
So here we have a co-dependency between A and B. Now say there was a method in A to mutate its state:
void changeState(int i) {
this.x = i;
b.s = i.toString();
}
This breaks encapsulation because A is directly changing the state of B, which could result in some broken functionality as B attempts to operate with an externally mutated state.
Now say that there is no explicitly defined co-dependency, and A and B instead communicate through an event bus:
// A
void changeState(int i) {
this.x = i;
fireEvent('A-changed', this);
}
// B
listenToEvent<A>('A-changed', handleEvent);
...
void handleEvent(A source) {
this.s = source.x.toString();
}
Now encapsulation is maintained because A and B are communicating their state changes, and each one is responsible only for maintaining its own state.
This is exactly what happens in provider with ChangeNotifier. When an object updates its state and then calls notifyListeners, Flutter uses an internal event bus to notify any widget that is listening to that object, either explicitly or via provider's Provider.of or use of a Consumer. The object is not directly causing the widget to rebuild, but is instead communicating through the event bus and informing the widget that it should rebuild itself. This preserves encapsulation as every object involved is only ever responsible for its own state.
As for how provider is different from global variables, that's because provider utilizes a pattern called "dependency injection" (or DI for short). With DI, you can take a non-global object and "inject" it into the widgets that "depend" on it. This is most commonly done through a constructor, i.e.:
class SomeService {
Database db;
SomeService(this.db);
}
In that example, the SomeService class needs to communicate with a database, but instead of calling some global database service, it has the Database object passed to it upon its creation. This gives SomeService a database to communicate with without relying on a global object. (This also allows you to mock the Database object for testing purposes.)
With provider, it implements DI using a slightly different approach. Instead of using constructors, provider embeds the resources into the widget tree. Widgets from that point in the tree down will then be able to retrieve that resource dynamically, but widgets that are above that point or in a different section of the tree will not have access to it. This is how provider implements DI, and is what separates it from global variables.

Related

Why are all the methods in BlocObserver empty?

Looking through the class that defines BlocObserver, all the methods do not have any functionality defined. The BlocObserver does not inherit anything from any other class. It is only connected to the Bloc class by being created during instantiation of a Bloc.
How do the methods in BlocObserver have functionality when they are empty inside BlocObserver?
Read through the BlocObserver definition, and read through the Bloc definition.
What to do
The way you are expected to use BlocObserver is described pretty well in Core Concepts.
Basically, as BlocObserver is an abstract class, you would extend it in your own class, providing implementations for the handler methods as appropriate for your use-case.
So, roughly:
class CustomObserver extends BlocObserver {
#override
void onChange(BlocBase bloc, Change change) {
super.onChange(bloc, change);
// Perform logic based on the change
}
}
Then, you would assign an instance of this class as the static observer on Bloc, for example:
Bloc.observer = CustomObserver();
After this point, you would expect any changes that propagate through Bloc to call your CustomObserver.onChange() method.
How this works
The pattern of providing some framework object a definition of the code you'd like to run when certain events happen is a pretty common one, so it's useful to come to grips with it. Usually (and also in this case) it's way simpler than it appears.
As discussed above, you provide a BlocObserver to Bloc by setting a static member. This means both that:
you can only have one observer in the system at a time, and
any code can access it directly by calling Bloc.observer
Then, when making state changes, you ensure you do so via an instance of BlocBase (such as Cubit), which takes care of calling the appropriate method on our observer.
So, once again using Core Concepts as a base, when calling CounterCubit().increment(), the call stack looks like this:
CounterCubit.increment
CounterCubit.emit/Cubit.emit/BlocBase.emit (through inheritance)
CounterCubit.onChange
BlocBase.onChange
SimpleBlocObserver.onChange
At this point, you're back in your own code, and you can see that SimpleBlocObserver.onChange(...) calls super.onChange(...). No magic, just function calls.

How do I use ChangeNotifier?

From the docs I understood that one can call addListener() on a ChangeNotifier instance to add a custom listener to the stack.
This method accepts a callback with zero arguments (according to notifyListeners()), e.g.:
class MyClass extends ChangeNotifier {
MyClass() {
addListener(() {
// ...
});
}
}
From within the callback, how does one find out what properties or parts of MyClass have been changed?
ChangeNotifier does not have such capabilities inherently. You will have to implement your own logic. Specifically, you either have access to all of the properties of your ChangeNotifier implementation because you add the listener in its scope or you have access to it because you have a reference to it in your scope.
ChangeNotifier simply implements Listenable and provides some utilities for managing listeners. Furthermore, the documentation states the following about it:
ChangeNotifier is optimized for small numbers (one or two) of listeners. It is O(N) for adding and removing listeners and O(N²) for dispatching notifications (where N is the number of listeners).
I am not sure about options with better runtime complexity for notifying listeners, but you will not run into any issues in a regular Flutter app.
ValueNotifier
ValueNotifier is a pre-made implementation of ChangeNotifier that will notify its listeners when its value property is changed.
This is sufficient for most case, but since it appears that you want to create a custom ChangeNotifier, you can use the source code of ValueNotifier to take a look at an example implementation (it is very straight forward).
If you are just looking to do state management in general, ValueNotifiers usually work great. However, they are not applicable in every scenario. Hence, here is an extensive list with different state management options.
Considering the questions, I think the techniques that fit your needs best and the most popular options are the following:
InheritedWidget as it lets you notify dependents based on what data changed. Additionally, there is InheritedModel as an extension of this and InheritedNotifier that works with Listenable, just like ChangeNotifier does.
The BLOC pattern, which works with streams.
The provider package which is mostly a convenience wrapper for various Flutter state management techniques (InheritedWidget, StatefulWidget, ValueNotifier, etc.).

React: Are classes without state still considered stateless/pure?

I've been refactoring my app to make more components stateless/pure components; i.e., they're just functions. However, I noticed that some components will need to connect with the redux store via mapStateToProps. Which causes me to do something like this:
const someComp = (props) => {
const {
funcFromReduxStore,
} = props;
return (
...
<SomeComponent
func={ funcFromReduxStore(myArgs) }
...
);
};
This will not work because I am executing funcFromReduxStore. An easy solution is to wrap the prop in an arrow function. However, this causes many unnecessary re-renders b/c the function won't be bound.
The question then becomes: How do I bind a function in a stateless component?
Is it still stateless if I make it a class, without a constructor, and create a class instance field as so:
class someComp extends React.Component {
const {
funcFromReduxStore,
} = this.props,
wrapper = (x) => funcFromReduxStore(x) // equivalent way to bind w/ ES8+
render() {
...
<SomeCompnent
func={ wrapper(myArgs) }/>
...
}
}
I don't have a constructor, nor state. I want to keep the comopnent stateless, but I also want to bind the function to avoid unncessary re-renders. I also want to continue to keep it stateless b/c React has stated there will be performance benefits for stateless comopnents. Does this qualify as a workaround?
Short answer, no. Stateless functional components need to be simple functions.
You should take a look at the Recompose library for some really cool helpers that allow you to beef up your SFCs.
If you're trying to prevent unnecessary re-renders, you could look into onlyUpdateForKeys() or pure().
EDIT: So, I've been thinking about this a bit more and found this really great article on React component rendering performance. One of the key points in that article that pertains to your question:
Stateless components are internally wrapped in a class without any optimizations currently applied, according to Dan Abramov.
From a tweet in July 2016
So it appears that I was wrong. "Stateless Functional Components" are classes...for now. The confusing thing is that there have been performance improvements theorized:
In the future, we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations.
At this point, I think the answer to your question becomes largely subjective. When you make a class that extends a React Component, any instances of your class get the setStateprototype method. Meaning you have the ability to set state. So does that mean it's stateful even if you're not using state? Thanks to #Jordan for the link to the code. SFCs only get a render method on the prototype when they are wrapped in a class by React.
To your point about wanting to bind functions, there's only two reasons I can think of that you'd want to bind the function:
To give the function access to this (the instance of the component). From your example, it doesn't seem like you need that.
To ensure that the function passed as a prop to a child component always retains the same identity. The wrapper function in your example seems unnecessary. The identity of the function is determined by the parent component (or mapStateToProps, or whatever HOC).
You should also take a look at React's PureComponent which does the same kind of shallow checking that the pure() HOC from recompose does.

Should a ViewModel be initialized via constructor, properties, or method call

I'm fighting a few different design concepts within the context of MVVM that mainly stem from the question of when to initialize a ViewModel. To be more specific in terms of "initializing" I'm referring to loading values such as selection values, security context, and other things that could in some cases cause a few second delay.
Possible strategies:
Pass arguments to ViewModel constructor and do loading in the constructor.
Only support a parameterless constructor on the ViewModel and instead support initialize methods that take parameters and do the loading.
A combination of option 1 and 2 where arguments are passed to the ViewModel constructor but loading is deferred until the an Initialize method is called.
A variation on option 3 where instead of parameters being passed to the ViewModel constructor they are set directly on properties.
Affect on ViewModel property getters and setters
In cases where initialization is deferred there is a need to know whether the ViewModel is in a state that is considered available for which the IsBusy property generally serves just as it does for other async and time consuming operations. What this also means though is that since most properties on the ViewModel expose values retrieved from a model object that we constantly have to write the following type of plumbing to make sure the model is available.
public string Name
{
get
{
if (_customerModel == null) // Check model availability
{
return string.Empty;
}
_customerModel.Name;
}
}
Although the check is simple it just adds to the plumbing of INPC and others types of necessities that make the ViewModel become somewhat cumbersome to write and maintain. In some cases it becomes even more problematic since there may not always be a reasonable default to return from the property getter such might be the case with a boolean property IsCommercialAccount where if there is no model available it doesn't make sense to return true or false bringing into question a whole slew of other design questions such as nullability. In the case of option 1 from above where we passed everything into the constructor and loaded it then we only need to concern ourselves with a NULL ViewModel from the View and when the ViewModel is not null it is guaranteed to be initialized.
Support for deferred initialization
With option 4 it is also possible to rely on ISupportInitialize which could be implemented in the base class of the ViewModel to provide a consistent way of signaling whether the ViewModel is initialized or not and also to kick off the initialization via a standard method BeginInit. This could also be used in the case of option 2 and 3 but makes less sense if all initialization parameters are set all in one atomic transaction. At least in this way, the condition shown above could turn into something like
How the design affects IoC
In terms of IoC I understand that options 1 and 3 can be done using constructor injection which is generally preferred, and that options 2 and 4 can be accomplished using method and property injection respectively. My concern however is not with IoC or how to pass in these parameters but rather the overall design and how it affects the ViewModel implementation and it's public interface although I'd like to be a good citizen to make IoC a bit easier if necessary in the future.
Testability
All three options seem to support the concept of testability equally which doesn't help much in deciding between these options although it's arguable that option 4 could require a more broad set of tests to ensure proper behavior of properties where that behavior depends on the initialization state.
Command-ability
Options 2, 3, and 4 all have the side effect of requiring code behind in the View to call initialization methods on the ViewModel however these could be exposed as commands if necessary. In most cases one would probably be loading calling these methods directly after construction anyways like below.
var viewModel = new MyViewModel();
this.DataContext = viewModel;
// Wrap in an async call if necessary
Task.Factory.StartNew(() => viewModel.InitializeWithAccountNumber(accountNumber));
Some other thoughts
I've tried variations on these strategies as I've been working with the MVVM design pattern but haven't concluded on a best practice yet. I would love to hear what the community thinks and attempt to find a reasonable consensus on the best way forward for initializing ViewModels or otherwise dealing with their properties when they are in an unavailable state.
An ideal case may be to use the State pattern where the ViewModel itself is swapped out with different ViewModel objects that represent the different states. As such we could have a general BusyViewModel implementation that represents the busy state which removes one of the needs for the IsBusy property on the ViewModel and then when the next ViewModel is ready it is swapped out on the View allowing that ViewModel to follow the stategy outlined in option 1 where it is fully initialized during construction. This leaves open some questions about who is responsible for managing the state transitions, it could for example be the responsibility of BusyViewModel to abstract something similar to a BackgroundWorker or a Task that is doing the initialization itself and will present the internal ViewModel when ready. Swapping the DataContext on the view on the other hand may require either handling an event in the View or giving limited access to the DataContext property of the View to BusyViewModel so it can be set in the traditional state pattern sense. If there is something similar that people are doing along these lines I would definitely like to know because my google searching hasn't turned up much yet.
My general approach to object oriented design, whether I am creating a view model, or an other type of class is that; Everything that can be passed to the constructor, should be passed to the constructor. This reduces the need to have some sort of IsInitialized state and makes your objects less complex. Sometimes certain frameworks make it hard to follow this approach, IoC containers for example (although they should allow constructor injection), but I still adhere to it as a general rule.

ServiceContainer, IoC, and disposable objects

I have a question, and I'm going to tag this subjective since that's what I think it evolves into, more of a discussion. I'm hoping for some good ideas or some thought-provokers. I apologize for the long-winded question but you need to know the context.
The question is basically:
How do you deal with concrete types in relation to IoC containers? Specifically, who is responsible for disposing them, if they require disposal, and how does that knowledge get propagated out to the calling code?
Do you require them to be IDisposable? If not, is that code future-proof, or is the rule that you cannot use disposable objects? If you enforce IDisposable-requirements on interfaces and concrete types to be future-proof, whose responsibility is objects injected as part of constructor calls?
Edit: I accepted the answer by #Chris Ballard since it's the closest one to the approach we ended up with.
Basically, we always return a type that looks like this:
public interface IService<T> : IDisposable
where T: class
{
T Instance { get; }
Boolean Success { get; }
String FailureMessage { get; } // in case Success=false
}
We then return an object implementing this interface back from both .Resolve and .TryResolve, so that what we get in the calling code is always the same type.
Now, the object implementing this interface, IService<T> is IDisposable, and should always be disposed of. It's not up to the programmer that resolves a service to decide whether the IService<T> object should be disposed or not.
However, and this is the crucial part, whether the service instance should be disposed or not, that knowledge is baked into the object implementing IService<T>, so if it's a factory-scoped service (ie. each call to Resolve ends up with a new service instance), then the service instance will be disposed when the IService<T> object is disposed.
This also made it possible to support other special scopes, like pooling. We can now say that we want minimum 2 service instances, maximum 15, and typically 5, which means that each call to .Resolve will either retrieve a service instance from a pool of available objects, or construct a new one. And then, when the IService<T> object that holds the pooled service is disposed of, the service instance is released back into its pool.
Sure, this made all code look like this:
using (var service = ServiceContainer.Global.Resolve<ISomeService>())
{
service.Instance.DoSomething();
}
but it's a clean approach, and it has the same syntax regardless of the type of service or concrete object in use, so we chose that as an acceptable solution.
Original question follows, for posterity
Long-winded question comes here:
We have a IoC container that we use, and recently we discovered what amounts to a problem.
In non-IoC code, when we wanted to use, say, a file, we used a class like this:
using (Stream stream = new FileStream(...))
{
...
}
There was no question as to whether this class was something that held a limited resource or not, since we knew that files had to be closed, and the class itself implemented IDisposable. The rule is simply that every class we construct an object of, that implements IDisposable, has to be disposed of. No questions asked. It's not up to the user of this class to decide if calling Dispose is optional or not.
Ok, so on to the first step towards the IoC container. Let's assume we don't want the code to talk directly to the file, but instead go through one layer of indirection. Let's call this class a BinaryDataProvider for this example. Internally, the class is using a stream, which is still a disposable object, so the above code would be changed to:
using (BinaryDataProvider provider = new BinaryDataProvider(...))
{
...
}
This doesn't change much. The knowledge that the class implements IDisposable is still here, no questions asked, we need to call Dispose.
But, let's assume that we have classes that provide data that right now doesn't use any such limited resources.
The above code could then be written as:
BinaryDataProvider provider = new BinaryDataProvider();
...
OK, so far so good, but here comes the meat of the question. Let's assume we want to use an IoC container to inject this provider instead of depending on a specific concrete type.
The code would then be:
IBinaryDataProvider provider =
ServiceContainer.Global.Resolve<IBinaryDataProvider>();
...
Note that I assume there is an independent interface available that we can access the object through.
With the above change, what if we later on want to use an object that really should be disposed of? None of the existing code that resolves that interface is written to dispose of the object, so what now?
The way we see it, we have to pick one solution:
Implement runtime checking that checks that if a concrete type that is being registered implements IDisposable, require that the interface it is exposed through also implements IDisposable. This is not a good solution
Enfore a constraint on the interfaces being used, they must always inherit from IDisposable, in order to be future-proof
Enforce runtime that no concrete types can be IDisposable, since this is specifically not handled by the code using the IoC container
Just leave it up to the programmer to check if the object implements IDisposable and "do the right thing"?
Are there others?
Also, what about injecting objects in constructors? Our container, and some of the other containers we've looked into, is capable of injecting a fresh object into a parameter to a constructor of a concrete type. For instance, if our BinaryDataProvider need an object that implements the ILogging interface, if we enforce IDispose-"ability" on these objects, whose responsibility is it to dispose of the logging object?
What do you think? I want opinions, good and bad.
One option might be to go with a factory pattern, so that the objects created directly by the IoC container never need to be disposed themselves, eg
IBinaryDataProviderFactory factory =
ServiceContainer.Global.Resolve<IBinaryDataProviderFactory>();
using(IBinaryDataProvider provider = factory.CreateProvider())
{
...
}
Downside is added complexity, but it does mean that the container never creates anything which the developer is supposed to dispose of - it is always explicit code which does this.
If you really want to make it obvious, the factory method could be named something like CreateDisposableProvider().
(Disclaimer: I'm answering this based on java stuff. Although I program C# I haven't proxied anything in C# but I know it's possible. Sorry about the java terminology)
You could let the IoC framework inspect the object being constructed to see if it supports
IDisposable. If not, you could use a dynamic proxy to wrap the actual object that the IoC framework provides to the client code. This dynamic proxy could implement IDisposable, so that you'd always deliver a IDisposable to the client. As long as you're working with interfaces that should be fairly simple ?
Then you'd just have the problem of communicating to the developer when the object is an IDisposable. I'm not really sure how this'd be done in a nice manner.
You actually came up with a very dirty solution: your IService contract violates the SRP, wich is a big no-no.
What I recommend is to distinguish so-called "singleton" services from so-called "prototype" services. Lifetime of "singleton" ones is managed by the container, which may query at runtime whether a particular instance implements IDisposable and invoke Dispose() on shutdown if so.
Managing prototypes, on the other hand, is totally the responsibility of the calling code.