Learning BYOND #11: The Power Of Modular Programming

Though I think of it as being a couple weeks off, this is in mostly counting minor dabbling: the actual amount of time I spent away from hardcore BYOND development is more like a month.  I’ve spent the pretty much the entire weekend (in which I had four days) hammering BYOND, and I think I’ve finally caught up with my lost knowledge.  This, and more.

I’ve picked up and dusted off my old Learning BYOND series for a special installment about the power of modular programming.

What is modular programming?

Modular programming is briefly detailed by Dantom in the Official Manual where, in the chapter just after his discussing User-Defined Data Objects he broaches the fundamental truth behind modular programming:

“Fortunately, most programming tasks do not require exponential complexity. With a good design, you can split the project into pieces which interact with each other in a fairly simple way. These pieces are often called modules which is why this practice is termed modular programming. (It is interesting to note, however, that all such schemes to avoid exponentially complex code ultimately fail. They only move the exponential growth to a higher level–from individual statements to procedures to objects and on and on. It may be true that complexity will always win out in the end and that every project undergoing perpetual growth must periodically be redesigned from scratch in order to remain comprehensible. Or perhaps this tendency is merely the result of a periodic increase in wisdom to offset the inevitable decline in intelligence. In my own case, I know this to be a prominent factor.) (Source)

That mouthful can basically be summarized as this: Since the dawn of programming time, programmers have noticed that their code has a nasty tendency to mutate from an orderly list of things for the computer to do into a horrible jumble of uncomprehensible mishmash.  It’s not always moldy spaghetti code, but it’s still tough enough to turn one’s stomach to deal with.

Modular Programming, which is closely related to Object Oriented Programming, attempts to make things simpler by breaking down code into simple black boxes.   You basically design your code in blocks which accept input what you have and return output what you want so you can never worry about how you got there ever again.

So, how do I use this fabulous programming methodology?

To some extent, BYOND’s object oriented environment makes it natural to use some modular programing.  Many of the basic data types you are provided, such as mobs, turfs, areas, and objects, are (by default) highly modular.

The trouble arises in that we’ll tend to screw this up out of laziness.  I start making these objects run processes that require constant interaction between eachother’s variables, and in doing so, I pretty much glued them together.  They’re no longer modular and separate, but rather attached in such a way that if I try to draw one away, something crashes.

Here’s a tip I found that help to preserve the modularity:

Use Interfaces On The Root Object

“Interfaces” is the term used to describe a procedure within an object that is used to interact with the contents of that object.  It seems harmless enough to directly reference a variable on another object, but then certain conditions manifest where direct manipulation of that variable is a really bad idea, and stuff starts breaking.  Thus, creating an interface on the object that is used for all references to that variable is a good idea.

One example I see this coming up a lot is when I see that I’m type casting something in order to make it work.  I might be doing something like this in order to assign gold to a player.

if (istype(thisMob,/mob/player))
   var/tmp/mob/player/thisPlayer = thisMob
   thisPlayer.gold = 15

A better method is to go into the actual mob object and define something like this:

mob
   proc/AddGold(var/newGold)
   switch (type)
      if (/mob/player)
         // Run whatever checks are necessary to make sure assigning gold
         // is okay.  
         var/tmp/mob/player/thisPlayer = src
         thisPlayer.gold += newGold
      else
         world << "Invalid gold assignment to type [type]"

Now, I don’t even need to worry about if I’m assigning it to the proper kind of object or if the right variables exist on that object or if conditions exist where assigning it to that object is inappropriate. The interface handles that for me.

The real benefit of modular programming is not just in convenience, however. Well-made modular code is able to accomplish a lot more with much less effort. Several-hundred line behemoths are cut down to a fraction of their size, much easier to understand at a glance, and much easier to understand fundamentals to improve. What’s more, modular code is ready to be re-used in later projects.

Don’t worry if modular programming seems far outside of something you can comfortably do. With regular practice through coding, the mind naturally builds the ability to understand the how and why of modular programming. If anything, this entry helps to foster awareness of these practices so you end up doing this sooner rather than later.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: