ID:1846521
 
I'm just wondering what tips and tricks everyone has that they use to make their code more easily testable.

Here's my approach.
I use divide my systems into folders, and subsystems into .dm files. I then define at the top of each DM a variable like var/DEBUG_FLOORS which I then disperse throughout that code file with world.log outputs, to let me test the system to make sure the right calls are happening at the right time.

var/DEBUG_BUILDING = FALSE

/*
...
*/


building

var contents[]

New()
contents = new

proc/Add(atom/movable/am)
if(DEBUG_FLOORS) world.log << "DEBUG BUILDING: 3a; building.Add([am])"
am.building = src
contents.Add(am)


proc/Remove(atom/movable/am)
if(DEBUG_FLOORS) world.log << "DEBUG BUILDING: 3b; building.Remove([am])"
contents.Remove(am)
am.building = null

proc/Merge(building/b)
if(DEBUG_FLOORS) world.log << "DEBUG BUILDING: 3c; building.Merge([b])"
for(var/atom/movable/a in b.contents)
b.Remove(a)
Add(a)

b.contents = contents
del b



Aside from that, unless I'm releasing something to be downloaded or hosted from a hub, I always have debug defined.

What does everyone else do to make debugging and testing easier for themselves, or what have they seen other do? I'd love to hear it.
Instead of using variables, you could use preprocessor macros and achieve the same thing:

#define DEBUG_BUILDING

building
// ...
proc/Add(atom/movable/am)
#ifdef DEBUG_BUILDING
// This block only executes if DEBUG_BUILDING is defined.
world.log << "DEBUG BUILDING: etc"
#endif
am.building = src
conents.Add(m)

// ...

This works for any preprocessor:

#define DEBUG

mob/Login()
..()
#ifdef DEBUG
world << "Running in debug mode."
#else
world << "Running in release mode."
#endif
I know, but preprocessors work from the top down, so if I defined the macro below a hook into a subsystem that was referencing it, DM would shit on me.

I have a few old projects I did that with, eventually I found that I had to pop the macros into a _debug_defines.dm to make sure they were always above where they were being used.

I do like how they let me warn myself if they're on though...
In response to F0lak
Ah, right. Another way of getting around that (aside from having a file with a name that precedes the other files) is to simply include the macros at the top of your file (similar to how C and C++ handle headers):

// debug.dm
#define DEBUG_WHATEVER

// action.dm
#include "debug.dm"

#ifdef DEBUG_WHATEVER
#warn Debug whatever mode.
#else
#warn Release mode.
#endif
I might be misunderstanding, but would that let me work with the macro outside the file (above the #define)? I've never worked with C or C++, only DM, so I don't really know what headers are. :3
Oh, cool. I just always assumed to never touch the .dme. What are header guards?
So if I'm correct a simple
#ifdef DEBUG_FLOORS
world.log << message
#endif


would be all that's needed. That's what I used to do before, with the define stuff in another file at the top of my files
I usually just throw the defines I need in a particular sub-system into a file called "_defines.dm" in the folder with said sub-system. It'll always be at the top.
Do you work using DM at all?
Ah... i see. Different views are different views i guess. Either way that would seem interesting if such support through an extension could end up being available sometime in the future, but that is just talk at this point in time though :P.