In the beginning…

At the beginning of the Labs unit at Lambda, I was assigned to Team B on the Citrics project, a project to complete a site for digital nomads to choose the next place they would like to live. The project was created by Parth Shah, one of the instructors at Lambda.

Our problem was to provide an easy way for digital nomads to find cities they might be interested in moving to based on various demographic data such as the population, cost of living, and housing cost. Our product was a website that would provide an easy way for a user to narrow down the cities that interested them according to that data and would store their preferences for future visits.

We had concerns when starting the project. Both the front and back ends were a mess of poorly written code that we would have to sort out. We had no data science members on our team and the data science API was not functioning; a problem that would be difficult to solve with no one on the team who understood the technology used in the malfunctioning API.

A plan comes together…

I worked on the project’s back end. When I examined the existing back end code, I found that it was poorly written. There was little separation of concerns, symbols were poorly named, autowiring, which has been deprecated by the Spring project, was used extensively, and code errors were ignored.

The first thing I decided to tackle was the symbol naming. Many variables had short, undescriptive, variable names, and database field names munged all the component words together with no casing convention. Spring recommends using camel case for Java field names and automatically converts them to snake case in the database.

As an example, I changed the field names in the class, I modified the model for the database table according to this convention:

Previous convention:

  /**
* Generate City id
*/
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long cityid;

/**
* The City name (String)
*/
@NotNull
private String citynamestate;

New convention:

  /**
* Generated City id
*/
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long cityId;

/**
* The City name (String)
*/
@NotNull
private String cityName;

This new convention rendered the code more readable, while at the same time causing the JSON provided to the front end to follow established Javascript naming conventions.

Other challenges we faced were the lack of a working data science API, a lack of filtered endpoints, and a lack of any way to save preferences. I handled the first by writing Python scripts to scrape the data from an existing back end that was still running from a previous project. The others I handled by writing new endpoints to provide the missing functionality.

In the end…

We shipped our product with the following features:

  1. Users can specify filters to list cities according to population, cost of living, rent, or home cost.
  2. The database contains 1273 cities.
  3. Users can show graphs of historical data including housing cost, temperature, precipitation, and area income.

Features that may be added in the future include:

  1. A working data science API that will keep the database up-to-date.
  2. Graphs of historical data
  3. Better comparison visuals
  4. Support for OAUTH2 providers such as Okta, Google, Facebook, etc.
  5. Saving of filtering endpoints to save filters and city favorites across sessions.

Technical challenges that may result from adding these features include finding or creating new components to provide a better visual presentation, deciding which OAUTH2 providers we will support, and finding someone experienced in data science to get the data science API up and running.

Some of the lessons I learned while working on this project include using IDE code analysis and refactoring features. I also learned how to scrape other APIs and how to save the resulting data. I got experience using the Postgresql command-line client to add the scraped data to the deployed database. This project will help demonstrate my skills to future employers.