This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-03-23
Channels
- # bangalore-clj (5)
- # beginners (136)
- # boot (1)
- # bristol-clojurians (6)
- # cider (46)
- # cljs-dev (172)
- # cljsrn (35)
- # clojure (82)
- # clojure-china (2)
- # clojure-dev (9)
- # clojure-dusseldorf (1)
- # clojure-finland (15)
- # clojure-italy (54)
- # clojure-norway (4)
- # clojure-russia (6)
- # clojure-spec (19)
- # clojure-uk (61)
- # clojurebridge (1)
- # clojurescript (55)
- # community-development (23)
- # cursive (7)
- # datomic (19)
- # emacs (10)
- # events (4)
- # fulcro (108)
- # graphql (7)
- # hoplon (1)
- # leiningen (7)
- # lumo (14)
- # off-topic (68)
- # onyx (23)
- # parinfer (8)
- # portkey (40)
- # precept (11)
- # re-frame (5)
- # reagent (40)
- # ring-swagger (5)
- # shadow-cljs (58)
- # specter (5)
- # tools-deps (37)
- # unrepl (13)
- # vim (9)
- # yada (12)
@thheller https://github.com/awkay/demo-25 I’ve pushed snapshots of a few of the projects, including a 2.5-SNAPSHOT of Fulcro. Not all of my tests are passing in the new aux library yet, but this demo does work with the new Fulcro (and all of the tests are passing for Fulcro). This drops pretty much all of the external deps except for cljs, clj, transit, react, garden, and async.
I like the cleanup, but it won’t be a solid release until I do a bit more work. But, this would likely get you started.
(the demo is client only…so while it pretends to be full-stack, there is no server to start). Also, the fulcro-spec library uses easy server, which means it’ll end up pulling in fulcro-auxillary…though in the test scope. I removed testing from that repo just to see the resulting deps)
So, it turns out that the tests that are failing are due to shadow-cljs code generation differences breaking with-redefs
. See #shadow-cljs
@tony.kay got it to work. Looks like the culprit was cljs 1.10.217
. Things started working when i downgraded to 1.10.191
. Posted an issue over in #shadow-cljs about this.
not seeing any detectable performance hit from your change in 2.4.3-SNAPSHOT
@tony.kay I have this issue thats bugging me about om/fulcro query setup. the point of query language like graphql to me is that components just ask for what they want and don't have to worry where the underlying data is coming from (or its shape) yet in om/fulcro the components ALSO basically define the database schema via idents or am I just understanding idents wrong? idents just break the entire model for me yes having a normalized database is nice but the components shouldn't be the ones deciding how the normalization happens in my mind I guess I might just need to use fulcro more and let it sink in but every time this nagging feeling just keeps coming up (edited) I understand why idents are on the components but it still feels like a mistake
ok, so let's split up the issues: 1. the query lets you ask for what you want (there are two subcomponents of this: local and remote) 2. something has to normalize the data 3. components need to share that normalized data (when they are using the same instance) so that UI stays in sync
There are also these facts: the data has to live somewhere under some schema on both the client and server...and you want the two to be able to not match
i.e. the client schema is about UI, the server is about overall persistence in a larger picture
OK, so select some specific thing you want to work with in UI. The structure of that sub-graph likely matches the schema of the server. So, in the common case, that subgraph can already work against the real server; however, the whole point of a parser on the server is to allow you to map any given query to the real schema of the server.
So, the parser/interpreter model is the join-point for deciding how to map the server's schema to an arbitrary UI schema (as a tree)
This is the same problem with GraphQL or anything else: what you need at the client may not match what the server has natively. There is no getting around that.
yes I agree. however that components have to care about normalization feels wrong. you could still do the normalize in the parser not coupled to the component tree in some way
@thheller I like to look at idents as client ids
, they are your local identity of that thing, and it can match the server thing, making things connect in a very easy and concise way
I really dislike the schema idea, what I love about Fulcro is exactly that we can archive all the power without having to define any schema at all
think about refactoring your UI...you've defined a structure that statically defines things in tandem with your UI and database
for a schema like that to work, you have to have to notion of "entities", since your queries are free to ask for any data at all, this is what makes the query flexible, the ident thing is really a very light way make the connections of things, by having idents we never have to know the "type" for that query, and this is very powerful
and what @wilkerlucio said. The flexibility of no schema is really powerful
at the end of the day, idents are a very simple, easy-to-understand mechanism that gets you everything, with minimal binding to static things
I currently think of it like this: the query defines what it returns. where that comes from doesn't matter to the UI. so even you you change the underlying data it doesn't matter to the UI since the query still defined what you get
if you change the query you need to touch both yes but you do that anyways since you need to adjust the parser and UI in case of fulcro
kind of, depend on the change, you only touch the server parser if you need new data that wasn't available before, if you stay on same data space you never have to touch the server
so, let's try to stay on one topic at a time...I think the main concern is normalization, yes?
coupling of normalization to the components yes. normalization itself is great and I want that.
the component doesn't query this table. the component asks for person(id: 3) { name }
to use graphql
the parser maps it to a table. that its even a table doesn't matter to the component.
could be an entity, a table, anything...but ultimately you have to care about the abstraction as something concrete...because the data has to come from somewhere and go somewhere
so, please let me agree with you that the concern can "be somewhere else", but lets talk about the details
if we're going to argue subjective opinion, I don't have much interest. If we are going to be objective, I'm fine 🙂
it is almost certainly the case that a schema would be better for certain use-cases, but would totally suck for others
schema is an artifact I have to maintain that talks about a lot of coupling. It has to talk about graph edge. You initial state has to match it. Lots of maintenance points.
co-located initial state, idents, and queries take care of all of that, even through refactoring. Mutations never have to be rewritten, because the data they work on simply uses stable idents. Yes, there is coupling there, but it is the loosest possible.
mapping to arbitrary server state is relatively simple. It has few cases: your tree matches, easy. your tree mis-matches, parsing/interpreting.
Nope...idents are chosen based on what concept a given set of components is rendering
(and all 20 different components could query for different sets of props about that concept)...but namespaced props and open data means it works fine
Stock Om let you completely define the client database, so I would posit that David agrees with something you're getting at: the components should not care about normalization or the schema.
from a stock Om Next perspective, an ident is "interpreted" just like a "query" is...on the server and client. The "default db" format (as adopted by Fulcro) gives them the meaning you're seeing.
but in Om Next, all that is pluggable, and idents are completely optional. You can define merge to be whatever you want.
So, it is my take, that the default db format with idents for normalization can be made to be "pragmatically good"...that is my goal: something with minimum boilerplate, and easy maintenance. Refactoring, testing, addition of new features, etc. should cause few headaches.
And, at the end of the day, you can still write a clojure spec that says what shape your client db should have, and can be used for interesting schema-like things. When people talk about schema, this is usually the benefit they're looking for: data validation. But it adds overhead and complexity. So, having that concern as an "add-on" is good. Fulcro without schema/spec does have some headaches with respect to typos 🙂
I guess the thing I'm struggling with is that I thinking about data normalization based on my components. I can't just ask for data, I first have to create a new component and give it some ident. what if I have a component where I want to display how two different entities relate to each other
so components that don't render anything and just serve as an ident definition are fine?
@thheller by giving away the idea of entities, we can also combine what would normally be differnet things in a single one, for example, here at our internal graph on nubank, this is a valid query:
[{[:customer/id "1234"]
[:customer/name
:account/current-balance
:card/card-number]}]
because the way data relates, it's easy to write resolvers that depend on any data, and the attributes are the connection points, if we had to define a "type" for this, merging the information would not be easy (because you start having to design interface linking those separated things, and those grow wild like classes on a Java app)
That's also a good point, Wilker, of a different variety: sometimes you don't want to normalize a whole entity to just get at an attribute
If the UI doesn't need it normalized (doesn't display in different places at the same time), then this kind of back-end denormalization is quite useful.
@wilkerlucio did we release the custom read parser support on the client?
yes we did
ah, so with that, you can also customize how the query is interpreted...but I consider that an advanced use that most users should avoid. As #pathom improves I hope we'll soon have some plug-in options there that allow you to easily customize this kind of query on the client without having to write much code.
I mean, you already can...pathom is quite good already. I just expect we'll soon have some "prewritten" options.
thanks a lot for the discussion. lots to think about. I need to work with this some more.
Hi, I have an issue with linked query in root component. My query:
{:query [{:all-contacts-list (prim/get-query comp/ContactsList)} [:ui/loading-data '_]]}
But loading-data is always nil. When I use [:ui/loading-data '_]
in ContactsList component it works - why?
in fact, the global load marker should be fine…so, what is your props access for it?
@piotrek actually disregard the comment about named load markers. I misread your question…this is abt the global load indicator
link queries say “read this from root”, but you’re at root…I’m not sure why the internals don’t like a link from root to root, but that may be an issue
ok, I should probably add a note to the developer’s guide (or fix link queries from root)
For those using shadow-cljs
and fulcro-spec
: I just learned that shadow defaults to using static functions, which breaks provided
and when-mocking
. There is no fix in spec itself, because of how code is generated when static-fns is enabled. To get them to work, add this to your test builds in shadow-cljs.edn
:
:compiler-options {:static-fns false} ; required for mocking to work