refactor with metaprogramming