split functionality into modules to make it easier to test