Add tests and refactor many things