code modified a bit for better decoupling