Improving our example (2)
In our previous post we have created an example with everything we learned so far. But our code has many things that we can improve, both logically and performance wise. So lets start.
class Shop {
#products;
constructor() {
this.#products = {}; // Moving products from array to object
}
add(product) {
this.#products[product.id] = product;
}
get products() {
return this.#products;
}
sell(productId) {
const product = this.#products[productId];
if (!product) {
throw new Error(`Product with id [${productId}] not found.`);
}
delete this.#products[productId];
return product;
}
}
class Product {
constructor(data) {
this.id = data.id;
this.name = data.name;
this.price = data.price;
this.currency = data.currency;
}
}
// Introducing Wallet class to store all money related info
class Wallet {
#balance;
#currency;
constructor(data) {
this.balance = data.balance;
this.currency = data.currency;
}
get balance() {
return this.#balance;
}
set balance(value) {
if (value < 0) {
throw new Error("Value is below 0.");
}
if (this.#balance - value < 0) {
throw new Error("New balance is below 0.");
}
this.#balance = value;
}
}
class Customer {
#wallet;
constructor({ id, wallet }) {
this.id = id;
this.#wallet = wallet;
}
get balance() {
return this.#wallet.balance;
}
buy(data) {
this.#wallet.balance = this.#wallet.balance - data.product.price;
}
}
const wallet = new Wallet({
balance: 1000,
currency: "EUR",
});
const customerOne = new Customer({
id: 1,
wallet: wallet,
});
const shop = new Shop();
const productOne = new Product({
id: 1,
name: "Product 1",
price: 10,
currency: "EUR",
});
const productTwo = new Product({
id: 2,
name: "Product 2",
price: 20,
currency: "EUR",
});
shop.add(productOne);
shop.add(productTwo);
shop.sell(productOne.id);
customerOne.buy({ product: productOne });
console.log(customerOne.balance); // 990
console.log(shop.products); // [ `2`: Product]
At first glance, above code seems the same as previous post example but if you look closer you’ll notice some very important differences.
Shop
We have changed our products
variable from array to object
//Before
this.products = [];
// Now
this.#products = {};
This has to do with time complexity
(known as Big O
) and it shows how much time it takes for worst case scenario(⏭️). For our case, if we have n
amount of products in our array, what happens if we want to delete one specific product? We need to go through for loop
until we find that specific product and then remove it from array. So if that product is last in array we would have to go through for loop
n
times. But if we use object instead then set our key
to be id
of product and value
to be Product
object we can immediately find that product and remove it. That is exactly what we do in add
and sell
functions.
Product
stays the same
Wallet
Newly introduced class that hold balance
and currency
values. The reason we have introduced this class is because Customer
should not know anything about the implementation of a wallet, it should only know that it has access to a wallet of sorts but it should not worry/know anything about how that wallet makes changes to balance. This is why we have moved our set balance
from Customer
to Wallet
.
Customer
Almost the same as before but now we instantiate wallet
and pass it in as a parameter for customer
. We have also made slight change to buy(data)
function.
What Now?
Now that we have somewhat improved our code try to find even more ways to improve it. For example, what happens if wallet currency and product currency are not the same? If you want easier solution then just make it possible to buy when the currency is the same and if you want harder and better solution then try to make your own conversion function that has few most popular currencies and conversion between them.