refactor, add docs, write tests