Stepping Up Your Game: Overcoming the 9 Characteristics of a Poor Coder from a CTO Perspective
Learn about the common features of poor coders from a CTO’s point of view and discover how to improve your development skills and career prospects.
May 11, 2023 | 15 min read
Writing code can be a complex task, but software development is far more than just writing code. The ultimate aim is to solve real-world problems for businesses and end users. Indeed a large part of the job is understanding business challenges well in order to offer the right solutions or to work in a team to overcome common roadblocks. Despite the stereotype of the lone hotshot coder, software developers increasingly have to do more than write code. They have to be multi-disciplinary and collaborative. Some of the characteristics of a bad programmer in this list are technical, but many are not. Development is as much about strict coding skills as it is about soft skills. Many can simply write code, but relatively few can navigate team dynamics, understand business challenges and design simple code bases.
As technology advances, best practices have to keep up. However, a solid base in some of the key principles of the profession will set you apart from your weaker peers. As a CTO, I interview, work with, and give feedback to developers all the time, and these are some characteristics that set mediocre programmers apart from strong ones. In this blog post, I’ll outline some of the characteristics of poor coders and offer ways to improve your development skills and career prospects.
Good programmers know overengineering is the real enemy in development. The simplest, most efficient design that achieves a goal is often the best solution. For a software developer to make an app more complex than it needs to be, shows a lack of understanding of the business challenge, the technology, or both. As the expression suggests, it's using the wrong tool to achieve a goal. Will it work? Sure, it will, but there are better, less cumbersome options. Complex code is often redundant and unnecessary and creates more problems down the road for businesses or developers who want to update the software. That can lead to a worse user experience, higher maintenance costs, and security risks.
To overcome this tendency, it is important to embrace simplicity in design, using the simplest solution possible to solve a problem. Instead of trying to come up with complex solutions. One way to achieve this is to use small predefined solutions that have already been solved by other developers, which allows you to read and understand what the code does, and avoid implementing structures where there's no need.
A big part of this is letting go of an ego and being more collaborative with your peers. Some are wary of using someone else's code. But admitting what you don’t know is just as important as showing off what you do. Both junior and senior developers can stand to learn new methods and share findings with one another. Reaching out to colleagues on your own team or further afield in development forums, stack overflow, or a quick google search for solutions. Changes are, other developers, have been where you are and can offer ways to simplify overly complex code.
When working on a project, it's important to focus on the needs of the project, rather than trying to create a solution that is overly intricate. By keeping things simple and straightforward, you can ensure that your code is efficient, easy to understand, and easy to maintain. This will help you to become a better programmer and will help your team deliver better outcomes.
The second characteristic of a poor coder is being too self-focused. Like those that create bad code in isolation, coders that are too self-focused tend to work only on their own code without cooperating with the rest of the team. Like any design, good software is a collaborative process that combines the efforts of whole teams of experts. Each person contributes a unique perspective and a slightly different set of skills to solve problems. Being too cagey or uncooperative can be detrimental to the project and to the organization as a whole since it can lead to a lack of communication, redundancies, and resentment.
Counteract this trait by communicating your progress with the rest of the team, and get involved in other developers' work. By doing so, you can help to ensure that everyone is on the same page and that the project is moving forward in a coordinated and effective manner.
Effective communication is key to being a good programmer. Make sure that you keep the rest of the team informed about your progress, and ask for feedback and input when necessary. This will help to ensure that everyone is working towards the same goals and that everyone understands their role in the project.
Getting involved in other developers' work is also important. By doing so, you can learn from your colleagues and help to improve the quality of your own code and the project overall. Don't be afraid to ask questions, offer suggestions, and provide feedback to your colleagues. This will help to foster a sense of collaboration and teamwork that is essential for delivering successful projects.
Being a team player is an essential characteristic of a good developer. By communicating effectively, getting involved in other developers' work, and working collaboratively, you can help to ensure the success of the project and the growth of your own skills as a coder.
Good application flow and layering are critical to ensure that the code is easy to read, maintain and modify. When a developer doesn’t pay attention to these aspects, it can result in code that’s difficult to understand and change. Think of the next developer who has to pick up the code to work on. Do unto others.
It’s also vital to the principle of business continuity. If one person is the only person who knows where to find a snippet of code, or how it works, that’s a big bottleneck and an expensive risk for the agency and end-client alike.
Poorly structured code, or "spaghetti code" is tangled old code written in a way that can be difficult for others to follow. This can happen when the application does not have a clear structure, and different parts of the code interact in unpredictable ways. Global variables can also cause problems by allowing data to be accessed from different parts of the code, making it difficult to track changes and bugs. This is both expensive to maintain and to untangle. Coders can write code poorly from inexperience, ineffective supervision or bad habits left uncorrected.
To avoid these issues, developers can use simple architectures like layered/MVC ones. These architectures divide the code into logical layers or modules, making it easier to understand and change. Code documentation is also critical to ensure that developers can easily understand the code's purpose and behavior. Basic folder structuring can also help to keep the code organized and easy to navigate.
By following these practices, developers can ensure that the code is structured well, easy to read, and maintainable. It also helps to reduce bugs and improve code quality, making the application more reliable and efficient.
Being detail-oriented is critical for writing code that works as expected. Ignoring details may result in bugs, security vulnerabilities, or performance issues that can be difficult to unit test and fix.
One way to work against this problem is to start from a helicopter view of the project and then dive into the details while working. This approach helps to ensure that all aspects of the code are accounted for, and that the developer has a clear understanding of the project's requirements and goals.
It’s also important to verify the work before pushing it to the testing environment. Developers should test their code thoroughly to ensure that it meets the requirements and works as expected. This can include testing input validation, edge cases and error handling. Being a tester before submitting code for review can help to catch issues early on.
Another way to improve detail orientation is to learn from code reviews. Developers should seek feedback from peers and reviewers to identify areas of improvement and to learn from mistakes. They should take note of critical points in the review and work on addressing them in their future work. This approach can help to improve the quality of the code and to avoid common mistakes.
Developers should sticklers for detail, taking care to start from a high-level view, verifying their work, and learning from feedback in code reviews. This approach can help to produce code that works as intended, is secure, and performs well in the real world.
When writing code, performance is often an important factor that should not be overlooked. Developers who prioritize other aspects of their code and neglect performance may have trouble ahead since that code often requires significant resources to run. This can lead to slower applications, increased costs, and unhappy users.
Developers should instead remember the concept of "divide and conquer." This means breaking down a complex problem into smaller, more manageable pieces that can be solved independently. This approach can make code more efficient and easier to optimize.
Another solution is to plan before writing any code. It's important to consider the Big O notation of the algorithm that will be used. Big O notation estimates the time and space complexity of an algorithm, which can help developers anticipate performance issues before they arise. By estimating complexity, developers can make informed decisions about which data structures and algorithms to use.
Lastly, learning more about the language being used can help developers make informed decisions about optimizing their code. Understanding the strengths and weaknesses of a language can help developers avoid inefficient coding practices and take advantage of built-in performance optimization features.
By focusing on performance, developers can create more efficient code that delivers a better user experience, reduces costs, and improves overall application performance.
Get informed about the most interesting MasterBorn news.
Appropriate structuring is essential in creating maintainable and scalable code. However, developers with little knowledge of appropriate structuring often end up creating poor data structures or fat static utility classes. Poor data structures can result in code that’s also hard to maintain and can lead to a cascade of performance issues. Fat static utility classes can be hard to test and reuse, leading to code duplication and increased technical debt.
To avoid issues with structuring, developers need to have a good understanding of appropriate techniques and a consistent coding convention. One effective approach is to use abstraction to identify repetitive patterns in the code and create generic solutions that can be reused throughout the application. This can help reduce code duplication and make the codebase more maintainable.
Keeping data flow linear is also crucial in creating a well-structured codebase. Developers should ensure that data flows smoothly from one module to another without causing unnecessary delays or bottlenecks. This can help improve the overall performance of the application and make it easier to maintain.
Another issue that developers with little knowledge of appropriate structuring often encounter is the creation of big balls of mud, or murky, difficult-to-read code. These are codebases that are hard to understand, modify, and maintain. A good programmer should split the code by the problem it solves and the domain it touches. This can help ensure that each module or component has a clear purpose and can be easily maintained.
Appropriate structuring is essential in creating good code that's maintainable. Developers who lack knowledge in this area should learn about abstraction, keep data flow linear and split the code by problem and domain.
Developers who are masters of only one solution are limiting their options and missing out on potential solutions that could be more effective in different contexts. Different programming paradigms have their strengths and weaknesses, and it is essential to know when and where to use each one.
For example, functional programming is great for handling large sets of data and processing them in parallel, while object-oriented programming is excellent for modeling complex systems and maintaining code. Event-driven programming is ideal for building responsive user interfaces and handling asynchronous operations.
Developers should strive to learn and master multiple programming paradigms to have a wide range of tools at their disposal to solve problems effectively. They can do this by studying new programming languages, exploring different frameworks and libraries, and experimenting with new programming techniques.
By becoming well-versed in multiple programming paradigms, developers can create more robust and efficient solutions that can adapt to different environments and requirements. It can also help them better communicate with other team members who may be less experienced programmers or have different perspectives, leading to more effective collaboration and problem-solving.
Using one database for everything can lead to scalability and performance issues, as well as data loss and security problems. Developers should take into account the specific needs of the application and the data it will handle, and choose the appropriate database engine accordingly.
For example, if the application requires complex queries and transactions, a relational database such as MySQL or PostgreSQL may be the best choice. If the application requires high scalability and performance, a non-relational database such as MongoDB or Cassandra may be a better fit.
In addition, developers should also consider the size and complexity of the data and the budget available for the database solution. Using a cloud-based database service like Amazon RDS or Google Cloud SQL can provide scalability and high availability, while also reducing costs compared to managing a database in-house.
It's also important for developers to stay up-to-date with the latest trends and technologies in database management, as well as best practices for data modeling, indexing and optimization. By learning continuously and experimenting with new database engines and techniques, developers can make informed decisions and optimize the performance and scalability of their applications.
Being a successful programmer is so much more than just being a programmer. A lack of perspective on business challenges or of the initiative to learn are characteristics of bad software engineers. Developers who do not have their ideas and only work on existing code need to fill team gaps, work with the business closely, show initiative on various aspects, and be proactive.
Some developers view themselves as mere code writers, with no other significant contribution to the team. This mentality can lead to stagnation in career growth and a limit future opportunities in the field.
To avoid falling into this trap, developers should strive to fill the gaps in their team's skill set by learning new technologies, tools and techniques. This could mean studying design patterns, exploring new programming languages or frameworks, or becoming familiar with project management methodologies.
Getting a grasp on the business challenges clients face is also highly valuable for many. Learning not just about the code aspect, but also about challenges that in-demand business verticals face is vital for a gainful career trajectory. Developers can become more valuable to their team by working closely with the business to understand their needs and create solutions that meet those needs. This requires effective communication, empathy, and a willingness to collaborate.
Being proactive is also essential for developers who want to avoid being just a programmer. They should take the initiative on various aspects of the project, such as suggesting improvements to the codebase, finding and fixing bugs, or contributing to the development of new features. This shows a sense of ownership and investment in the project's success.
Rather than being just a programmer, developers must be willing to go beyond just writing code and take on a more active role in their team's success.
In summary, the blog post highlights nine common mistakes made by developers and provides solutions to overcome them. These mistakes include overthinking and overengineering, being self-focused, not creating good application flow/layering, not paying attention to details, ignoring performance, lacking knowledge on appropriate structuring, mastering only one solution, being "just a programmer," and using one database for everything.
The solutions to these problems involve keeping good code simple, being a team player, using simple architectures, paying attention to details, prioritizing performance, using appropriate structuring, learning and adapting to new solutions, filling team gaps, and choosing the appropriate database engine. By avoiding these mistakes and following the solutions provided, developers can create better code and contribute to the success of their team and organization.
Table of Content
- 1. Using a cannon to kill a fly
- 2. Being self-focused
- 3. Not creating good application flow/layering
- 4. Not being detail-oriented
- 5. Not being performance-oriented
- 6. Poor knowledge of appropriate structuring
- 7. Being a master of one solution
- 8. Using one database for everything
- 9. Being “just a programmer”
World-class React & Node.js experts
CTO as a Service: What is CaaS? Key benefits and risks
CTO as a Service is not just another XYZaaS fancy word. It’s a solution based on responsibility that generates more and more buzz in the startup world.
Why your startup doesn’t need a CTO
I know it’s a bold statement, but I don’t believe every company needs a CTO in the very beginning.
CTO myths debunked: Interview with Masterborn’s CTO Przemysław Królik
What is a CTO and what are the most popular myths about the role of a CTO? Read the Interview with MasterBorn's CTO Przemek Królik