Resource icon

How to: User-friendly code and Plug & Play

I myself absolutely suck(ed) at making scripts Plug and Play/user-friendly, and making it easy for people to implement a script/resource of mine. A perfect example of that is my old generation 7 project.

I saw someone suggest a tutorial on how best to make Plug and Play scripts, so let's get started.


Plug and Play


1.) Classes can be overwritten and added to from elsewhere.
Let's say you want to add an attr_accessor to the PokeBattle_Trainer class ($Trainer is an instance of that). What you could do is to tell people to locate the script section the class is in and add it there. That's not at all efficient, however. You can "open" the class in a different section and simply add the attr_accessor in there. In this example, we want to add an attr_accessor :quests to our PokeBattle_Trainer class. Our original class is in a conveniently named section called "PokeBattle_Trainer". We'll make a new section and write the following:
Code:
class PokeBattle_Trainer
  attr_accessor :quests
end
This will simply add the getter/setter to the class without removing anything. If the accessor already exists in the class, it will be overwritten. If not, it will simply be added.

2.) Aliasing
Ruby has a very convenient keyword called alias. It allows you to rename methods during runtime without actually changing the code you write. The method can still be called, but you'll have to call whatever you renamed the method to. An alias follow one, basic format:
Code:
alias new_name old_name
old_name is the method you want to rename, and new_name is the name the method will get.

Aliasing is often used when you need to add code at the start or end of the method. You can alias methods in the main scope (not in a class or module), but you can also alias methods in a class (most common), and even in a module (less common and a bit harder). Here's an example of how to alias a method in the main scope:
Code:
def my_method      # This is our method
  p "Hello world!"     # It prints "Hello world!"
end

my_method      # We call our method above

alias old_my_method my_method  # We rename our method above to old_my_method
def my_method      # We overwrite our method
  p "I have been aliased!"   # We do something different
  old_my_method      # We run our initial method
end

my_method      # We call our aliased method
It works pretty much the exact same way for classes:
Code:
class Test               # Initializing a new class
  def my_method            # Creating a new method
    p "This is the first method!"
  end
end

myTestClass = Test.new          # Creating an instance of our class
myTestClass.my_method          # Calling the method we just created

class Test                # Opening the class back up
  alias my_old_method my_method    # Renaming our method to my_old_method
  def my_method            # Overwriting our method
    p "This is the overwritten method!"
    my_old_method            # Calling our old method
  end
end

myTestClass.my_method          # Calling our method again
We'll now do the exact same, but for a module:
Code:
module Test               # Initializing a new class
  def self.my_method          # Creating a new method
    p "This is the first method!"
  end
end

Test.my_method              # Calling the method we just created

module Test              # Opening the module back up
  class << Test            # Aliasing inside modules happens here
    alias my_old_method my_method    # Renaming our method to my_old_method
  end

  def self.my_method          # Overwriting our method
    p "This is the overwritten method!"
    my_old_method            # Calling our old method
  end
end

Test.my_method              # Calling our method again
As you can see, we can't just alias in the main module itself. We have to do class << ClassName and do the aliasing in there.


As you can only add code above or below by using alias, you may sometimes want to copy some code from the original method. Don't go too overboard with this though, as the user can have changed the method (which would overwrite their changes)!


3.) New methods and classes don't always need to be in one specific section.
This is dead obvious, yet I failed at this myself at one point. If you add a new method that is related to the content in one section, it does not need to be in that section. For example, I made a new method for drawing text at one point and told users to put it in a section called "Messages". This is only adding to confusion, as putting it in there is not even necessary. My resource would be the only one making use of the method, so it could just go inside the script of my resource. That's something you should think about.


User-friendliness


Constants and instance variables in one place.
Let's say you're making a resource. It's a good habit to work with constants at the top of your class, or instance variables (@variable) at the top of whatever method initializes the class/sets up the module.

Some examples of things you may want to make constants or instance variables:
  • Coordinates for sprites or other important things
  • Text color
  • Sound effect names/volumes
  • Paths to files
  • If you have moving elements (for transitions), move speed
  • If you have animating sprites, how often they animate (e.g. every X frames)
Those are just some examples; if you deem something important or neat, consider making it easily changeable.
Here's an example:
Code:
class MyUI
  SPRITE_PATH = "Graphics/Pictures/my_graphic"
  SPRITE_X = 255
  SPRITE_Y = 0

  def initialize
    @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
    @sprite = Sprite.new
    @sprite.bitmap = BitmapCache.load_bitmap(SPRITE_PATH)
    @sprite.x = SPRITE_X
    @sprite.y = SPRITE_Y
  end
end


COMMENT your code
You'll have likely heard it hundreds of times and chances are, you've got a great argument against doing so, too. Think from the perspective of who will be using your resource or else, though. Often times, people will want to do minor or major adjustments. By commenting here and there, you can be a big help to those people (which is what your aim is anyway when you're making a public resource, right?)
Of course, commenting every line or every few lines is ridiculous. It would be a good practice to comment method calls that do important things that people might want to change (messages, positions of certain sprites/elements). Aside from the method calls, consider commenting what arguments your methods take. A big complaint which I myself have myself with some methods in Essentials is the lack of "documentation" on a method. For example, if a method has (*args) and you actively use that in the method (args[0], args[1], args[2], etc.), the user has no way of knowing what everything stands for. That's all the more reason to want to document that, as it would really annoy people.


Of course, I speak as a relatively new programmer, and these are just some things I've encountered or found to work.
Likes: chikorita
Author
Marin
First release
Last update
Rating
0.00 star(s) 0 ratings

More resources from Marin

Top