3

I'm working on (and have actually finished) a project that fetches price quotes based on user-entered data. I've written the code already and it works fine. It's written in javascript/jQuery using events and functions, more like this (example I just wrote for this question, not actual code):

// event - when the quantity field changes
$('input[name=quantity]').change(function(){
    // get the product
    var product = $('input[name=product]').val();
    // run function to set the base price
    setBasePrice(this.value,product);
});

// function - set the base price
function setBasePrice(quantity,product){
    var basePrice = quantity * getTierPrice(quantity,product);
    // show the base price to user
    $('.basePrice').empty().val(basePrice);
};

// function - set price based on quantity and product
function getTierPrice(quantity,product){
    // switches through 6 tiers (based on quantity)
    // e.g. - If product is x and quantity is y, price = z
    // returns a value
};

There are many more working parts but I wrote that to illustrate how it's put together. It just seems really verbose and a lot of moving parts. When it comes time to update it, it's a pain.

But I'm wondering if I should be using OOP for something like this? I really just want to get to the root of javascript best practice and find out how something like this should really be put together. I feel like a lot of the code I write, although works, isn't always the best way, maybe it's because I am self taught and haven't really dug in deep enough.

I broke the functionality into pieces if it helps to understand what is going on. It's not crucial for you to understand how every bit works:

Things I'm expecting 

    = zip code (number)
    = product (string)
    = quantity (number)
        - Need to verify number is between x and y (e.g. - 100 to 10000)
    = artwork colors (number)
        - Need to verify number is between x and y (e.g. - 0 to 6)

Things I'm calculating

    = base price (number) 
        - Depends on the product selected
        - Depends on the quantity entered (6 tiers of pricing based on quantity)
            e.g. - "Product 1" quantity of 101 to 200 = $9, quantity of 201 to 300 = $7, etc

    = screen charge (number)
        - Depends on the number of artwork colors entered
        - Depends on the quantity entered (uses same tier as when calculating base price)
            e.g. - "Product 1" quantity of 101 to 200 add 1.00 per artwork color
        - Gets rolled into the base price
            e.g. - base price = base price + (artwork colors*quantity);

    = shipping cost (hits url via ajax to fetch rate, returns number)
        - Depends on zip code entered
        - Depends on product selected (each product has different weight)

Things I need to output

    = final price
    = shipping cost
    = base price

So should I be using OOP, should I look at the YUI Module Pattern? If so, at a high level, how would I start? I don't need a full code sample, just an idea of where to begin. I really want my code to look good and be structured properly. Any advice, resource links, etc is greatly appreciated.

casperOne
  • 73,706
  • 19
  • 184
  • 253
jyoseph
  • 5,435
  • 9
  • 45
  • 64

5 Answers5

3

What you could do, is look into the MVC-paradigm - an architectural separation of logic that aims to abstract your code's components into Models, Views and Controllers. It's mostly known in frameworks for backend-languages (CakePHP for PHP, Rails for Ruby, Django for Python etc.), but is absolutely also applicable to JS.

See this post for some handy references. Personally, Backbone seems like an easy light-weight place to start off (and it supports jQuery (as I saw you referred too)).

Community
  • 1
  • 1
laander
  • 2,243
  • 2
  • 23
  • 15
  • 1
    Awesome. It's interesting, one of the things that lead me to relook at my js is recently getting into Ruby/Rails. I fell in love with it (and the MVC pattern) instantly, now I feel like other parts of my code need to be trimmed up. I will look at this, thanks! – jyoseph Jan 20 '11 at 22:23
3

My general test for "should I make this chunk of free floating functions in to a set of methods on a class" (which applies to any language, not just JS), is simple: am I passing the same variables around all over the place?

If so, I think it helps matters to make those variables in to fields of a class, and then make those functions in to methods, because then all of those methods can reference all of those variables, without you having to pass everything around "by hand". Furthermore, you can control things much better this way.

For instance, let's say you have several functions that takes a "foo" argument and call "setBar" on it, then set a "dirty" flag on it. With that setup, it's easy to accidentally forget to set the "dirty" flag. However, by making foo a field, and creating a setFooBar method (which calls "setBar" and sets the "dirty" flag), you can ensure that the "dirty" flag always gets set.

