Comments (7)
On a side note, C# 7 pattern matching would be great way to write clean reducers :
https://github.com/dotnet/roslyn/blob/features/patterns/docs/features/patterns.md
from redux.net.
One workaround for this is to use the Visitor Pattern. With this you only have to type cast one time and the Visitor will take care of the rest. Your example can be rewritten using the Visitor Pattern as follow.
First create an IVisitableAction inherited from IAction which can be visited by the Visitor.
public interface IVisitableAction : IAction
{
LoginState Visit(LoginState prevState, ActionVisitor visitor);
}
Then with each action type you create a concrete class implementing IVisitableAction. Each class can contain their own additional information for the action.
public class LoginStarted : IVisitableAction
{
public string Username { get; set; }
public LoginState Visit(LoginState prevState, ActionVisitor visitor)
{
visitor.Visit(prevState, this);
}
}
public class LoginSuccess : IVisitableAction
{
public LoginState Visit(LoginState prevState, ActionVisitor visitor)
{
visitor.Visit(prevState, this);
}
}
In the ActionVisitor class, add a Visit function for each concrete action class that perform the actual logic for it and return an appropriate state.
public class ActionVisitor
{
public LoginState Visit(LoginState prevState, LoginStarted action)
{
// here the Visitor can access action's properties
DoLogin(action.Username);
return new LoginState() { IsProcessingLogin = true };
}
public LoginState Visit(LoginState prevState, LoginSuccess action)
{
return new LoginState() { IsProcessingLogin = false };
}
}
Now you can rewrite the reducer to utilize all this.
public static class Reducer
{
static readonly ActionVisitor VISITOR = new ActionVisitor();
public static LoginState Reduce(LoginState prevState, IAction action)
{
var visitableAction = action as IVisitableAction; // there is only one type casting here
return visitableAction?.Visit(prevState, VISITOR) ?? prevState;
}
}
from redux.net.
I'm not as familiar with the Visitor pattern, which probably makes this feel like it's harder to reason about what is going on. I can appreciate the use of this new pattern in this architecture but it probably won't be for everyone.
from redux.net.
Thanks @dinoc for the question.
First of all, it's important to note that clarity was my main focus when I made the reducers in the samples. In my experience, the type checking / casting has never caused a performance issue. Performance issues are often related to doing too much work on the UI thread or the shape of the state.
However, I can explain why I did not add an ActionType property on IAction and how to optimize your reducer.
I can see a major flaw to the enum ActionType. What will be the values of the enum ActionType if it was defined in the Redux.NET library? It's the responsibility of the consumer to define all the possible action types.
The is operator is slower than comparing enums but you will need to dispatch a LOT of different actions type to see the difference. (See this stackoverflow question for a benchmark http://stackoverflow.com/questions/686412/c-sharp-is-operator-performance)
The as operator is more efficient than the is operator + casting, but I choose not to use it for the reducer because it is a little more verbose.
The visitor pattern proposed by @hungnd1475 is a good solution. If you want to simplify it, you could use simple polymorphism.
public asbtract class ActionBase : IAction
{
public abstract LoginState GetNewState(LoginState state);
}
public static class Reducer
{
public static LoginState Reduce(LoginState prevState, IAction action)
{
var actionBase = action as ActionBase; // there is only one type casting here
return actionBase?.GetNewState(prevState) ?? prevState;
}
}
The disadvantage of this solution comparing to the visitor pattern is that you associate the reducer business login directly to your action. If you use the visitor pattern or the polyformism solution, you lose some advantage of reducer composition given by the functional approach.
Hope it answer your questions !
from redux.net.
What about adding a simple GetClassName method on the ActionBase and comparing against those in the reducer? That would remove reducer logic from the action.
If you wanted to take that a step further too....creating a new Fody add in to weave a property in for the class name would be kind of cool too.
from redux.net.
Good news...there already is a fody add-in for this - https://github.com/NickStrupat/NameOf
from redux.net.
A bit late to the party But I think simple method overloading can clean up the if-else mess in reducers rather than Dynamic Polymorphism which would add more fuel to fire of redux boilerplate issue.
from redux.net.
Related Issues (20)
- Make compatible with .NET Standard HOT 4
- Observable collection that keeps suitable items HOT 3
- Saga HOT 23
- Is the return value from Store.Dispatch useful for anything? HOT 13
- What is the point of this Redux.NET line HOT 3
- [Question] Any plans for state persistence? HOT 1
- Future of Redux.NET / version 3.0 HOT 29
- Create store bug HOT 9
- Refactor GetState() to State (property) HOT 2
- Make InnerDispatch protected virtual
- New ActionDispatched event would duplicate StateChanged HOT 11
- Won't compile in Xamarin HOT 2
- Question about Dispatching Actions. HOT 3
- What's the status of this project? HOT 19
- WPF Dev Tools don't work
- C#.NET Windows Applications. HOT 8
- Is this Dead project & no longer being maintenance? HOT 2
- Could not link assemblies HOT 1
- The call is ambiguous between the following methods or properties: 'System.ObservableExtensions.Subscribe<T>(System.IObservable<T>, System.Action<T>)' and 'System.ObservableExtensions.Subscribe<T>(System.IObservable<T>, System.Action<T>)' HOT 1
- Nuget Package should be marked deprecated.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from redux.net.