Focus Is Key to Creating Product Value

Wed Dec 20 2023

TL;DR: Focus is key to creating product value with software. In this article, I illustrate what happens if you do not focus, using a Python project as an example. I then conclude that product value is best created by being conscious about the outcome you are trying to achieve while prioritizing ruthlessly and choosing boring technology by default.


It's Monday morning and you're in a good mood, you've had an excellent weekend and are excited about the week ahead. What's more, you've finally been assigned to investigate if Python's new some-cool-package SDK is a good fit for building a certain new product feature.

Excited, you fire up a shell via iTerm2 on your Mac, create a new project directory, and open it in your editor VS Code. Now you just have to create a Python project to get started. Should be easy... Right?

1. Installing Python

Turns out you only have Python 3.11.4 installed while you really want to use the cutting-edge version 3.12.1. You'll just use the Python version manager pyenv to install that.

# Installing a new Python version
pyenv install 3.12.1
# python-build: definition not found: 3.12.1

Hm, pyenv doesn't find the Python version. Ah, you haven't upgraded it in a while, so you need to do that first. It's installed via the macOS package manager Homebrew, so that shouldn't be too hard.

brew upgrade pyenv

Turns out that you have a lot of brew formulas that need to be updated. Why, it's important to update your packages now and then, so you let it run. Some of the packages were really big so it takes about half a century for the upgrade to complete, but now it's done! Time to install the desired Python version.

pyenv install 3.12.1

This also takes some time to execute.

Before getting packages, you need to setup a project-specific Python environment so you don't contaminate the global Python installation. You usually use virtualenv and pip for this, but you're in a good mood so why not try something new? You do some research and eventually decide to give the Python dependency management tool poetry a spin!1

2. Shell Commands: Poetry, Install!

There are different ways to install poetry and you opt for the approach using the Python application isolation tool pipx, because that's the default in the poetry docs. You'll first install that with brew and then use pipx to install poetry.

# Install & setup pipx
brew install pipx
pipx ensurepath

# Install Poetry
pipx install poetry

3. Creating Poetry

Now you can finally setup poetry. This has taken longer than expected, yet you're still in high spirits. After reading the docs, you decide to navigate to the project and then initialize poetry.

cd "<project>"
# Setup the project in the existing project folder
# You just want to execute it without any interactive elements
poetry init --python 3.12.1 --no-interaction

So far, so good! Now it's time to add packages. You know you need to connect to other servers, so other than some-cool-package you'll also install requests.

# Installing primary dependencies
poetry add requests
# ... works as expected
poetry add "<some-cool-package>"
# The current project's supported Python range (3.12.1) is not compatible with some of the required packages Python requirement:
#   - some-cool-package requires Python >=3.8.1,<3.12, so it will not be satisfied for Python 3.12.1

What's this? some-cool-package is not compatible with Python 3.12.1! Ugh, you'll have to use an older version, guess you should have looked that up before.

4. Troubles Using Poetry

No worries, you'll just downgrade to Python 3.11.6. You first remove the virtual environment.

# Output the environments
poetry env list

# Delete the environments outputted
poetry remove "<outputted environment>"

And then update poetry to use another version of Python.

poetry env use 3.11.6

# The specified Python version (3.11.6) is not supported by the project (3.12.1).
# Please choose a compatible version or loosen the python constraint specified in the pyproject.toml file.

Ah, of course you need to update pyproject.toml with the new Python version first.

# (...)

[tool.poetry.dependencies]
python = "3.11.6"  # updated here
requests = "^2.31.0"
# (...)

You then try again.

# To test that you can use the desired Python version
poetry env use 3.11.6
# Creating virtualenv project-IKdluREu-py3.11 in /Users/USER/Library/Caches/pypoetry/virtualenvs
# Using virtualenv: /Users/USER/Library/Caches/pypoetry/virtualenvs/project-IKdluREu-py3.11

# Installing the pacakge
poetry add "<some-cool-package>"

Excellent! You can almost feel the taste of some_cool_package now. The last step should be to make a sanity check to ensure that you can actually import the primary dependencies.

# Activate the virtual environment in the current shell
poetry shell

# Using the -c command to execute Python code in an interpreter
python -c "import some_cool_package; import requests"

# Traceback (most recent call last):
#   File "<string>", line 1, in <module>
# ModuleNotFoundError: No module named 'requests'

What the-! Why can some-cool-package be imported but not requests? After some googling you stumble upon the obvious answer: You have created the virtual environment, installed some-cool-package, but not installed the package that was successfully added to poetry before you removed the virtual environment, namely requests. You try to install it now.

# --no-root to install only the dependencies, in this case
# it will install `requests` with its dependencies
poetry install --no-root

# Testing it again
python -c "import some_cool_package; import requests"

And it finally works!

5. Interpreter Selection in VS Code

Though somewhat fatigued, you fire up VS Code to get started doing what you wanted to do in the first place.

