mingles

Getting Your First Software Engineering Job

July 2023

Most universities only teach the basics of coding, not the software engineering knowledge required to actually build the systems in industry. If you have learned basics of programming, you are on a level playing field with most new grads. It doesn't take much learning to teach yourself some basic software engineering concepts and implement an example project to stand out significantly when looking for that first job. Additionally, a lot of these companies have extremely inconsistent codebases which often require you to learn it from scratch every job you start. This results in most people, even experienced engineers, being surprisingly unproductive for a long periods of time. If you’re highly motivated to learn whatever the system is, you can carry yourself extremely far with just that in an organisation. 

The Point of all of this 

I would say this is the smallest subset of knowledge to get started in Software Engineering. While it all can seem pretty overwhelming, it’s a surprisingly little amount of knowledge you can familiarise yourself with to get started building an app. 

After you create a couple of tutorial apps, you basically have the skillset to get started in industry. This is what a lot of coding bootcamps do, often charging thousands of dollars. I don’t think this is necessary given the amount of good, free tutorials available. Supplement your learning with articles and YouTube videos while you implement. Don’t worry too much about technology specifics (languages, frameworks, etc.) since they change wildly from job to job and you want to get yourself in a position where you are being paid to learn them. 

I will outline a good place to get started below, but remember that technologies move so fast that they often go out of date, so whatever you learn, prioritise the concepts over the specific implementation details. 

In the following article, we will use a basic Blog website as an example. We can reduce this down to these functionalities:

  • (C)reate a blog entry.
  • (R)ead a blog entry or entries.
  • (U)pdate a blog entry.
  • (D)elete a blog entry.

Note that the acronym here spells CRUD. This is a very common pattern of functionality within these systems. In this article, I will attempt to explain in detail each of these functionalities and the software architecture involved. 

What Software Engineers do 

Most Software engineering work comprises of “Front-end” and “Back-end” engineering. Engineers that can do both are known as “Full-stack” engineers. I’d recommend having some experience with both to A) figure out what you like and B) maximise your usefulness across the stack. If you can create end to end platforms, you have all the tools you need to basically build and run a company by yourself.

The "Front-end" is what the users interact with. It pulls the data it needs to display the information from the "Back-end", which is a data orchestration layer, often accompanied with a database. 

Front-end

The front-end is the website you see and interact with in the web browser. It should be primarily used to interface with the back-end in a way that is intuitive to the user. Modern websites are built with the following technologies:

  • HTML (HyperText Markup Language) - This is the notation which displays the content and layout we see in webpages.
  • CSS (Cascading Style Sheets) - This is the language that describes how we present the display of HTML. 
  • Javascript - This is the programming language that we use within the front-end to communicate with the backend and execute logic (such as validation) to manipulate the display of HTML/CSS. While this was traditionally quite basic with only small scripts being used, this has evolved into Javascript being the bedrock of modern web apps with technologies such as React or Next.js (more on these below).

I wouldn't recommend explicitly learning HTML or CSS beyond the basics; most of the time you can just learn by doing what you need within a given project.

Visual design is a large component too of front-end; the goal is to make an interface to enable the user to execute whatever task in the most intuitive manner.  

Back-end

You might have heard of the term API to describe this - think of this as just a non-visual way of interacting with a database or executing some kind of logic. It might have some kind of authorisation which requires you to login before accessing. 

Backends generally follow a MVC (Model-View-Controller) design:

  • Model layer:  a thing (e.g. the blog) being stored in a database. You would define the attributes associated with the blog here: every blog has a unique ID within the system as well as a title, body text, date, category, etc. This would align with the database columns for a blog. 
  • Controller layer: is where all the logic happens; we would interact with the database here, fetching or posting data associated with our blog model.
  • View layer: This is the part that exposes the controller to the web; we would define an HTTP endpoint which is fundamentally an HTTP method combined with a web accessible URL allows external systems to interact with the Controller and underlying database. This is the entry point for the front-end to send and request the data it needs. The set of HTTP endpoints defined for front-end and back-ends to communicate with is commonly referred to as an API (Application Programming Interface).

