DEV Community

Discussion on: Elegant patterns in modern JavaScript: Ice Factory

Collapse
 
billsourour profile image
Bill Sourour

I didn't learn about composition or inheritance from MPJ, he just provided a fitting quote about new and this that I incorporated.

Having said that, the thread you linked to makes a valid point; by destructuring the ProductList into the ShoppingCart and subsuming its methods we do, in a way, "inherit" them rather than simply make them a part of our composition. And this does lead to some of the problems we see with inheritance in general (especially, the "fragile base class" problem).

I will update the post and sample code to better reflect this. Thank you for your input.

Collapse
 
nickwalt profile image
nick walton

I really like this way of doing things (the Ice Factory Function). Thanks for writing a great article.

There seems to be a fundamental difference between the OOP way of reusing methods and properties from one object by calling them in another (object.method), and the FP way of just passing data from one function to another via arguments.

Does FP have objects with methods and properties? Could the Ice Factory Function be considered a "functionalised" OOP pattern?

I'm trying to understand how these two paradigms can be mixed together in JavaScript. What would the architecture of the application look like?

Also, the idea that an object can have properties seems to me to potentially inhibit composition because there is a tight coupling between object and data (or state).

Varun Vachar demonstrated stateless UI objects being passed state by another object. This loose coupling and the way he did that feels nicer to me than putting the state in the UI object.

Thread Thread
 
billsourour profile image
Bill Sourour • Edited

Hi Nick.

Thanks for the feedback and the question.

The Ice Factory pattern takes a decidedly OOP view of the world. It just sidesteps some of the drawbacks of inheritance and a lot of the quirkiness around JavaScript's class syntax.

It's easy to feel like anything that doesn't have the word "class" in it must be something other than OOP, but as Dave Thomas once said:

"Design with Objects, not Classes... It's OO Programming, not CO [Class-Oriented] Programming".

Having said that, FP is great. There is a lot we can learn from FP, and JavaScript is a fascinating language in that it gives us both Objects and Functions as "first class" citizens of the language, so we can take advantage of both paradigms and match the approach to the problem we are trying to solve.

In FP, we separate the data from the code that transforms the data. In our shopping cart example, the data is a list of items and the transformations include adding and removing items from the list.

An FP-style shopping cart could look something like this:

// shopping-cart-fp.js

import freezeMap from './utils/freeze-map.js';

export function addProductToCart(product, cart) {
    const newItem = Object.assign({}, product);
    newItem.qty = newItem.qty || 1;

    if (cart.has(newItem.id)) {
        newItem.qty = cart.get(newItem.id).qty + 1;
    }

    const newCart = new Map(cart);
    newCart.set(newItem.id, newItem);

    return freezeMap(newCart);
}

export function removeProductFromCart(productId, cart) {
    const newCart = new Map(cart);

    if (newCart.has(productId)) {
        const product = Object.assign({}, newCart.get(productId));

        if (product.qty < 2) {
            newCart.delete(productId);
        } else {
            --product.qty;
            newCart.set(productId, product);
        }
    }
    return freezeMap(newCart);
}

I'm using a Map here – which can't be frozen – so we need a little utility function to freeze it to ensures that no one messes with our cart data. Like so:

// freeze-map.js
export default function freezeMap(map) {
    map.set = map.clear = map.delete = () => {
        throw new Error('Attempted to change a frozen Map object.');
    };

    return map
}

Hope that's helpful.

Regards,
Bill