Object Oriented Design

JavaObject OrientedReflection

Saturday, March 16, 2024

Hi there, as I was going through my old projects, I found many from my university days. This is one of them, my first encounter with game development and the idea of "Object-Oriented Design".

Feel free to check out the project here.

This project introduces me to SOLID principles and understand the importance of design in a project's scalability and flexibility. Today, I will write a reflection on my learning outcomes and evaluate what can be improved with the experience I gained over the years.

Design Overview

The assignment was structured in 3 parts, each with requirements simulating a client's request for improvements and scalability. This structure reflects a real-life project development, where client needs evolve and software must adapt.

There are a few constraints as well:

  • The inability to modify the given game engine
  • Avoid extensive reliance on downcasting
  • Adherence to SOLID principles must be fully justified with a design rationale.

Throughout this project, I've embraced the principles of abstraction, inheritance, and polymorphism, applying them to meet the project's constraints. By leveraging Object-Oriented Programming (OOP) techniques such as inheritance and interfaces, I succeeded in augmenting the game's functionality without modifying the engine code.

Abstraction was useful, helping me structure the game more cohesively, which, in turn, simplified maintenance and enhanced scalability. The strategic use of UML Class and Sequence diagrams proved invaluable, allowing me to visualize my design decisions and confirm the robustness of our architecture.

Challenges with Constraints

Faced with the constraints of not modifying the game engine and minimizing downcasting, I initially questioned their necessity. These limitations seemed, at first, to be mere obstacles rather than learning opportunities.

However, with more exposure to good code practices, I began to appreciate the significance of these constraints. It became clear that these constraints closely mirrored industry scenarios, teaching us the importance of adaptability and clean coding practices.

  1. In the industry when working with engines like Unity or Unreal, we cannot simply modify the engine code directly.
  2. Overuse of downcasting has a couple of downsides to it:
  • It breaks the concept of abstraction, which is one of the core principles of OOP, leading to a violation of encapsulation.
  • It introduces more error-prone code since it requires explicit type checks, making it susceptible to errors such as 'ClassCastException'.
  • Overall, this approach results in a design fraught with flaws, limiting its flexibility to scale and making it harder to maintain.

Reflecting on Design Rationale

Reflecting on the game design now, with the depth of experience I've gained from working on industrial-grade solutions and my understanding of Object-Oriented Programming (OOP) over the years, Despite having earned a High Distinction for it at the time, I now recognize there were opportunities for improvement that were not apparent to me then.

Here is the final UML Class Diagram for our game, collaboratively designed by my partner and me as a team of two. In this diagram, the classes highlighted in red represent new additions to meet project requirements. Conversely, the classes in white were provided as part of the game engine's original code.

Feel free to refer to a clearer version here.

Based on the diagram, our handling of the 'Zombie' feature suggests areas where our initial design approach could have been rigid. Notably, the introduction of 'Mambo Marie' in the project's final phase shows a significant oversight in our design's flexibility.

In our design, 'Mambo Marie' was segregated into a different package, separate from Zombie which is also a hostile entity, due to her late addition to the game requirements and the class diagram is provided here:

This separation revealed a flaw in our design: the lack of flexibility to accommodate new enemy types or hostile actors. A more robust design would have anticipated the need for scalability in the game's narrative and mechanics, allowing for easier integration of new elements without substantial restructuring.

And this is just one of my few observations... As we can see from the diagram, it is quite a mess.

What's Next?

Reflecting on this, it's clear that what was once considered a fine design may still have much room for improvement. The contrast between the starting design and subsequent iterations illustrates how foundational experiences can inform and enrich our understanding of more complex concepts. This encourages me to create more game projects in the future, hopefully with better design decisions.

I have uploaded all the different iterations of the project, even the design documents in Github, from A1-A3. You may refer to them if needed.

Thanks for reading my reflections! Feel free to reach out to me via email to connect or give me some feedback :)