Был у нас когда-то магазин, перл+ООП, так что все написанное ниже — субъективный опыт и описание конкретной реализации, а не строгая догма.
Во-первых, все очень хорошо и с пользой разбивается на объекты. Часть объектов мысленно «можно потрогать» — к ним можно отнести объекты юзера, товара, объект корзины с подъобъектами-позициями (товар + колво), объект заказа с позициями (товар+колво+зафиксированные цены) и много всякой другой мути. Часть объектов «потрогать» уже сложнее, но их введение тоже дает профит благодаря полиморфизму и наследованию — в этой категории, например, у нас оказались объекты, отвечающие за реализацию различных способов доставки и оплаты. Как обычно, наиболее интересным и не слишком простым оказалось все это увязать в единую систему. Многие объекты в обе стороны зависят друг от друга, но тем не менее избежать циклических связей удалось.
Что вам могут дать объекты? Самый наглядный пример — это, конечно, товар. Предположим, у нас есть две таблицы — с книгами и дисками — и классы ActiveRecord, прикрученные к ним. Начинаем определять, что же нам нужно от товара. По большому счету, это цена (с валютой, если есть необходимость) и название. Остальное менее интересно и может пригодиться в частных случаях. Например, для расчета стоимости почтовой доставки пригодится информация о весе, а для всяких маркетинговых штучек — поле «цена со скидкой» (для красоты чисел удобнее не задавать это поле в процентах). Определяем методы, которые будут эту информацию возвращать. Допустим, захотелось сделать комплекты из нескольких товаров. Заводим новый класс, для которого можно будет определить свое название и цену со скидкой, цена без скидки суммируется по входящим в комплект продуктам. Ну и так далее, на странице товара его можно отображать как угодно и полей может быть сколько угодно, «корзинка» же видит свой набор полей, и только его. По большому счету, если у нас уже есть система, умеющая книги, прикрутить к ней комплекты — цена написания одного небольшого класса с парой обязательных полей.
Доставка также обладает названием, стоимостью, произвольным образом зависит от содержимого корзины, адреса доставки, может быть валидной или невалидной в данных условиях (как правило, курьерская доставка в Петропавловск-Камчатский невозможна). Аналогично и с оплатой, но она зависит также и от доставки (нельзя оплатить курьера наложенным платежом).
Корзина включает в себя информацию о товарах, юзере, доставке и оплате. Заказ — до боли похож на корзину, но вся информация, которая может измениться, в нем сохраняется отдельно. Измениться могут например цены, адреса.
Если приступить к реализации, начните с простого — с товаров и корзинки. Подумайте, что такое корзина, что в нее входит кроме товаров, сколько корзин может быть у юзера, возможна ли «анонимная» корзина. Первые два вопроса позволят вам решить, какие поля и методы должны быть у объекта, вторые два — как получить конкретный объект корзины, когда захочется показать ее на странице. Реализуйте то, что получилось, пока без доставок и оплат, но чтобы на экране выглядело «как у всех». Добавляйте постепенно остальное, ищите места, где можно сделать несколько разных реализаций чего-либо при одинаковом интерфейсе — возможно, это можно будет выделить в отдельный объект. Но без необходимости тоже не крошите, будет сложно собрать в одно целое :)
Как-то так. Успехов!