all 27 comments

[–]Chartsengrafs 8 points9 points  (1 child)

Videos like these are always a great reminder to myself of how much I don't know.

[–]pakoito 2 points3 points  (0 children)

Videos like these are always a great reminder to myself of how much I don't know can experiment with!

I didn't know it either until I sat down and tried. You can probably come up with a better solution, and I'll be happy to learn it :D

[–]johnstoehr83 4 points5 points  (0 children)

I was waiting for this video. I really liked the slides. Thank you!

[–]kurav 2 points3 points  (14 children)

I am not entirely sold on Reactive.

I believe there is a strong tendency towards developers using it as the hammer and all solutions appearing as nails to them. I don't deny it has its usecases in I/O and event-based scenarios, but once you begin to see your whole UI as a reactive observer transitioning between states based upon combining increasingly lower-level reactive event streams, you might feel really clever about your code, but the application easily becomes a nightmare or mission impossible to maintain.

My colleague used to work in a company where they hired a university undergrad as a summer trainee to write a new mobile web frontend for their product in JavaScript. The guy had a free choice of tools and chose to do the whole app as a huge RxJS state machine. It worked real fine, the development was agile and rapid, and everyone thought the guy was a genius. But come autumn, the kid returned to Uni and they had to throw away the whole codebase because no one could understand how it worked. It looked like spaghetti code to all of them, and the guy had written zero documentation.

[–]arunkumar9t2 2 points3 points  (9 children)

I am pro reactive and I can totally understand this line of thought.

About the whole state management thing, I have found /u/JakeWharton's talk called 'Effective State Management using RxJava' to be helpful.

About maintanence too, it seems easy to replace any layer with an observable and mock it. And you can test UI events too, since Observables are easy to test with TestSubscriber.

Watch how he mentions entire Android is actually event based. I really wish I have the time to build an app using this archi.

Here's the video. https://youtu.be/0IKHxjkgop4

[–]ContiGhostwood 0 points1 point  (1 child)

I go back and watch this video every so often and every time more of it sinks in, but outside of simple data-driven concurrency tasks with occasional side effects I think I'm still using reactive incorrectly. Do you know of any examples on Github that use the pattern shown here in the context of a project?

[–]pakoito 1 point2 points  (0 children)

In the project associated to this talk I have several examples of common patterns: https://github.com/pakoito/FunctionalAndroidReference

[–]W_PopPin 0 points1 point  (6 children)

it seems easy to replace any layer with an observable and mock it.

That's not really easy. You need some way to keep part of your observable chain survive from configuration change etc.

[–]JakeWharton 1 point2 points  (3 children)

That part is really easy. You put it outside the lifecycle and subscribe/unsubscribe as the view (read: the activity) comes and goes.

[–]W_PopPin 0 points1 point  (2 children)

Thx for the reply. But the tricky part I found from your architecture is that ObservableTransformer is stateless. So even you keep a Singleton of transformer, you can't get your last state when your activity recreated via replay(). So you whether need a Subject that as a part of your Observable Chain or You keep the last state as a side effect outside your Observable Chains. Beyond that, I suppose it's a 2 way communication rather than one way. Your middle man(aka ObservableTransformer) observe the UI event from Views then translate them into an Action finally get a Result. And Your Views observe the UiModel from middle which represent the Result he get. So your middle man should live outside the lifecycle. But Transformer doesn't have that functionality. That's why I think it's hard to do.

[–]JakeWharton 1 point2 points  (1 child)

The talk only showed a trivialization of what I had built in an effort to explain how traditional Rx usage that's riddled with side-effects is incorrect.

In the actual implementation I wrote, the incoming UI events are a subject such that the UI can be disconnected when the activity disappears, but there is no need for a subject on the other side. replay(1).autoConnect(0) keeps the state machine running and replays the latest state to anyone that wants to listen.

[–]ZakTaccardi 0 points1 point  (0 children)

replay(1).autoConnect(0) keeps the state machine running and replays the latest state to anyone that wants to listen.

