refactor and tests