That being said, game development, and really realtime application development in general, is an exercise in highly constrained and complex interactions between many systems. This means that if you fail to focus your efforts, fail to really address the needs of the application or game you're building, you'll be spending what could easily turn into an eternity developing and refactoring those systems.
As an example, take the case of a steering/locomotion pipeline. The idea of making a robust system that can handle any type of terrain and blend all kinds of different steering and decision making sounds great and that's exactly what you'll set out to do if you're not trying to develop a system for a particular type of steering. Similarly, event systems are things that can easily lure you into providing for every use and edge case.
This is not to say that all of your code should be written in a way that can only be used in a specific case, far from it. Merely that instead of building in the substantial amount of infrastructure necessary to facilitate generic handling of lots of different cases/environments, your goal becomes building chunks of code that handle various tasks. Then, when you need them, you put them in the project you're working on, tweaking as necessary. This might seem wrong, and certainly I'm sure that many people would disagree with me, but I think that this is the sweet spot if you're developing a game. You start there, at that finely detailed and narrow scope, and move out as necessary... not the other way around.
As an exercise, think of any GUI system you have ever seen or worked with. There's a reason that they're often brutal to work with and perform poorly. They were made to address abstract ideas like "A button" in any way which you might make something function as a button. Sometimes, however, you just need a button and don't want to make a style object to pass to the GUILibraryButtonFactoryHandler and then register that with the GUILibrarySceneMaster singleton... sometimes there isn't a single point in your whole project where you need anything other than a simple button...
Workflow, also, can help you incrementally approach the correct scope for the problem you're trying to solve. If you give yourself some building blocks to get in place, which helps for bootstrapping in general, you can test at those intervals. A lot of happy surprises come out of those moments. You realize that you don't actually need a finer level of path finding, you realize that you don't need to write an IK system, that you don't need about half of the features of a full blown behavior tree setup, that the stock shader is fine, that you over thought the implementation and were just about to waste many precious hours.
P.S. I had promised myself to include more pictures, diagrams, and code in these posts... you can see how well that's going.