refactoring and add tests