I usually always pay a lot of attention to writing clean code. I find a solution to a problem in 5 minutes, then I spend 2 hours trying to figure out how to write this solution within certain standards that are compatible with the project architecture. For example, if I spent 1 year making a game, 11 months of it goes to keeping the code clean, 1 month goes to the actual game.
I am currently making a game without paying attention to the code and I am so fast that I can’t believe it. I finished the game in 4 days, which would normally take me 3 months to write clean code.
Let me tell you what I mean by clean code to make the subject clearer
No two-way dependency
High level modules should not be directly connected to low levels
A good separation of concerns
Isolated independent systems
DRY etc.
Good control in script communation
I am not including general things like good naming, correct access modifier usage etc. because they are not time-consuming and really useful.
I started to think that trying to comply with these causes more loss of time than gain. Of course, I am not talking about completely abandoning and writing random code, if they will be clearly beneficial, they should be implemented, but I started to think that putting in extra effort just to comply is unnecessary.
What do you think about this? I have also heard in some YouTube videos lately that this is oop’s fault. It is very difficult to keep the code clean due to its structure.
I am thinking of starting ecs just for this reason, I heard that it makes you write clean code without wasting much time due to its structure. No matter what you do, there is a certain separation of concerns because entity/component/system
I mean you should write ‘clean code’ if it will save you time in the future. Such as a heavily used system, or a core API used in the project.
But for anything on the fringes, just get it working and move on. If the needs change, your can refactor it. The more you code the easier it is to anticipate your future requirements as well.
We code to solve problems. If you’re writing code that isn’t solving any problems, why are writing it?
Its like everything. You can spend time and money (in essence) now on the hope its done and dusted or pay for it later if it bites you in the butt.
I would also argue there is a scale of dirty to clean its not so binary. Ranging from “shoot me if someone ever knew i wrote that” to “this should be on the church wall as sacred”
I very much fall into the camp of get functional first.
if you spend 11 moths from 12 to make the code “pretty” I think you are obviously wasting your time
as always there are exceptions when you could spend 90% of the entire codding process to make sure the code is perfect like when you write code to control the engines fuel flow for a space rocket that send people to the space station.
but for a game that takes a few days to make as you said? just make 24 games in a year instead of one. and if the user reports a bug then make 20 games a year and spend one month patching the eventual bugs.
I guess you are working alone. Then who cares how perfect the code works if the game runs and plays. You could start writing some books about optimizing codes and you can create one of those youtube channels where they “develop” a game for years that they never complete but keep posting work in progress and live streams because I think you enjoy more writing code that creating games. just saying
I am a firm proponent of being of a hybrid mindset – like spiney said, fringes can and should be slightly chaotic – I always say here in the forums that it’s important to endorse a mentality of letting some places be unorderly or messy.
Why would that be important? For moving along at a steady pace and keeping the enthusiasm high, of course, which is the only attitude that will meet the project’s end.
However, it is equally important not to be messy when it’s neither the time nor place – allow me to call this principle the separation of messiness
As an added bonus, after learning how to keep it steady between the two extremes, you’ll likely become a fun person because this is also about being capable of handling life the way it always turns out to be: pretty much unaffected by our pathetic desires to keep everything in check and accounted for.
In my opinion trying to program everything strictly in accordance to principles like the dependency inversion principle isn’t a worthy goal when it comes to game development. If you put an interface between everything - even when it’s not being used for anything - it ends up hurting performance, readability, modifiability and debuggability, for probably no gain.
If you are building a library, then being able to unit test absolutely everything becomes considerably more valuable, and in that context maybe it can be worth it to use dependency inversion everywhere by default. But even then, I personally prefer just injecting the real objects instead of mocking them, when it’s easy enough to do so, and only add an interface if and when it’s really needed.
The way I approach balancing speed of development with avoiding accruing too much technical debt, is to focus almost all of my efforts into just creating good abstractions. As long as the public APIs of objects are easy-to-use and flexible enough, I think that has the largest effect on keeping the overall complexity of the project in check. Whether or not the implementation details of an API are following SOLID principles or not doesn’t matter in the slightest to all the many client objects that make use of that API. And I find it very rare that a single class in isolation becomes so large and complicated, that maintaining it becomes a major pain point during development.
Another strategy that can help avoid wasting excessive amounts of time fighting perceived technical debt, is to not invest considerable amounts of time into refactoring something, until after it has actually become a major pain point during development. Even if something is clearly implemented in a very suboptimal way, one can just add a TODO-comment like // TODO: This class has too many responsibilities. These members should be extracted into a separate class., and then move on to other things. You’ll probably find out that the refactoring ideas in something like 95% of those comments never end up getting implemented, because they’re just not providing much value in practice. And this is great, because it means that you can save 95% of all that time, and invest it into something else, like adding more features into your game, polishing it more, or releasing it earlier.