If you are new to development (as a junior, or as someone who just started out), it might seem overwhelming when you start working on larger projects. In fact, I’ve always found the development process to be rather difficult at times, mostly because it is quite vast in its scope.
A naive person (or an outsider) might think that most of my time is spent writing code — and that’s actually not true. I spend a lot of time in a code editor, don’t get me wrong, but I’m also spending a lot of time thinking about things.
Here’s what my process looks like:
- Being on the same page
- Thinking before you code
- Mastering the toolkit
- Flexibility analysis
- Building for the future you
- Adding documentation
- Preparing for maintenance
🚩 Sometimes during this process you might run into what I consider to be red flags, which are a great indicator that something is wrong or non-optimal. They can be an indicator of a bad work environment, bad customer or a symptom of your dev process gone wrong. It is important to look at these and try to fix them. I’ve added special sections that identify these issues.
The first thing that should catch your eye is just how coding is just one-eighth of the process. I imagine that for most of you, these are just some words without any context — so allow me to elaborate:
Being on the same page
Whether it is a customer or management, at some point as a developer someone will tell you to do something.
You could just follow instructions without complaints… or you can be an actual developer and ask yourself if you understand why you are being asked to do things, and provide a meaningful and maintainable solution, made possible by everyone’s insight. That’s what teamwork is all about.
You’ll uncover the following information:
- What is being asked: What exactly is the issue, or what is missing? You don’t need to think through the entire problem just yet (we’ll do that next) but you should at least have a top-level understanding of the problem. It’s important to understand here that you probably haven’t come up with a solution yet.
- Why the request was made: What thought process led to the request in question? Is the requested thing wise? Is there perhaps something else that can be done in response to the problem?
- Why you were picked: Was it because of your skill set? Or was it because it is grunt work, and the work just needs to get done? If you’re part of a team that’s dealing with larger projects you probably don’t have to ask yourself this question, although it doesn’t hurt.
Okay, so assuming you are the right person for the job, we can move on to the next step. If you are not the right person for the job, you have two options:
- Pass the buck: Find someone who is the right person for the job. This can be a colleague or an outside expert.
- Educate yourself: Look up what is possible, and try to do the thing you’ve never done before. This means you’ll be consulting good sources (usually on the internet).
I’m going to be honest, in most situations you should embrace this as a learning opportunity and accept that you’re going to do something you’ve never done before. That’s just part of the gig. You’ll figure it out.
That being said: it pays off to know when you’re not informed enough to get something done. That way, you can educate yourself as soon as possible, or ask for help.
Generally, the question I end up asking myself is this: have I ever done this before, or something quite similar? If the answer is no, I have to look at the complexity of the issue. In many cases it’s fine, but sometimes you need to talk to your colleagues about the optimal approach.
Passing the buck is inadvisable in certain situations, as you might come off as incompetent. If the work seems insurmountably difficult, it may be time to find someone who can help you break down the issue.
🚩 Generally speaking, your colleagues (or management) should be happy to help you or find help, otherwise you can consider this a big red flag. Junior developers should not shy away from asking for help or tutoring.
Thinking before you code
One of the most common mistakes I used to make when I just started out with development is not thinking things through.
I’d talk about the features that needed to be implemented, and I just… began. As you can imagine, this means my code became quite the mess. I’m not proud of some of the code I produced back then.
Okay, some of you reading this post might be wondering: what kind of questions do you ask yourself, then?
Here’s a few:
- How many systems does this new feature impact?
- Can this break any tests? (Assuming you have tests.)
- What impact does this new feature have on the rest of the software?
- Are there any edge cases that I can think of that could cause issues?
- Can I break this feature? Are there security concerns? (This is usually a valid question if users can influence the code you’ll be writing.)
- For big tasks: what is the runtime of the code I will be writing? It’s a good idea to know what you are dealing with. (See also: Big O notation.)
- How flexible does this system need to be?
- How likely is it that this feature will be maintained by the client or customer?
- How likely is it that this feature will require changes within the next few weeks? How easy does it need to be to change things up?
(This is by no means a comprehensive list.)
Sometimes, you will end up at a dead end here: you’ll be lacking information about the desired behaviour of a feature in a specific situation. In that case, you’ll need to get back on the same page as the person who requested the feature, so we’ll be asking that person (or those people) and re-evaluate the first step all over again.
Okay, so now you’ve thought about the problem. You probably have some idea of the scope of the problem, so now you could make an estimation, right? No! Not yet — you don’t know (or haven’t considered) what’s available to you to implement this feature… You just understand the constraints.
🚩 If management does not take “thinking through problems” into account when planning out the time needed to complete the project, then that’s a big red flag. Bring this up the next time you can, because rushing to write code is almost always a bad idea.
Mastering the toolkit
Okay, now that you understand what needs to be done — you can start looking at solutions. We’re talking about coding, so it is quite likely that someone else has already done what you want to get done, and open sourced the solution. This is where it gets interesting. Now, you have to decide:
- Does the framework offer me an easy solution for the problem?
- Is there a package that I can use to get this working? (Note: assuming the license is in order and the package is maintained properly. If not, forking the code might be required.)
- Should I build my own package (is this functionality generic enough)?
- Should I just come up with a custom solution within the project’s constraints?
If possible, you want the first solution, going from the first to the last item in this list. If the framework offers a simple solution, go with that. If not, try to use a well-maintained package.
Sometimes you will need to write a package or tooling that you’ll be using internally. I can only cheer this on, since it means that you’ll be able to deliver future software more quickly because of smart investments made today.
🚩When looking at third-party packages (as opposed to using your own packages) you have to consider how the package is written, licensed and maintained. If this is not looked at properly, it can be an indicator of reckless dependency usage, which might come back to bite you in your behind at some point. As such, this can be quite a red flag if not considered properly.
Okay, we can almost start coding — cool. There’s just one more thing missing, and that is a flexibility analysis.
I know what you’re thinking: you already mentioned this in the second step. This is true, but while we just asked ourselves the question before (“how flexible does this system need to be?”), now the time has come to ask ourselves some more questions.
Let’s define flexibility first. A system is flexible if it can be either: (1) easily adjusted, updated or tweaked, (2) extended, or (3) replaced.
You see, there’s internal (or in-house) and external flexibility.
Internal (or in-house) flexibility means that it is easy for a developer to make a change to an existing system or feature, which is often the case — as developers we’re supposed to make systems very flexible and extensible. You’ll need access to the source or the server to make these changes.
The truth is, for clients, sometimes that means you’ll be billing them (since coding is required to get “the thing” done). You need to be careful about which systems you wish to expose to the end user — the latter being external flexibility.
So, you have these:
- In-house flexibility: code that can easily be swapped out by developers; usually coded to a particular interface
- Partial external flexibility: admin panels, not exposed to the end user
- Pure external flexibility: admin panels, exposed to the end user (and also possible mistakes or stupidity by the end user; a thing you should not underestimate: build in safeguards!)
Adding external flexibility often involves admin panels that can be accessed by the end user and building those is not always a thing you should be doing, because it often complicates development extensively.
Therefore, it is important that you discuss with your client what needs to be externally accessible and flexible. As a developer, you should know about these things at all times as well, or you might expose certain code that you did not mean to expose.
(Practically speaking, a colleague could abuse or expose an API you intended to be for in-house usage only. Make sure your class and method visibility is set up correctly. Comments in shared code don’t hurt, as long as they are informative and don’t just describe what the code is doing. Most code should be self-explanatory.)
🚩 I consider it a red flag if it is not known how certain systems will be exposed to the client. This is vital information and the exact details of the flexibility needs to be known ahead of time. This information should also be shared among colleagues. Everyone should be in the loop.
Building for the future you
Future you is like you, except future you has forgotten at least 75% of the things that you’ve been thinking about for the past few steps in this already complicated process. As such, future you is a potential code hazard, or a time waster — but future you doesn’t need to be! You just need to be prepared.
This is where you should document your efforts. If you’re working on a big project, it is quite possible that you won’t be able to memorise everything that you need to implement in the first place, so having a document that details your implementation plans can be helpful.
Depending on the use case, you might find yourself writing complex documents, or on the other hand, perhaps a simple markdown file. It’s your call.
Just remember — memory can be quite brittle.
🎈 A project that is started without a document that paints a big picture can be a developer liability, and is considered a red flag. A flag that gets exponentially larger as the project grows in size. It is very easy for a project to balloon (= grow larger) if the scope is not documented and contained.
This bit is pretty straight forward if you’ve planned everything out. Most developers are quite familiar with this process, but teams tend to have different coding processes. I might elaborate on this step at some point.
This step includes, but is not limited to:
- Actually writing the bulk of the code
- Writing packages
- Updating packages
- Upgrading dependencies
- Reviewing code with colleagues
Hold up, didn’t we just prepare for our future self?
Sure, but that’s you. In most projects, you’re not the only person working on feature X. In that case, I’d recommend you maintain additional documentation about how to set up the project and keep it running properly.
Sometimes this means you’ll be writing a migration guide. The good news is that you probably have done at least half of the work by preparing for future you. Good work. Now go make your colleagues happy, and document away!
🚩 If a project does not contain up-to-date documentation (or god forbid, no documentation at all) you’re in deep trouble, usually. That’s a red flag if I’ve ever seen one.
Preparing for maintenance
When you write code, you end up writing code that future you will be maintaining, as I’ve been repeating a couple of times now; I’m sorry to repeat myself so much, but a part of the development process is maintenance.
If you want to be a good maintainer, you sometimes need to say no.
This applies to public-facing projects, as well as internal projects. For example, if you maintain an open source project, you may wish to reject perfectly serviceable pull requests because you don’t want to maintain the code that would be otherwise pulled in.
It’s easy to just say yes and up with many more systems you have to maintain in the long run. (If you don’t, and drop the functionality, that also won’t make folks happy.) It’s harder to say no.
So, learn to say no – and accept the no when a maintainer rejects your pull request.
When handling new projects
I haven’t even mentioned that I also have a special step that I always take into consideration: I always ask myself a bunch of questions before embarking on a new or existing project, because these are important to me.
Some of these might not be that relevant to you, but nonetheless, let’s go over them:
- What is the current stack being used / what stack will be used? Red flag if the stack is quite outdated.
- Are we using the latest versions of the software / dependencies? Red flag if the dependencies are outdated and you’re stuck on older software due to laziness or lack of budget.
- What’s the code quality like (if quantified at all)? Are the common design patterns in use? Red flag if the code quality is bad or not easily quantifiable.
- How tested is the code base (if tested at all)? Red flag if there are zero tests, or there is no easy way to test all code. (Which usually means that tests need to be present.) A lack of tests can be a red flag, but the presence of tests usually gives me hope.
- How maintained is the project? When were the last changes? Red flag if the code hasn’t been reviewed or maintained in a while.
- What code style has been decided upon for this project (if any)? Red flag if there is no agreement on code style.
- Does the code get reviewed by peers? Red flag if no peer reviews take place.
There’s a lot that can go wrong during the development process of a program that is sufficiently large; therefore, it is a good idea to make sure you’ve checked the following boxes at the very least:
- The project’s constraints have been clearly defined
- The problems have been thought through
- The code that will be written will also be tested and reviewed
- The code, once written, is documented properly
Alternatively, you can use my comprehensive development process flow as detailed above, and use the list of questions in the section right above this one; it will allow you to catch even more potential issues.
Finally, remember – most of the development process is not the coding, but everything around it, including the human factor – a topic I haven’t even tackled in this particular post.
I will, briefly, right now: be nice to your fellow humans. They can just as easily have a bad day as you. Helping each other out will only make what you’re building a better product at the end of the day. Strive to learn from each other.