5 ms·
Calling methods via strings where you control all the source code to your own application is pretty toxic. Since there are no network or persistence boundaries
by an_opabinia 5y ago
Calling methods via strings where you control all the source code to your own application is pretty toxic.
Since there are no network or persistence boundaries - it's a local app the developer owns 100% of - there are no engineering constraints that require the kind of decoupling of an event bus.
The execution boundary thing ("post messages to other threads") is also pretty dumb. There are a dozen simpler ways to coordinate between a UI and background / business logic thread. Since most application's long-running behavior is only HTTP calls, today's developer doesn't have to think about it at all - the callback or promise (CompleteableFuture) returned by their URL fetcher forces them to do the right thing.
RxJava is almost always the better choice to be more expressive about UIs. Otherwise, an Android developer should adopt Kotlin for coroutines. Or, frankly, reduce timeouts for HTTP calls to be closer to frame rendering times (16-32ms), pay the extra pennies to serve networked services better, and focus on low-latency remote APIs.
- sgt 5y agoWill also need a lot of unit tests that would normally be unnecessary.
- ncann 5y agoMaybe I'm dumb but I've read your comments a few times over and I still haven't quite understand what you were trying to say. "Calling methods via strings where you control all the source code to your own application " -> what do you mean by this and how is it relevant to this library?
- wffurr 5y agoInstead of posting a string and a payload to the event bus, which a listener picks up and unpacks to call method in the receiver, just call the method. It does introduce a direct dependency where it was indirect before, but is otherwise much simpler and significantly faster than all the string comparisons.
- void_mint 5y ago> It does introduce a direct dependency where it was indirect before Which is okay if you've used any amount of DI and testability-focused thinking to set up your code. The event bus pattern works great if you don't know (or want to know) what's going to happen to an event once it's emitted. If the only thing that happens is a different method in your app gets triggered, you should really just trigger that method and skip the event bus altogether.
- ncann 5y agoAh ok I guess my confusion is from the fact that there's no explicit "string" being passed around with this library, but the concept of a payload makes sense.
- hota_mazi 5y agoIntroducing the direct dependency is exactly what you want to avoid and what event buses provide. With your approach, you are coupling views and model with n*m links, with an event bus, it's just n+m. Much easier to decouple your logic. I do agree with you that I'm not a fan of the loss of static typing that event buses usually introduce.
- an_opabinia 5y ago> Introducing the direct dependency is exactly what you want to avoid Why? It's a GUI application on Android. Everything that listens to this event bus is a direct dependency configured at build time. Every modern optimization, like ahead of time compilation and code stripping, benefits from direct dependencies. This is why I used the word toxic, and not stupid.
- the_gipsy 5y agoCalling by strings is not decoupling. You just fooled the type system. Or yourself, if you want.
- chris_overseas 5y agoThere is no string comparison here, the subscriptions and posting of events is based on the class of the POJO being sent.
- Quekid5 5y agoI think they might be referring to Stringly Typed Programming.
- an_opabinia 5y agoEventBus uses an annotation processor and reflection to reify a call. A ton of things look like this. Like that's also sort of what a REST API is. It makes a ton of sense for crossing boundaries from owning the code to not owning the code, and back again. But since you own the code, you own 100% of the source in your GUI application, why would you need indirection? There's no reason to hide part A from part B. That's why giant companies who author all their stuff in house use monorepos. I can't believe I'm saying this, but hiding stuff, like trying to mark code as proprietary or "not maintained by my team" (as Amazon would do), is a social construct. This is relevant to the library because many times, people who have the experience of using this library in real Android apps and having a positive experience with it - they are using the library for to do, "my team does this part, and this other team does that part." "This developer is stupid and junior, so must decouple their work." Toxic! Amazon: extremely toxic. If I were a code anthropologist, DI and EventBus would be, "Artifacts of toxicity." When you look at how it's used by other apps, like Signal for Android, with small teams, it just looks stupid, and they work around its warts anyway, and use direct calling anyway, just in a far more roundabout fashion.
- ncann 5y ago> But since you own the code, you own 100% of the source in your GUI application, why would you need indirection? So what is your proposed non-indirection way? I'm assuming you meant the traditional listener/observable way of registering event producers and event listeners together, in which case this FAQ explains pretty well their downsides compared to an event bus: https://github.com/google/guava/wiki/EventBusExplained#faq https://github.com/google/guava/wiki/EventBusExplained#faq
- optymizer 5y agoI find your comment overly dismissive of EventBus and I respectfully disagree with you on not needing to decouple components for a local app. I've worked with GreenRobot's EventBus on a large (100M+ installs) app years ago. I worked with RxJava as well. I've also worked with more feature-rich proprietary solutions to EventBus. EventBus is a library with a straightforward API that junior developers can use with little issues. "Launch this event and add this annotation to make sure it gets processed off the main thread". This is a very real practical advantage, that is not unique to EventBus, but it works well for large teams and does not require you to rewrite methods to return Observable objects just to be able to chain some things together. Does EventBus lead to some eventual problems? Yes. Are they manageable? Yes. On the other hand, RxJava is a framework and, once it's in, it starts spreading Observables through all the classes in the codebase. Most developers need significant time to ramp up to become productive with it. I used to work with 30+ developers on an Android app. The app I work on now at a different company has thousands of developers working on it. People at these companies collectively concluded that RxJava doesn't bring sufficient benefits to these large teams. Both companies have ripped it out pretty quickly after the initial excitement wore off and the downsides started kicking in. Kotlin made things much better in the recent years, but it doesn't mean that EventBus is now 'dumb' or 'toxic'. Coroutines on Android weren't widely used in these large apps a few years ago, before Google announced official support, so people were calling "new Thread()", using AsyncTask or, more likely, having ExecutorService threads created by various components in the design without any regard to CPU contention or priority of execution, and instantiating "new Runnable" all over the place. Also, using the HTTP handler's thread to process business logic _blocks that thread_ and makes it unavailable until the logic is done running - which could take a long time. Boundaries for execution are absolutely required, unless you're working on a small app that doesn't need to care about these issues and where pretty much anything goes. You want to have control over which logic runs on which thread, otherwise you'll needlessly spend time debugging race conditions and deadlocks in production, like me. HTTP threads for delivering HTTP results, image threads for processing images, database threads for writing to the database, and you want to set priority for background, I/O and foreground threads. That last point you have about reducing timeouts to be closer to frame rendering times is also incredibly narrowly useful. You can invest a ton of time and have the server respond in microseconds but if your users in Bangladesh are using cheap $20 Android phones over 3G connections you still have the same problem and you won't be anywhere near 32ms.
- mwcampbell 5y ago> Or, frankly, reduce timeouts for HTTP calls to be closer to frame rendering times (16-32ms), pay the extra pennies to serve networked services better, and focus on low-latency remote APIs. To be clear, are you suggesting that network requests in an Android app should block the UI thread, on the assumption that everyone will have a good enough connection (and one close enough to your server) to receive the response quickly?
- an_opabinia 5y agoIf you really want to achieve a great experience for an interactive networked application, you should engineer things where everyone is close enough to your servers to get a response quickly. Or design an experience that does not need to be network interactive. > are you suggesting that network requests in an Android app should block the UI thread I'm suggesting that if network requests over a cellular connection could just be made within a frame (really, a tick, nothing is that fast), like they are on Fortnite or Roblox for Android, for example - if people applied the same engineering practices and standards to GUI applications as for realtime multiplayer games - yes, the apps would be way better, and as a side effect, way easier to author. The server and deployment story would get more complicated. But maybe that's a good thing, to put the hard work where it's easier to do. For a concrete example of what that would look like, the io_uring thing posted here just a bit ago was really fascinating. It's probably the way HTTP should have been done in Java from the get go - a request that returns immediately, but you must poll in the GUI that actually needs its results to render, and you must poll at the right time. Clunky, but still, all synchronous and all direct.
- mwcampbell 5y agoMy understanding was that unreliable and high-latency mobile connections are inevitable, especially outside of major metro areas in the developed world, so we have to design around that.
- Marazan 5y agoErr network games deal with latencies in the hundreds of milliseconds.
- 8note 5y agoWhat do you mean by "you own"? I can shine a wide spectrum of things I can make commits to vs not at all