Wow, thank you very much. That's definitely a lot simpler. I'm going
to try reimplementing it via your suggestions and see how it goes.

I like your idea about not maintaining cart state on the server,
because it would make my functions easier to test and debug (no need
to setup & teardown a fake session) but I'm not sure it would work
well in practice. If a user is browsing Amazon, for example, they
might add something to their cart, then visit 10 random pages before
they go to checkout. I would need to embed the cart in each of these
pages and resubmit the cart to the server for each request. The
purpose of sessions are to avoid exactly this hairy situation.

I wrapped cart in a Ref in case multiple browser windows are open and
there is a concurrent "add to cart" click.


On Tue, Oct 27, 2009 at 12:41 PM, Timothy Pratley
<timothyprat...@gmail.com> wrote:
>
> Hi Robert
>
> On Oct 27, 9:48 pm, Robert Campbell <rrc...@gmail.com> wrote:
>> Hey guys, I'm looking for _any_ feedback/thoughts on this Clojure code
>> I wrote. I just feel like the entire thing is way too complex, but I'm
>> not sure about how to simplify it. I wanted to try something "real
>> world" so I made a simple shopping cart ref to put in a session:
>
> Great, an open invitation!
>
> structs are really no different from maps except as a performance
> optimisation (and not a huge one). So dropping the structs would
> remove some boilerplate if simplicity is your goal. Also why not make
> the cart a map of products to qty and forget about subtotal...
> subtotal and total are easily calculated by separate functions for
> view or checkout... something like (untested at all):
>
> (defn add-to-cart [product qty]
>  (if (pos? qty)
>    (dosync (alter cart update-in [product] #(+ qty (if % % 0)))))
>
> (defn update-cart [product qty]
>  (dosync (alter cart assoc product qty)))
>
> (defn remove [product]
>  (dosync (alter cart dissoc product)))
>
> (defn subtotal [product]
>  (* (@cart product) (price product)))
>
> (defn total []
>  (reduce + (map subtotal @cart)))
>
> But in a real-world example I'm not sure a ref would be the best way
> to deal with the state... wouldn't you have the cart sent up in the
> request and a new cart returned? ie: you wouldn't need to maintain a
> ref on the server, just provide the hooks for building a cart and
> checking out. So the functions might be better if they take a cart as
> input and return a cart. Doing that pretty much makes them empty
> functions:
> (defn remove [cart product]
>  (dissoc cart product))
> So do you even need a remove function? Maybe not.
>
> Just some thoughts - I'm no web-shop programmer so disclaimer
> attached.
>
>
> Regards,
> Tim.
>
>
>
> Regards,
> Tim.
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to