SQL vs NoSQL (Parse vs Firebase)

Two of the more popular ‘Backend(s) As A Service’ for mobile apps are Parse and Firebase. I’ve used Parse in the past for other projects, and both are great ways to quickly bootstrap a database for a project. Both make user authentication incredibly easy. Both have relatively intuitive APIs, with Firebase potentially edging out Parse in terms of ease-of-use due to the Flutter plugins that have been created specifically for Firebase. In my opinion (pricing aside), the biggest difference between the two is that Firebase opts for a NoSQL data model, and Parse opts for a more traditional relational model. So what are the pro’s and cons of each?

An old-fashioned database

If NoSQL is the new ‘hip’ thing, relational databases would probably be considered ‘classic.’ Intuitively, this model organizes data into relations (tables), which are grouped into an unordered collection of tuples (rows). Generally, they are most used in situations where the data naturally has some sort of regular structure– think sales or banking transactions, but they don’t have to be. Relational databases have been the most popular data model almost since its inception in the 1970’s.

One criticism of the relational model is the fact that in order to use the data in our application – we need some sort of intermediary framework to translate the tables and rows into the objects we use in our app. One common such framework is an Object-relational mapping framework like, say, SQLAlchemy used in Python-based web apps.

Another criticism of relational databases is that they don’t necessarily work well in situations where the data being queried tends to be a self-contained document, and tends to be queried as such most of the time. Depending on the application, an address could be an example of this scenario. In a relational database, addresses often represent a many to many relationship, necessitating at least three different tables: one table for the address itself with a foreign key to the intermediary table, one for the intermediary table with referenecs to the address table and user table, and one for the user table, again with a foreign key to the intermediary table. But does your app store user addresses and only query them along with the user as unit every single time? Or does it often want to run other queries on the address information– sorting all users who live in certain states, for example? The latter would be a better fit for the relational database that can run complex queries with many JOINs efficiently, but a relational database might not be the best fit for the former because it adds all this additional complexity without much tangible benefit.

NoSQL on the other hand can be organized in many different ways. Firebase specifically uses a documented-oriented database. So in contrast to relational databases- it tends to favor the former situtation in our example above- where addresses would be queried as self-contained documents, mostly. Additionally, there is no strict schema to adhere to, so designs that simply wouldn’t fit the relational model could be customized with the document model. As a result, in the right situation, NoSQL databases should scale better than relational.

The wrong situation for NoSQL databases would be those in which queries require many complex ‘JOINS’ (because support for joins is either weak or nonexistent in a document-oriented data model). Often, we’d have to create the ‘join’ in the application code itself, instead of utilizing the the optimizations that relational databases have for exactly that kind of query. Put another way- the document model works best in situations where we have lots of many-one relationships, and few many-many relationships.

The Cloud

These tradeoffs are worth considering when sitting down to think about the design of even personal projects, and more than once I’ve gotten the ‘why relational?’ or ‘why NoSQL?’ questions when discussing my personal projects with interviewers. Next week, I’ll discuss exactly the database design of our Meal Planner app and why the pros and cons of using NoSQL for it.

Working as a Team

Time finally came this week to roll up our sleeves and do some actual development. My part of the work this time was to integrate firebase into our app, and add the login / registration functionality. The result is the below:

My contribution is that first screen. The one with the login and registration buttons. But notice the screens after that- the ones with the navbar at the bottom along with their placeholders. Those are the work of my teammate. The gif lends itself to a key difference between (most) development work during school, and the development work done in the real world.

Compared to school, very little of my (albeit small amount of) real life experience has been spent actually writing lines of codes. Since starting an internship back in mid-June, much of my time has been spent on knowledge transfers, code reviews, reading documentation, or clicking my way through endless amounts of tools and workflows. All this in the name of making sure everyone on the development team is on the same page regarding development for a codebase millions of lines long.

All this extra work is needed because in the real world – it’s not just a single person in a hoodie with the lights off hacking away at whatever app or pet project they are working on. Developers of projects come and go all the time depending on business need. As Robert Martin, author of Clean Code, says:

“Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …[Therefore,] making it easy to read makes it easier to write.”

Martin makes the point that because we spend so little time writing code as opposed to reading it- we should make code as easy to read as possible. But there’s also a whole slew of practices that come into play when developing as part of a group as opposed to developing on our own.

First – version control suddenly becomes a lot more important. Working alone, all I really used to use git for was as an super-powered save-button, spamming commits like a kid cheating a game with constant save-states. Working as a team; however, means that a number of us can work on our apps features simultaneously– nearly doubling our productivity.

