I’m working with Meteor for some months now and have to admit that I still don’t feel that I am really good at dealing with publication/subscription, collection management, latency compensation and all that related stuff.
When I started, I was quite amazed by the possibilties offered by Minimongo and client-side, latency-compensated collection updates. But as soon as I removed the autopublish and insecure packages, things got more complicated, of course.
Then I added template-level subscriptions to the picture, had to deal with referential relationships between several collections, had to care for security and data privacy, and also had to take into account that my app is mainly running on mobile devices, so the network / DDP connection is rather unreliable. And I also read that relying on allow/deny rules tends to get quite complicated / insecure if your application grows.
In the end, I noticed that I more and more switched to the “traditional mode” of client-server calls, i.e. I created server-side methods for nearly every data-base update and waited for the results on the client side. Which I think is not really optimal from the user-experience point of view, but it often was the “easiest” way to get all these requirements fulfilled.
Still, I am looking for ways to improve my code, so I am looking for “real-world” samples / best practices that go beyond beginner scenarios (I’ve read a lot of these beginner tutorials on latency compensation, pub/sub and all of that stuff, but then struggled to apply these principles to my more complex scenarios).
Very interesting topic, I’ll also gladly read the answers.
In the end, I noticed that I more and more switched to the “traditional mode” of client-server calls, i.e. I created server-side
methods for nearly every data-base updated and waited for the results
on the client side. Which I think is not really optimal from the
user-experience point of view, but it often was the “easiest” way to get
all these requirements fulfilled.
Do you keep creating stubs on the client side? That is, you keep your server-side method working also on the client, except for the security-related parts? With them, I don’t really see big difference between client-side and server-side updates.
No, I mainly use the methods on the server-side only. I tried to use these kind of “simulation” methods, but having all these “.isServer()” or “.isSimulation()” calls spread over the code just did not “feel good”. Also, I did not want to risk that I inadvertedly expose code that should be hidden on the server to the client. Besides, this also blows up the lines of codes on the client, which I want to keep as low as possible to take care for a fast startup time on my mobile devices. So the only solution would be to create two methods with the same name, one on the client and one on the server. But maintaining this felt a bit like “spaghetti code”, because you often need a good portion of the logic on both sides. I tried to solve this by adding model objects encapsulating the common code, which also kept the methods rather short, but this also added more complexity. So I was wondering if I just “overdo” things and make them unnecessarily complex and would be happy to hear the experiences of the community.
In my application, I definitely use methods for each database access (to me, allow/deny is evil). But most of them have the same code for client and server. In other words, only a few methods need client/server differentiation and I use isClient/isServer rarely.
So maybe you could explain why you need so much client/server differentiation. For example, you are saying that you did not want to risk that I inadvertedly expose code that should be hidden on the server to the client. What do you mean by that?
Well, I have to admit it’s more a “feeling” than a real problem yet. Of course I am using Meteor.settings to hide sensitive API keys and such stuff. But exposing server code to the client just did not feel good for me. Maybe I should change my attitude here…
I’ve never had a problem with allow (don’t use deny, not because I think its evil, I just haven’t had the need). Whenever I create a collection I think about who has rights to this data. I allow that and go to bed knowing everything else is denied. I don’t mind someone reading or writing data via mini mongo any more than I do with server methods. Using server methods for CRUD is the equivalent of using stored procs for that purpose. Don’t get me wrong, if that’s what you like by all means go for it.
As for subscriptions the question is how long is the data going to be needed. For example, if your app has 5 tabs and your user is likely to flip between them often, then load the data for the 5 tabs in the parent template. If each tab is big and the user is likely to stay on 1 tab for long periods of time then put the subscription on each tab.