“They Didn’t Teach Us This”: A Crash Course for Your First Job in Software
There’s a curious phenomenon that happens when new web developers take their first job. You’ve just gotten your CS degree or graduated from bootcamp, and you’ve spent months or years learning to write efficient code, practicing for interviews, and building portfolio projects. Finally you’ve accepted an offer, and you’re thrilled—you’re now a Software Engineer™. You march in on your first day, your head held high. And then, in your first week of work, it dawns on you just how little you actually know.
In your quest to become a developer, you’ve learned to write performant, elegant code that can solve any well-defined problem. However, in order to effectively support and expand a web application, you need to understand the tools, frameworks, and workflows that allow your team to collaborate on and deploy a live (“production”) application.
These skills are difficult to pick up while studying or working on personal projects, and aren’t often expanded on in bootcamps or CS programs. Worry not! This article will serve as a crash-course for the many things you’ll need to know to succeed as a developer in your first job—besides actually writing code.
The Why: From Personal Projects To Production Code
While working on personal or portfolio projects, you’ve probably deployed and maintained code. So, what’s the difference between pushing changes to your personal projects and contributing to the code base at DoLitter, the fast growing new kitty litter delivery startup you just joined?
User load: DoLitter may be accessed by hundreds or even thousands of users from all over the world all at the same time. Downtime could cost the company hundreds of dollars a minute in orders, tarnish the brand, and anger existing customers.
Scale: DoLitter is a robust service with a consumer-facing application, an API for mobile and native apps, and integrations with other major players in the industry. As the team and codebase grow, the code needs to be well-architected and well-documented so other developers are able to contribute effectively. Before any change goes out to users, it needs to be thoroughly tested in an environment as close to production as possible to ensure it doesn’t hinder existing features and works across multiple devices.
Security: DoLitter is beholden to international privacy laws like GDPR, and works with large corporate partners, which follow strict rules around how their user data must be handled. If anything ever goes awry, you’ll need monitoring software to catch vulnerabilities or data breaches as soon as possible, and robust server logging to review exactly what went wrong.
Accessibility: Not all DoLitter users have the same visual, auditory, and motor abilities, and may use DoLitter with assistive devices like a screen reader. It’s crucial that the app is equally accessible to all your users, following a standard like the Web Content Accessibility Guidelines.
Reliability: Users—particularly paying users—expect the website to be functional, accessible, and secure—all the time. DoLitter needs to store business data safely and back it up regularly, so that if one database server crashes, for example, you can quickly restore data from another.
Communication: Accomplishing the goals we’ve outlined so far requires collaborating with other developers, designers, and product managers. You might design, code, and support a personal project by yourself. At DoLitter, however, you can’t do everything alone—and your coworkers are your best support! Learning to effectively communicate with other developers, how to seek and offer help, and how to delegate work, are all essential (and often most rewarding) aspects of working on a large team—a crucial topic that could form the basis for a whole other article!
The How: a Trip Through Processes
So how does a development team meet all these lofty requirements? With a whole host of tools and processes! Let’s go over the difference between how you’d introduce a change to a personal project and all the processes involved in pushing one to the DoLitter codebase.
Depending on the size of the team and codebase, your workplace may not use all of these, or it may have even more niche tools. Don’t worry about remembering all the names and acronyms. Focus on the problem each tool is trying to solve, and if it’s a tool you see often, make sure to research it further.
Git Workflow
If code is how you make changes to software, a version control system like git (and less popular alternatives like Mercurial and SVN) is how you track and share your work. When you work on your own projects, git can be a helpful tool to revert to previous versions of your code or share your code with others. At DoLitter, however, its power is greatly amplified.
With git, (and its closely-associated web interfaces like GitHub and GitLab), you can share bits of your work, have your code reviewed, check out what other devs are working on, merge your work with that of others, and even view individual commits. Git can also help merge changes and resolve conflicts when multiple people work on (and commit to) the same file. All this helps DoLitter ensure that you contribute high-quality code that benefits from the context of your colleagues.
Once you’re confident in your code changes, you submit a pull request (a change you want to contribute to the codebase), and the new code will be reviewed by several members of the team—sometimes colleagues with specific domain knowledge or focus, and sometimes anyone willing to take a look.
While learning, you’ve probably come across three main activities in git: pushing, pulling, and committing code. At work, you’ll need to get comfortable with:
- creating branches, which delineate a new feature or line of work
- submitting pull requests (“PRs”) for your local changes to be pulled into the central, or “master” repository
- resolving merge conflicts when several engineers make changes to the same code
- maintaining a clean git history by ensuring descriptive and accurate commits
- rebasing, a common alternative to merging that helps maintain a cleaner, linear project history
- cherry-picking, which allows you to move commits between branches
- blaming, which shows you who previously touched the code you’re working with. It may sound accusatory, but it’s not. It’s there so you know who to ask for context, not to point fingers.
Understanding git will make it much easier for you to save, manipulate, share, and review code you’ve written. Get comfortable with it, and you’ll find it much easier to collaborate.
Testing and Staging and Prod, oh my!
On personal projects, you can often push code right into production—your seven users are pretty tolerant of bugs (thanks, Mom!). However, DoLitter uses several different programming environments to help you write code quickly, test efficiently, and deploy it confidently. For example, before the code goes live, it’s a great idea to use it in an environment similar to what your users will see.
You can accomplish this by pushing to a “staging environment”; an internal-only clone of your production environment meant to replicate the experience your users will have. Then, if your code has passed automated tests and internal review, you can merge it into production. To keep track of different needs for different environments, DoLitter has explicit configurations, stored in config files.
Upon being uploaded to the production server, the code usually undergoes a final build process. And then, lo and behold! Your changes are live. But, have you ever wondered what exactly happens during the deploy process?
The Deploy Process
Although you can still firebase deploy your personal project, DoLitter needs to ensure that changes pushed to production (“prod”) are ironclad and don’t break anything. Your team may deploy several times a day, or whenever a new change is merged into the master branch, following a process called “continuous integration.” This process may be managed by a Continuous Integration tool like CircleCI.
So, what exactly happens during a deploy? To start, you’ve been working in a local “development” environment, which gives you the ability to see changes nearly instantly. However, what gets deployed to production often aren’t the exact files you work with on your local machine.
- The files you use are bundled into one, compiled to another language, and minified by stripping out whitespace and shortening variable names.
- A suite of single unit tests and compound integration tests runs over your code to ensure there are no glaring syntax or logic errors.
- Additional tools like CodeClimate may measure your code quality (by analyzing your syntax for best practices), while others check for visual changes, load-test the build to ensure it’s able to handle an influx of users, and even measure performance.
- If your code passes all the tests, the build is successful, and you have a version of the app you can show to users.
Error Monitoring
Your code is live. Time to see how it does in production. Once your code is in production, there are a host of platforms that tell you how it’s doing. Tools like Airbrake or Sentry help you find errors your application hits in production, which can happen due to:
- faulty third-party connections, like when an API you talk to times out
- inconsistencies in your data
- logic errors in edge cases not caught by tests
In addition, monitoring tools like Datadog and NewRelic focus on live application performance. They track how long your website takes to respond to requests and even which areas of your code take the longest to load. Sometimes, the code doesn’t throw any errors, but still runs slowly; performance monitoring can help you figure out where the problem is. Finally, if errors do arise, server logging tools like PaperTrail can help you track down the error.
Whew, that’s a lot!
When you begin to work on a production-scale web application, you realize there’s a lot more to being a developer than just writing code. Learning a new codebase can be a challenge—but learning the industry tooling and workflows alongside it can be downright daunting. Many new developers feel like they go from knowing something to not knowing much at all. This experience is common and completely normal, but it becomes easier as you get used to the tools and workflows companies use.
Your first job is likely to involve a flurry of tools and processes that make writing code feel like an afterthought. Remember, you were hired not just to write code, but to maintain and build out an application—and doing this effectively involves mastering your tools and learning to appreciate the problems they solve. With time, you’ll find yourself writing more robust and effective code—and helping DoLitter dependably deliver kitty litter all over the world.
26 Comments
It’s a interesting view – I just hope it doesn’t scare new developers – this is part of the job, after all.
Ugh. A CS degree or a bootcamp does not make you a software engineer.
No, of course not. The article doesn’t try to say that. It’s saying that people that have just finished their CS degree and been hired in their first development job usually don’t realise just little they know, and how much more there is to being a software engineer than what they’ve learned at uni. In other words, you’re a software engineer in title only, at this point.
Surely the ™ makes that obvious.
Agree, this feels like more of the same gate-keeping mentality which translates into the thinly veiled hostility I see in so many perfectly reasonable newbie questions on SO itself.
Unless you are going to get seriously rich developing software, it’s not worth it.
The level of difficulty is normally high and permanent. And the difficulties not only depend on how difficult is to master the tools, but also and specially on the lousy ways to get the training:
* The books and manuals (when there are any) are usually written by people with zero pedagogical abilities, so you have to overwork to figure out stuff. Horrible
* Often, there is nobody to clarify doubts that are normal when you are assimilating new knowledge. Your bosses suppose that you should magically know because you are being paid.
* Most of your colleagues come from institutions where the education system is a joke: you are supposedly becoming a pro by listening to a guy speaking and filling a blackboard (with chalk!) during two hours. If you develop material from your own sources, that said “teacher” is nowhere to be found, because he/she got burned trying to explain stuff that you can learn by yourself in a book. So there isn’t any personalized tutorial help available for your. So, professionally speaking, most of your colleagues and bosses suck. They are not formed, they are deformed!
You are just describing any job – the more complex and difficult a job is, the more you will (or should demand to) get paid. And while there will definitely be difficult moments in a first development job, the feeling you get when you solve a difficult problem will be priceless 🙂
So true. Those wizard moments are priceless.
To add to the list of training methods:
* the internet – and sites like stackoverflow
If you try hard enough, you can work through most any problem with a computer and an internet connection, while the rest of the office is gone. You just need to learn to be resourceful.
Wow! Thanks for the article. I’ve recently decided to jump back into trying to develop my portfolio, and then possibly a job. My biggest fear about that is exactly what you mentioned! Thank you so much!
I think the main problem in the title is not addressed: while these workflows and technologies are what is used *today*, there’s no guarantee it will be the same 5 years from now. Even today, there may be companies that still use Fortran, an old and obscure framework for Java or a weird mix of techs you’ve never thought to use together.
The most important thing to be a developer is to learn how to solve problems and learn how to learn new things. The point of the CS program is (or should be) give you the tools to solve problems and see the differences and similarities in different tech. They’re not there to teach you the latest in embedded Kotlin or Serverless js (or whatever is the current buzz words when you read this). They’re there to teach you to recognize the patterns so you can learn each new structure and adapt accordingly
So correct. There’s nothing like learning the latest and greatest, then landing in your new job and finding that they’re locked to 10-20 year old paradigms/technologies due to something you have no control over. All those fancy features don’t exist in the older versions, or you’re working with a stack where some concepts weren’t conceptualized yet and you’re forced to do things in incredibly obscure ways.
I think git-blame refers to the commit that’s to blame for each line. Knowing who committed that code is only a side-effect. (though, blame is a far more memorable name than Annotate or whatever else it could be called.)
It, and things like git-bisect (a tool for doing an efficient binary search of your repo history) make finding when, why, and where a bug got introduced so much easier.
“…code that can solve any well-defined problem.”
Perhaps not the first day, but soon thereafter, you will learn that frequently the problem is not well-defined.
Amen!
I would say 90 % of the time, the requester has f-all clue about what he or the customer wants, but created a ticket anyway. Then it’s your job as a developer to work with what was given to you (two sentences of description, if you are lucky!).
So what you should do instead is start out by mapping what you think was wanted, and create a list of clarifying questions – “What if I want to add more items to my cart? Should the temp order be deleted now or after N days? Which fields are needed in the form?” – and then create something that makes sense to you. Don’t get too attached, it will be rewritten immediately after showing it, as they have no idea what they want, but they know REALLY well what they *don’t* want 🙂
Gotta agree pretty heavily with John Hascall here…..
@Chris, John:
Based on the deliberate punctuation in “Software Engineer™” I think the article is just pointing out that people commonly *think* they become software engineers as soon as they get a job once they’re fresh out of uni. It’s not trying to say that getting a CS degree or graduating bootcamp actually makes you a software engineer.
What they also don’t teach: Ethics.
@Chris
> What they also don’t teach: Ethics.
That’s what your parents are supposed to do…
Lots of *major* commercial sites have no sort of QA process that a traditional developer would recognize. It’s not uncommon for “testing” to involve deploying code to some fraction of live servers and flipping A/B bits. The idea is to rely on logging and monitoring systems to statistically detect problems.
Personally I think that’s insane, but it’s not “weird” in this world.
Strongly disagree! In fact, all of the mentioned tools were taught to us in the graduation. But having your first job is culture shock nevertheless. Well, when beginning in little companies where the codebase is not the main business but rather used for infrastructure, EAI intranet applications etc. you will learn in the first days, that:
1. The problems are NOT welldefined like in the graduation, but will rather change every week (the only constant in softare development is change). You need to work with nothing more than some example files without proper schema definition, and the internally used framework is not documented at all.
2. That furthermore, most of the information about business logic and requirements are scattered over the company in different departments, and communcation can be very messy and error-prone.
3. That we use a versioning tool (like we did in the graduation for standard), but an older one, half of the colleagues are not aware to much more than committing (dont start to talk about rebasing, most of them just know enough to resolve conflicts). Even better, the standard deployment tool can only deploy the master branch on the test system, so you need to merge into master anyway before deploying to the test system.
So I’d rather say that you learn everything for sober programming in theory, then you got thrown into the cold water and must be able to work in a complex and for most parts unknown domain. Sometimes you have to balance out clean coding principles against more pragmatic requirements like stability, rough deadlines, external wishes from customers etc.
Your article sounds like the study is not able to teach us the simplest principles of maintaining a service properly, this is why I am a little bit disappointed in reading this.
The tasks are poorly defined. The existing source code is written in a mixture of five styles, none of which are familiar to you, and until you learn the code base it will take you days just to find the code you need to change.
That’s pretty much expected when you are new and inexperienced. Lots of things to learn outside the curriculum and the experience is the best teacher.
I’ve recently decided to jump back into trying to develop my portfolio, and then possibly a job. My biggest fear about that is exactly what you mentioned! Thank you so much!
nice blog I really like it. it’s a really helpful one for someone who needs a job in software field
This made me laugh (and cry).
>DoLitter needs to ensure that changes pushed to production (“prod”) are ironclad and don’t break anything
I started working in a startup a year ago. We have no resources to do testing. I had to implement git myself, and my coworker keeps bypassing it. CI/CD is but a distant dream. Some change or another is always due next week. Things will get fixed When There’s Time™. Testing will be done When There’s Time™. Our process will be improved When There’s Time™. I don’t know what I’m doing but it’s fine because neither does anyone else here.
Naturally there’s never Time because we’re always so busy doing stuff and fixing stuff, probably because we lack a process and testing.
It’s so much fun working here.
This is a good write-up of challenges I have seen again and again over the last 20 years. When thinking back to my own time during education I was extremely lucky. A local company took a couple of us in as interns during our education. While studying, I was introduced to a lot of these subjects which meant that I had an advantage compared to some of the other candidates when moving to a professional position in software development. This is not an attempt to highlight my own skills since a lot of the guys were more talented than me. But more reflections on how the educational system should maybe be better at working with IT colleges to better prepare the students for the real world.