further refactoring for easier understanding