refactor + tests