Before you get to that, however, you notice a warning from VS Code's Python extension Pylance about some_cool_package not being resolved in the import statement. Turns out VS Code is having troubles finding your virtual environment. What have you done to deserve this?!

You first try to run Python: Select Interpreter and select the virtual environment's interpreter manually, because the IDE doesn't detect the virtual environment. This should work, you think, but does not for whatever reason.

After some googling you find that VS Code can auto-detect a virtual environment if it is placed in the root folder of your project. You also find that there is a flag in poetry for this.

# Setting the poetry flag --local to set it on a project basis,
# rather than globally
poetry config virtualenvs.in-project true --local

# Removing all virtual environments
poetry env remove --all

# Creating a new virtual environment and installing 
# all dependencies
poetry install --no-root

And VS code suddenly detects your virtual environment! If this didn't work, you also find a post online that informs you that you can set "python.venvpath" in your VS Code settings, restart your IDE, and auto-detection will work better.

{
    // ... other settings ...
    // In .vscode/settings.json. Assuming your poetry virtual 
    // environments are placed in the below folder
    "python.venvPath": "/Users/USER/Library/Caches/pypoetry/virtualenvs"
}

After another hour of experimentation, talking with ChatGPT, and existential crisis you finally manage to solve the issue.

6. Focus Is Key

Now four hours have passed and all you've managed to do is setup a development environment. Not only did you miss your deadline, you also lost your Friday mood somewhere along the way. You feel numb, depleted, and broken as you stare into the abyss that is your screen while asking yourself: Whatever went wrong?

After a period of reflection you come to the conclusion that this situation arose from a lack of focus.

6.1. Be Conscious About Your Desired Outcome

You set out to investigate whether some-cool-package was a good fit for creating a product feature. You realize that the raison d'être for the feature was to create value for a user of the product in a way that works for the business.

In what way did the usage of, for example, a cutting-edge version of Python contribute to that? Indeed, syntatic sugar can help you deliver faster, yet the connection in this instance seems farfetched at best. You didn't consider the value you were creating for the users and the business when deciding to upgrade Python and it ended up having the opposite effect by slowing down shipping.

You could also have ignored the VS Code Pylance warning, since your editor doesn't have to be optimally configured for you to write code. However, that would have made your coding experience worse, with no autocomplete and false warnings flying around, which can affect the software quality and your development experience. So you made the call, right or wrong, that this was important enough to fix. Indeed, you can see how this fix speeds up your devlopment and what value it created towards your desired outcome.

Regardless, you realize that you need to be conscious about what outcome you are trying to achieve and then focus only on that. Unless your intention is to go down rabbit holes for fun or learning2, you want to minimize the amount of holes you fall into.

6.2. Prioritize Ruthlessly

When upgrading pyenv with brew you decided that you might as well let brew upgrade the other installed packages. Instead, you could have considered performing a targeted upgrade of the package to get started3.

Irresponsible? Perhaps, yet when investigating the capability of a package locally, that doesn't necessarily matter. If it is important that you have the latest brew version and formulas installed that is a separate issue that you can tackle at another time. Write the problem down so that you can prioritize and focus on it in the future.

You have to be ruthless when you prioritize what you spend time on. There will always be a multitude of things around your project that you can improve and you have to decide what is worth doing, given the outcome you want to achieve.

6.3. Choose Boring Technology By Default

You're testing the new fun technology some-cool-package. Given that you are testing something new and fun, you should have maximized the amount of boring technology used around it to minimize the amount of problems that were sure to arise. Boring technology in this case refers to tried-and-tested technology you know works, that you are familiar with, and perhaps even have installed. In this instance, using poetry and cutting-edge Python added no value to your desired outcome, so what could you have done instead?

  1. Used pip for package management, because that is what you were familiar with. You could have prioritized and focused on testing poetry in the future when you deemed it important enough.
  2. Used the version of Python you already had installed, because it was new enough for your purposes.

That would have saved you hours of work and frustration.

6.4. Conclusion

Focus is key to creating product value with software. To maximize the value you create, you need to be conscious about the outcome you are trying to achieve and then focus only on that by prioritizing ruthlessly and choosing boring technology by default. Focus also has the added benefit of saving your peace of mind by minimizing the amount of unnecessary rabbit holes you have to go down.

With that realisation you regain some of your fire and decide to write this testament of your own incompetence, so that your colleagues can indulge in your wisdom. You open Apple Notes... But wait! Apple Notes cannot possibly be the best editor for writing articles like these. So you do a Google search for "best article editors" and initiate a frustrating afternoon of pointless searching for a tool you don't need...


Footnotes

  1. This article makes no judgement of the best practices for brew, poetry, Python package management, VS Code, or any other technology. These are only used as examples.

  2. Which indeed could be your goal and a worthy endeavor in another situation.

  3. Another option that I used recently was to remove the large packages that were unused. This reduced my install time significantly.