a

    alexsullivan114

    2 years ago
    Tangental but kind of related to the above ambient question - right now the docs for an ambient show an example of, like, getting a current user via an ambient. My gut reaction is that that's putting the wrong stuff into ambients and is better handled by some other caching layer, but I could be off base here. I think I like ambients (a lot) for styling or strings or size paramters and whatnot, and I think I like them a lot less for application logic. A user, for example, could (presumably) be correctly modeled as not existing in an application (before they're logged in for example), and trying to use an ambient for that feels like it sets you up for very surprising crashes at runtime when you realize you re-used some component that's using the user ambient in your logged out state. It's similarly difficult to handle in a default way without dramatically reducing it's utility - if all ambients need a default, you could have an ADT or something representing a logged in vs logged out user, or a nullable user, but now the components that actually want a user are forced into dealing with a lot of ambiguity. Honestly it's the same problem that plagues all of the cross cutting react APIs (Context, Redux, etc) in my opinion. You need some initial state for things, and a lot of stuff doesn't have a logical initial state that's not just "null".
    wasyl

    wasyl

    2 years ago
    You captured my (only) fear about Compose very well. It feels like it is so useful for state management, that people will inevitably put all state in Compose layer. To me this is pretty similar, and equally bad, to putting API calls inside fragments. I don’t recall specifically, but I think some Compose samples/examples even actually did reach out to database/API from Compose primitives, to show e.g. “where to unsusbcribe from the database stream”. I do hope some clean patterns will emerge and get popular early.
    I do understand why these samples are there and look like this though — whether people will tie their application to Compose or not is up to them. Compose should allow us to do things both ways, it’s not necessarily authors’ responsibility to make sure people implement their apps one way or another
    a

    alexsullivan114

    2 years ago
    Well there's internal composable state management, which I'm fine with, and ambients, which I find scary for a different reason than what you mentioned - i.e. because whatever thing they're fetching could or could not be there and will crash if it's not there
    Adam Powell

    Adam Powell

    2 years ago
    doing state management in compose is no different than doing it in an android ViewModel or similar. At some point it's probably talking to another repository-like source of truth but it's kind of a spectrum.
    A ViewModel might not be the in-reality source of truth for something, but for the UI layer it might as well be since it's the point of access
    And if you have an ambient where the only logical default is
    null
    , that's fine too since it's represented in the type system. The ambient is necessarily declared as
    Ambient<Foo?>
    and kotlin's null handling applies for consumers - they have to think about it, can use
    ?:
    and friends, etc.
    But yeah, you can see where the pitfalls are there if you make a habit of it everywhere.
    a

    alexsullivan114

    2 years ago
    That's true, but there's another kind of "nullability" involved, right? Like, the type system can help you handle the ambient value once you've got it, but what if no one declared the provider?
    To be clear I don't dislike ambients (or the context API), I just fret a little about using examples like storing a user value
    As you mentioned, I think it shines really well for places where there's obvious default values
    Adam Powell

    Adam Powell

    2 years ago
    The ambient itself carries the default value so it doesn't matter. The consumer doesn't know whether it's getting the declared ambient default from the actual ambient object's construction, or whether it's getting a value that was set by a provider.
    ambientOf(defaultValue)
    etc.
    a

    alexsullivan114

    2 years ago
    Ah right - that's with the proposed default value approach mentioned earlier right? Or is that how it's structured now? Talking it out makes me feel like the default value solves the primary objection I have. So I think I like that a lot.
    Adam Powell

    Adam Powell

    2 years ago
    if it's not how it's structured now it's how it will be shortly 😅 I think the only difference is that we currently have it as a factory lambda instead of a direct value, I forget if we have both overloads now or what
    it used to be
    Ambient.of(...)
    but I think we were unifying to match
    listOf
    and friends
    a

    alexsullivan114

    2 years ago
    Oh maybe I'm just working off incorrect data here....well in that case, ambient + default value = good I like it 👍 to y'all 😆
    Adam Powell

    Adam Powell

    2 years ago
    yay!
    you're not wrong though, I fully expect the first ~year of compose post-1.0 to be full of a ton of ambient abuse and, "considered harmful" blog posts and conference talks while people figure things out for themselves in addition to whatever docs we produce
    but at the end of the day it's just too useful not to have
    a

    alexsullivan114

    2 years ago
    Got it, begin writing blog post on why ambient is harmful and time a one year later blog post for why its great