Module or class?

nio kasgami

VampCat
Veteran
Joined
May 21, 2013
Messages
8,949
Reaction score
3,042
First Language
French
Primarily Uses
RMMV
Hi people

I currently get requested by Vexed Enigma for making a battle system similar to Parasite Eve I

so this more a opinion I ask because  I am the type to  Divide my information in multiple section (EG : Sprite Class handle all the graphics and such) 

but my battle system handle a lot of datas and a lot of them move to a class to a another class

so I wounder if my main Class where all most of the information is handle should be a Module or a Class?

I know Modules are good for making Data information and such but this not  to much fragile for support heavy data?

Class can support as well the heavy data (like algorythm and such) but I found this was hard to swap information and data between each class... (EG: class Custom to Game_Map)

so can I have your opinion if I should use Module or Class ? (for support data who move a lot between each class)

thanks for your further answer!
 

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
5,592
Reaction score
6,522
First Language
Indonesian
Primarily Uses
RMVXA
I would go with class if I want to make new objects and store data dynamically.

I would go with module if I want to make a static / constant configurations

Also, if it's a general function, I would go with the module as well. For example in my grid battle system (which is still in development), I use module to calculate the grid position instead of putting them into the class. The terms is like Math module where you can use Math.cos everywhere.
 

nio kasgami

VampCat
Veteran
Joined
May 21, 2013
Messages
8,949
Reaction score
3,042
First Language
French
Primarily Uses
RMMV
okai sound legit if I show a exemple of one of my module who not change a lot but this permit to handle my datas

I guess this one is a good way of using the module?

Code:
module Dynamic_Character_Pose class << attr_accessor :frame attr_accessor :pose attr_accessor :situation end def self.init @pose = "" @chara = Game_actor.name @frame = 0 @situation = 0  end  def self.define_pose   unless classic_pose  @pose ~= Skill.note "/<@pose>/" endenddef self.classic_pose(pose,frame) case @situation when 0 # no move @pose = @chara.to_s + "_Iddle" when 1 # move   @pose = "" when 2 # dash  @pose = @chara.to_s + "_Dash"  endendend
 
Last edited by a moderator:

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
5,592
Reaction score
6,522
First Language
Indonesian
Primarily Uses
RMVXA
I would go with class instead. I never use module to store data

Mostly I use module to make something like this. To counting grid

