You lost me at this sentence:
The problem is that I have not finished even the main functionality of my program, so I cannot truly refactor, and I feel discouraged to go on perfectly aware that my code's design is flawed.
I believe in the principle (stated in Systemantics) that
- A complex system that works is invariably found to have evolved from a simple system that works.
- A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over, beginning with a working simple system.
So, writing a complex system includes
- Writing a simple system
- Making sure it works
... i.e. the following steps:
- Write a bit of code
- Test it to make sure it works
- Write a bit more code
- Test again
- Etc.
Note that step 3 might involve:
- Write a bit more code
- Refactor existing code to prepare it for new addition
- Test the refactoring to ensure it still works
- Add the new functionality
Also, Step 2 "Test it to make sure it works" might involve some rewriting if it doesn't.
If I were building on a rotten code-base I'd be disinclined to add further functionality. So I'd be inclined to schedule something like "simplify the existing threading implementation" as the next piece-of-work to be implemented. Assuming that you have been testing as you go along, you ought to be able to treat this as a refactoring exercise. The success/exit criteria for this work-phase would be:
- Source code is simpler
- And no new bugs introduced
- (And some old bugs eliminated)
Incidentally, "testing it to make sure it works" doesn't necessarily mean "unit tests" -- when the team structure is simple, you can test a (simple) system using (simple) system tests (instead unit tests)(simple) system tests (instead unit tests).