You are lucky enough to be experiencing what it’s like to be part of a real software project. It is not at all unusual to be in this position for weeks or even months depending on the complexity of the code base.
If you somehow manage to continue until graduation, you will have invaluable experience that virtually no other job candidates at your level will have. It will be a massive advantage over your competitors, and when you are asked about your experience you’ll have specific and credible stories to draw on when you talk about how you solved problems.
At the very least, congratulations on sticking to this for as long as you have. This stuff is hard. That’s why they pay us a lot of money for it.
Either you have misunderstood the meaning of "abstraction", or the code base has what people call "leaky" abstractions.
The point of abstraction is to create stable internal APIs, irrespective of implementation details. The entire point of abstraction is to create the separation that your code base seems to be lacking.
> No matter how much documentation and how much code I read I come no closer to making any changes in the codebase whatsoever
This approach is necessary, but you won't really understand the code until you start debugging. Can you tell us more about the stack (and, ideally, the project itself) so that we can give you better tips? Sometimes understanding code is a lot easier with the right tools (IDE, debugger, etc.)
> I am starting to wonder if I have what it takes to become a programmer
I'm sure you can do it, but it's also important to figure out if you want to. If you work on multiple code bases, including your own, and you don't enjoy it, or the frustration you're feeling now is not healthy for you, then this might not be the right career for you.
A lot of being a programmer is banging your head against a wall for many hours longer than a typical person would be willing to, until you finally get past an obstacle. Sometimes the obstacle is bad documentation, often it's bad configuration, other times it's a bug.
If the fun parts are not worth the not-fun parts for you, then that sounds like an unpleasant career path.
This is a virtue and a fault. After some successes and some failures, you are likely to learn to be more wise when choosing which problem to deep dive into. The wrong deep dive will damage you.
It also takes time to learn that cowboy duct-tape solutions are sometimes correct: this is best learnt by being in a team with someone who is productive in that manner (the downsides of it are obvious to engineer types; learning the positives of hacks is harder for engineers; judging when to apply fast solutions needs a good engineer). If you can only do anal retentive engineering, then your skills are still super valuable, but perhaps try to veer towards projects where beauty and correctness are valued.
For many engineers, I think it is worthwhile to learn the dark side: how to deliver a quick and dirty compromise that meets a need e.g. most web development. I personally find this difficult: google “yak shaving”. Some engineers never learn how to make good compromises, and they sometimes end up stuck in a dead end.
“but yeah... Just get the impression I'm not smart enough for this.“
Keep your humility, use it to connect with clients and users. They feel it 10x.
Finally I’ll add that the best developers I’ve ever worked with have been technically mediocre. Their other skills have made them great - abilities to concentrate on the right things and not worry about being technical goddesses or gods. I have worked with technically great people, that just do a shit job because they can’t get on with others or they produce something that only they can understand.
Do `git show COMMIT_HASH` for the first ones and you'll see the genesis.
You're looking at the result of thousands of commits, each one having required countless hours of thinking and coding. This can be overwhelming.
Here[0] are some tips that help getting to know a codebase. Some may be irrelevant.
A concrete suggestion that came to mind is isolate the simplest unit of functionality the project implements and try to implement it yourself fromsscratch using the existing code as a reference; stripping out all the error handling, edge cases etc.
The feasibility of this depends on the project but it can be a useful way to understand both the basics and the rest of the code that seems like spaghetti which is probably due to error handling, edge cases, etc. As an example I implemented part (a simple passwordless connection and select statement) of a database connection library from scratch in c# and it really helped me understand the existing solution better.
Working on someone else's codebase—especially if it's an open source project with many different contributors over a long period of time—is its own distinct thing that has to be learned. Everyone has to learn how to do it, regardless of where their abilities as a programmer are. If you are adept (as it sounds like you are) at building your own software, then it can feel like the rug has been pulled out from under you ("Am I actually any good at this?") when you try to contribute and simply can't grok what's going on, but if you persist, you will pick it up. Don't take your struggles now as a reflection of your abilities.
Keep expanding your knowledge.
Read the new pragmatic programmer.
It took me about 5 years to get over my imposter syndrome.
Dont get hung up over one project. I have written a lot of bad code and a lot of clever code. Both in the same project.
Being a good dev is a lot like being a good doctor. Study and practice, sometimes you will get it right, sometimes you won't.
Embrace it. School is designed to give you set pieces that can be understood in isolation, the outside world rairly has that luxury. You won't truly improve without discomfort, though the particulars will be personal and multidimensional.
The end skill is solving problems in the wider world.
tldr; don't give up.