Code:
#===============================================================================# TSBS Addon - Grid Battle System (Pre-Alpha)# Version : 0.1#-------------------------------------------------------------------------------# * Configuration part#===============================================================================module Grid  MaxRow = 3  MaxCol = 4    PosDebug = true # Display dummy box for positioning  Party = [    [302,169],[356,169],[414,169],[471,169],    [304,222],[360,222],[422,222],[482,222],    [306,270],[364,270],[430,270],[493,270],  ]    # Troop grid coordinate should be reversed  Troop = [    [244,169],[188,169],[132,169],[ 77,169],    [242,222],[184,222],[126,222],[ 66,222],    [240,270],[180,270],[114,270],[ 55,270],  ]  end#===============================================================================# * Grid Counting Module#===============================================================================class << Grid  #----------------------------------------------------------------------------  # * Grid direction rules  #----------------------------------------------------------------------------  # 2 = DOWNWARD  # 4 = FORWARD  # 6 = BACKWARD  # 8 = UPWARD  #  # 1 = DOWN-LEFT  # 3 = DOWN-RIGHT  # 7 = UP-LEFT  # 9 = UP-RIGHT  #----------------------------------------------------------------------------  # * Get neighbor grid  #----------------------------------------------------------------------------  def neighbor(index, dir)    coordinate = index    coordinate = point(index) unless index.is_a?(Array)    case dir    when 2; coordinate[1] += 1  # DOWN    when 4; coordinate[0] -= 1  # FORWARD    when 6; coordinate[0] += 1  # BACKWARD    when 8; coordinate[1] -= 1  # UP          # Diagonal direction    when 1      coordinate[0] -= 1      coordinate[1] += 1    when 3      coordinate[0] += 1      coordinate[1] += 1    when 7      coordinate[0] -= 1      coordinate[1] -= 1    when 9      coordinate[0] += 1      coordinate[1] -= 1    end    return cell(*coordinate)  end  #-----------------------------------------------------------------------------  # Translate point coordinate [x,y] into Cell Index  # > Column equal as X axis  # > Row equal as Y axis  #-----------------------------------------------------------------------------  def cell(col, row)    return nil if out_of_bound?(row, 0, Grid::MaxRow - 1)    return nil if out_of_bound?(col, 0, Grid::MaxCol - 1)    return (Grid::MaxCol * row) + col  end  #-----------------------------------------------------------------------------  # * Translate cell index into point [x,y]  #-----------------------------------------------------------------------------  def point(index)    return [index % Grid::MaxCol, index / Grid::MaxCol]  end  #-----------------------------------------------------------------------------  # * Simply check if the value is out of bound  #-----------------------------------------------------------------------------  def out_of_bound?(value, min, max)    return value > max || value < min  end  #-----------------------------------------------------------------------------  # * Max Index  #-----------------------------------------------------------------------------  def max_index    Grid::MaxRow * Grid::MaxCol  end  #-----------------------------------------------------------------------------  #                           TARGETING PART!  #-----------------------------------------------------------------------------  # * Surrounding grid  #-----------------------------------------------------------------------------  def surrounding(index, directions = Grid::Movement, compact = true)    result = directions.collect {|dir| neighbor(index, dir)} + [index]    return result.compact.uniq if compact    return result.uniq  end  #-----------------------------------------------------------------------------  # * Spread search. Expand node using BFS iteration  #-----------------------------------------------------------------------------  def spread_search(index,directions = Grid::Movement,limit = 1,compact = true)    i = 0    result = [index]    iteration = [index]    until i == limit      temp_res = []      iteration.each do |it|         cells = surrounding(it, directions, compact)        cells.delete_if {|c| result.include?(c)}        temp_res += cells      end      temp_res.uniq!      iteration = temp_res      result += temp_res      i += 1    end    return result.compact.uniq if compact    return result.uniq  end  #-----------------------------------------------------------------------------  # * Linear repeated search  #-----------------------------------------------------------------------------  def linear_search(index,directions = Grid::Movement,limit = 1,compact = true)    result = []    directions.each do |dir|      result += spread_search(index, [dir], limit, compact)    end    return result.uniq  end  #-----------------------------------------------------------------------------  # * Random grid drop  #-----------------------------------------------------------------------------  def random_grid(index = nil)    return rand(max_index) unless index    result = nil    result = rand(max_index) until result != index    return result  end  #-----------------------------------------------------------------------------  # * Horizontal line  #-----------------------------------------------------------------------------  def horizontal(index, limit = Grid::MaxCol)    linear_search(index, [4,6], limit)  end  #-----------------------------------------------------------------------------  # * Vertical line  #-----------------------------------------------------------------------------  def vertical(index, limit = Grid::MaxRow)    linear_search(index, [2,8], limit)  end  #-----------------------------------------------------------------------------  # * Eight direction spread  #-----------------------------------------------------------------------------  def dir8(index, limit = 1)    spread_search(index, [1,2,3,4,6,7,8,9], limit)  end  #-----------------------------------------------------------------------------  # * Four direction spread  #-----------------------------------------------------------------------------  def dir4(index, limit = 1)    spread_search(index, [2,4,6,8], limit)  end  #-----------------------------------------------------------------------------  # * Cross shaped area  #-----------------------------------------------------------------------------  def cross_shape(index, limit = 1)    linear_search(index, [1,3,7,9], limit)  end  #-----------------------------------------------------------------------------  # * Plus shaped area  #-----------------------------------------------------------------------------  def plus_shape(index, limit = 1)    linear_search(index, [2,4,6,8], limit)  end  #-----------------------------------------------------------------------------  # * All area  #-----------------------------------------------------------------------------  def all_area    Array.new(Grid::MaxRow * Grid::MaxCol) {|i| i}  end  end
 

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,846
First Language
English
I've never really understood the purpose of using a module full of singleton methods but I'm assuming the devs just wanted to make it clear that there should only be one instance of it at any time.


Plus the term "module" just makes it sound different from "class" even though one's just a child of the other.
 
Last edited by a moderator:

tyler.kendrick

Caffeine Addict
Veteran
Joined
Nov 21, 2014
Messages
52
Reaction score
14
First Language
English
Primarily Uses
modules are useful for monkeypatching (adding features to existing objects)

classes are fine if you're creating new objects.

for example:

module Logging def log msgbox(self.inspect) endendThe logger module contains functionality for displaying an alert.  Using this new functionality is where the differences between modules and classes become apparent.

In addition to this module, we are going to create a class to more clearly articulate the disadvantages of each.

class Logger include LoggingendThe Base RPG::Skill class is something we will attempt to augment with the new behavior.

class ::RPG::Skill < ::RPG::UsableItem # Nothing is added yetendThe rpg skill object does not contain the new functionality we want to see in the module, so we will attempt to add it with the two options we have made available.

First, the correct way (using a module to extend behavior):

class ::RPG::Skill include LoggingendThis will allow us to call $data_skills.each { |x| x.log }

The wrong way would be to use a class:

class ::RPG::Skill < LoggerendThis relationship will actually cause an error because RUBY (ergo RGSS) doesn't allow for multiple inheritance relationships.

Because RPG::Skill has already defined an inheritance relationship with RPG::UsableItem, we cannot add another inherited class.

So, use a module if you would like to extend your functionality/data to existing classes.

Otherwise, use a class.

Hopefully this answers your question.
 

Shaz

Veteran
Veteran
Joined
Mar 2, 2012
Messages
40,098
Reaction score
13,704
First Language
English
Primarily Uses
RMMV
Have you looked at the way Ace handles things? A module to handle all the turn/action logic, and classes to handle the scene, graphics, participants, etc.
 

Lemur

Crazed Ruby Hacker
Veteran
Joined
Dec 1, 2014
Messages
106
Reaction score
124
First Language
English
Primarily Uses
That's a really odd way to think about classes and modules.

