refactored to support testing