What I Learned from My Year-long Engineering Internship
How my 4-month summer internship turned into a 1-year full-time job
It was a cool spring afternoon in New London, CT, mid-March. I was sitting in my bedroom, trying to make sense of why my changes in the CSS file did not take effect on my personal website when I had this notification, the one that drifted my next year toward an unexpected direction: due to the increasing severeness of the Covid-19 pandemic, all students must move out of campus and all study activities would be moved online. The next morning, I booked a flight and came back to Vietnam.
In Vietnam, I was fortunate enough to get a summer internship at Got It AI, a Silicon Valley-based start-up, and joined their Conversational AI team as a backend intern. Time flew and there came August, the point when school was about to start. I had to choose between:
- Go back to the US for offline classes
- Take only online classes for the next school year
- Take a gap year and do something meaningful with it
I wasn’t sure where the third option would take me to, but I knew I did not want the first and second ones, since going back at that time was still highly risky, and online classes were simply not that efficient, both financially and academically. Fortunately, my team lead at Got It offered me to stay there during my gap year working full-time, and I didn’t hesitate for too long.
When I off-boarded at the end of last April, exactly one year after my first day, looking back, I see how far my journey has led me and I decided that I got to write something so that the lessons I learned along the way can be of good help to others, and to my future self too. So here we go!
What I learned (or wish I have known sooner)
- Clean code matters
At school, it is generally easy to get away with writing bad code. By bad code, I mean code that has confusing variable naming, extensive use of if-else, lacks error-handling engines and is non-reusable and tightly coupled. In tightly coupled code, changes in one module affect and require changes in several other modules that are absolutely irrelevant and have no relationship to the code you try to change. At school, professors have to grade many students’ code, so they mostly don’t have time to comment on your code’s style and habit; in other words, your code only has to function, and function only.
At work, the story is completely different. Your code does not only have to work; it has to also be easy to understand, loosely coupled, has good naming, thorough comments, and documentation so that when others read or have a task related to it, it could be changed and maintained easily. So even if your professors don’t explicitly request, try to write clean code at all times. To get a better sense of clean code, I highly recommend this classic book by Robert “Uncle Bob” Martin.
- Just Git it
I did a small survey with 10 engineering students and 11 of them confessed that they have or used to have, the habit of writing all their code locally and after finishing, upload all those files to GitHub all at once through the GUI as one single commit. Doing so, they have wasted the main power of version control: the ability to see the history of changes, preserve code, and roll back to a certain point if needed.
When working at Got It, I got to learn version control with Git professionally. Honestly, Git saved me a few times, at least as I recalled, with its ability to see changes and roll back. With Git, you can also see who is the author of this particular line of code, so that you can get the right help when needed (or blame them).
I realized that Git is not only limited to code, it is version control. What this means is that you can use Git in other activities as well, for example, writing a blog, writing a paper, storing business documents, … For detailed usage of Git, I recommend the chapter on Git in this book that I’m really into.
- Optimization is important
At school, sometimes you have a project that runs very slowly, yet it works so your professor is fine with it. But at work, your users won’t feel okay. Each sub-optimal operation, e.g. redundant request, query, …, on their own, does not seem to be a big problem. But a bunch of them will do. So it’s important and recommended to run extensions to check which and how many web requests, database queries, … your application is making per user request so that we know if it is close to optimal or not. If it is not, the cache might be of good help.
- Good design doesn’t mean good code, but good code requires good design
Starting to code without a clearly defined design is like heading to war without a strategy. Before coding, we usually spend hours or even days designing the structure and components for our database schema, API endpoints, configurations, SDK functions, libraries, … and finally, have a design review involving senior engineers. By doing this, coming out of a design review, we all will have a consensus on what and how to implement. Thus, everyone is well-informed and on the same page.
- Always authenticate and authorize
Although sometimes these terms are used interchangeably, there is a slight yet crucial difference. Authentication means verifying the identity of the request sender, while authorization checks if the authenticated sender has the right to access the resource or not. These operations are of utmost importance, especially when your product is used by a large number of users. There might be someone lurking and waiting to hijack your resources, and they might not have good purposes. The consequence can be serious beyond what you possibly imagine, so always make sure to authenticate every request sent to the server and authorize the sender’s right. Trust me, I learned this the hard way.
- Programming is a team game
I used to think that to get a good job, I have to be the Jack of all trades, knowing Backend, being able to craft a beautiful UI in the Frontend, having DevOps skills, and mastering the art of teaching machines with Machine Learning. But I realized (and a colleague told me) that I don’t have to. In a team, there will be guys specializing in Frontend development, there will be Backend dudes, and there will be DevOps engineers to handle the deployment. So it’s better to choose a particular area and be really good at it, an area where you can contribute the most. A company does not find a well-rounded engineer who can do everything; instead, they find people with spikes to fill into a well-rounded team.
- Don’t be afraid to ask, but not before trying to figure it out yourself
As an intern/junior, it’s absolutely okay, even recommended, to come to senior engineers asking for help. But it is irresponsible to ask if you haven’t look it up on your own, or at least have a good sense of your question. By searching for the solutions, you sharp your problem-solving skills gradually, which is one of the differentiating factors between a junior and a more senior engineer.
- Communicate transparently
People often think of engineers as nerds who spend their whole day staring at the dark IDE screen. No, that’s not how our job looks like (or at least a part of it). To deliver a feature, an engineer must communicate with the PMs and clients to clear the requirements (and sometimes to scope it down or negotiate the due date), exchange with the test engineers the expectation of the feature, and chat with other engineers to break down and divide the work. Sometimes we have to explain to our team members the function and reason for a certain line of code we wrote in the far past. Well, as you can see, lots of communication.
Therefore, having good and flexible communication skills is absolutely crucial, as it would ease our (and our colleagues’, too) day a great deal. Not to mention that a junior engineer aiming to become a senior one should hone this skill too, as a senior engineer is expected to have the ability to mentor those with less experience.
- Keep an Engineering dairy
This is the same thing that Andy and Dave called the “Engineering Daybook” in their book “The Pragmatic Programmer.” The point is that you should keep a handbook and jot down what you have accomplished or learned, every engineering decision or design you made, or what you could have done better, daily. Doing that, you can have a clear answer when someone asks about your tasks last week, last month, or even further, and you can look up easily if you ever forget any engineering knowledge.
All these takeaways come directly from my experience at Got It AI, so you might find that a bit of modification can be made to fit your shoes. Getting a chance to be away from college for a year and convert my summer internship to a year-long job is incredible, and I can’t thank the amazing people at Got It enough for the experience. This is kinda my first non-tech blog, so please be tolerant if I wrote any socially awkward sentences, which I probably did. Happy coding!