Home About
Courses Concepts Tools
GitHub

Advice on Simulating Events

Sketch out your ideas beforehand

Whether that's actually sketching out your ideas on pen and paper or writing documentation for the functions you know you'll be writing, it's always best to go into a complex project with your ideas already set down concretely. In the case of a complex event simulation, this is even more relevant due to the inherent complexity of events which depend on previous results and aren't generated as needed independently.

Split your code into small parts

The last thing you (or anyone else on your team) wants to debug is a large monolith of code. It may be marginally faster when getting started to just throw everything into one large function or class, but this will soon become unmanageable and indecipherable.

Example: How not to structure your event handling

if (first-condition) {
  do thing 1;
  do thing 2;
  ...
  do thing n;
} else if (second-condition) {
  do thing 1;
  do thing 2;
  ...
  do thing n;
} else {
  do thing 1;
  do thing 2;
  ...
  do thing n;
}

If you can, try to split the processing of each type of event into its own function, like so:

Example: How to structure your event handling

if (first-condition) {
  updated-state = process-first-event(context);
} else if (second-condition) {
  updated-state = process-second-event(context);
} else {
  updated-state = process-last-event(context);
}

Use functions functionally

As you may have seen in the previous example, each event processing function had an argument context which was passed to it, and each function returned a value that became updated-state. This is a functional style of programming, which limits the amount of side effects that occur each time you call a function. This style of working with events will limit the amount of time you spend trying to figure out exactly when and where the global state of your event simulation was modified, and will save you a lot of time in the long run. (Also, it's cleaner.)

Use objects when necessary

Although object-oriented programming isn't the best option in many situations, it can occasionally be useful in event simulation. The best place to use it is when you would find it convenient to have methods associated with your objects. For example, if you are working with Cellphones, which have an attribute uptime and have the ability to restart (which resets the uptime to 0), it may be beneficial to have the following class structure:


class Cellphone {
  ...
  function restart (self) {
    self.uptime = 0;
  }
}

But say you are working with various ingredients, each of which has a different set of nutritional value attributes. It's unlikely that ingredients will be updating their attributes on their own, so it may be better to use a dictionary or a tuple (or a dataclass) instead. You can use a function instead of a class initializer, which returns that datatype:


function create-ingredient (nutrient-1, nutrient-2, nutrient-3) {
  return {
    "nutrient-1" : nutrient-1,
    "nutrient-2" : nutrient-2,
    "nutrient-3" : nutrient-3
  }
}

There's no reason to make your code all convoluted by defining classes all over the place. But make sure you stay consistent and document your code so that others who are working with the non-object items can know how to access their attributes.