I say nearly doubling because adding extra folks to the development process also adds to the complexity I alluded to before. Instead of just pushing to main, now my teammates and I have to checkout branches to work on our features. And then, when merging our features back to main, there are often conflicts that we have to resolve.

Second – automated testing becomes more important (and more impactful), as adding testing coverage to our features when we deploy them means that when another person, potentially unfamiliar to the codebase, makes a change – they can do so with confidence that they didn’t break anything.

Clearly- more people, more complications is the theme of this post, but when even the most successful single-person passion projects take the developer over four years, it’s simply the reality we have to live in order to keep up with the industry.

Design

The first big milestone for this capstone comes up in just three weeks. At that time, we need to have a tangible .apk file, with a working product that showcases our current progress to our ‘client’ (the instructor). To that end, we’ve spent the last few days focusing on design.

In projects like these where I’m wearing all the hats (frontend, backend, QA…), I like to map out how I imagine the UI before thinking about the actual program architecture. It’s helpful to visualize what exactly we want to show to the user before making decisions for, say, what data structures we want to use to represent the end-result.

To start out with, a rough sketch is great for brainstorming and workshopping ideas for little cost. Just sketch a picture! When drawn- the problem is right there in front of you instead of having to spend the precious extra braincells visualizing a concept in your head.

My first pass at creating a wireframe for our app looked like this:

This first pass at our app design led to a few insights. First- we definitely want a navbar. These are relatively standard these days in mobile apps, but it’s good to get visual confirmation that the overall user experience works; however, our also noticed that the bar is kind of busy with five icons. The navbar should only include navigation to the most-used functionalities of the app. In the end, we decided to remove the barcode launcher because we felt that it would make intuitive sense to just add that navigation to the Pantry screen, and because we did not want to code a stretch goal immediately into the navbar.

The wireframes also got us thinking about the architecture behind the design as well. It became clear that we would probably want a kind of recyclerview for the Pantry and Recipe Search screens. We might want to re-think the Calendar screen because integrating all the functionality of a full-fledged calendar into the screen could be ambitious with everything else we need to do. For the filter screen- we might want to keep things extremely simple with radio buttons or checkboxes to represent boolean values.

Taking that feedback, I made digital wireframes that culminated into the following prototype:

This prototype is simply a series of digital wireframes built and animated using Figma’s software, but it’s a great way to get a sense of an app’s look and feel without having to invest any amount of time worrying about the code. It makes sharing and workshopping ideas easy, and when it finally comes time to write down some code- we can do so without having to make UI decisions at the same time. We’ll just build to spec. It’s also a great visual for showing design progress to the less technical. A customer can look at this and get a real sense of what they’re buying.

Design: MVP & Stretch Goals

One interview question I’ve gotten a few times is:

“Can you tell me about a time that you knew you couldn’t finish an assignment, goal, or project.

Random Interviewer

The first time I got that question, I think I was still in the middle of my first degree, and my thought process was something along the lines of, “Pssh- I’ve always finished everything I’ve ever set out to do,” which of course is pure cringe-worthy arrogance. A lot of the times, it seems like I never finish anything– because nothing ever feels finished. There’s always more to do.

Enter the concepts of a Minimum Viable Product (MVP), Stretch Goals, and Acceptance Criteria. A MVP is exactly what it sounds like– the minimum amount of features needed for the product to work for whatever predefined use case you’ve thought up. It kind of reminds me of what we used to call getting a ‘perfect score’ was for getting a passing grade on a licensing exam in my old job (72%). Barely passing meant that you studied the ‘perfect amount’ to pass without putting in unnecessary effort……..

Anyway- stretch goals are the opposite. They’re the nice-to-haves. For the over-achievers. Or, to put things another way, for those who want to go the extra mile (which might not sound so goofy once we’re talking real stakes with real money).

To that end, we’ve decided on a tentative list of MVP user stories and Stretch Goals for our Meal Planner project. Here they are in all their glory:

MVP

  • Account Creation (user auth)
  • Users can add and save ingredients (which persist)
  • The app will return potential recipes that fit the user’s saved ingredients

Stretch Goals

  • App will track likely expiration dates for saved food items
  • User can favorite recipes and save them for future use
  • User can filter recipes based on criteria (such as food genre)
  • Recipes returned are sorted to maximize ingredients on-hand, but also
  • can include recipes with missing ingredients
  • User can generate a shopping list with missing ingredients from chosen recipes
  • Barcode scanning

Because it’s so early in the design process- there is still plenty of work to be done for each of these user stories (just what does Barcode Scanning mean?). They’ll need to be broken apart into bite-sized chunks. Potentially weighted by both difficulty and importance. But it’s a start.