Делите ТЗ на модули, определяете их внешние интерфейсы (то, что одни модули могут запрашивать у других), стараетесь их минимизировать.
Например, модуль авторизации и аутентификации - это много всего внутри, но снаружи - только общие данные юзера (для вывода) и возможность узнать, авторизован он или нет. Если реализованы права пользователей - то прочим модулям совершенно не нужно знать, как именно (например, принадлежит ли пользователь к какой-то группе). Им нужно узнать, есть ли у него конкретный уровень доступа к конкретному модулю или нет.
Когда определились с модулями - делаете внутри каждого из них аналогичное разбиение на классы: сначала интерфейс, потом потроха.
И только перейдя к реализации каждого класса, можете обернуться на свою процедурщину и посмотреть - есть ли код, который можно оттуда использовать как сырье для методов класса.