Anyhow, I can't tell from the limited code examples you've provided whether your code passes the test, but hopefully this gives you some food for thought.

machineghost
  • 33,529
  • 30
  • 159
  • 234
  • It does, thanks! I am doing exactly that, seems like I am constantly going back to check the product (e.g. `$('input[name=product]').val()`) and quantity, zip, etc and then passing those values around a lot by hand as you mentioned. When you said "... making foo a field" what do you mean by that? I wanted to know so I could google some examples. Thanks for the hand! – jyoseph Jan 20 '11 at 22:29
  • machineghost is referring to "member fields". see my code example for more explanation on that. "member fields" is the full name (i think), but i refer to them simply as members. some call them fields. "beloved child has many names" ;) – davogotland Jan 20 '11 at 22:56
  • and this is a very good rule of thumb! i also +1:d it. – davogotland Jan 20 '11 at 23:00
1

All the javascript work you can do only by functional scripting can be done by oop scripting and vice versa.
In most cases, using javascript as an OOP language is more elegant and powerfull, but not necessarily more efficient.
When I started to put toghether the javascript OOP basics , I was so fascinated by the prototipical inheritance , that i used objects everywere... until I realized that I was complicating everything (ex: instead of a normal 2-line image preloader script, I started coding ImgObjects that were much more complex than my original task required).
From the little code you provided, I can't really tell if OOP would bring major improvements on your project, but i suggest you take a peak at prototipal inheritance and maby some design patterns (this book is amazing), but don't forget that javascript is a fully functional language!

gion_13
  • 41,171
  • 10
  • 96
  • 108
1

i always promote oop! i think javascript works quite ok as oop language. there's a book called "javascript patterns" from o'reilly. it's written by some yahoo guru named stoyan stefanov, and it's very good at explaining when to use oop in js, and how to do it in a good way.

according to this book, i think that you would make an object that has a constructor taking your input data, validating it, and then saving to members. then it would have some methods for performing the calculations you write about. and those calculations would be made with the help of the members stored during object creation.

here's an example class:

//class named SomeClass
//constructor taking two arguments named init1 and init2
function SomeClass(init1, init2) {
    //members, use of keyword "var" makes them private
    //logic makes the members have validated values, if input is not satisfying
    var m_init1 = init1 > 5 ? init1 : 5;
    var m_init2 = init2;
    //so that was the constructor


    //well, this is still the constructor, but
    //conceptually, it's not anymore.

    //here are some public things
    //they are method calls, and they represent functions
    //that are private in here, but are made public through
    //the use of this.bla = Bla;
    this.publicMethod = PublicMethod;
    this.otherPublicMethod = OtherPublicMethod;

    //private function, made into a public method above
    function PublicMethod() {
        //this function/method has access to private members
        //of parent function object. yay!
        return m_init1;
    };

    //private function, made into a public method above
    function OtherPublicMethod(arg) {
        if(arg > 5) {
            m_init2 = arg;
        }
    };
}

var a = new SomeClass(2, 3);
alert(a.publicMethod()); //outputs 5

the way you structure information above is a very good basis of documentation to build an oop project upon. and it sort of looks like a class i think. what i'm saying is that it seems as though your documented model would fit right into my little code example here.

davogotland
  • 2,718
  • 1
  • 15
  • 19
  • This is sort of the track I'm on right now. Except I am using the JSON method to define and create an instance of that class. Not sure if that's okay or not? I am looking here at #2: http://www.phpied.com/3-ways-to-define-a-javascript-class/ – jyoseph Jan 21 '11 at 00:43
  • yeah, the stuff under section number 2 is good stuff! very easy to read :) – davogotland Jan 21 '11 at 10:20
0

I would worry less about OOP verses non-OOP than with refactoring - e.g. if you have "setBasePrice" and "setXXX" and "setYYY" that are very similar, you should convert them to a generic "setAnything()" call. OOP might help in that task but is not vital to it

DVK
  • 126,886
  • 32
  • 213
  • 327
  • I see your point, and it's well taken. I broke that out (setBasePrice and getTierPrice) because getTierPrice is pretty meaty; It switches through several products, each having 5 base prices. Although some refactoring is in order, I think sticking with the same structure is what is muddying up the script. – jyoseph Jan 20 '11 at 22:25