((EDIT: Damned editor is eating large portions of my post when I embed citations. So here we go without…))
You can ask ;) but any and all answers you get will not unburden you to make your own decisions and learn from what goes well and what goes wrong. There is no single right way. This is because a game is inherently complex. FWIW, I usually follow these guidelines:
1. Solve problems the top-down way; consider how the problem is embedded in the entirety; divide a problem recursively until getting eatable pieces.
2. A unit of software should have 1 concern or should be responsible for 1 thing (how blurry that concern ever is ;) ); if it had more than 1, then bullet point 1 isn't went along far enough.
3. Bullet points 1 and 2 leads naturally to the use of interacting sub-systems; build this as hierarchy; higher level system use lower level systems and work together with same level systems; lower level systems should not use higher level systems; a system should not use another directly that is more than 1 level below.
4. Use the data-driven approach where appropriate.
5. When OOP-ing, do use inheritance where appropriate but prefer composition over inheritance.
Examples:
The game loop rules the coarse order in which things happen. You've seen in the "Game Engine Architecture" book (that of Jason Gregory, right?) that a specific order of animation steps on the level of the game loop helps to solve problems of dependencies. This is also true for other sub-systems. Blindly removing a game object without the
knowledge whether another sub-system is still working with it would be disastrous. Also not good would be to instantiate a new game object at a point in time where AI, animation, or collision detection already have been done. Hence having a defined point in the game loop, e.g. just after input gathering, where all game object addition and removal w.r.t. the scene happens, means that game objects do neither pop up nor disappear at the wrong moment. (So we have considered the environment in which spawning and removal happens, and have seen that it is beneficial to make it synchronously.) Well, such deferred addition and removal requires that (a) we use a kind of job object and (b) we have a sub-system where the jobs can be send to. Here the scene management comes into play. Because the concern of the scene management is to manage all game objects that live in the scene, it is the sub-system that can process said jobs. Furthermore, it shows that the scene management has an own point of time for updating within the game loop.
Now that we have introduced the scene management, should we put the scene graph into it? The scene graph has the purpose of propagating properties. This is a different concern than the existence of game objects, so no, it should not be part of the scene management as defined above. A scene graph is another structure used for another purpose. Similarly, say, an octree used for collision detection is an own structure, as well as a render job queue is, and so on. What structure does a scene manager then needs? It depends on the API. Until now we have said that game objects should be added and removed. We can use a handle concept and IDs for naming game objects, then 2 arrays would be sufficient to hold the indirections and the game objects themselves. This would also be sufficient to serve game object retrieval requests.
Resource management is another good example, because it occurs so often. What is the concern of resource management? The supply of resources for the game. Fact is that resource live persistently on a mass storage, what means that we are working with 2 copies of resources (the other one in RAM). Well, 2 copies are enough; we don't want more. The resource management should hide all these details. So, since we have used a bit fuzzy description of the concern of resource management, we identified 2 tasks belonging to it: resource caching and resource loading. Since these are 2 lower level concerns of resource management, we should implement resource management separated as a front-end that defines the API for clients, and a back-end by 2 delegate objects, one for caching and one for loading. The front-end manager then uses the back-end objects to fulfill the API. This can be done further down, e.g. the loader may use a file format wrapper to do the actual loading).
Well, all the above is somewhat general; it gives no explicit answers to your questions. Feel free to ask more questions, but remember that specific answers need specific questions.