This question probably already exist but its too specific and hard to seach for it.
So, imagine that we have a ecommerce application.
On page 1 we have a list of products. And when its tapped, we go to a page 2, where it holds more information about the product that you just tapped for. Pretty much like any other ecommerce out there.
Which one of these two situations are better:
When one product is tapped, we pass via arguments all the informations about this product to the page 2. Then, no requests to the database is necessary.
When one product is tapped, we pass its ID only, then we need to do a request to get this product information from database.
You might think its obvious that the option 1 is better, but with option 2 we pretty much guarantee that all product informations have the last update from database, because the owner might change the product price milliseconds after you just clicked.
image describing user interaction
I would go for the second option most of the time.
As you already said, the information will always be up to date. Also if you request all the products with all of their information it creates quite some overhead, depending on the size of the product page and the information about the different products. Another thing is updating the information live. Maybe you'll decide to add a Stream later on, updating the information while the user is on the product page. Querying each product will make that easier as well.
If you can afford the resources of requesting the product every time and your process isn't too expensive it's in my opinion the better option.
Related
I am building a microservice that has two separate services: a user service and a comments service. The user service stores the user details like email, first/last name job title, etc, and the comments service stores all comments made by the user.
In the UI, I need to populate the comments (via a REST API) and show the first/last name, email, and job title of the user.
Is it recommended that we store all these user details in the comments database?
If yes, then every time a user changes their details first/last name or job title then I will have to update their details in all the comments (I don't think this is a good idea )
If no, then if I store just the userid in the comments DB, how am I supposed to get the user details for each comment? Let's say we want to show 20 comments per page in the UI.
First, challenge architecture. Let's assume that the both services in the question are part of a larger ecosystem of microservices that all make use of the user information. Else separation will most certainly be overengineered. But from the word "comments" we can at least guess that there is at least one other class of objects, that is the things being commented. So let's assume a "user service" is a meaningful crumb to break out into a microservice, because at least some other crumbs get the necessary weight to justify the microservice breakup.
In that case I suggest the following strategy:
Second, implement an abstraction layer into your comments service right away so that most of the code will not have to care about where the user comes from (i.e. don't join or $lookup). This is also a great opportunity for local testing, because you can just create a collection with the data you need and run service level integration tests against it.
Third, for integration with the user service, get the data from there via API (which should support bulk data selection in any case) every time you need it. Because you have the abstraction layer, you can add caching, cache timeout and displacement strategies and whatever you may need below this abstraction without caring in the main portion of the code. Add such on an as needed basis. Keep it simple.
Fourth, when things really go heavyweight and you have to care with tens of thousands of users, tons of comments and many requests per second the comments service could, still below the abstraction, implement an upfront replication pattern to get the full user database locally. This will usually be done based on an asynchronous message being sent by the user service to all subscribers when something changes in te user base. When it suits the subscribers (i.e. the comment service), they can trigger full or (from time to time) delta replication of the changes. Suitable collections will be already in place from what you did for caching. And it will probably be considerably less info you need in the comments service, than is stored in user service (let alone the hashed password, other login options or accounting information).
Fifth, should you still hit performance challenges, you can break the abstraction for the few cases you need to and do the join or $lookup.
Follow the steps in order, and stop as soon as the overall assembly works fine. Every step adds considerable complexity, and when you don't need it, don't implement it.
I'm designing a ticket booking API. Right now booking a ticket resolves into POST /users/{id}/tickets but each /events/{id} has a maximum of available tickets. How do I properly design a check?
I've come up with two ways:
1) having an availibleTickets: field into the /events/{id} that gets checked and possibly updated each time I POST a new ticket.
2) having a maxTickets: field into /events/{id} and check the length of GET /events/{id}/tickets array, compare it to maxTickets
Anyway I have to perform a GET request inside the POST handler but it doesn't look right to me, do you have any suggestions?
How would you desing a ticketing system for a Web page? The same steps you apply to a Web page also apply to REST as it is just a generalization of the same interaction flow used on the Web.
Usually, on the Web you have a link you can see an event you can order tickets for. On this page you have a link to order tickets for that particular show. Depending on the system you use, you might see a layout of the event venue in the form of buttons or images to click if there is a certain seat order where available seats are marked as green and ones that are already booked as red or whatever color scheme you use. A click on a seat will trigger some reservation logic on the server that returns almost the same page as before but this time with the seat marked as orange to indicate a reservation. Next you click the available seat next to that seat to reserve a further seat. This story continues until you either have enough seats marked as reserved or no available seats are available and you have no options left as to either cancel the reservation, proceed to the order step or unreserve seats you marked as reserved beforehand. Once you are satisfied with your choice, you will find an order or submit button or link where you turn your reservation into a booking. This might involve some further steps like entering your contact and/or billing information. Though this is in principle how I'd design such a system for the Web.
As you might see, this turns out into some kind of state machine where the server tells you all of the options you have available at this current state of the process. This is exactly what Asbjørn Ulsberg mentiones when talking about affordance and state machines. From the blueprint of the venue and the respective seats on that blueprint, which are actually buttons or images you might click, you knew what these widges are for and you somehow know what will happen when you click on one of the seats. This is what affordance is all about. By seeing it you know what you can do with it.
The interaction concept outlined above should be taken and translated to REST. As a client you don't need to know the structure of the URI, all you need to know is what seats are available and what happens when you click certain links. This is usually done in REST through link relation names that give the mentioned link some semantical context to the current state of the resource the client just fetched. Such link-relations may seem like a-priori knowledge needed by the client, which is a bit anti-REST, as REST tries to decouple clients from servers to allow the latter one to evolve freely without risking clients to break, though as link-relations should be standardized, or should be based on extensions, such as dublin-core or other microformats. Buidling up on standards will either lead to broad acceptance and support by different clients or on mechanisms to plug-in such knowledge into a client later on. This in general avoids so-called out-of-band information or process flows that force you to lookup up the manual on how to use that system.
The approach outlined above would utilize an own reservation resource that is uniquely created on "entering" the reservation, which is kept till the order ticket step is invoked. This reservation resource keeps track of the reserved seats the user has chosen so far. Whether the system considers reserved seats by other users as taken or not is an implementation detail. It is ok to either use a first-come system or a more polite one that guarantees the reserver his seats until some grace-period has passed and the user didn't order them. This gives you a good impression that such resources can be volatile and just be part of a certain process.
In regards whether to use GET, POST or other HTTP methods, a Web page that sends you to a reservation page will show you a form containing all of the seats of the venue. As HTML does only support GET or POST, the latter one is the most appropriate thing. In a REST or HTTP API you might use PUT though. A server might already have assigned you a certain, unique "reservation" link that you can just invoke with PUT. If the reservation resource does not exist yet, it will be created for you, if it did, the whole content will just be updated. Especially when you dealing with reservations and money flows you want to use idempotent methods such as PUT.
I hope I could give you some ideas on how you might design your reservation system by letting a server teach a client everything it needs to know to proceed through its task.
It's inside the post method (server-side) that you must check if tickets are available before book the event.
you can create a specific route to know how many tickets is available if needed. the client could call it before book an event. Or give the availibleTickets in the get /events/{id}
Imagine 10 client trying to buy the last ticket at the same time, if the security is not in the post method, you'll book 9 imaginary tickets
I've gone through several tutorials on Flutter and I find that they cover basics just fine but there are some nagging aspects of good design and good architecture that are consistently missing. I'm writing my first actual (not toy) application in Flutter and find myself running into these missing points.
Global data. Once a person installs the application and tries to use it, I ask them to log in / create an account, since this is an application specifically for managing groups of people. I'm using Firebase on the back end, and the package to do authentication winds up returning Future<FirebaseUser> from everything. So, yes, when it comes to building a Widget that uses the user's data, I can use a FutureBuilder. That said, it seems weird to have to keep typing boilerplate FutureBuilder code to dereference the user every place I want to use the user's ID to look up their data (what groups are they part of, what actions do they have pending, etc.). I really feel like there ought to be a way to invoke the future, get the actual user object, and then store it somewhere so that anything that wants a user ID for a query can just go get it. What's the right solution? I can't believe I'm the only person who has this problem.
Updatable data. I've got a page where I list the groups the current user is a member of. The user, though, can create a new group, join an existing group, or leave a group. When they do that, I need to redraw the page. The list of groups comes from running a Firebase query, so performing an action (join, leave, etc.) should signal the app to redraw the page, which will have the side effect of re-running the query. Conceivably, one might make the page dependent (how?) on the query results and have it redraw whenever they update, and instead have some widget somewhere that keeps track of the query. There's another answer here that hints that this might be the right way to go, but that's really concerned with relatively invariant data (locale doesn't change all that often for a single user). So, again, I can't believe I'm the only one who does this sort of thing. What's the best practice in this case?
I'm going to try my best to explain the question as it is a bit confusing. I'm creating a restaurant rating app for its users to rate restaurants(on a 1 to 5-star rating scale). I will be keeping the users votes on Firebase then calculate the average rating for that particular restaurant and display it in my app.
To summarize, in my main tableview there will be restaurant names and next to them their ratings, which are kept by a UIImage(star icon) and a label(to show their ratings). I have already created a comments section for each restaurant by keeping track with a parameter which cell(restaurant) the user has clicked on and based on that, that restaurant's node is created or updated in the firebase database and can show the comments specific to that restaurant in the app without a problem. When a restaurant is clicked, users are directed to that restaurant's comments section.
Now I'm also thinking about storing the ratings on the same nodes for each restaurant. As I said earlier, I want to store the overall ratings just next to the restaurants, in a label, before reaching to the comments section. My question is that after I store the ratings on my database, how will I actually manage to display the correct ratings to the labels? I mean I kept track of which comments to display in my comments section by creating a parameter to track which cell was clicked but now, I want my app to display the restaurant ratings directly, before the user clicks on the restaurant.
Is this possible? If yes, how can I manage this? I hope I explained things clearly. I'd appreciate any help. Thank you very much for reading my long post!
this question is a little bit outside the scope of how questions should be asked here, but I'll do my best to give you some advice here!
What you're looking is absolutely possible, and honestly a great place to start for an iOS project.
1: Firebase database is a great tool, but if you're starting a new project, you should really be using Firebase Firestore. Firebase Database is being deprecated (i.e. they're going to cut of support for it at some point), and Firestore is generally easier for to get the hang of.
2: A common approach to do what you're trying to do with Firestore is to have one document contain all the data about each restaurant, and then for each restaurant to contain a collection of all the comments.
3: Firebase also has a feature called Functions, which you should absolutely check out. Functions can run whenever something "happens" in Firestore. Thus it's actually pretty easy to create a function that whenever a new review/comment for a restaurant is created it collects all the reviews, creates an average, and then would update your restaurant with that average score.
So here's a rough idea of a data structure that works:
[restaurants]
-> {restaurantId}
- about
- name
- blahBlahBlah
- averageRating
- [reviews]
-> {reviewId}
- text
- rating
Happy coding!
It should be fairly straightforward:
First model your rating system; Second keep instances of those
rating;
create a method within your Restaurants class that returns the current rating based on the result of your rating system.
** hint: (What this method returns is what you display on your label.) ***
Finally, In your tableview/collectionView label you should just be calling that method. If you do everything correctly. The tableview will collect that data and display regardless of any changes you make to your rating system in the future.
To be more explicit:
load your restaurants up to firebase.
when a user rates a Restaurant, have a method within the Restaurant class to handle such requests. e.g. currentRestaurant.updateRating()
Load the changes up to the firebase database.
in tableview/CollectionView call something like currentRestaurant.retreiveRating()
Also, your dataManager should be handling any uploads/downloads not the actual Restaurant object.
So basically I want to implement the same functionality as StackOverflow's:
viewed 59344 times
So here is some background information:
I want to count only unique visits. The assumption that registered users will read the article many times (it is evolving)
I use MongoDB as a store
I would like it to be close to real-time
My system will have a registration, but I want to count the views of anonymous users as well
I understand that the best way to count unique visits is through registration, but the thing is that a big chunk of users will be just passive readers who do not need to create an account to read the information from the application. As far as I understand, the most convenient way is to save the IP address of every user, who reads the post. I also understand that IP addresses will not provide uniqueness (some different users will have the same IP, because they are behind the same ISP and one user can have different IPs, by using proxies, tor, etc)
The use of Mongo is not absolutely essential, just the thing is that everything is written in Mongo right now, so I will switch only if it will be much faster/convenient.
Background
Are you certain you need to track "unique" views?
I actually wouldn't expect popular sites to try to keep the view counts unique - bigger is better and re-visits for new comments are still additional "views" in the the sense of showing new content/comments/ads. There are other possible subtleties to "correctness" that may or may not be important for your use case, such as excluding crawlers or your own company's users/IPs.
Instead of spending time tracking unique views (which isn't overly meaningful), I would look at counting unique user interactions such as voting/liking/commenting on the page. You can then determine "popularity" of a page with some formula based on those metrics. There is an interesting example of this approach in the Radioactivity module for Drupal, where a "hotness" metric is calculated based on activity based on recency of user interactions.
Approaches to consider
1) For a simple view counter in MongoDB, I would just use $inc to bump up the view count when the page is loaded. You can exclude logging users by role as needed (for example admin users).
2) For a more accurate view counter I would pass off the problem to a web analytics platform (which you should be using with your site for more detailed analysis anyway). For example, you can use Google Analytics API or an open source application like Piwik. Web analytics systems already have solutions in place for determining unique users/views, and the API calls for these can be asynchronous via JavaScript.
3) If implementing your own unique view tracking a definite requirement, I would use a separate collection for tracking views and upsert based on your uniqueness criteria (unique view per user,article pair for registered users or session_id,article pair for anon users). I would combine this with approach #1 (incrementing a view counter for the article views) by incrementing a counter of article views if the upsert results in an insert.
One of the way that you can solve the problem is using the cookies , once a user has visited the page , you can have one cookie added saying that he is already visited the page and you do not need to count him again. You can keep on appending some key to know what all pages he had visited. I know cookies can be deleted but in any solution there will be tradeoff.
From the mongoDB prospective , if you want very fast insert and read , i would suggest couple of things you can do.
1) As you create a article , create a document like this in your may be log collection
{"_id" : "Article URL" , {"Hit" : 0}}
Why i am not suggesting to add IP address or any other information because , as you will add IP addresses , the size of the document going to change mongoDB need to find new allocated space. Which is bad from performance angle. As you are only incrementing the counter it will not increase the size of the document and it will no need to change it place. + You have limitation on the maximum size of the document you can have.
2) Creating document in advance will give direct update statement and no worry to check for the existence of the document for the article Id or not.