7 Lessons I Learned From My First Software Engineering Job @ CTCT
I am writing this piece as a way to celebrate two years at my first job out of college. It has been a positive experience transitioning from college to professional life, albeit with some inevitable ups and downs, but that should be a guarantee. Nevertheless, below are seven nuggets of knowledge and wisdom I have acquired in my first two years in Silicon Valley. I hope that this will be a useful resource to any upcoming engineers who are looking forward to a great career in tech. Note that though this will be a post will be filled with mobile engineering examples, all of these lessons can be translated to many software engineering environments. Feel free to reach out to me if any questions or comments arise.
Number Seven: Know your Abstraction Layers
Ian, a whiz CS lab partner in college, once relayed to me how important it was to not just piece together libraries, frameworks, and open source projects together for an app, but to understand at an algorithmic and implementation level how they work. I will never forget how he would always opt to re-implement his own versions of really common UI components (JS carousels, drop down menus, grid frameworks, etc…) just so he would understand how they worked, even though he knew there were options like Bootstrap available.
As a software engineer you will most likely be a consumer of languages and tools in order to create features and products. You will also be a provider of APIs, tools, and abstraction layers to other teams. Therefore, it is imperative then that you understand not only how to consume the tools that you are using, but to also understand how they are made. Otherwise your tools are just magic. Don’t aim to be just a consumer of systems that were made for you, learn how the system works so you have the option to build a better one in the future.
A good rule of thumb is to understand how your work fits in your the layers of abstraction you directly impact, and understand at least one level above and below that layer.
Number Six: Adopt A Craftsmanship Mindset
Making an app look and feel great starts with being really meticulous about the details. Have you ever wondered how developers build 5-star apps that land them in the top charts of iTunes and Apple Design Awards? They do so by acknowledging that a large part of mobile development is about good craftsmanship. Our VP of Engineering, Mike Adler, once spoke to us about how the same mindset it takes to build great cabinetry is very similar to the mindset needed to build great applications. Much like how a carpenter focuses on the perfect alignment or cut, engineers too must focus on our markers of quality. While chefs can be meticulous about her ingredients or taste, we must be equally scrutinizing in our code, testing, and look and feel.
I started by first appreciating quality work in other industries, like: the attention to detail my dad gave while cutting hair, or the grace of artists and performers at shows. I then garnered a better appreciation for their craftsmanship mindset by thinking about the mindset they had to adopt in order to achieve that caliber of performance. Finally, I introspected on how I could adopt that mindset to my own code, just like an artist would with their art. Identify what art or artists inspire you, then think about how you can mimic their mindset to see your code as art.
Despite what others may think, I truly believe this craftsmanship skill can be learned and honed – and once learned, it becomes a natural attitude.
Number Five: Manage Complexity and Dispel Ambiguity
Often times, I’ve been given product requirements and acceptance criteria that have been vague about implementation details. Realize that for every N features we put into a view, we will create NxN complexity to deal with. For example, suppose we have a view with a search button, a search field for text input, and a listing of search results. The questions we should start asking ourselves is:
- What type of characters do we allow in our search? Is there a string limit?
- What do we display while the app is searching?
- What do we display if we cannot find any search results?
- Can a user interact with the search button after it has already been tapped? If not, what should the interaction feel like
- What happens when the user is offline, if there is a phone call that interrupts the search, etc…?
- Does the UI layout change for phone vs. tablet?
- How does a user cancel out of search? Can we swipe or tap out of the search bar to cancel searching?
- What happens when we tap on a search result?
- Does our searching behavior change for users with small search results vs. large search results?
As an engineer, play chess with the requirements – go through any and every combination of actions or scenarios you can think of that a user may take that you think are relevant to your app. Some of those scenarios you think of may be relevant enough to code a solution for, and most of them may already be taken care of for you at the OS level. Nevertheless, the potential ambiguity you may receive is something you need to manage both at the team level and in your code.
A great way to manage that ambiguity is to ask the type of questions listed above. You can also manage complexity by providing code that can adapt to new requirements easily through writing testable code and tests, as well as looking into frameworks and design patterns to organize your code in a more strategic way. MVVM, MVC, ReactiveCocoa, and Promises are some pointers to take a look at.
Intro to MVVM: http://www.objc.io/issues/13-architecture/mvvm/
ReactiveCocoa: http://reactivecocoa.io/
ReactNative: https://facebook.github.io/react-native/
Promises: http://promisekit.org/
Number Four: Study the Process of Building Things
In addition to code, testing, and design, there is a whole other world of how all these different specializations fit into a larger process or pipeline. Yes, learn waterfall, learn agile, and study the origins of these ideas as you will gain immense appreciation for why these processes exist. For example, at CTCT, we have tried a few different development methodologies, including: Kanban, Scrum, and SAFe (Scaled Agile Framework).
There are two concepts to keep in mind when exploring this topic: there is a distinction between a proactive process and a reactive one. Proactive processes encompass the yearn to produce goods, services, products, and features that the world has yet to see. Waterfall and many agile methodologies try to solve this issue of how to manage the process of materializing these concepts into reality. Phases to manage would include: fleshing out product requirements, user discovery, UX testing, code production, and delivery pipelines. Reactive processes deal with the need to improve said processes either through feature refinement or bug fixing. This includes bug triaging, incorporating user feedback, and looking at analytics to analyze app usage.
A key is to figure out how the proactive and the reactive processes work in tandem. I take inspiration from processes that have existed far longer than software engineering has, including: restaurants, factories, and hospitals. For example, next time you are at the hospital, notice how medical professionals triage patients in terms of priority, and how extensive documentation occurs so that any given doctor or nurse can just jump in on a new shift and has the most up to date context about a patient. How can that be replicated on a software team dealing with customer support calls and crash reports coming in?
Note that there is a growing concern of the buzz word of the “agile” way of building products. However, we should acknowledge that though no process is perfect, it is better than no process to build from.
Here is original paper on Waterfall by Winston Royce: http://www.cs.umd.edu/class/spring2003/cmsc838p/Process/waterfall.pdf
Here is more about Agile: http://martinfowler.com/bliki/AgileVersusLean.html
The famous Agile Manifesto: http://agilemanifesto.org/
Number Three: Find Great Mentors
I’ll never forget the first day I started on the mobile engineering team.
Gyuri and Richard both dropped what they were doing and got me set up on Android Studio and walked me through the Android toolchain. When Gabriel came onboard to our team, we talked about my career goals with mobile and in a week he had me switched over to iOS. Gabe immediately sat down with me and I ended up making my first web browser all in Obj-C. Keep in mind that before this, I had only ever done mobile apps via Safari. The following day, Danny sat me down in front of a whiteboard and gave me a history lesson of Objective-C. He talked about NeXT, about message passing and SmallTalk, and nullability and inheritance from NSObject. When Phil Sims came onboard, he gave me some of the most relevant career advice that I have stuck to since.
There are countless other stories from the rest of my team about how they took the time out of their own schedules to help me get up to speed. I was not used to that coming from college, where I felt like it was definitely a sink or swim life unless you formed a community of learners who would stick together. Not so in the Valley – everyone is a part of a team and ready to relay their experience about code cleanliness, best practices in testing, or managing a feature.
My point is that there will be tons of people who can help you on your journey to become an engineer’s engineer. Don’t be afraid to ask for help in what you want to learn or how you want to grow. Remember that everyone has something you can learn from them, whether through osmosis, pair programming, or by having active one-on-one conversations.
Number Two: Put the Hero at the Forefront
We have a great customer service department at Constant Contact, and an even greater relationship between them and the mobile engineering team. One of my fellow engineers, Nick, was a former customer support representative turned engineer on our team. He actually sits right in the middle of our call center, so our team always catches wind of bugs in production immediately. We also get to listen to customer calls about the pain points in our product, which has made us all the more accountable to our customers to create stronger application and test code over time.
There is one story where Ben, our manager at the time, sat us down to listen to a call from a customer who was panicked. This person had already sent out a newsletter to her customers with a broken link. She did not know what to do so she called into customer support to ask for help. As we listened, we were able to pinpoint the issue back to an update we pushed to the App Store that broke links in newsletters. I will never forget that feeling of accountability in my stomach as I realized how our mistakes had consequences to real people that relied on us to get work done. We patched a fix and sent out an update, but that feeling of responsibility in the code has never left me.
On a more proactive perspective, caring about the hero also means stepping into their world and seeing what journeys they take to solve common problems that might come up for them. I recall Jim, our product owner at the time, challenge me to come up with a more intuitive way to create newsletters on mobile. I also recall our innovation team here (C Todd, Jill, Ethan), walking our team through countless user exploration sessions to define our hero and map out what our hero’s journey looked like. Identify your hero and name them in order to anticipate problems that might arise for them.
Number One: Relationships Matter
The most important thing I learned at Constant Contact has less to do with software engineering, and more to do with the importance of teamwork. In times of extreme pressure and project deadlines it is imperative to not forget that your relationships with your team members stands above everything else – especially the project. I learned this lesson about a year ago when we were frantically trying to get two apps to the iOS App Store. Though everyone was under extreme stress to get the apps done in time for our launch, it was crucial to our future productivity that we not forget that it was our working relationships with one another that would continue past the deadline. This means that the core foundation you should focus on is how you treat and communicate with one another both in times of stress and bliss because that is the constant tone that will persist no matter what project or task you end up tackling together.