Ask HN: What boosted your confidence as a new programmer?
When anyone starts out in a new craft, even after grasping the fundamentals of the tools they are quite shaky and low on confidence until they have a significant experience in doing something that ultimately ramps up their confidence in their craftsmanship.
Similar things happen with novice programmers when they start out.
Then they read a beautiful codebase which they can fully understand and replicate, or build a project from scratch, or read a book or take a class on a subject. And their confidence is tremendously boosted thereafter.
What was it for you? How did you gain this confidence to take the first step from being a tinkerer to being a skilled craftman?
244 comments
[ 3.0 ms ] story [ 301 ms ] threadWent away to college for something completely different, psychology, but when I got home and started applying for jobs, nobody would hire someone with a bachelors in science only.. so I decided to pull out an old trick of mine: I would apply to the programming companies too. Got an interview. Got the job. Even though my math skills were horrendous.
The confidence in my programming skills came a few months after they hired me. Til then, I'd been working on building various little programs that had no real purpose. A ping pong came, a slot machine, etc. My tyrant boss had me go through training to use various functions in Visual Basic 6. Some of the most valuable ones were using arrays and collections, which had helped me understand databases later on when I was learning PHP.
I was developing software for an autobody shop. I really couldn't wait to work "in the main program" but once it was established that I was ready, that's when the confidence started taking off.
About 6 months later, his customer base went from a few hundred to a few thousand. My job was to focus on the UI, making it more user-friendly and easier to use and fix existing bugs in the program. I loved and hated that time of my life because it led me to meet a wonderful woman, yet I was going through hell everyday for that tyrant. Fortunately, I took what he taught me and used it to further establish my career elsewhere.
At that point, you lose the feeling that there are magic things out there that you will never understand and that for the most part everything is just regular old code that regular people wrote.
If you highlight a method you call from external code and hit CTRL + F12, Visual Studio will automatically decompile it for you.
Dotpeek is integrated into Rider and is a world class decompiler. It also integrates into Visual Studio either standalone, or with ReSharper.
You can also integrate external source symbol servers into your IDE of choice as well that will let you debug into libraries seamlessly.
In the case of non-compiled languages, of course you don't even need this step since all your libs exist in source form already, so it was pretty simple for me to step through Ruby library code with a simple debugger and no fancy IDE.
I have a habit of sometimes debugging even horribly abstract framework (e.g. Spring) code when I don't understand what it's doing. That's maybe not the most efficient method, but it does usually make me understand why thing X is not working the way I expected it to work.
I don't really remember when I felt that external dependencies were magic, but thinking about this, it explains a lot of the behavior I see on some developers who are very negative about the more challenging parts of the job.
Some of them don't really believe the research stuff we do at work are even possible. They're constantly surprised when other devs finish those tasks. Some don't believe that other devs can code in C++ or Rust, or write parsers, database modules, implement IQueryable in C#, or develop novel algorithms for novel applications.
To them, if a package exists it must just work, and that package comes from another breed of developer that can't coexist with them. I see a similar thinking with AI: now with ChatGPT and GPT-4, there's a hubbub about there being "no reason for our AI team to exist anymore".
I'm not a big fan of working with those developers.
I agree. And it ties into something I often see that puts me on edge: programmers not taking responsibility for the code they put into their projects.
What I mean is that when you incorporate any code, from any source (library, framework, copypaste, etc), then you are responsible for that code and its proper behavior as much as for the code you actually wrote. So you're well-advised to understand it.
That's one of the reasons why I won't include code that I don't have the source code to. I need to understand it and be able to fix it.
The "out of sight, out of mind" approach doesn't really work for code you're actually responsible for.
To me the issue is they assuming everyone around them is like this. I'm totally fine with lack of experience or knowledge, but a co-worker constantly underestimating their peers is not alright.
Where it really stings is when I do something of my own initiative (like, for example, create a transparent API over memoizing and caching some expensive calculation, or refactor some of our common client customizations into their own set of classes so it’s easier to extend) and he ignores it or scoffs at it.
Only to then find a third party library that implements something similarly. THEN it’s presented to me as a “brilliant idea” that we can take advantage of.
At that point, when I say “we” already do this, he usually rephrases what his brilliant 3rd party library does, as though he can’t fathom that I would be capable of doing something like that myself, and clearly I’m just not understanding what he’s telling me.
I think it’s a defensive mechanism for his ego against one of his peers or employees being more capable than he is.
But it’s also not like he can’t learn this stuff himself, he just doesn’t ever put in the time or effort.
For, say, security implementations for authorization and access controls, or even low level HTTP request routing? Absolutely. The goal there is to adhere to something standard and battle tested by experts, and the third party libraries tend to be fewer in number, and of higher quality, with longer term support and clearly defined upgrade paths.
But that’s the lower level stuff, where your special custom needs are superseded by the primary goal of just “doing the one right thing”, or “adhere to the commonly agreed upon standard”.
For all the other things that make an app unique - things like CSS frameworks, UI components (beyond basic, accessibility-minded building blocks), chart drawing, report generation and caching - my experience has taught me otherwise, the hard way.
Being stuck using a 3rd party library that doesn’t do what the client or business needs it to do, having to juggle our own internal patches and bug fixes with updates to the library itself, all only to have the library abandoned or deprecated in favor of the author’s next pet project, really sucks and often comes with a high opportunity cost and a high development cost.
I now consider third party implementations of higher level features (and especially anything front-end) to be something that needs to be evaluated as equally costly as an internal implementation by default, and not favored just because somebody else wrote it.
Maybe I’ve just been unlucky in my experience, though. I also suspect ecosystem makes a difference. The PHP and JS ecosystems are full of poor libraries with snake oil sales pitches. I suspect this is different with, say, Rust.
I’ve mostly worked with Python and JVM languages, which probably explains why I’m less passionate about the counter-argument than you are. Ecosystem definitely matters a lot. VanillaJS is the only good JS framework IMO.
So the go to for every solution is to find a third party library from a “real” witch or wizard, and follow its basic tutorial. Maybe try to customize it a bit at most.
If something breaks, just start randomly moving things around or copying and pasting more code from forums until it works.
I can’t live like that. I need to know why something’s not working, AND why it IS working. I like stepping through my code with a debugger just to make sure things look right, even when they’re working.
I think the craziest part, though, is just how much people with this “software is magic” mindset can actually get just by brute force cobbling things together.
That mediocre dev is a straight shooter with middle management written all over them…
It's a matter of preference but IMO/IME it works better when a manager is actually good at it.
A manager that is supposed to be technical but only wants/knows how to do the management part, and can't make more than the basic stuff won't really fly. I've seen a couple of those getting fired during probation period.
On the other hand, the "bad developer" that thinks packages are magical will eventually settle as an expert beginner in a low-expectation environment. Which is fine.
The other thing I find is that big libraries are either mostly dependency bloat (as implied above) or dealing with a hard domain problem. If it's the latter, what you're really struggling with is not the library, but the domain it's trying to represent.
But this doesn't change anything of the programmers problem. If I stumble on a bug in a physics libary I am using for a game, I cannot just jump right into there and go fixing things. I mean I can start doing it, but at the cost of not getting anything else done for quite some time.
There are lots of hard domains in programming. Cryptography is hard. Networking is hard. Fast rendering is hard. Efficient DBs are hard. OS are hard. Drivers are hard.
You can maybe fix a trivial error in such libaries, but everything else is usually a (big) project on its own.
Additionally, once you recognize that you can also recognize if you’re dealing with incidental complexity (e.g. poorly thought out/designed code) and inherent complexity (e.g. physics calculations). The former can be fixed, the latter cannot. Knowing the difference saves much pain.
For React devs, this means learning how React actually works under the hood.
Imagine buying a hammer, that hammer not working, the hammer's design being so complicated that it's impossible to understand or mend, and then having to design and build your own hammer, and then putting up with that situation over and over again and accepting that as the status quo. That would be the correct analogy.
We have do have tools like the hammer - there is one design, everyone more or less agrees on it. There is still high quality and low quality, but it has one job. We have tools like a bulldozer - complex, numerous parts, requires constant maintenance, closed source.
As the parent said - it is not uncommon to have to maintain old equipment, as well as design new tools as new requirements pop up.
Sure, our rust is a little bit different - time wears on software in a different way. Use wears on software differently. (Changing product requirements leading to a new tool is probably common.)
The maintenance may be trickier - but I'm sure changing components on a tool when a certain component is no longer available is not easy, thats where shim layer comes from!
A mine site usually fixes its own tools used to do their job, they usually fixed things they've purchased to use that are broken or become broken, is that not the same?
Very different situation
I've also found that the software industry obsesses over tools more than any other industry
On a mine site, the job is to mine and process minerals. That includes engineering a mine using products that eventually fail over time and need fixing. As part of that process an automotive electrician may need to fix the electronics on a vehicle that have become faulty or damaged.
Mechanics and engineers need to inspect, rebuild, and fix the tools they are given to do their job. The difference is that yours may not work up front, whereas these tools need maintenance over time.
The difference between most professions and programming is that we have open source. The equivalent of that in the real world is getting blueprints to build our tools and then building them ourselves, with no guarantees.
This was and is quite common in any blue-collar field where works don't always have the money or time for a brand new jawn every time something goes wrong.
I love estate/yard/garage/barn sales and going through the tools and reading the tales they tell from their wear patterns, field repairs, revisions, and hacks from their owner.
Case in point, here's a tool which has gotten multiple leases on life through modifications. https://youtube.com/watch?v=oTA513ttrbQ
For example, I have a graphics project where screen tearing suddenly started appearing although my code didn't change, and the tearing wasn't there before. Is the issue in Skia, OpenGL, the graphics driver, the Intel or NVidia GPU, or the OS? Or is it some latent issue in my code that started showing up because of a change in these dependencies? Or is it some other complex interaction between multiple dependencies? I couldn't possibly know, and I actually don't think there is anybody that actually knows. And there is zero chance I could ever figure it out. I mean, it at least appears it was a driver issue as after some updates and a reboot it just went away, but there is zero insight into why or what actually made it go away.
If I modify a plow because some part as originally designed was flaky and constantly broke, you usually know to a pretty good degree why your fix works.
In software, the abstractions are such that it is practically impossible atbtimes to understand.
Sure, welding back on a hardpoint that broke off a plow is concrete and obvious (maybe that's analogous to fixing a broken dependency that got renamed), but there are other fixes that definitely fall under "I don't know why it works but it works". I've had electrical gremlins and fixed them by grounding something that looked like it ought to be grounded, and was grounded when I tested for continuity, but nonetheless was acting floaty. It was probably a loose connection elsewhere in the system, but I didn't know that for sure, nor do I even know that it was the problem in the first place.
Software definitely reaches insane depths of complexity, but again, if you can dig down and understand the abstraction well enough to attempt a fix, and the problem goes away, isn't that good enough? The real difference is mechanical systems typically only have a few layers of abstraction, while software has dozens to thousands of layers of abstraction.
I think the real skill then is to learn to navigate big codebases in few days time than taking a few weeks and then feel dejected by the time spent and still unsure.
I often feel ambitious for such endeavors but navigating big codebases take time, any tips?
More importantly is to use an IDE with a good fast global search function and get comfortable with it. At least for me, 99% of navigating a large codebase is global search.
You can goto or peek definition in VSCode. And the find tool has the option to find all occurrences throughout your project.
1) I can figure out issues in other people's implementations.
2) The best solution may not be the best solution for you, and my hunches on optimization might be correct
3) It's fun to look like a wizard to your peers
The chief one, I think, comes from simply having achieved enough challenging problems to the point where one knows that, even if their solution isn't perfect, they can figure out basically anything. The overwhelming majority of programmers can get to this point eventually.
Confidence also comes from the eventual realization that, with few exceptions, the majority of programmers you think are "better" than you are really aren't objectively better. They may have a fancier title, a bunch of GitHub stars, have given presentations, or maybe they've written a book, but this doesn't mean they are a better programmer than you. It might be hard to understand as a novice, because virtually every novice is going to feel inferior for lack of experience. After having gained sufficient experience, to the point where there's seemingly no problem one can't solve, it may become obvious that these programmers one once viewed as elites actually just broadcast their craft in a way that gives them higher authority; I stopped viewing most programmers as being better or worse than each other because I've witnessed enough problems caused by the clever solutions of senior and staff developers. It's just much easier to blame a junior engineer's solution when it doesn't work out. This isn't to say that more seasoned programmers aren't worth their salt, but there's almost never something they have that you can't have, and every programmer out there writes bugs all the time!
And finally, seeing the tech hype come and go over a long enough period of time can eventually bring one to the point where they look back on methodologies, frameworks, and design patterns they were once introduced to and come up with the original thought of "You know, I think that X was kinda bullshit to begin with." I think it's really unlikely that a programmer can have a 20+ year career (or even a 10+ one for that matter) and not come to some conclusions like that. Though it's easy for a novice to get caught up in the churn thinking they've got to learn all the things and feel inferior for not knowing it all, experience may someday teach the programmer that most of the churn was hype and that their own ideas on how to program effectively probably would have worked just fine.
I would say that I gained my confidence by just trying enough times and gaining experience.
In the late 90s to early 2010s it was fashionable to think of code as a graph of dependencies, and as long as you honor those dependencies when changing the code you would be ok. This is simplifying but pernicious POV IMO - reinforced by the zeitgeist that code is truth and comments (in code or otherwise) may not be. This is a cul-de-sac.
Unless developers see things as nouns or verbs, they don't acquire the ability to scale and see the bigger picture, because there is nothing to hold these smaller entities and connections between them (O(entities^2)). The concepts are the bags. Wish someone would explicitly teach us these things, because, sure as hell they didn't teach it in college.
May be people who have a liberal arts background are good at seeing these things, because one of the things they explicitly study is perspective, framing etc. Engineering is quite limited because we don't explicitly study about that.
You’ll gain confidence when you realize you can just hack away until it works and that is OK.
Seeing shapes collide, bounce, roll, and understand exactly what was happening in the code I wrote was a huge confidence booster.
if the capability is the question, well i don't have any answers. 10 years in and the imposter syndrome is still strong.
For the confidence? It was working with others. The first job I had I got to sit down with one of the company's programmers as part of my on boarding and watch him work through tickets. After I saw just how flawed everyone was I felt a lot better about myself. I suppose that's a weird thing to say: Oh he was pretty shit, so I shouldn't feel bad about my poor performance...but that's not the point I want to make really. More that, it is wrong to compare your efforts to learn and grow against the final product of others. Once you sit down with the experienced devs and see how they shape and form the product and all the bumps along the way it doesn't feel so bad to struggle on your own.
Ultimately the skills that I honed that gave me the best boost in confidence were not really the direct programming parts where I put letters and numbers in files. It is the debugging. Understanding how things move and where to look for problems makes me feel like I can solve any problem with the right tools.
I knew I could outwork everyone and brute force being a better programmer by a function of continuous improvement through hours of work. (btw I was wrong, there is always someone out there that will outwork you...and they will be smarter than you, but hey it made sense to me).
I didn't realize I made it until
a) People would recognize me in meetings because of my code
b) New programmers started to ask me for advice
...now I'm in the Sr Devs, Tech Leads, and Lead Architects ask me for advice level. Honestly, I still have the same attitude, if I work effectively, I can keep getting better. Notice that I remove the "work harder" part.
A simple CRUD app is magic to the average user, if it does something they haven’t seen done in software before - and that could be as simple as some calcs in a custom domain.
The first customer who tells you “this is great”, if it’s anything like my experience, changes everything.
It also helped that some of my early forays were to clean up code by a guy ten years my senior which was rammed with bugs - fixing those one by one was satisfying and helped me earn trust with my team and in myself.
There's a nice concept in theater that says, effectively, "if you blow a line, don't broadcast it to the audience." The subtext of that is, simply, the audience doesn't know any better and what they don't know, won't hurt them.
By and large, this applies to many fields, and certainly to software development. The users, in the large, do not care over a huge amount of stuff that we, as practitioners, care about.
We're in a results business. The users care that they get the report they want or can update the data they're supposed to. How that's done, in the back end, is filed under "blah blah blah".
The reason this is important is not as an excuse to do crummy work, or to not be passionate about the minutiae that consumes us, but to be cognizant that as long as the end result is functional and capable for the user, it's OK for the processes that get to that point to be a bit messy. Don't beat yourself up over a lot of the things we beat ourselves up, or criticize others over.
Ship. Get your code in front of users, interact with them to make their experience better. We are in a service industry. Strive to be better, but you only get better by shipping, and moving on.
The confidence is that, for the most part, "it's just software" and you can fix it. You can change it later. You can correct mistakes.
Another saying is that you're not a professional until you've lost production data. Thankfully in our work, loss of production data rarely kills people, in contrast to the path of becoming, say, a doctor. If you are in an industry where people can be hurt, then that's going to be more rigid, for obvious reasons.
I have lost data, I have been SCREAMED at by clients, I have stood under the withering "What has just happened here" glare from management. It happens. Ah, the warm camaraderie of being thrown into a data entry pool to help rekey some of the 6 months of data you destroyed. A cold truth in our business is that it has to happen, as we only learn through practice, and through practice, sometimes we miss.
But to do that, we have to ship. We have to get the work out there, "I don't test often, but when I do, it's in production". Sometimes you just got to open the firewall up, let the traffic in, and see what happens.
A cynical view is the that the more we ship, the more we learn what we can get away with. There's a truth to that as well. We're all victims of not listening to "you're not going to need it". For all sorts of values of "it". But that doesn't mean we can't keep those concepts close, practice them as best as we can (because, truth is, sometimes you do need it!).
Through the work, and shipping, you learn the balance, and get more comfortable with it.