As software engineers, we often get caught up in the day-to-day details of our job without even knowing it. We make hundreds of decisions each day, such as the architecture of our programs, what to name our variables, when to add a new function, which ticket to work on, how to design our database schema, and so much more.
While these are all fun decisions to make, they require us to consider the long-term implications of our choices, debate the pros and cons, and ultimately settle on a solution. There are so many choices to make that sometimes we fail to see how an individual decision fits into the grand scheme of things. We lose sight of the bigger picture because weβre so focused on the details of the current problem weβre trying to solve.
As you gain experience and progress in your career, youβll learn how your decisions fit into the overall system, and your decision-making skills will evolve. Youβll start to comprehend the trade-offs between solutions and understand the positive and negative impacts your decisions could have on the business. Youβll start to understand the implications of changing one part of the system and how it affects other parts. Eventually, youβll improve your ability to know which decisions add the most value to the customers and the business, and to prioritize those decisions above the others.
A strong quality of senior developers is that theyβre able to identify on their own where they can add value to the business. So, how do they do that? Letβs take a look at different ways in which you can add value, both with code and without.
An important thing to remember as you work towards a senior developer role is that your job is not to build perfect software, which is a common misconception among developers when theyβre starting their careers. Yes, writing clean, reliable, and bug-free software is an ideal outcome, but ironically, thatβs not what you were hired to do. Your real job as a software engineer is quite simpleβto build value for your company. Sometimes that means shipping code that isnβt fully polished, and sometimes it means taking your time to get your design right before shipping a solution. In the end, itβs all about shipping code. The more code you can ship, the more value you can deliver and the more valuable you become to your employer.
Itβs essential to understand the business and the industry you work in because you canβt deliver disruptive value unless you have a deep understanding of your customerβs pain points and how your products solve them. It may take a long time, sometimes even years, to fully understand the complexities of a business or an industry, but that domain knowledge is needed in order to deliver value. When youβre just starting a new role, youβll only have limited experience, but there are still ways you can build value for your business that donβt require years of institutional knowledge, and itβs all about improving productivity so you can ship code faster.
There will always be one thing that you have full control over, and that is your own productivity. You may not fully understand the business context behind the changes youβre asked to make, but at least you are able to control how quickly you can ship code and deliver those changes to customers.
Even if youβre just getting familiar with a new codebase or learning a new language, there are habits you can build that will help you stay focused and work efficiently. Letβs look at different ways to help increase your own productivity.
It sounds obvious, but sometimes itβs easier said than done. During the workday, do your best to stay focused on the task at hand, rather than checking news websites, your stock portfolio, or browsing social media. There are tools you can use that allow you to block certain websites or apps for a specified period of time so youβre not distracted. And there are time management tools like the Pomodoro and Flowtime techniques that are designed to help you stay focused for short bursts of time.
Itβs easy to feel like you always need to be working on something, whether itβs coding a new feature, fixing a bug, or refactoring some tech debt. We feel productive when weβre sitting in front of our IDE churning out codeβitβs where weβre most comfortable. It may be tempting to pick up a new task as soon as you submit your code for review, but sometimes that can hurt your productivity. You may think you can get started on another feature while you wait for your coworkers to review your code, but keep in mind that youβll need to switch context if you need to answer any questions or make changes to your pull request. This often can slow you down as you shift gears to focus between multiple things.
In the first few years of your career, you should try to focus on one task at a time, even if that means youβre sitting idle waiting for feedback. There are other ways you can be productive while you wait, such as reviewing other developerβs code, writing documentation, and planning and researching tickets. Remember, itβs more efficient to give 100% of your effort towards one task than it is to give 50% of your effort towards two.
Thereβs a lot of information thrown at you every day. You may be focused on the task at hand, but your boss might ask you to do them a small favor. Or you might receive an email or chat message that you canβt respond to right away. Or maybe your coworker assigned you as a reviewer on their PR that theyβre waiting to merge in. Itβs easy to let things slip through the cracks and forget about all the small things you need to do during your day.
One of the best ways to make sure youβre keeping track of everything you need to do is to keep a to-do list. It sounds simple, but itβs effective. A lot of developers try to keep track of everything in their head, and they forget to do certain things they promised or were asked to do. When you can write down your tasks on a notepad or an app, it helps you clear your head to focus on the task at hand. When you have a break in the day, make sure to check your to-do list for the next thing you should work on.
Itβs tempting to jump right into a task as soon as you pick one up, but it pays to be patient. Developers early in their career often have a habit of starting to code right away without thinking through the problem first. They may start implementing a solution without thinking about trade-offs or alternative solutions. Itβs a common mistake engineers make, and it can lead to reduced productivity if they need to change direction after the code has been written.
The saying βmeasure twice, cut onceβ is a good mantra to keep in mind when picking up a new ticket. Before you start coding a solution, make sure youβve thought through multiple solutions so you can be sure youβre implementing the correct one. This helps reduce the amount of wasted work if your first solution wonβt work out for any reason.
These are just a few examples of things you can do to increase your personal productivity. Every developer works differently, so try out different tools and techniques to find what works best for you. Once youβve found your own productivity groove, the next step is to focus on helping increase your teamβs overall productivity.
Attention Is My Most Valuable Asset for Productivity as a Software Developer (zwbetz.com)
Pomodoro Technique (wikipedia.org)
Flowtime Technique (lifehack.org)
Team productivity is one of the most important things an engineering manager focuses on. Itβs their job to make sure their team is working at as close to full capacity as possible. That means making sure their team members are not blocked by any issues preventing them from finishing their task, making sure the product requirements are fleshed out enough for the engineers to turn them into technical requirements, and making sure there is enough work coming down the pipeline for their engineers to pick up. The last thing an engineering manager wants is for their team members to be sitting idle and not shipping any code.
As an individual software engineer, there are things you can do to help your manager increase team productivity. As mentioned in the earlier section, Working with Your Manager, you should consider your managerβs goals to be your own goals, so if theyβre concerned with keeping team productivity high, so should you be. If you can demonstrate to your manager that you can help them keep the team moving forward, you will prove that youβre a valuable asset to the team and the organization.
So, what can you do to help improve your teamβs productivity?
If your team doesnβt already limit the amount of work in progress (WIP), you may want to suggest implementing that practice for your team. It may seem counterintuitive that limiting the amount of work being done will help your team move faster, but the idea is to eliminate bottlenecks in the pipeline. Your teamβs output is limited by the smallest bottleneck. This could be, for example, the number of engineers available to work, the number of engineers that have time to review pull requests, or the number of test engineers that are able to test features for quality assurance.
When work begins to back up at one of these bottlenecks, productivity grinds to a halt. Adding a WIP limit allows you to control when work is released onto the queue to be picked up by engineers, which helps ensure that work is always moving through the pipeline and not backing up at a bottleneck. Another advantage of WIP limits is that they encourage engineers to limit the number of tasks theyβre working on, which allows them to focus on finishing a task before picking up the next one.
Putting the βflowβ back in workflow with WIP limits (atlassian.com)
DevOps measurement: Work in process limits (cloud.google.com)
Most engineers early in their career focus solely on completing their own tasks, but a common sign that a software engineer is ready to move to a senior role is when they shift their focus to helping teammates complete their tasks. When you complete a task, you may have some free time to help others before moving on to your next task, so try to leverage this down time to help keep things moving for the rest of your team.
βexampleβHere are some examples of how you can keep tasks moving:
Donβt let pull requests build up. If there are PRs waiting for review, focus on those. The work has been done and the code is waiting to be merged into the release pipeline. Help your teammates by reviewing PRs so they can move those tickets off the board and pick up the next ones.
Ask your teammates if they need help. Someone might be stuck on a tough problem and could use some advice, or perhaps another engineer is having trouble getting their development environment up and running. If another developer is stuck, try helping to get them unstuck before starting a new task.
Help define the requirements for upcoming tickets. Take a look at the tickets in your teamβs backlog and check to make sure there is enough information in each ticket for the developer to complete the task. Sometimes, tickets make it into the backlog with only a sentence or two of what needs to be done, when there are often additional product or technical requirements that need to be sorted out before a ticket can be started. Does the ticket need mockups from the design team? Is the expected functionality spelled out in the acceptance criteria? Are there steps to reproduce a bug? Making sure each ticket has enough information will help your team so they donβt have to track down the information after theyβve already started the task.
Entire books have been written on productivity, at both the individual and team levels. These examples just scratch the surface of what you can do to help improve productivity, but if you want to add value for your team, there are always things you can do to increase the throughput for the work you need to deliver.
Think about your typical customer for a minute. When a customer buys your product or service, theyβre looking to solve a specific need, whether thatβs to save time or money, perform a difficult task, automate something, or even provide entertainment value. What they care about the most is that their needs are met by your productβthatβs what makes your product valuable to them.
What they almost never care about is how your product is built. They donβt care what language you used or what data structures, algorithms, or application architecture you chose for your codebase. They may not even care about all the features that are available in your product. What they do care about is that your product solves their pain points, which is why itβs important to focus on the customer when writing software. Sometimes using a new framework or using fancy data structures is fun, but that doesnβt always add value for your customers. Solving a customerβs problems always adds value.
βexampleβHere are some good questions that will help you focus on your customers:
How am I adding value for the customer right now?
Which customers, if any, are requesting this feature?
Which customers are affected by this bug that Iβm fixing?
Is this feature a must-have requirement before customer ABC signs the contract?
If you ask yourself these questions regularly as you work on new features and projects, youβll build a better understanding of how your work adds value for the customer. Youβll get a better idea of which tasks are important and which are lower priority. Sure, there may be some tech debt in a part of the codebase thatβs been bugging you for a while, but if fixing it doesnβt add any value for the customer then maybe you should focus on something else that does. If youβre adding value for the customer, youβre adding value for your company, and in the end, thatβs all that matters.
Itβs satisfying to see your code in the hands of customers and providing them value, especially when they pay for your product. Itβs even more fulfilling to write code that has a high impact, especially when it comes to helping your business grow. If youβre lucky, the code you write may become necessary to the success of the business, at which point it becomes business critical.
Business-critical code is typically complex because itβs required to handle multiple use cases for many different customers. The complexity grows over time as new use cases are discovered and new customers are supported. However, business-critical code doesnβt necessarily equate to state-of-the-art code. Surprisingly, the most profitable code is sometimes rather outdated and boring. The most important part is that the code works, is reliable, gets the job done, and is in the hands of the customer.
All business-critical code becomes legacy code over time. Itβs just a fact. When you have a codebase thatβs necessary to the success of the business, making changes to the code can be risky if not planned carefully. Small improvements add up over time, but you probably wonβt be refactoring half the codebase to a new architecture. As they say, βIf it ainβt broke, donβt fix it.β
As long as the critical systems are in place and still making money for the business, there will always be a need for people to maintain and support those systems. Depending on the expertise and domain knowledge required, you may be able to leverage your knowledge of the codebase for job security and a rewarding salary.
Keep in mind there are trade-offs, as with most things related to software engineering. Although job security is important to a lot of people, you should expect to be working on possibly outdated technology and working with code that other people wrote. Legacy code can often be difficult and time-consuming to change and stressful to debug. Itβs certainly not for everyone, but some people prefer to work on legacy systems rather than the ambiguity of newer codebases.
With most legacy systems, things move slowly. Youβll need multiple approvals to make any significant changes to the system due to the risk involved. While some developers donβt mind the slower pace, others may find it frustrating to get anything done. You may be better suited to work on projects where youβre building new products or iterating on existing ones, especially early in your career.
A common misconception among new developers is that youβll be working on interesting problems and engineering state-of-the-art solutions all the time. While this may be the case for some products, more often than not, the code that makes money will be rather boring.
βexampleβA checkout page for an e-commerce company is one example of code that is almost never state of the art. Itβs a well-known problem with well-known solutions, and itβs not exactly the most exciting part of the codebase. But every single transaction in an e-commerce business flows through that page, so the code that powers that checkout page is code that makes money.
While somewhat counterintuitive, a common path to adding value is to ship code that reduces cost for your customers or for your company. If a product solves a customerβs pain point better, faster, or cheaper than if they built it themselves, the customer benefits from a return on their investment. When a customer purchases your companyβs product, theyβre doing it in order to free up capital or other resources. This allows them to shift resources to help grow other parts of their business. Itβs a win-win for both your customers and your company.
While saving your customers money is a great way to add value for your company, writing code that reduces cost for your employer is another opportunity for you to have a significant impact. Operational efficiencies are vital in highly competitive industries, as that can make the difference in whether the company makes or loses money in a given quarter or year.
Businesses are incentivized to control their costs and increase their efficiency as they work to produce more goods and services with less resources. This usually means building internal automation tools, scaling existing infrastructure, and streamlining processes to gain efficiency. While you may not get to work on projects like these right away, there are things you can focus on that help reduce the cost of delivering software, such as writing clean and modular code.
Clean, modular, and extendable code adds value by reducing the amount of time it takes to make future changes to the codebase. Business requirements always change over time, and that requires frequent modifications to the codebase to support the requirements. Letβs look at some ways in which you can add modularity and extensibility to your codebase so you can ship more code with less cost.
Different customers have different requirements, so ideally, weβd write software that can be configured to each userβs individual needs and preferencesβall while using the same codebase. Itβs generally considered a bad practice to hard-code configuration values because, at some point, you may need to change that value. If itβs hard-coded into the codebase, that means youβll need to modify the code and deploy a new release in order to change the configuration, which is time-consuming and adds risk.
When we hard-code logic for specific configurations in our codebase, programs become rigid and inflexible, making it difficult to modify the system as our customerβs requirements change. Therefore, itβs better to build our systems in a way that can easily handle changing requirements. Whether you need to add a new shipping option, toggle a feature on or off, or increase the threshold for some limit, try to build it in a way that lets you or someone else update those values without needing to deploy new code. When you separate configuration values from the application itself, youβre able to modify the software to fit customersβ needs with less time and effort.
Existing applications probably already have some sort of configuration system, so itβs important to understand how it works. Try to learn what its possibilities are and also where the functionality falls short. In almost all cases, itβs better to use the existing configuration system rather than build your own from scratch.
Itβs often difficult for new programmers to think in abstract concepts when writing code. It often comes down to the fact that you donβt know what you donβt know, and thatβs okay. Sometimes itβs hard to think about how to abstract code if youβve never seen it done before. Luckily, an easy solution to build this skill is to study other peopleβs code.
The single best way to learn abstractions is to study code written by experienced engineers. An experienced engineer will write code abstractions in order to be able to adapt that code to many different use cases. By writing code that is abstract, they can easily extend or reuse the logic as requirements change because the code is designed to be used in multiple scenarios.
A well-abstracted part of a codebase allows teams to make changes quickly when they need to support new requirements for the business. This allows them to deliver value more efficiently, which saves the company money and allows the programmers to move on to the next task.
Unfortunately, thereβs no silver bullet to learning this, as it is both an art and a science. Over time, youβll learn how to identify opportunities where code can and should be abstracted to handle different use cases.
The more experience you gain during your career, the more natural itβll be to design your programs with abstractions in mind. Youβll see how other developers separate their logic, which will influence how you write your own code. Writing modular code is a skill that takes years to develop, but finding time to study code written by experienced engineers or in popular open-source projects will help you learn and identify patterns you can reuse. Youβll pick up techniques and start to incorporate them into the code you write, and soon enough, youβll be able to write abstracted and modular code.
Sometimes, small abstractions can have a big impact on how quickly youβre able to extend the logic, saving you time and resources, so itβs worth taking the time to build that skill. But be careful, though. As you learn to think about abstractions and build them into your codebase, keep in mind that every new level of abstraction added will increase complexity and the cognitive load youβll need to fully understand how your program works. Additional levels of abstraction also often come with a performance cost, so itβs important to consider the trade-offs involved with introducing new abstractions in your code.
For most engineers, writing automated tests feels like a chore at first, but over time, youβll understand why automated testing is critical in the software development lifecycle. There are many benefits to building out good code coverage with a test suite, but the most important reasons weβll look into are:
To catch bugs earlier in the process before they hit production.
To reduce the burden on QA engineers from having to manually test each part of the code to ensure the next changes donβt introduce regressions.
Thatβs it right there. Those two bullet points address issues that are incredibly costly to an engineering organization, so if you can ensure all of the changes you make have corresponding test coverage, youβll be able to ship code that helps reduce costs for your company. Youβll know your code works according to your test cases, so the QA engineers can focus on testing other parts of the application or building test automation.
A bug is cheap and easy to fix in your local environment, but it becomes exponentially more costly to fix a defect thatβs moved through staging environments and been deployed to production. The cost is not only in the time and resources needed to identify, fix, test the fix, and deploy the updated code to the affected environments, but also in the opportunity cost of not being able to work on another task that could build value, not to mention any cost of mitigating damage done by the bug. If you can reduce the amount of bugs introduced into staging and production environments, you can reduce the cost associated with shipping code.
Building value with an automated test suite is similar to forming a new habitβitβs going to require some real effort, and itβs not going to happen overnight. But if you chip away at it with every code commit, youβll eventually have good code coverage on all new code written, and youβll hopefully build a healthy culture around testing within your team.
Having an automated test suite with good code coverage improves the efficiency with which you can confidently make changes to the codebase. Youβll be able to quickly refactor and make modifications to your business logic while knowing that youβre not breaking existing functionality. Software is complex, and there are often unintended consequences from our code changes. A test suite with sufficient code coverage will help you catch those side effects before they make it to staging or production, leading to higher-quality software and more time to work on tasks that build value.
An important point to understand, however, is that your tests are only as good as the assertions they make. Your tests can only catch behavior that youβre explicitly testing for, so donβt expect your test suite to catch every bug for you. Tests can be incomplete, and they can have bugs, just like all code.
βcautionβ Just because your tests are passing does not mean your code is error-free.
Now that weβve covered how tests help reduce the cost of shipping software, letβs look at how and when to write tests.
Any time youβre fixing a bug, include at least one unit or functional test with your code changes if you can. The benefits are twofoldβfirst, youβre adding a test to the suite that ensures that the bug is in fact fixed, because you can set up a test case with steps to reproduce the bug and to prove with assertions that the bug no longer exists. Second, you now have tests written that will catch that bug in the future in case you or another engineer make changes that accidentally reintroduces it.
The complexity of a codebase increases over time. As new developers join the team, experienced developers move on to new roles. Business requirements change and parts of the codebase will need to be rewritten. The more lines of code youβre rewriting, the riskier the refactor becomes. So, how do you replace old code in a production environment without breaking anything?
Automated tests are not the silver bullet, but theyβre a crucial tool that can be used to ensure youβre not breaking existing functionality. When refactoring code, the goal is to make sure you have tests in place before you begin making changes to the structure and logic of the code.
This helps define the existing functionality: how the system should work. As you refactor your code, run your test suite periodically to ensure that any new changes you make arenβt breaking the expected behavior. If your tests are still passing, youβll be confident the system is still working as intended with the modified code.
Itβs always fun to write something new rather than fix or extend code that someone else has written. You get to choose the names for your methods and variables, design the APIs, and come up with a clean solution. As youβre building out new features in your codebase, think about how youβre going to test the code that youβre writing.
Ideally, all new features you add should include automated tests. This isnβt always possible, but try to limit the situations in which you commit code that doesnβt have associated test coverage. If for some reason the code is difficult to test, try asking yourself how you can modify it to make it easier to test in the future.
A proper automated testing pipeline and a test suite with good test coverage adds a significant amount of value and can reduce the amount of cost associated with writing software. But automated testing does not ensure youβre producing quality software. There are trade-offs you should be aware of when writing tests.
Itβs entirely possible to write bad tests. Some of the features we build and bugs we fix are complicated. You may find yourself writing dozens of lines of code to set up the data for a test, which introduces opportunities for bugs within your tests.
βexampleβHere are some examples of how tests can be bad:
Incorrect tests. These are tests that test the wrong behavior of a piece of code, or tests that pass when they should actually fail. This can be misleading since you think your code is well tested when in fact it isnβt.
Poor code coverage. The tests do not cover all of the code paths or edge cases needed in order to be confident a piece of code works the way it should. If there are parts of a system (whether a few lines in a function or entire files in a module) that are not covered by tests, you may be missing critical bugs.
Poor maintainability. If you have tests that frequently fail or fail inconsistently when other parts of the system change, your tests will be difficult to maintain. Additionally, tests need to be updated as the underlying code theyβre testing is modified and refactored. Tests are code, after all, and will need to be maintained along with the core business logic.
Nondeterministic tests. These are tests whose behavior is not consistently reproducible. For example, if a test generates random test data, then your tests will not run under the same conditions every time. Some data may cause a test to fail, but it will be hard to reproduce because the test will generate different data the next time it runs.
Designing good tests takes some skill, but with a little practice, you can learn good testing habits in no time. The main idea is to build towards correctness and determinism, then increase coverage and maintainability as much as possible.
Here are things you can do to ensure tests are isolated and consistent:
Make sure your test data is the same every time. Itβs okay to generate fake data dynamically, but be aware that test data that changes for each run may introduce unreliable results, causing your tests to fail intermittently.
Make sure your tests do not rely on shared state, such as data from a database or cache that other tests are also modifying. Ideally, each test sets up its own data and cleans up the data after itself.
Each test should have one responsibility and should be testing one thing. Tests that make multiple assertions are more prone to being unreliable.
Itβs important to remember that faulty or incomplete tests can actually have a negative impact on productivity for you and your team. All code you write needs to be maintained, even the tests. When a test breaks, itβll need to be fixed, which means taking time out of your day to track down the failing test, reproduce the failure, and fix it. And any time you spend fixing a broken test is not time youβre spending adding value for your company and your customers.
It takes a fair amount of work to build and maintain a test suite with good code coverage, but donβt let the amount of work deter you from doing it. Anyone with a little discipline can build a valuable test suite, but sometimes youβll need to hold your teammates accountable when they try to commit code without test coverage. As with all good habits, it will take time at first to build a foundation, but once itβs there itβll help reduce costs over time.
You may be fortunate enough to work for a company or a team that has a dedicated team of test engineers that maintain some or all of the automated test suites. While having a team responsible for testing code quality is helpful, it does not mean you are free to add features and make changes without writing tests for your own code. All engineers on a team share the burden of making sure the code works correctly, so itβs important to work together with other developers and test engineers to ensure good code quality. You will most likely still be responsible for writing unit or functional tests, and the test engineers will be focused on writing integration and end-to-end tests for the system as a whole.
While some people may embrace a well-defined process that provides structure, it may bring a negative connotation to others who value autonomy and independence. At some point, all programmers feel the frustration of dealing with βred tape,β or the lengthy process to gather the necessary approvals to move forward with a decision. But processes arenβt always a bad thing, as they provide a tremendous amount of value.
Whether you work for a large Fortune 500 enterprise, a development agency, a small scrappy startup, or even freelance for a living, you will follow processes every day and probably even develop new processes. Building a process provides value because it allows you to standardize a set of steps to complete specific tasks. By doing so, you are able to increase efficiency and scale your throughput by training others to follow the process.
When you take a set of steps, which may need to be done in a specific order, and formalize them into a process that can be followed by anyone anytime that task needs to be completed, you add value by creating consistency. Youβve defined a standard way of doing something that can be completed the same way every time, regardless of who is performing the task.
Assuming youβve documented your newly formed process, you unlock numerous advantages. First, you can reference the steps in the process at any time, which can save you in the future if you forget how to perform a task you havenβt done in a while. Sometimes a process only needs to be performed on a monthly, quarterly, or yearly basis. As long as you have your process documented, you can always reference the documentation and be confident youβre performing the steps correctly every time.
Second, you can scale your process by training other people on how to perform the tasks. Whether itβs a sales process or a deployment process, youβre now able to train an entire team on how to perform a specific task. You have just created value.
Furthermore, processes can be measured, and anything that can be measured can be improved. If youβre able to define specific and quantifiable metrics that accurately reflect the efficiency of the process, you can track how well youβre performing the process. Once you have a baseline for how efficient your process is, you can work towards refining it to improve that efficiency even further.
And lastly, in many cases processes can be partially or fully automated. Processes often define a set of repeatable steps, and if some or all of those steps can be automated with scripts, programs, or third-party tools, you may be able to reduce the burden on teams and individuals who rely on those processes. The time saved by automating a process adds up over time and can provide a significant amount of value for a company depending on how often that process is performed.
So, as a developer, how can you add processes to add value? Start by observing your day-to-day tasks, and look for things you repeat over and over again. A good rule of thumb is if you repeat a task more than three times, thatβs a potential candidate for a process, if thereβs not already one in place.
Help your team formalize an onboarding process for new hires.
Help formalize a deployment process to ensure the code getting pushed to production has been thoroughly tested.
Add a process around code reviews, even if itβs just adding a standard template for the description to include testing instructions, a change log, multiple approvals, or anything else that should be filled out before opening up a pull request.
Propose adding, modifying, or removing steps in the software development lifecycle that you think will help your team work more productively.
Push for better-defined requirements from the product team before you begin designing the technical solutions.
Push for more-thorough design documents before you and your teammates begin implementing a solution.
Document the process for applying a hotfix to a release build.
Document the steps needed to manually run a set of commands from the command line to perform a specific task.
Help formalize a bug reporting process to make sure youβre gathering the required data every time, such as date first seen, browser version, the userβs role, and steps to reproduce.
With a little creativity, you can create a process around almost anything. And as you build out these processes, youβll start to see what works and where the processes break down and need to be improved. Then, you can rework them to accommodate a new use case and improve the process. This improves efficiency and reduces errors because itβs documenting a standardized way to perform a task. Think of it like bumper lanes in a bowling alley or swimming lanes in a lap pool. The process is supposed to guide someone to perform a task while reducing the chances of making costly mistakes.
Processes are a great way to formalize a set of steps that others can follow. Processes give you leverage to scale those tasks at the expense of adding rigidity and extra work. Keep in mind that too much process can be a bad thing, so thereβs a balancing act youβll need to look out for if youβre looking for areas where you can add or improve a process.
While most of the ideas in this section so far have involved coding, there are other ways to add value without writing any code, such as writing documentation. Often overlooked by both young and experienced developers, the ability to write clear and concise documentation will set you apart from the rest of your teammates.
Transferring knowledge through written sources has been used by almost every civilization thatβs ever existed. Thereβs a reason itβs so valuable, and writing is a skill that anyone can do and anyone can learn.
As a business matures, knowledge is gained. That knowledge is valuable, and it probably took a lot of effort on someoneβs part to build an understanding of a specific problem, a customer pain point, or a nuance of the industry. When you work hard to solve a problem, fix a bug, or develop a new feature for a customer, try to document what you learned on an internal knowledge base.
It may seem like itβs extra work, but it adds significant value even if it goes unnoticed at the time. For starters, you can reference this in the future, as mentioned earlier. You may forget why you made a certain decision or chose to solve a problem in a specific way, and itβs helpful to be able to look back on your notes to figure out the context behind a decision.
Second, itβs an easy way to contribute to the knowledge base for your company, and itβs something you can do on day one when starting a new job. You may not even have access to the codebase yet, but you can make edits to the onboarding instructions if something was confusing or missing.
Third, the content you create on your companyβs knowledge base will be searchable, so it will help your teammates find answers to their questions quicker and sometimes without interrupting you and your coworkers. Itβs an asynchronous way to share knowledge, ideas, decisions, and processes that help newcomers build on the work of those before them.
Fourth, new developers will join your team and experienced ones will leave. Sometimes, important knowledge about how part of the codebase works or why something was built the way it was will disappear when a developer leaves the team. By documenting what you know and what you learn, as well as encouraging others to do the same, youβre able to pass along that knowledge to those who come after you.
Just like well-defined processes, thorough documentation is a quality of high-performing engineering organizations. If your team already has good documentation, you can add value by contributing to whatβs already there. If your team doesnβt have any documentation, you can add value by documenting what you know and what you learn as you fix bugs and design new features, and by sharing that information with your teammates.
An important point to remember, however, is that itβs common for documentation to become out-of-date if itβs not updated regularly. When youβre concerned with shipping a new feature or a critical bugfix, itβs easy to forget to update the documentation to reflect the new changes. It takes discipline to keep documentation up-to-date and prevent it from becoming a knowledge graveyard. If you donβt take time to remove outdated documentation, it could easily have the effect of turning people away because they know the information in the company wiki is out-of-date and no longer relevant. Just like code, it takes a lot of work to maintain an internal knowledge base, but the payoff from a well-maintained system is significant.
As you can see, there are so many ways you can add value to make yourself, your team, and your company more efficient. Itβll take a little creativity at times, but the opportunities are there if you can find them.
The techniques outlined in this section only scratch the surface of ways in which you can add value, so you should constantly be looking for new opportunities. In doing so, youβll prove to your manager that youβre a valuable asset to the team and that youβre constantly putting the team first while trying to improve the system. A rising tide lifts all boats, and you have the power to drive improvements within your organization. Now itβs up to you to find those opportunities.
Code-first vs. Product-first (thezbook.com)
What is value? (dwyer.co.za)
You Are Not Paid to Write Code (dzone.com)
How Can You Increase Your Value as a Software Engineer (tomastrajan.medium.com)
How to increase your value as a developer (enterprisecraftsmanship.com)
The Software Engineerβs Path to Providing More Value and Gaining More Visibility in Your Organization (byteperceptions.com)
In the previous section, you learned that one of your primary responsibilities as a professional programmer is to create value. We looked at a number of ways you can create value, both with and without writing code. In this section, youβll learn about a second major component of your job, which is to manage risk.
Before we jump into the details of how to manage risk, we need to take a step back and answer a fundamental question: what is risk?
Risk in software development is the probability for uncertain events to occur that can have a negative impact on an organization or other entity. In essence, risk is the probability for bad things to happen. Shipping buggy code, lack of communication, changes to consumer behavior, and missing deadlines due to poor project planning are all kinds of risk that can harm your organization. Risk comes in all shapes and sizes, and each one has the potential to cause harm in one form or another.