Archimedes and Input-Output Thinking in Programming

Archimedes and Input-Output Thinking in Programming

Daily short news for you
  • Dedicating to those who may not know, snapdrop is an open-source application that helps share data with each other if they are on the same Wifi network, operating based on WebRTC.

    Why not just use AirDrop or Nearby Share instead of going through this hassle? Well, that’s only if both parties are using the same operating system. Otherwise, like between Android and iOS, or MacOS and Linux or Windows... At this point, snapdrop proves to be extremely useful 😁

    » Read more
  • 24 interesting facts about SQLite Collection of insane and fun facts about SQLite. I have to say it's really amazing 🔥

    » Read more
  • bolt.new is so awesome, everyone! It can handle all types of Front-end work. The thing is, I was out of ideas, so I went there and described in detail the interface I wanted, the more detailed the better, and it just generated it for me, which was surprising. Although it's not perfect, it's very similar to what I imagined in my head, and making adjustments is easy. By default, this tool generates code for React or something, so if you don't want that, just ask it to generate code for the platform you're using.

    The downside is that each subsequent prompt will replace all the old code -> it consumes tokens. You probably can only request a few times before running out of the free tokens for the day. The upside is they are currently giving away 2 million free tokens for everyone. Go get yours now 🥳

    » Read more

The Problem

"Give me a lever long enough and a fulcrum on which to place it, and I shall move the world." This is a famous quote by Archimedes. Many evidences indicate that even if he had a fulcrum, it would still take thousands of years to lift the world. Not to mention, where would he find a lever of unimaginable length? But in this article, I'm not discussing the accuracy of the quote. What I find fascinating is his way of thinking: "Give me...I will..."

"Give me x, I will return y" is an input-output thinking in programming. It is a very common problem-solving mindset. Instead of immediately writing code, take the time to evaluate and identify where the approach "give me x, I will return y" can be applied. You may have heard of it in the article Just Code, or Focus on Developing Your Programming Mindset?.

A Simple Example

For ease of imagination, let's take an example of a simple shopping feature. Its logic looks like this:

function createOrder(product, quantity, customer) {
  // find product information
  const productInfo = ProductModel.findOne({
    where: {
      product_id: product,  
    }
  });
  if (!productInfo) {
    throw new Error('Product not found');
  }

  // check quantity in stock
  if (productInfo.quantity < 1) {
    throw new Error('Not enough product in stock');
  }

  // create order
  const order = OrderModel.create({
    customer: customer,  
    product_id: product,  
    quantity: quantity,  
    total_price: productInfo.price * quantity,  
  });

  return order;
}

If you think in terms of input-output, you can make the above code look more concise and reusable. To achieve that, think about separating the logic into smaller pieces, making them Pure functions if possible. If you don't know what a "pure function" is, you can read the article Pure Functions in Javascript. Why Should We Know It as Soon as Possible?.

In the example above, we see three distinct and well-defined logics: finding product information, checking quantity in stock, and creating an order. From there, we can extract them into 3 smaller functions.

Give me a product ID, I will return the product information.

function getProductInfo(product) {
  return ProductModel.findOne({
    where: {
      product_id: product,  
    },  
  });
}

Give me the product information, I will check if it is in stock.

function checkProduct(productInfo) {
  return productInfo.quantity > 0;
}

Give me the necessary information to create an order, I will create and return the order.

function createOrder(productInfo, customer) {
  return OrderModel.create({
    customer: customer,  
    product_id: productInfo.id,  
    total_price: productInfo.price,  
  });
}

With these 3 functions serving clear purposes, you can easily reuse them. Anytime you need to find product information, use getProductInfo. Anytime you need to check quantity in stock, use checkProduct. Someone may ask why checkProduct needs to take productInfo as an argument instead of just the quantity attribute. The answer to this question depends on your experience in the project. By receiving the entire productInfo, it increases the ability to expand in the future. For example, if later on there is additional logic that only allows creating orders for products created after one week.

function checkProduct(productInfo) {
  return productInfo.quantity > 0 && productInfo.created_at < moment().subtract(7, "d").toISOString();
}

Of course, you can continue to break down checkProduct into even smaller functions if deemed necessary.

function checkProduct(productInfo) {
  return checkQuantity(productInfo.quantity) && checkDate(productInfo.created_at);
}

The benefit of writing input-output functions is that they are very easy to create unit tests. Since they have no dependencies (such as using a variable outside the function), you can write test cases to validate their correctness. For example, to test if checkProduct works as expected, simply pass in productInfo with quantity and created_at attributes, and the function will return true/false. With one input corresponds to one output, you don't have to worry about whether the function utilizes variables outside the function or has any side effects.

To sum up, thinking in terms of input-output, along with the ability to create Pure functions and limit side effects, allows us to write reusable and easily testable features.

Until now, Archimedes' quote has not been substantiated whether he could lift the earth given all the necessary conditions. But the functions you write can certainly be easily validated for correctness.

How to Think in Terms of Input-Output?

There are several ways to help you practice thinking in terms of input-output. After reading the suggestions below, the important thing is to practice by applying them in your personal projects or projects you are involved in.

Firstly, take the time to learn about what Pure functions are? What benefits do they bring?

Secondly, before starting anything, take the time to evaluate the feature you are about to implement. I have an article about the 4 steps to hone your skills at Just Code, or Focus on Developing Your Programming Mindset?

While writing code, do it naturally. Then, review if there are any logics that can be separated. If possible, separate them into Pure functions.

Repeat the above steps, and gradually you will develop the input-output thinking. Later on, when preparing to work on a new feature or a feature similar to a previous one, this thinking will come back to help you save time in evaluation and coding.

Conclusion

Thinking in terms of input-output is not new, you may have used it before without noticing. Hopefully, this article helps you realize the importance of this thinking and enables you to write code more efficiently and effectively.

Premium
Hello

Me & the desire to "play with words"

Have you tried writing? And then failed or not satisfied? At 2coffee.dev we have had a hard time with writing. Don't be discouraged, because now we have a way to help you. Click to become a member now!

Have you tried writing? And then failed or not satisfied? At 2coffee.dev we have had a hard time with writing. Don't be discouraged, because now we have a way to help you. Click to become a member now!

View all

Subscribe to receive new article notifications

or
* The summary newsletter is sent every 1-2 weeks, cancel anytime.

Comments (0)

Leave a comment...
Scroll or click to go to the next page