Question about structuring an OOP game

A little while ago I discovered the power of OOP when used in Roblox games and ever since I’ve been wanting to incorporate it into my games. I have a pretty good understanding of using metatables to create classes, etc. but I still have two major questions about OOP:

  1. How can I structure my game to support inheritance through a master class, similar to Java’s Object class? I’ve seen games have a master class that has methods such as :New(object), :Extend(object) and :IsA(class)
  2. Should I have a separate client sided class structure and if so how should it interact with the server side?

I’d really appreciate some guidance in these regards. Thanks in advance.

Object Orientated Programing is not always the best tool for the job. Don’t get me wrong I’m an OOP nut job, but there are many cases were it is completely unnecessary and it is important not to fall into the belief/trap that OOP is the god send/save all for code organization and efficiency. To use the mention “Object” master class, the :Clone() method and subsequent Cloneable interface is a case study on OOP getting out of hand. Programmers talking to Java Engineers: You played yourself.

Now onto your actual questions

  1. Code example


local SubClass = {};

local SuperClass = require(game.ReplicatedStorage.Object); --Superclass object


SubClass.__index = SubClass; ---OOP indexing for lua


function SubClass.New()-- Instantiation method
	local SuperClass = SuperClass.New();--java equivolant of calling super()/ instantiating the superclass;
	local self = setmetatable(SuperClass,SubClass); --This is the line of code that inherects from the superclass 

	return self;
end



As for the IsA method, the easiest/quick and dirty way would be to implement a stack structure and every time a class is instantiated it adds the String name of itself to the top of the stack. Then for the IsA method simply have a loop iterate through the stack checking if the parent exists in the stack.

  1. OOP is an organizational tool more than anything else, the rules don’t change at all. So say you’re still gun-hoe to make everything from a single superclass. Plz don’t but fine… whatever Lets say you are making a custom tool object, you’d have to expose all the parent classes running all the way back to your original Object. Not to difficult if you stay organized as you go along. Just as long as you are hiding the server logic you will be fine.
3 Likes

So if you think I shouldn’t have a single superclass what should I do? And I don’t really understand your answer for the second question. For example if I have a gun class how would that interact with the client? Should that class only exist on the server?

According to the OOP bible, everything is an object. Being surprised that there is a good way besides having a single super class tells me you’ve drunk the OOP koolaid. You can have multiple objects, and they can be independent of each other. If there isn’t a functional reason to force everything to inheirate from a single ancestor, then I recommend not doing it.

More than that, inheritance is one of the questionable features of OOP. The diamond inheritance problem is an example of the issues it causes. A better (think: higher, holier) way would be to break functionality into functions. Functions are one of the oldest features of structured programming, have lived through the ages, are proven to be turing complete (see Lambda Calculus), and will almost always neatly break your logic into parts that can be easily composed together.

PS if you want to continue down this route, I have a good read / watch for you: https://devforum.roblox.com/t/why-oop-is-bad-video/281506

1 Like

Who hurt you? In all seriousness though, the diamond problem is a result of inheriting from multiple classes simultaneously, how could it occur in this context?

OOP hurt me. It lied to me. It promised code reusability, extensibility, clarity. And fails. Behold, the great truth:


From:

Also a good read:

http://www.smashcompany.com/technology/object-oriented-programming-is-an-expensive-disaster-which-must-end

3 Likes

So following a strict adherence to the OOP bible Which again can’t reccomend enough not doing. Like I said the rules are the same is just the structuring is difference. So make a gun is two parts, client interaction and server verification/replication. So the client object would be responsible for all things a gun client would normally be, cross hairs, ammo counter, reloading animations, ext. The server object would be something along the lines of “WeaponHandler” that would replicated bullets/hit detection and whatnot.

Same jobs just a different structure.

This is what you do

  1. make your game work in one single script ignoring server client mumbo jumbo.

  2. Then every time a block of code is used over and over, make a function out of it.
    – pretty straight forward i think.

  3. If that block of code is used solely on a single scheme of data then make a class for it.
    – using a module script as a metatable can let you inject functions into your tables easy peasy

  4. If it is a single data set you can make a singleton
    – think meta data, large picture stuff about the server, constants, stuff that might be referenced in several places

  5. If it is a data structure that will have multiple unique instances, standard object constructor format.
    – I like to do it if I am going to have a table to keep track of a list of tables that are pretty much the same info type.

Lua

  • Everything is a table, whether you make the table an object or not, its still a table. And the code for mutating/accessing will be sitting somewhere, may as well combine them.
  • You can add functionality to data with metatables (class stuff)
  • If that functionality is only used on that kind of table, you gain nothing by avoiding the intuitiveness of an object.

Trying to make everything a class or worse drinking the evo koolaid and thinking everything in life can be viewed as a sensible derivative is a complete waste of time.
Trying to avoid standardizing data structures is silly if they will all share the same functionality. On the rare occasion you have a legitimate subset of a group of objects you can consider inheritance.

TL;DR Don’t structure anything as OOP, if you are coding an object (collection of data that does specific things) use Object techniques, else just program. One extreme or the other are both extremes and will likely waste time as you try to fit your task into their paradigm.
Everything is a tool, some more efficient or prettier than others, but at the end of the day, just need it to work.

5 Likes

Can even the new members even read it? Otherwise, here’s the video:

Yea- I watched most of it already. I’ve been using OOP for a long time in Java and I think I’m going to stick with it.