refactor and reorganize for easier testing