I can help you with that. However, I don't see the Italian text provided. Please paste the Italian text, and I'll be happy to assist you in translating it into English while following the given rules.
There is an unfounded type of security that arises at the end of a long and demanding study path. It's not arrogance - it's something more subtle: the belief that completing the course means acquiring what you need to do the job. In my case, after graduating in Computer Science, that conviction was present implicitly. I didn't think about it consciously - I wouldn't say "I already know everything". But there was a sense of completeness that influenced how I approached my first developer job.
The greatest mistake I made is not a single episode - it's a way of working in the job that manifested itself in many episodes over the first few years. It can be summarized like this: I confused academic knowledge with professional competence. They are not the same thing. Academic knowledge is the base - it's necessary, useful, and permanent. Professional competence is built on top of that base through years of real work, errors, feedback, and iteration. It doesn't transfer automatically from one to another.
Why is this relevant to this series - for those coming from a non-CS background? Why do many of you arrive at your first tech job with an unspoken set of expectations about how it will be, what you'll be doing, and how quickly you'll acquire the missing skills. Some of these expectations are realistic. Others aren't. And the unrealistic ones are the ones that cause harm - not because the work is difficult, but because the distance between expectation and reality produces frustration that is often mistaken for personal inadequacy. It's not.
This article tells the story of what it was: a misalignment between expectations and reality, not a lack of ability. And it tells the lessons I learned - lessons that, I am convinced, apply to anyone who starts working as a developer, regardless of where they begin.
A point I want to make clear when I say "my biggest mistake": I'm not saying that my first year of work was a disaster. It wasn't. The work was decent, the results were acceptable, and my colleagues didn't notice most of the difficulties I was facing internally. But "acceptable" is not the level I want to have. And the distance between "acceptable" and "good" was, at that time, mainly caused by the error I described. Recognizing it in hindsight is the only way to avoid repeating it - and to prevent it from happening again for those who are just starting out.
A note on the title: "greatest error" implies that I also made other errors. Of course. But this is what had the greatest impact on the quality of work in the period following my training - and what I observed most frequently even in those coming from a different background than mine. The other errors I will recount, in more abstract form, in the sections "Typical difficulties" and "What worked for me" of each of the upcoming articles on specific backgrounds.
Typical difficulties
Before entering the specific error, it's worth identifying typical difficulties of the post-graduation period - that phase where one passes from studying to real work. These are almost universal difficulties, which I have observed in people with diverse backgrounds.
The distance between "knowing" and "doing production"
The biggest difficulty of the first year of work as a developer is the distance between knowing how to do something in theory and being able to do it in a real system with real constraints, deadlines, other developers who depend on your work. The code written in tutorials and courses is isolated code: it has no real users, it has clean and unpredictable data, it has no dependencies on third-party systems that can fail, it has requirements that don't change during implementation.
The code in production is all this simultaneously. And the transition from one world to another requires an adjustment that cannot be made by reading books - it's done by failing, correcting, and failing again in different ways. This is normal. The problem is when you interpret this difficulty of transition as a confirmation of personal inadequacy instead of as an inevitable part of the process.
Asynchronous indirect feedback
During training, feedback is almost always immediate and direct: the test passes or fails, the code compiles or does not compile, the teacher tells you if you understood or not. In real work, feedback on how you're working is often delayed, implicit, and poorly structured. You may not discover for weeks that an approach you were using was not the right one. You may never receive direct feedback on certain areas of your work.
This asynchronous feedback delay is hard to manage, especially at the beginning. The risk is of moving forward with incorrect approaches for longer than necessary - because nobody told you, not because they were acceptable. The countermeasure is learning to proactively seek feedback: asking for code reviews, seeking mentorship, participating in team retrospectives, and asking specific questions instead of waiting for general evaluations.
The underlying culture of the team
Every development team has an implicit culture: unwritten conventions on how to write code, on how to communicate problems, on what is acceptable and what isn't, on how to manage technical disagreements. This culture is not documented anywhere - it's acquired through observation and often through errors. Anyone entering a new team from non-CS background must do double work of decoding: understanding the technical skills of the role and understanding the team culture. Both require time.
Perfectionism as a block
A specific difficulty developers with a strong academic background - both CS and non-CS - face is perfectionism. Academia rewards completeness, precision, and the pursuit of optimal solutions. Real-world work often requires delivering a good enough solution on time rather than the optimal one delivered late. This shift is not immediately apparent and is not obvious. The perfectionism that was once a virtue in studying becomes an obstacle in delivery more often than not.
There is a useful version of perfectionism - that which leads to writing readable code, testing edge cases, and documenting assumptions. And there is a damaging version - that which prevents delivery because there's always something to improve. The practical distinction is this: if your perfectionism produces something that others can use, it's functional. If it causes stagnation, it's dysfunctional. The line between the two isn't always clear-cut, but team feedback and delivery rhythms are useful indicators.
Overengineering as a form of insecurity
A related error to perfectionism is overengineering: building more complex solutions than necessary because "it might serve in the future" or "it's the most elegant solution". Overengineering is often a disguised form of insecurity: if the solution is sufficiently complex, it's difficult to criticize it, because complexity is mistaken for expertise.
Reality is the opposite. Ben Halpern on DEV.to describes this paradox well: senior developers tend to write simpler code, not more complex code. Simplicity is the result of understanding the problem well enough so as not to need artificial constraints of complexity. Overengineering, on the contrary, is the result of not understanding the problem well enough to find the simplest solution that works.
For those who are just starting out: when you feel like adding an abstraction, a design pattern, or a generalization "for the future", ask yourself this question: is there a concrete and current requirement that justifies this complexity? If the answer is no, don't add it. The refactoring of the future, when the requirement arrives, will always be easier to do on simple code than on already over-abstracted code.
What worked (Federico)
The error I described does not resolve with a single insight - it resolves with a change in the way one works at the job. These are the practices that have contributed to this change.
Treat the first year as a learning year
The first thing I changed - and what I would have liked to change sooner - is how I thought about my first year of work. Not as "the year in which I demonstrate what I know," but as "the year in which I learn what I don't yet know, and that cannot be learned elsewhere." This shift in perspective has changed the relationship with errors: they were no longer something to hide, but signs on where to focus my learning.
The Pragmatic Programmer by Hunt and Thomas (ISBN 978-0135957059) describes this mindset well with the concept of "knowledge portfolio": a professional developer systematically invests in acquiring new skills, just like an investor diversifies their portfolio. The investment does not end with initial training - it is a continuous practice throughout one's career.
2. Requesting systematic code reviews
One of the practices with the highest ROI that I have adopted is to do code reviews systematically - not just when it was mandatory for the process, but proactively, even on parts of code that I had already written. Code review is one of the most effective mechanisms for receiving calibrated feedback on the quality of your own code, for learning patterns and conventions of the team, and for exposing your technical reasoning to external verification.
The psychological cost of asking for code reviews is real, especially at the beginning: exposing your code to judgment that may reveal errors or flawed approaches. But this is exactly the point. Code reviews accelerate learning in a much more efficient way than solo study, because feedback is specific, contextualized, and immediate compared to the code you just wrote.
3. Writing readable commit messages
One of the first concrete things I learned and that changed how other developers perceived my work was writing readable commit messages. This seems like a minor technical detail - it's not. A clear commit message tells the story of a change: what changed, why it changed, and what didn't change. It is real-time documentation that other developers use to understand the history of the code.
The simplest format I recommend: a first line that describes the change in a imperative and specific way ("Add validation for email format in registration form"), followed by an empty line and a description of the reason if it's not obvious ("Existing code accepted addresses without @ sign causing downstream failures in email service"). It's not a paragraph every time - only the necessary information to understand the commit without reading the code.
Learn to say "I don't know, I'll check and tell you"
Another practice that has changed my relationship with work is learning to say "I don't know, I'll verify and respond" instead of making a plausible response to avoid appearing unprepared. In tech teams, improvising on technical questions comes at real costs: it produces decisions based on unverified information, creates false expectations, and when discovered, damages credibility much more than a straightforward "I don't know but I'll verify" said directly.
I spent time learning this. The implicit pressure to seem competent - especially at the beginning, when it's perceived that others expect a lot - leads to responding with confidence even when that confidence isn't based on facts. The first step out of this pattern is recognizing it. The second is practicing saying "I don't know" - which is much shorter than it seems, and less damaging than feared.
Building a personal technical notes system
A practice that has had a lasting impact is keeping a personal technical notes system - not public, not a blog, not formal documentation. A text file (or a system like Obsidian) where I annotate: problems I've solved and how, patterns I've learned, errors I've made and what I changed, useful resources I've found. This system has two functions. The first is increased memory: when I encounter the same problem again after months, I already have the solution annotated. The second is reflection: re-reading last month's notes shows concrete progress and directly fights impostor syndrome.
6. Calibrate delivery speed
Another thing I've learned over time is to calibrate the delivery speed: understanding what the sustainable pace is in the long term for producing quality work, and proactively communicating when something requires more time than expected. In my early years, I tended to underestimate times - due to optimism, fear of appearing slow, because I hadn't yet developed an accurate model of how much time things require. The result was late deliveries that could have been avoided with a more honest estimate from the start.
The accurate estimate of time is a skill that develops with experience, but can be accelerated by a method: keeping track of the time it takes to do things (not just total time - actual work time), and using that historical data to calibrate future estimates. It's surprising how different the perceived time is from the actual work time, and how this gap produces systematic underestimates.
Cognitive framework
Two frameworks that have helped me understand the error described more effectively, transforming it from a source of embarrassment to a source of data.
The Dreyfus Cycle of Skill Acquisition
The Dreyfus model of skill acquisition describes five levels: beginner, advanced beginner, competent, proficient, and expert. Each level has specific characteristics in how it approaches a problem. The beginner follows rigid rules because they lack the context to determine which rule to apply when. The competent can manage new problems using principles, not just rules. The expert acts intuitively without having to explicitly apply rules.
The error I described - confusing academic knowledge with professional competence - is essentially a disalignment in the Dreyfus model: I believed I was at a higher level than where I actually was. Applying this framework changed how I approached challenges: it's not "I'm incompetent because I don't solve this problem like an expert", but "I'm at this specific level, and the next step is that".
Mistakes as a learning system (Hunt and Thomas)
Hunt and Thomas in Il Programmatore Pragmatico (ISBN 978-0135957059) describes the professional developer as someone who treats errors as data, not judgments. An error says something specific about where there is a gap between the mental model and the reality of the system. That gap is precious information - much more valuable than a correct answer obtained without understanding why it was correct.
The concrete practice I derived from this framework: after every significant error - a production bug, a difficult code review, an approach that didn't work - I stop and write three things: what happened, why it happened (not at a superficial technical level, but at the level of the flawed mental model), and what I would change as a consequence. This transforms the error from an event to be quickly forgotten into an investment in the learning system.
The concept of "bugged code as a learning opportunity"
A less formalized but very practical framework: treating every significant bug as an opportunity to learn something about the system you didn't know yet. Bugs are not incidents - they're the reality of the system that tells you something your mental model hadn't predicted. The most frustrating bugs are those that reveal fundamental assumptions that were wrong - and would have caused similar problems even in the future if they weren't encountered first.
I've learned to distinguish between "stupid" bugs (digitization errors, incorrect variable references, off-by-one errors) and "revealing" bugs (those that show a gap in understanding the system). Stupid bugs don't teach much - they happen to everyone and can be resolved with attention. Revealing bugs are those that need to be investigated deeply, because the pattern they revealed probably will reappear in different forms if you don't understand the root cause.
Keeping a list of revealing bugs encountered over time - with a brief description of the gap they showed - is another form of personal technical note system that I described above. It's also one of the most useful documents to review before a technical interview: it shows how your mental model of the system has changed over time.
Readings and Resources
These are the resources I recommend specifically for navigating the transition from training to professional work - a moment in which impostor syndrome is often more intense and in which errors have more visible consequences.
Foundational Books
- Andrew Hunt and David Thomas, Il Programmatore Pragmatico (ISBN 978-0135957059) - The book on the profession of a professional developer. The chapter "Your Knowledge Portfolio" is directly applicable to the difficulties of the first year. I re-read it every year - every time I find something new because I have more context to understand it.
- Robert C. Martin, Clean Code Note: I'll translate the text while preserving the original formatting and capitalization style. Here is the translated version: Clean Code Please let me know if you'd like me to translate anything else! (ISBN 978-0132350884) - A book on readable code writing. Not a book about algorithms or architectures - a book on how to write code that other developers can understand, modify, and maintain. Relevant from day one of work.
Online resources
- Ben Halpern, "Why Senior Developers Write Dumb Code" (DEV.to) A brief and dense article on one of the paradoxes of the profession: expert developers write simpler code, not more complex. Complexity is not a signal of competence.
- Joel Spolsky, "The Absolute Minimum Every Developer Must Know About Unicode" A sample of the type of fundamental knowledge that developers acquire in real work, not in courses. Joel on Software is a repository of practical wisdom on the profession of developer.
The CV template I prepared includes three concrete examples of unconventional paths - with sections that work best for those with a non-linear background. You can download it for free here above.
Next step in the series
The next article - the fifth in the series - is called Private networking through email (not LinkedIn)It's not an article about creating professional connections in a general sense. It's a specific article on how to build meaningful professional relationships starting from direct emails, without pretending enthusiasm for networking events, and without LinkedIn personal branding performance. For many people with non-CS backgrounds coming from sectors where professional relationships work differently, this is a very concrete topic.
You can find all articles in the series on cornerstone of the series.
See also: What would I do today if I started again from scratch as a developer The third article in the series, which is the operative complement of this: this tells about the error, that one tells about the alternative plan.
What have I learned writing this
This article was the most difficult of the four I have written so far. Not technically - but emotionally. Writing about an error you made in a honest way, without downplaying it or exaggerating it, requires precise calibration. The temptation is to go in one of two directions: either the mea culpa that's overdone ("I made a serious mistake that had terrible consequences") or minimization ("it wasn't so bad in the end"). Both directions distort the story.
I tried to stay in the middle: the error was real, it had real consequences on the quality of work I did in my early years, and those consequences were recoverable over time through the practices I described. It's not a story of triumph - it's a story of progressive adjustment. That's probably the kind of story that is most honest and most useful.
Something I removed from the first draft: a section on specific errors made in particular projects. I took it out because it violated the D-07 constraint - the specific projects I worked on are tied to my current work context, and mentioning them would introduce references I don't want to make. But this forced me to do an useful exercise: abstraction. Instead of "in project X I made error Y", I wrote "this type of error produces this type of consequence". Abstraction loses its narrative color but gains applicability: it works for any context, not just mine.
There's something I've realized during the writing process that's worth mentioning: the error I described isn't specific to those with a CS degree. It happens after any intense training - bootcamp, master, long self-study. The pattern is the same: training gives a sense of completeness that the start of real work demolishes. The difference between who recovers quickly and who struggles is how one handles errors. Those who treat them as data move forward. Those who treat them as judgments stay stuck.
If you made an error like that - if you confused acquired knowledge with professional competence - and found a way to get out of it, I'd love to know about it. The stories of repair are the ones I find most useful, because they show that the path is not linear and this is okay. Write to federico@federicocalo.dev.
I respond. Always.
Frequently asked questions
What is the main difference between academic knowledge and professional competence?
Academic knowledge is the base, necessary, useful, and permanent, while professional competence is built on top of that base through years of real work, errors, feedback, and iteration.
Why do many developers struggle with the transition from theoretical knowledge to practical application in a production environment?
The biggest difficulty is the distance between knowing how to do something in theory and being able to do it in a real system with real constraints, deadlines, other developers who depend on your work.
What is asynchronous indirect feedback, and why can it be challenging for new developers?
Asynchronous indirect feedback refers to delayed, implicit, and poorly structured feedback that may not be received directly or immediately. This can make it difficult to manage, especially at the beginning, as it may lead to moving forward with incorrect approaches.
What is overengineering, and how can it be a disguised form of insecurity in developers?
Overengineering refers to building more complex solutions than necessary because "it might serve in the future" or "it's the most elegant solution". It can be a result of not understanding the problem well enough to find the simplest solution that works.
Commenti
Caricamento commenti...
Sign in to comment