A good backend divides functionality up into well defined layers. It is possible to write any old code to pretty much do anything, but a lot of the skill in Software Engineering comes down to deciding how to structure the code into layers that each have specific responsibilities. These are called Design Patterns and MVC is an example of this

Requests and Responses

When sending data between your front-end and back-end, we do this by sending Requests and receiving Responses. We do this using HTTP (Hypertext Transfer Protocol) which is a set of standards which enable online systems to communicate with each other. Requests require an HTTP method as well as a URL and can have an optional body which is used to attach payloads of data.

HTTP Methods

When we make a request, we use an HTTP method against our url. The most important ones to consider in our context are the following:

  • GET - The request is requesting to read data.
  • POST - The request is posting (sending) a payload of data, referred to as the "body" to the backend, usually to create a resource.
  • PUT - The request is again posting a body of data to the backend, but usually in the context of updating a specified resource.
  • PATCH - The request is posting a body of data to the backend to partially update a resource. This differs slightly from a PUT request in that we are only altering the values explicitly referenced in the body. The PUT equivalent request would interpret the values we don't reference as empty values. 
  • DELETE - The request will attempt to delete the specified resource.

GET and POST are by far the most common and you can build most systems with just a combination of the two. 

HTTP Endpoints

To successfully send a request and receive a response from our back-end, we need an HTTP method as well as a url. The combination of these two is an HTTP Endpoint. These are defined in the View layer of our MVC design pattern. Certain urls may seem identical, but each should be associated with it's own HTTP method which in turn would have it's own functionality as defined in the controller layer of the backend design. To reference our blog example again in terms of the CRUD functionality, we would need the following endpoints:

  • CREATE
    • POST "api/blogs" - The request posts a body of data to this endpoint to create a new blog.
  • READ
    • GET "api/blogs" - The request requests what's called a "List View" which returns a list of all the blogs.
    • GET "api/blogs/<blog_id>" - The request requests what's called a "Detail View" which returns a given blog referenced by it's associated ID. 
  • UPDATE
    • PATCH "api/blogs/<blog_id>" - The request partially updates a given blog as referenced by it's associated ID with the attributes supplied in the body. 
    • PUT "api/blogs/<blog_id>" - The request updates every attribute for a given blog as referenced by it's associated ID with the attributes supplied in the body. 
  • DELETE
    • DELETE "api/blogs/<blog_id>" -  The request deletes a given blog as referenced by it's associated ID.

Note: this is just a portion of the URL relative to the back-end itself. The fully public equivalent would map to something like "http://www.myblogwebsite.com/api/blogs".

Good software design on the backend defines HTTP endpoints that are easily understood and consistent with existing software design patterns. 

HTTP Body Data (JSON)

When data is sent and received via HTTP, it is attached to the Request or Response body as a payload. This takes the form of JSON (JavaScript Object Notation) which allows for a standard format to be used between the front-end and back-end. This way, our front-end can make assumptions about what our backend data looks like; when we request our backend for a list of blogs it will use JSON which might look something like this:

[
    {
        "id": 1,
        "title": "Blog title 1",
        "body": "My first blog",
        "date": "2023-01-01"
    },
    {
        "id": 2,
        "title": "Blog title 2"
        "body": "My second blog",
        "date": "2023-01-01"
    }
]

The square brackets “[]” imply a list with a bunch of elements denoted with curly brackets “{}”. These elements are singular blog entries that have all the attributes defined in our Blog example.

We also send a body of JSON to our backend via a POST/PATCH/PUT request. The body of a POST request that creates a new blog might look something like this:

{
    "title": "Blog title 3",
    "body": "My third blog",
    "date": "2023-01-02"
}

HTTP Status Codes

