refactor code and add a pile of tests