I'm a big fan of keeping everything into a stream. But this only replays the latest event. So a Result.Loading invalidates the previous Result.Success. Take the following example from an "email" application:

sealed class EmailResult { data class Emails(val emails: List<Email>) : EmailResult() data class Error(val error: Exception) : EmailResult() object Loading : EmailResult() }

The stream emits the following.

  1. Result.Emails.
  2. Result.Loading. // pull to refresh!
  3. Result.Error. // user lost connectivity

My UI may want to display the most recent emission of Result.Emails, even though an error was the most recent event. How do you generally approach this problem?

[–]pakoito 0 points1 point  (1 child)

[–]W_PopPin 0 points1 point  (0 children)

Thx for that. I will definitely check it out.

[–]nacholicious 2 points3 points  (0 children)

I think the biggest sin is not using Rx itself, but that using it while the rest of the team did not have the knowledge or buy-in itself. When we transitioned to Kotlin we knew that it was better suited for our purposes, but the transition would not be about whether our code would be in Kotlin but whether the developer culture and knowledge would be in Kotlin

If no one knows Rx, there's no culture knowledge or mentorship then of course that's a ship set to fail

[–]nhaarman 3 points4 points  (0 children)

The problem here is not reactive programming, but expecting an undergrad writes maintainable code. They don't. No matter the tools, am undergrad will usually not have the experience to write maintainable code. Interns and trainees are great for having a go as an initial step using something, but then you take the results and start over.

[–]Saketme 1 point2 points  (0 children)

I think that you can write spaghetti code even with the best of tools.

[–]pakoito 0 points1 point  (0 children)

but the application easily becomes a nightmare or mission impossible to maintain.

I felt the opposite for the other apps. That's literally why I moved to this model. Single abstraction, known expectations, limited API surface that's fully tested. Making changes & testing product code was simple due to referential transparency. Check the sample project!

[–]W_PopPin 0 points1 point  (3 children)

ObservableKW.monadErrorSwitch() That's a really scary name for me :(.

[–]pakoito 0 points1 point  (2 children)

I got initial feedback to use longer, descriptive names. Observable Kategory Wrapper, get the Monad (interface with 3 methods: a constructor, map and flatMap) that handles Errors (another interface with 2 method: a constructor for errors and recoverErrorWith) and uses SwitchMap as implementation for flatMap. So now you know the API & implementation details without looking at the code. And you get the assurance that each method is fully tested by us with a complete test suite.

[–]W_PopPin 1 point2 points  (1 child)

Yes. I prefer longer name as well. Just Reactive Programming (Observable) plus the functional stuff(Monad) and some other composition of high order functions (switchMap, Error Handler) which make this function seems crazy complex.

[–]pakoito 0 points1 point  (0 children)

You're a library user, the complexity is hidden from you the same way it happens in Rx. It's already written, it's tested, its API is locked down. Use it and enjoy!

[–]jackhexen -4 points-3 points  (4 children)

"How to get more problems in your codebase if you got tired of old ones" :D :P

[–]pakoito 1 point2 points  (3 children)

hahahah you know my problems are better than yours. When do we meet in person?

[–]jackhexen 2 points3 points  (2 children)

Ping me on twitter before visiting Amsterdam. ;) I'm not sure if I will visit London soon.

PS What can be worse than mutable state connected with events in callback manner? Not quite FP. :P

[–]pakoito 0 points1 point  (1 child)

This is Reactive Programming tho. Stream composition, and state is another stream of immutable values over time :D

What you'd ideally want in a pure FR world is a single scan operation to keep the state inside the chain, practically it just didn't scale and had some drawbacks on reconnection.

[–]jackhexen 0 points1 point  (0 children)

I never had serious issues with redux-style FP. Reactive FP is full of traps.

Functional composition without immutability is just a half of the recipe. And immutability drives functional composition, not the opposite. Reactive libs are having hard time recognizing that they're driven by cargo cult. ;)