I was recently asked to answer some questions to assist with a college writing course, but I figured I would share my answers here for others to read as well.
When I tell non-technical individuals that I am a software engineer, they often assume that I spend all day writing code. In reality, code is just a medium that reflects days of planning & problem solving that already occurred. With this in mind, a focus on problem-solving is critical to an aspiring software engineer's journey. Before code can be written, the associated problem must be found, researched, and a potential solution designed.
To take it a step further, how can we prepare aspiring software engineers to better solve these problems? The answer is to teach them the tools that allow them to solve different sets of problems. I would say the most important tools for software engineers would be abstract thinking, generalization, and an understanding of discrete math.
Abstract thinking is "the ability to understand and think with complex concepts that, while real, are not tied to concrete experiences, objects, people, or situations"1. A fair amount of software engineering is modeling real-world objects and interactions in a way that can be understood by digital systems. For example, to write self-driving car software, the engineers must first be able to abstract away the idea of driving a car and reduce it to the most simplistic questions, procedures, and steps. This allows them to come up with software implementations of the car that they can then build off of for their specific use cases.
The next step of abstract thinking in software engineering is to create generalizations. In our car example, we take what was determined to be the essential aspects of what it takes for something to be a "car" and we create a generalized implementation of it in code. This implementation should be able to represent a set of cars in a generic way. Students usually trip up when learning generalization as it involves taking abstract thinking to the next level; its one thing to reason about how something works, but it's an extra challenge to create an implementation to match that reasoning.
The third important focus, discrete math, is what closes the gap between the reasoning and creation of these implementations. Just about everyone is familiar with continuous math, which is what we are taught in algebra, trig, and calculus; it involves numbers, equations, and infinite values that can be reasoned or solved for. Discrete math is a different subset of mathematics that involves known items; for example in a computer, there is only True (1) and False (0). A computer must do everything using only these two values, which is where Binary Code is derived from. Software engineers must take the entire world and convert their generalized implementations to use abstractions that build upon these 1s and 0s. Discrete math helps to solve a large swath of problems across software engineering; there is graph theory, set theory, probability theory, data structures that build upon discrete math concepts, and functional programming based on discrete proofs.
If an aspiring computer science or software engineer student wants to be successful, I strongly consider these are fundamental concepts that they will need to understand.
I was fortunate enough to help design the next generation of the computer science program at the The University of Buffalo, so this is a pretty easy question to answer!
We attempted to introduce problems and their associated solutions through real-world examples. This made it easier for students to think abstractly to come up with solutions. Previously, students would be confused and would not be able to draw the relationships between real-world problems and software implementations.
This focus on practicality also allowed us to gradually introduce programming concepts by showing more difficult problems progressively to the students. Starting very simple and working our way towards more complex problems allowed students to follow along more closely without getting lost.
A significant thing that I would push for is ethics in software. As tech and software is more integrated in every facet of our lives, those writing the code must understand the implications of their decisions and implementations. I feel like this will become more critical as time goes on, especially when considering situations like the effects of social media on mental health, the environmental impacts of cryptocurrency & blockchain solutions, and the real issue of bias being input into Artificial Intelligence.
The biggest thing that helped me get my career off the ground was getting involved around campus. I was a member of the UB ACM chapter (Association for Computing Machinery), which allowed me to connect with other students who were interested in computers and technology. This club introduced me to competing in hackathons, how to interview properly, and helped me to start networking with different companies; one of which being Bloomberg where I interned and worked after college.
I significantly grew when my fellow ACM members voted me into the role of Vice President for the chapter. It was a transformative period for me, as it came with many new responsibilities that I had to manage on the spot. I learned many lessons in how to lead and plan strategically, but I also learned a few lessons of how to not lead correctly, which were just as important. Maybe those are for a future blog post, but feel free to check out my friend Angus' blogpost for his experiences leading the chapter
Apart from ACM, I was also involved with Blackstone Launchpad at UB and some local Buffalo events, such as Buffalo's Startup Weekend. Through these different avenues, I was able to meet some incredible people across diverse backgrounds, and that would not have happened if I did not get involved.
On the academic side, I also advise taking a class on a topic outside of your comfort zone that is still in your field of study. For example, I took an introduction to machine learning class that taught me some fascinating concepts about machine learning that I can use in my projects. It opened some doors and has provided solutions to problems that otherwise would have been more difficult if I did not have the background provided by that one-off class.
You can extend this further by taking a class outside of your field of study that you are still interested in. During my last year, I attended Dr. Will Kinney's Introduction to Astrophysics class and it was the coolest & most exciting class to take part in. I have a soft spot for astrophysics and space, and that class allowed me to learn more about those topics without sacrificing my own major and time commitments - it also counted as my required science class!!
My responses to questions 3 and 4 partially answered this, but I will add two additional points that I feel were not fully fleshed out;
I try not to notice faults in new grads and junior engineers because it's stressful to start working with an engineering team on new projects. So I figured it made more sense to look internally at the problems, frustrations, and concerns that plagued me when I started working right out of school. While I've overcome some of these issues, others have been much more difficult to get through.
The following sections are in no particular order and may overlap a bit in information, but I hope they are all meaningful.
School conditions us that failure is something to take personally; everything we write or submit directly reflects who we are as individuals or professionals. In reality, we fail quite often in the real world, and the juxtaposition between what was expected of me versus the high level of pressure I was putting myself under resulting in pretty quick burnout. In the real world, we are much more than whatever project we are working on or what team we are a part of; it is just a tiny piece of our professional identity.
With this in mind, we need to reverse this thinking and learn when to take calculated risks. These risks may pay off dividends of the work we put into them, or it may not work out, in which case we learn, adapt, and move onto the next project to try again. Failure may not always be an option, but it is nonetheless to be occassionally expected.
Alright, this one I am still guilty of. 😬 I tend to really overestimate what is expected of me, to the point where I needlessly burn myself out from trying to do more than what is humanly possible.
I feel like this comes from years of being taught in school that success is defined by constantly studying and working on the next assignment or else we fail. School constantly reinforced that work would never tolerate me not knowing an answer or failing to accomplish something. School to me always felt like it was a Sprint 🏃🏼♂️ whereas professional work is a marathon 🚶🏼♂️; a 20, 30, 40 year-long walk. There is always more work to do and always another team or project to work with, so we must take our time, solve problems efficiently & effectively, and learn not to overwork ourselves as much as we can.
An important distinction is understanding what is expected of us versus what our minds think is expected of us. Work gets 40 hours of my time a week (plus some for my startup & side-projects), whether or not I solve the problem. There needs to be time for personal life & hobbies or else there is no point to any of this. Do not define yourself solely by your work and understand that there is more to life than your job, so there is no need to overwork yourself constantly.
A fear of showing weakness in a topic area or professional capacity is the deeper-level version of my previous point, fear of failure. As a junior engineer, I frequently associated failure with personal weakness; every mistake made or amount of time wasted felt like it reflected poorly on me and negatively exposed my flaws. In reality, failure and struggle is just part of the job. As I grow, I tend to enjoy these struggling moments more because they provide more opportunities for growth & learning.
Admitting that I don't know something is way more helpful to my team than if I tried to fake confidence and ended up wasting a bunch of time floundering around. It's good to get out of our comfort zone, but its also important to be realistic with ourselves & our teams about our capabilities. It's impossible to know everything in your profession, so we must be attentive to how our unique experiences and talents can build up the team.
Engineering is more based on communication skills than I initially thought. Coding is just the final step in a long process of thinking, designing, and convincing that a solution is correct. Each of those steps requires conversations with engineers, managers, and other stakeholders. Much of the communication for me is through documentation.
Frequently, I find myself writing different forms of technical documents:
In any case, effectively communicating your intentions and knowledge is critical for the reader to understand why some software exists and how it will/should be used.
Finally, I find technical writing important for creating blog posts and tutorials for others to ingest. I enjoy writing, and I feel as though the more that I write, the better I get at it - Go Figure 🤣