refactor to make more subclassable