Background:
So I'm trying to create my first game engine for learning purposes. After looking up a few articles I was able to design the beginning portions of my engine to at least get me going. My design so far involves have my own "Framework" layer for which all other, higher level subsystems (graphics, input, audio, etc.) will use. This will help with code portability as well as give me the ability to change my underlying implementation code without having to change my entire code base (only my framework code). This structure has provided enough of a mental framework to get me going. However, after coding a few things and getting a triangle up on screen and moving via keyboard input I'm finding it difficult to decide how to structure my different subsystems (graphics, input, audio, etc.) further. I want to have a design in place to allow for communication between subsystems with as little coupling between systems as possible.
Issue:
My main issue is that I'm finding it difficult to architect my engine further since I don't really know where I need to go next. I would imagine this is a typical issue for any developer who is developing something new or unfamiliar. For example, I don't really know what kinds of functions I'm going to need or who will use those functions for my graphics system. Will individual objects be responsible for drawing themselves? Does the Window handle drawing graphics? With previous experience, I would have a better idea of these things and I could design my software accordingly but at this point I have none.
My Question:
My question is what are some thought processes or development practices that help you try and architect code for which you are unsure of where you need to go next? I understand this can be a big topic so I'm just looking more for quick tips to get me thinking about different possible techniques. I already have a few ideas below but wanted to get more thoughts from the community as well.
My Thoughts on Some Possible Solutions:
Draw some diagrams to get an idea of how things will hash out: After coming up with a design idea draw a few class diagrams with their interactions mapped out. These diagrams could help you spot possible limitations in your design idea quickly and without any code. However, you might need to create a lot of diagrams before limitations with you idea become apparent
Just begin experimenting with your idea in your code: With a versioning system you can just branch your code base and start experimenting with your idea. This will help give you immediate feedback with the limitations in your design as any code duplication or compilation issues will be immediately apparent after implementing. However, this will require more time and can be harder to see the bigger picture and ramifications of your design approach.
Fallback to established design patterns: Just figure out the main problems your system needs to solve and apply a corresponding design pattern to fix it. There are plenty of tried and tested design patterns that have helped solve issues for decades. You can just default to these patterns when you don't really know where to go and have them drive your design forward. Issues here are that there are so many different patterns out there for different problems that it can be hard to decide exactly which one will best solve your problem. Also, defaulting to a design pattern could drive your system architecture in a direction you don't particular want to go, but won't notice it until later on in the process.
Any other thoughts??????