A class is a container for data, such as a Person, an Item, or a Monster.

A module is a namespace to organize your code, or to mix in as a reusable component.

Think of module namespacing like this: what happens when another script defines a Person? Collisions, and the classes will overwrite each other doing some nasty stuff. You prevent that by namespacing it like so:

module MyScript  class Person    # code here  endend MyScript::person.new
With how many scripts you might end up putting into RPG maker, collisions will make it a very very bad day.

As far as component mixins, think of them as reusable functions. Enumerable is a great read in the Ruby StdLib.

Now then, as far as your code, I'll edit this post with links later:

Commented:

Refactored: 
 

nio kasgami

VampCat
Veteran
Joined
May 21, 2013
Messages
8,949
Reaction score
3,042
First Language
French
Primarily Uses
RMMV
Have you looked at the way Ace handles things? A module to handle all the turn/action logic, and classes to handle the scene, graphics, participants, etc.
haha yes I looked all the structure and for build the current battle system I mostly have to play with class and do a tons of alias

as I know I have to alias Game_Character , Game_Player , Game_System , Game_Temps

so for me module seemed more logics but class seem to works to

@tyle : thanks for the info haha ~ some information you give was unknow for me~

@Lemur : haha thanks for your answer well I primiraly follow Moghunter Logics of how he use Modules 

they are simple to use and just check for schala and is whole "battle" system where he no alias anythings is handle by a whole module called "Schala_Battle" so for me this seemed logics 

BUT 

I see your point module are primarily use for add extra informations and mixing 

and thanks for the further links this will help!

on these words thanks people for answer my question!
 
Last edited by a moderator:

Lemur

Crazed Ruby Hacker
Veteran
Joined
Dec 1, 2014
Messages
106
Reaction score
124
First Language
English
Primarily Uses
haha yes I looked all the structure and for build the current battle system I mostly have to play with class and do a tons of alias

as I know I have to alias Game_Character , Game_Player , Game_System , Game_Temps

so for me module seemed more logics but class seem to works to

@tyle : thanks for the info haha ~ some information you give was unknow for me~

@Lemur : haha thanks for your answer well I primiraly follow Moghunter Logics of how he use Modules 

they are simple to use and just check for schala and is whole "battle" system where he no alias anythings is handle by a whole module called "Schala_Battle" so for me this seemed logics 

BUT 

I see your point module are primarily use for add extra informations and mixing 

and thanks for the further links this will help!

on these words thanks people for answer my question!
I wouldn't use him as an inspiration for good practices. You'd be better off reading actual Ruby code from programmers in the field to be honest. If you really want to get good, read this book: Practical Object Oriented Design in Ruby

Moghunter has a ton of duplication in his code, and a lot of inconsistency of how he implements things. That's the bad part about scripting sometimes, it can make a mess fast without good structure.
 

nio kasgami

VampCat
Veteran
Joined
May 21, 2013
Messages
8,949
Reaction score
3,042
First Language
French
Primarily Uses
RMMV
thanks for your further answer : 3! 

well I know Moghunter is not the perfect exemple but at least he helped me a lot for begin most of time I also Follow Enu coding 

but the book seem interesting I will read it when I get time!  

Sadly read big documentation in English are a little hard for me due the fact I am not a pure English and they don't have a lot of documentation in french :/

Naturally I code  not in a way for make people easy to read my code this far more simply  I code in a way where Myself I can read easily the code I do 

Just this one is a exception because I do this battle system for someone else so I force myself for be readable. I can  show how naturally I would structure my code

EG : 

class Enigmadef initialize# insert normal stuffinitenddef initGraphicsinterpreterpuzzleenddef graphics@graphics = Graphicals.newenddef interpreter@inter = NewInterpreter.newenddef puzzle@puzzle = Puzzle_System.newendendI naturally Spare all my content into multiple class simply because I found more easier for me to update or to structure.
 
Last edited by a moderator:

Lemur

Crazed Ruby Hacker
Veteran
Joined
Dec 1, 2014
Messages
106
Reaction score
124
First Language
English
Primarily Uses
Always assume that someone else will read your code, and that they just so happen to be a psychopathic madman with anger issues that knows your home address.

Do note though in that code you should probably use ||= to cache those, otherwise you get a new object each time (unless that was intended.) You might also read into dependency injection in Ruby, that book I mentioned above does a great job of it.
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

People3_5 and People3_8 added!

so hopefully tomorrow i get to go home from the hospital i've been here for 5 days already and it's driving me mad. I miss my family like crazy but at least I get to use my own toiletries and my own clothes. My mom is coming to visit soon i can't wait to see her cause i miss her the most. :kaojoy:
Couple hours of work. Might use in my game as a secret find or something. Not sure. Fancy though no? :D
Holy stink, where have I been? Well, I started my temporary job this week. So less time to spend on game design... :(
Cartoonier cloud cover that better fits the art style, as well as (slightly) improved blending/fading... fading clouds when there are larger patterns is still somewhat abrupt for some reason.

Forum statistics

Threads
105,868
Messages
1,017,085
Members
137,583
Latest member
write2dgray
Top