rewritten from imperative to object-oriented