The responses sent back from the back-end always have a status code which let you know how the backend has managed the request. A few basic ones are as follows:

  • 200 - Ok. Your request has worked as expected.
  • 201 - Created. Your request as resulted in a new element created.
  • 404 - The element you are trying to GET does not exist. 
  • 400 - Bad request. The element you are trying to Create or Update has an invalid input (e.g. requires a “name” attribute that isn’t present.
  • 401 - Unauthorised. What you’re trying to do is unauthorised because of some authentication error - maybe you need to be logged in.
  • 500 - Internal Server error. The backend code has an actual error that hasn’t been handled (e.g. maybe the database isn't working).

There are many others you can learn as you go along. I wouldn't recommend learning these all up front as you will just come across them as needed. 400-499 are generally issues to do with an invalid request. 500+ are generally due to problems that the backend is facing. 

Summarising it all

We will list a bunch of use cases we wish to have for our blog website and define all the HTTP interactions associated with that:

Display a homepage which has all of our written blogs

  • Backend Functionality: Retrieves a list of all our blogs.
  • CRUD Operation: READ Blog List

REQUEST:

  • HTTP Method: GET
  • URL: “api/blogs”

RESPONSE:

  • Status Code: 200
  • Body:
[
    {
        "id": 1,
        "title": "Blog title 1",
        "body": "My first blog",
        "date": "2023-01-01"
    },
    {
        "id": 2,
        "title": "Blog title 2"
        "body": "My second blog",
        "date": "2023-01-01"
    }
]

When we click on the blog from our homepage, we want to see a page specifically for that blog

  • Backend Functionality: Retrieves a single blog detail given an ID.
  • CRUD Operation: READ Blog Detail

REQUEST:

  • HTTP Method: GET
  • URL: “api/blogs/1”

RESPONSE:

  • Status Code: 200
  • Body: 
{
    "id": 1,
    "title": "Blog title 1",
    "body": “My first blog",
    "date": "2023-01-01"
}

A page which includes the relevant entry fields to add a new blog

  • Backend Functionality: Creates a blog instance.
  • CRUD Operation: CREATE Blog

REQUEST:

  • HTTP Method: POST
  • URL: “api/blogs”
  • Body: 
{
    "title": "Blog title 3",
    "body": "My third blog",
    "date": "2023-01-02"
}

RESPONSE:

  • Status Code: 201
  • Body: 
{
    "id": 3,
    "title": "Blog title 1",
    "body": "My third blog",
    "date": "2023-01-02"
}

COMMENTS: Note that the id is generally created on the backend, often by the database incrementing automatically. It’s good practice to return a detail view in the response to a create/update request.

The create blog page should display an error if a blog is added without the required fields 

  • Backend Functionality: Fail to creates a blog instance.
  • CRUD Operation: Malformed CREATE Blog

REQUEST:

  • HTTP Method: POST
  • URL: "api/blogs"
  • Body: 
{
    "body": "My third blog",
    "date": "2023-01-02"
}

RESPONSE:

  • Status Code: 400
  • Body:
{
    "error": "Blog must have a title"
}

A page which includes the relevant entry fields to update an existing blog

  • Backend Functionality: Updates an existing blog instance given an id.
  • CRUD Operation: UPDATE Blog

REQUEST:

  • HTTP Method: PATCH
  • URL: "api/blogs/1"
  • Body
{
    "body": "Update my blog body!"
}

RESPONSE:

  • Status Code: 200
  • Body: 
{
    "id": 1,
    "title": "Blog title 1",
    "body": "Update my blog body!",
    "date": "2023-01-02"
}

COMMENTS: Note that we’re doing PATCH here. With PATCH we can send a partial subset of the model fields we want to update. A PUT request would require us to supply all the fields and they would all be updated to what we set in the body. Note that this would be behind some degree of authentication so only you as the authenticated admin would see it.

A button to delete a blog on the homepage. 

  • Backend Functionality: Deletes a single blog detail given an ID.
  • CRUD Operation: Delete Blog

REQUEST:

  • HTTP Method: DELETE
  • URL: “api/blogs/1”

RESPONSE:

  • Status Code: 200

COMMENTS: It’s not often we actually use this type of delete, often opting for more of a “soft delete”, whereby you would have an “active” column in the database, and you do an UPDATE request, setting the “active” attribute to false. Note that this would be behind some degree of authentication so only you as the authenticated admin would see it.

What to do with all of this

I would recommend just getting yourself familiar with some front-end and back-end technologies with the intention of developing your first project. This blog is just a high level explanation of some core concepts, nothing could be more useful than getting into these technologies yourself and resolving the challenges associated with that. Once you have these basic concepts down, creating your own app won't seem as daunting as it does now. All you need is a computer to start. You will hit technical learning curves, but every time you overcome one, you will expand your technical knowledge such that the subset of things that are unknown will get smaller. 

I recommend that you create at least two apps and have them deployed online. You can use these as portfolio pieces and discuss them in your future interviews. If you can't deploy them online, no problem. Create a Github account and upload all of your code there so prospective employers can view it.

With a couple of apps under your belt, you can often change the narrative in interviews away from being tested about technical knowledge into a discussion about your experiences in making these apps. This has a much higher chance of getting you hired as most organisations - especially smaller startups - only really care about getting stuff done and with these projects you have shown that you can contribute.

Implement a blog website as seen on the tutorial below. Once you have finished the tutorial, extend what you’ve done by personalising it to something you’re interested in. Some ideas could be: a recipe website, restaurant recommendations, movie script repository, or maybe some tool for tracking road potholes! This will give you some front-end styling experience as well as something you can share with friends and family.

Once you have done that, create another app (or extend the current one) to build on what you’ve learned. Perhaps try something which hosts media like an image upload. That way you can build something that has user profiles (like an instagram clone or a dating website!). 

Areas to explore further that I haven't gone into too much detail with is things like an authentication system (e.g. user accounts that can login) or more complex algorithms such as a recommendation system for serving up related blogs.

Picking technologies for your first app

This should be enough domain knowledge to get started in building your own app. You should start with a blog app. 

Obviously, there will be a lot of implementation problem solving specific to the tutorials you follow.

I would recommend starting with something in React, a Javascript library (a set of tools) for creating front-end applications. The technology has progressed such that you don’t really need to worry about a separate backend since we can actually just create a full stack application with the React framework Next.js. This is all we need to get quickly up and running with creating full-stack applications:

  • React - React allows you to create "components", reusable building blocks of webpages.
  • NextJS: A framework built with using React components which allows for server side rendering - this allows you to hook up things like external services and databases without the need for a separate backend.

I would recommend just going ahead and following this tutorial to set up a blog website: https://vercel.com/guides/nextjs-prisma-postgres 

Things will be frustrating

Depending on your experience with coding, different things will have learning curves. 

Language

Just learning the programming language can be frustrating; it might help do a quick coding tutorial to get familiar with a specific language. Many of these are free on places such as CodeAcademy

The Terminal

When running code, you have to familiarise yourself with the terminal/command line. It's basically just a text way of interfacing with an explorer within an operating system. It helps to do quick tutorial covering the terminal to familiarise yourself with the useful commands.

Frameworks

Getting to grips with a library/framework can also be a little confusing. A React project uses many different code libraries that all have to be connected in a specific way to work. When you download a starter project and install node, you have to install all the dependencies via the command: 

npm install

This will install all the code dependencies via the npm package manager as outlined in the file package.json in your project. As you progress, you can learn about how to update/add new packages to do specific tasks. Most software engineering ends up less about writing code to do everything and more about piping up different packages and libraries to do the task for you. Why bother implementing something when someone else has already coded and rigorously tested it! Sometimes getting all the dependencies to work together can be a massive pain and you might find yourself having to debug different versions of your libraries.

Debugging

Most of software engineering comes down to debugging - something isn't working and you need to figure out why. It often requires a decent amount of understanding on how the language and framework functions. It really helps to be able to read code and make guesses based on your knowledge about what might be the problem. You can likely get by initially by just Googling errors. Most common issues are well outlined on Stack Overflow. Get familiar with searching for solutions to problems. Eventually, you'll understand enough to just fix them yourself with enough experience. 

Maintainability

You'll find that you'll often forget how something was implemented, especially if it was written a while ago. It's for this reason, maintainability is important; always opt for the most straightforward implementation, striving for consistency over complexity within your project.

Types of job positions to go after

For your first software engineering job, I couldn’t recommend a startup enough. Prioritise smaller startups. (8-20 people). Founders can often be non technical in nature and can be impressed by a small body of work that you can present. While working in a small startup, you can pick up things really quickly due to the lack of defined process and the need for everyone to roll up their sleeves and work on everything. In positions such as these, you are better able to experiment with your abilities and more importantly, learn a ton on the job. Getting paid to fill in your domain gaps should definitely be the priority. 

In my experience, larger companies are mired in process around hiring and software development. You’re likely to be put on a task on the job which only touches a tiny amount of the codebase. This will stifle your learning as it makes it a lot harder to learn the end to end pipeline of software engineering. If you wish to work at a larger company, I would do this after a few years of startups since it’ll be much easier with experience. These types of companies often pay more than startups, but it’s going to be far more limited with what you can learn and they likely have more difficult interview processes.

I would recommend going for a new grad job or an internship for like 4-6 months (which likely would lead to a full time position). Getting the first job is always the toughest and it's likely you will be getting underpaid relative to a corporate software engineering position. You should probably expect $70-80K for these positions right out the door. Take the time though to learn as much as you can as the salaries often increase rapidly after the first 2-3 years of work. Most Software Engineers can easily be on 6 figures within a couple of years.  

Resume

Create a resume from a template.

Try to structure your points with a software engineering concept, followed by what it does while namedropping technologies (recruiters often are just looking out for certain terms). Following on from the linked tutorial, this would be something like:

  • Implemented a server side rendered blog application in React & Next.js for displaying and ranking recipes.
  • Deployed front-end using Github and Vercel using continuous integration to automate processes.

Don't list everything you've ever done as most people recruiting will merely glance at it for 30 seconds. Make sure points are succinct and reflect your knowledge and experience accurately. Also be prepared to talk about any point in a potential interview. 

Feel free to reach out once you’re at this stage. I’d be happy to review your resume with you.

Be sure to make a LinkedIn account too and try to mirror the information on your resume there.  

Getting Interviews

Getting that first Software Engineering job is probably the trickiest part of it all; companies are often wary that new grads need a lot of guidance, so if you can prove competence with a few certain technologies, you will stand out significantly. Students in university don't often get to a point where they're building functional apps, so you’re already ahead of most new grads if you have some experience in building stuff.

It’s going to be a volume game. Take that for what it is and don’t be disheartened when you send out 100 resumes and only hear back from a few of companies. They often use automated systems at large companies to filter resumes, so it's unlikely anyone's eyes got on yours. You only need one company to hire you. After a year or so experience, it will be a completely different ball game; recruiters will start approaching you and your professional network will be large enough to easily find the second job.

Websites such as LinkedIn, Indeed, Wellfound will be great for finding positions. Don’t spend too long on individual applications (e.g. you don’t need to do a cover letter). It’s good to have a spreadsheet to keep track of your status with every company you’ve applied to.

Attending Interviews

The reason I recommend startups is that the interview process is likely to be more flexible; you generally do a small coding challenge and are able to spend more time discussing your projects. You are also often interviewed by the people who you would be working with so you can gauge better what the culture will be like. 

Larger companies do very specific types of technical interviews. You are often being interviewed by random people at the company, not the team you are directly interviewing for. I would say you have less control over how you sell yourself in these interactions. These are generally split into two types of interviews:

  • Technical - you get a coding problem you need to solve in an optimal way. These can require a lot of practice and often build up from computer science concepts you come across in a degree. A common website for practicing these types of problems is Leetcode. It’s good to have at least a little experience with this. Start on easy and work your way up.
  • System - you have to architect a full stack system for a given type of functionality that has scalability in mind. Most of it is just learning a bunch of scalability concepts. Common examples are implement TinyURL, Dropbox or Twitter. Larger companies generally only ask this for more senior roles, but I was asked to do this a bunch of times for smaller startups. Search on YouTube for good examples of this, they are very formulaic and you will notice patterns after a few examples.

Most of this is luck based; getting the right interviewer with the right questions can sometimes take a little while. You will likely bomb interviews (I certainly did!). It sucks, but don’t feel bad - just take it as a learning experience for the next one.