What I learned from my first internship

Matthew Ellis
6 min readJun 25, 2021

In the last month I had the fortune to be able to work with Family Promise of Spokane, a non-profit organization working to help families struggling with homelessness find shelter and achieve sustainable independence. They work with volunteers to help prevent homelessness, help currently homeless families, and prepare them to have the skills and tools required to stay stable.

Family Promise envisions a future where no child experiences homelessness. They equip families and communities to end the cycle of homelessness.

In order to help measure their efficacy at achieving their goals, Family Promise wants an easy-to-use dashboard to track the services provided. Users need to be able to log a service provided and details, and easily view past entries. Additionally, users should be able to search the data in meaningful ways, e.g. “number of people helped” or “average cost of service X”.

Going into this my biggest concern would be that I wouldn’t know where to start and what needed to be done. Until this point, every project I’ve worked on was started from the ground up with no existing code. It was confusing to understand what has already been done, and what needed to be added. Fortunately, I had a great team that spent the time building a rock solid plan before jumping into coding.

What I learned about planning and teamwork

The most difficult part for me was figuring out where to start. Ultimately, the first and most important step was understanding the task at hand. This goes right into using the UPER framework; Understand, Plan, Execute, and Review. We broke down the roadmap into goals that would be achievable in the time we had, and talked with the stakeholder to better understand what should be prioritized. Some of the things we needed to do were:

  • Allow users to upload data
  • Deliver data to the data science team
  • Be able to filter data
  • Keep it flexible enough to add future features

We spent a lot of time planning for the last one in particular. For example, a possible feature would be custom form entries for different service types. We used a a jsonb column in the service_entries table in order to be able to store any fields that we didn’t build.

Planning with a team can be a difficult thing to do, and I felt that doing it remotely over zoom with more than 5 or 6 people was slower than planning in person, and harder to get input from everyone. Overtime I think we naturally started working in smaller groups of around 5 people, and we became more efficient because of it. Of course communication was still as important as ever in order to make sure everyone understood what they should be doing.

For us good communication started with having a meeting every morning to check on how things are going and get updates on progress. These were usually short, and we’d break into our groups if we needed to afterwards to go into more detail. We also made sure to do thorough code reviews for each other, and we caught many small mistakes before they were a problem that way. Having a fresh pair of eyes look over your code is beneficial for the same reason having someone proofread your English final is.

During code review we’d often find ways to simplify or improve what we built, because it can sometimes be easier to adjust an existing thing that works than start from the ground up. Two places I did this was in the recipientModel, we had a function for findAll, findByName, and findById. All of these functions could actually be just findAll with modification and one extra line.

const findAll = (filter = {}) => {
Accepts a filter that defaults to empty
.where(filter);
Searches for the filter

This simplifies the model file and improves functionality, something that is usually a tradeoff. With this change you can filter by anything, not just by name or id.

The next improvement didn’t change functionality, but did reduce identical code. We found ourselves copying/pasting

.catch((err) => { res.status(500).json({ error: err.message }); });

absolutely everywhere, which got a bit old pretty fast. It also cluttered the file and made it a bit harder to find the important parts. By using error handling middleware, we were able to extract out the repetitive code and reduce each instance of .catch((err) => { … }); to .catch(next);

Following UPER gave us a framework to get started, the steps to build, and the steps to review and improve.

Redesigning the database

The largest task we did was redesign the database schema. The one we got just wasn’t flexible enough to collect all possible forms of the data. For example, you couldn’t store multiple forms of contact info with a person, couldn’t have multiple beneficiaries and volunteers on a service entry, and you the service entry fields are difficult to change. The last wasn’t a feature we had the time to fully build, but laying down the groundwork makes it easier for a later group to pick it up.

Old database schema
Old database schema
New database schema
A pretty big mess

The new database schema takes care of all of those deficiencies, but at the cost of significantly increased complexity. I did my best to try to trim off the fat, and managed to show how 4 of the tables we were planning on using were not needed/redundant. I also contributed significantly to planning on how we would use json columns to increase the flexibility of what we store and how, and then built it to according to that plan.

What we accomplished and the future

I think we accomplished a lot in the time we had, and laid a good foundation for the next team to expand on. We built the migrations and seed files for the new database schema, and updated the model files to not break any existing functionality that we inherited. We also cleaned up the code a little through the introduction of the error handling middleware and other similar things.

One of the features that still needs significant work is the metrics. I’m still not entirely sure to be honest how data science is going to handle that, but our database should be able to hold the data they need. It’s just a matter of giving it to them in a way they can use. This is definitely a core feature though that needs a lot of attention from the next team. A feature I’m not sure will ever come to pass is the custom field entries for a service type. I feel like this feature can be important because of the variability in the services provided, and so the variability of relevant data for them, but I could be totally wrong. Either way, we’re prepared for the possibility.

I’m glad I got the opportunity to work on this project with such a great team and gain experience working as a software engineer on such an important project. I feel more ready to work full time as a developer now.

--

--