5 ms·
I fear that battle is already lost on this one, but I'm disappointed to see FRP making it into the officially supported workflow on mobile. I think FRP has a p
by skohan 7y ago
I fear that battle is already lost on this one, but I'm disappointed to see FRP making it into the officially supported workflow on mobile.
I think FRP has a place, and React has been a transformative technology for web, but in that case you generally don't even have to think about the rx primitives at all if you don't want to.
As far as RX as it's penetrated mobile development in the past few years, the result I have seen is that many projects have become unreadable tangles of reactive chains, where the stack trace is no longer useful, because of the unfounded assumption that "more reactive" means better code.
The iOS APIs are certainly showing their age, and there's a lot of warts related to their Objective-C pedigree, but I think they have always had a strength in terms of being fairly agnostic about how they are integrated into your program's structure. I really fear that sense will be lost if third party libraries adopt combine as the dominant interface paradigm.
- ajconway 7y agoMore reactive usually means less global state, which is generally for the better. It also encourages functional purity where possible. Previously (briefly) in iOS/macOS there was an attempt to move to closure-based APIs, which led to unreadable tangles of function invocations with often surprising calling threads. Before that for a long time there was a weak delegate object pattern, probably the least convenient way of interacting with things.
- pjmlp 7y agoIt also means more memory being used.
- skohan 7y agoAt least with closure based code, you can set a breakpoint and see the chain of executions which led to your critical portion. With FRP, basic flow of control is surrendered to the scheduler, and your stack trace doesn't tell you anything. The other thing I'm not a fan of with FRP is that it makes the assumption that it's somehow good to deal with everything through one big unified abstraction layer. Rather than just dealing with your concrete business logic, you also have to set-shift to think about the flow of your program in terms of abstract chains of observables. This level of abstraction makes the interfaces in your code less clear as well. For instance, with the delegate pattern, you can take a look at the protocol of the object you're consuming and get a clear idea about what the intent of that protocol is. In an FRP world, your interface point might be an Int-valued observable, which could be just about anything. To see how it's going to behave, you have to go see how that particular observable is defined in the calling context, which might end up being some chain of map-zip-filter-debounce operators which further obfuscate the intent. More abstraction rarely makes a program more readable or more performant, and FRP is all about abstraction. Also I think you're poking at a false dichotomy with reference to things like global state, and functional purity. It's very possible to write simple, imperative code which makes use of pure functional programming, and immutable state. FRP puts you in kind of a "jail" which encourages you to produce code with those properties, but it comes with a lot of unnecessary costs as well.
- ajconway 7y agoThere is no dichotomy here, it's perfectly fine to use imperative code where it fits better. I would not agree that using any particular technology makes code less clear. Also, I'm not sure how protocol interfaces, callback-based interfaces and reactive event sources differ in readability as they all basically provide a way to call your code at (without referring to documentation) random times.
- DrScientist 7y agoDoesn't an application still have a state, even if you don't store/manage it explicitly? Isn't a program more understandable if that state is sometimes made explicit rather than implicit? Also if your goal is 'functional purity' then you might want to read this article from ten years ago. https://prog21.dadgum.com/55.html https://prog21.dadgum.com/55.html
- ajconway 7y agoThe state is there, of course. The goal here is to minimize the amount of state the code has access to at any particular time. Functional purity is not the goal, it's just one way to reduce state.
- DrScientist 7y agoSo you still have state, but you can't get at it because it's been moved from the heap to the call stack? I'm not sure that makes programs: 1. Easily evolve-able. 2. Easy to understand. Well managed accessible state can be greatly simplifying. In my view the goal should be simple understandable code, not a meta-goal like removing all accessible state.
- ajconway 7y agoI don't know, actually. Should the state other that what the task (or sub-task) can observe matter for it to function? Where would be the boundary, as there are lots of things happening simultaneously in a computer, and the global state is huge.
- bradstewart 7y ago> Well managed accessible state can be greatly simplifying. Absolutely--and functional programming is one way to achieve that. From the perspective a given function, all "state" is captured in its inputs and outputs. You know exactly what existing state can be used by the function (inputs) and exactly what state can be generated by the function (outputs) simply from looking at the signature.
- tabs_masterrace 7y agoI must say I welcome it, unreadable tangles are agnostic, and can be written with any kind of pattern or language, and stack traces still work as you expect (although stack traces never been great on iOS). In every project you always end up trying to solve the same problem of how to best propagate events and errors, often in an asynchronous fashion. So you end up with delegates, notifications, callbacks - but after a while you realize that all of that can be neatly distilled down to a single way of doing things. Then you got all these powerful build-in operations, which come in handy sometimes, and it's also much better at making sure you're actually handling all the possible cases.
- skohan 7y ago> In every project you always end up trying to solve the same problem of how to best propagate events and errors, often in an asynchronous fashion. So you end up with delegates, notifications, callbacks - but after a while you realize that all of that can be neatly distilled down to a single way of doing things. I have seen this argument in favor of FRP a lot of places, but in my experience the problem is just vastly overstated. In terms of practical mobile development, the asynchronicity you're dealing with is mostly network operations which execute exactly once per page. The abstractions RxSwift, for example, give you for that are complete overkill for something which can be handled perfectly well by throwing a few lines of imperative code onto a background thread. Besides that, you might have a few global events to handle like login and logout, which can be handled perfectly well by any number of event/emitter APIs or even a hand-rolled implementation of a few dozen lines. I don't understand why I need to import thousands of lines of code into my project just to "unify" these concerns.
- dep_b 7y ago> In terms of practical mobile development, the asynchronicity you're dealing with is mostly network operations which execute exactly once per page. Absolutely not true, I have been dealing with a lot of "simple" apps and always once you start introducing stuff like Push Notifications that trigger actions, websockets that send and receive messages and other "unexpected" messages to handle the traditional MVC methods just fall apart. Having said that you can do pretty similar stuff without introducing RxSwift into your application. With or without it, getting these entangled multi-source event handling mechanisms to work well takes a really disciplined approach.
- bsaul 7y agoI couldn’t agree more. « All reactive GUI» on iOS has been a total disaster in the only place i’ve seen it tried. It’s just the new fashion buzzword of the day, and it will follow the same bell-curve as the rest : people will use it everywhere, then after they realize it sometimes makes simple things harder, will learn to use it only where it really makes sense.
- seanmcdirmid 7y agoSince when did FRP come to denote any random framework that focused on reactivity and was somewhat functional vs the stuff Elliott and Hudak did in Haskell?