Showing posts with label Software Development. Show all posts
Showing posts with label Software Development. Show all posts

Saturday, July 4, 2026

Practice what you Preach

I'm the maintainer of the Python tools for the Polylith Architecture, that adds useful tooling support for teams having their code organized according to the Polylith Architecture. So far in 2026, I have made seven Feature releases (i.e. minor versions) and a bunch of smaller ones (i.e. patches).

One of the features that was added this year is the possibility to inspect the coupling between individual parts of the code. In Polylith, code is logically grouped into something called bricks. For Python, these are what we know as namespace packages within the same repo.

Each package has an __init__.py, and you can define the interface of the package there. This is optional, and it is perfectly valid Python to access the modules within a package directly. In Polylith, a stricter approach is recommended: explicitly define the things that should be exposed outside of the package (aka brick).

      from my_package import my_function

      __all__ = ["my_function"]
    

The new feature is exactly about this: visualize and validate the usage of brick interfaces across the repository. With a simple command, you will find out if code is bypassing the explicit interface of a brick. This is still optional, and as long as it is valid Python you can safely ignore this. There's benefits of having code that interacts via explicit interfaces, such as refactoring - it's very easy to move code - and low-risk of breaking things when changing the code within the brick.

      # the existing command visualizing coupling between bricks
      poly deps

      # the addition, that will inspect the brick interfaces
      poly deps --interface

      # or inspect a single brick
      poly deps --interface --brick the_brick
    
Vizualize coupling, bypassed interfaces or circular dependencies.

What about circular dependencies between bricks?

Remember, a brick is a namespace package and that means that it is on a level above the individual Python modules. It can be valid Python to have two packages depend on each other, if the imports are for different modules in the packages. But this is an indication that something might be wrong with the Design. I would even go so far calling it a Bug. Two packages that import code from each other could be refactored into three, where the shared things are in a separate package. This is how the Polylith tool identifies circular dependencies between the bricks. The same command as for validating interfaces is used for this feature (poly deps) and it will inspect the code in the entire repo, to look for any circular brick dependencies. The interface lookups and the circular dependency checks are both internally using the builtin AST parsing.

Control your Agents

Many teams use agents today during development and knowing that agents can produce a lot of code in a fast pace, these two features are very useful if you want to avoid any unexpected side-effects of importing Python code without clear boundaries. Agents can use the poly tool too, just like when doing linting and testing. Static analysis is a great thing to have in the Agentic Engineering toolbox. The Polylith tool includes agent skills, so your agent will understand how to use it.

Practice what I Preach

I knew from before that the source code of Polylith tool bypassed interfaces in a couple of places, but I thought this is fine since it is valid Python. But I realized that my future self will thank me if these risky parts are fixed now and not later. Also, it is good if I actually practice what I preach being the maintainer of the Polylith tool for Python. So I fixed that. In addition, I also learned that two bricks in the repo had circular dependencies caused by a recently added feature. In this case, it was a circle of several bricks that initially made me worried. But the solution was simple: move the parts that caused the circularity into a different brick. I already had an existing brick that made sense to host the couple of Python functions that caused the circular dependency.

After refactoring: no interface violations, no circular dependencies.

Related posts and resources



Top Image generated by Mistral AI with modifications by me.

Sunday, June 28, 2026

Reflections: 6 months of Agentic Engineering

As many developers today, I'm using agents on a daily basis for software development. At work, we went all-in Agentic Engineering in early 2026 and for me it has worked well.

Not perfect, not 10x, but well and the shift was surprisingly easy. I quickly found that good coding practices are still applicable and relevant. I’m not into that vibe coding stuff, I care too much about the output. What has been occasionally overwhelming is the uncertainty about The Next Step - just like many developers out there I have thought about how we, the Humans, will keep up with the speed of the Agents?

Here's some reflections after about six months of developing software according to Agentic Engineering.

Human reviews have not become the bottleneck. From my experience, human reviews was a bigger bottleneck before Agentic Engineering. We have made efforts in our Team to improve the review flow, to avoid the need of constantly reminding people to review and approve changes. We have made the review process itself more efficient than before.

For me, the ratio of Development time vs Planning and Reviewing is about the same as before. I find myself designing and developing solutions the same amount of time as before the agentic era. In the beginning, I thought it would be the opposite!

I haven't run into the problem of having my agents produce hundreds of pull requests on a daily basis. I know there are people out there doing amazing stuff over the weekends with agents, but I'm not one of them. I haven't yet found a need to rebuild an existing SaaS tool from scratch with AI.

Quality is important. I think it is even more important than before, because an agent will be confused by complex code. Not only that, it will likely produce code that is equally complex (there's research about this available). This will be a downward spiral. Here's where Agentic Engineering is different from Vibe coding. A vibe coder treats the code, the output, as a black box. The risk with that is software that is very difficult to maintain. An agentic engineer keeps their eyes on the incremental result, and steer the agent during the process. The Human decides what Quality is, what is Readable code and what is Simple code (just like before).

Static analysis tools are a great to have in the agentic toolkit. Linters and Unit Tests are as important as before. I have added tooling that reports on complexity and readability issues, and use the Code Health MCP for that. Without the need of human interaction, the agent will verify its result while working and adjust it until the score is healthy before it reaches my eyes. Having static analysis tools doing this kind of work instead of an AI will reduce token spend. Reducing spend will be important in the future as the cost of tokens likely will increase.

Always bet on Open Source. Back in the days, as a .NET developer (when it was closed source and Windows only), developers were heavily dependent on Microsoft. Not only for the framework, but also for most of the tooling. I don't want to go back to that era, and see the same kind of vendor lock-in pattern with the AI providers of today. My tooling of choice is Emacs and the provider-agnostic tool Eca. When Anthropic has its downtime issues, I just switch to Gemini and can seamlessly continue while my colleagues at work are frustrated and post Claude is Down memes.

After six months, I still have a skeptic view on agents and LLMs in general. I simply don't trust the output. But at the same time, Agentic Engineering has made my workflow more efficient and I can more confidently step in to developing things outside of my comfort zone.

Related posts



Top Photo by me from Hoburgen, Gotland in Sweden.

Monday, April 6, 2026

A workflow for Agentic Engineering

"- Claude, build the entire Platform from scratch. Make no mistakes."

In the agentic engineering community, some think that 100% test coverage will guarantee the quality of generated code. I think that relying too much on automated tests is problematic, because testing is difficult. I'd rather review the actual source code. More importantly, having an active part in the development of it by steering the agent(s) in real time.

I usually develop a feature step by step, to not focus too much on upfront planning. I used to do this before the agents joined the development process, and have found that it works well today too. When beginning with a new task, I often have some clear ideas and some vague ideas about how to solve the problem. By starting with the things that are clear, I can postpone thinking about the implementation details of the more vague parts of the overall feature. I can worry about that later, when I have learned more. During the development, the how and what to implement will likely change. This is a natural thing, as you learn more along the way and understand more about the actual problem to solve. I guess this is the basic idea behind Embrace Change (from the Agile Manifesto).

I haven't yet felt any need to set up larger Agent Orchestrations for the kind of problems that I solve. It mostly seems like overdoing it, doesn't it? I don't know about you, but we are not building or reinventing an entire E-Commerce or Social Media platform every day. The things we do is on a much smaller and human-friendly scale. I think the idea about 100% test coverage might be about scaling up fast and the assumption that agents will produce so much code, that it becomes impossible for humans to grasp.

An Example

I recently developed a new feature that involved several repos, a combination of Python backends and Next.js apps. I decided to do this in smaller steps and began with the most straightforward step, which in this case was one of the backend services that I already know well. I had a pretty clear idea on what needed to be changed in there and added a simple Solution Design into the ticket.

For context: I used the same ticket for all the development of this particular feature. Each plan an agent produced was submitted as a comment to the ticket. I have automated this with an MCP server connected to the issue system that we currently use at work. It seems like having the relevant data collected in the ticket made the upcoming tasks clearer for the agent(s). Each task begun with a new context, but I instructed the agent to read the ticket that contained the problem to solve, the solution design, previous plans and linked pull requests before planning how to implement things.

It felt like things went pretty smooth. However, the very first task needed several iterations. I realize now that even if the basic setup of that particular repo was straightforward, the service has evolved over time and the structure of it has diverged. I think this is quite common in long-lived repos. This confused the agent, so I practiced the stop-the-line principle by rejecting generated code, correcting and steering the agent in real time. I did this when I noticed that the implementation (the code) went into a direction I didn't like. My agentic tool of choice, Eca, recently added support for a new steer command that is very useful for this kind of workflow. You can change the direction, or steer, while the agents are working. It is not always necessary to halt all ongoing work, sometimes a friendly nudge in the right direction is enough.

Sometimes, unexpected things happen: the other day, the main model I use was unreachable about half the day (again). Oh no. But I just switched to a different provider and continued the work! This is another thing where an Open Source and Provider-agnostic tool like Eca shines.

Another thing that I noticed was that the short summary the agent produced for each Pull Request covered the whole feature and the particular details pretty well. The data in the actual ticket was probably helpful for this kind of task too.

I've been advocating Test Driven Development (TDD) and the sibling REPL Driven Development for many years. The real-time steering, the stop-the-line principle with origins from The Toyota Way could be an Agentic Engineering version of the Test Driven approach. It's about fast feedback loops. What do you think?

Top Photo: that's me pretending to do something important on the cell phone, taken at Åreskutan, Jämtland, Sweden.

Sunday, March 15, 2026

Agile & Agentic Engineering

"Don't fall into a waterfall-style of software development."

Our industry is quickly adapting to the new ways of working and we are redefining what it means to be a software developer: Agentic Engineering.

It's not the same thing as Vibe Coding, and probably why I have had such a surprisingly smooth transition recently. As I see it, vibe coding is about treating code as a black box: it doesn't really matter how things are put together. The only thing important for a vibe coder is the output. As a passionate TDD and REPL driven programmer, this doesn't feel right for me today. Tomorrow, I don't know. Right now, I care about how things are constructed. More importantly, I need to have some understanding about the code itself to get ideas on how to change and improve the output.

This is where Agentic Engineering fits in: a structured way of developing software, where the human developer takes an active part in the process. It is not only about high level architecture or designing the solution, it's also about having the possibility to direct the agents into producing actual code that the human can understand and approve. For me, this is about keeping things simple and concise. Functional. Doing things in small steps, i.e. solve a problem by breaking it down into smaller parts. Experiment and learn along the way, step by step, rather than making big plans upfront. This is the core of the Agile movement.

It's well known that LLMs can produce verbose chunks of code and forget about important things. But it is possible to take control of that part as an agentic engineer. Similar to the stop-the-line principle (from the Toyota Way) where you can halt the production if you identify an issue. Take action (clarify or give new instructions) and then proceed. With these skills, agents can produce chunks of code that are just right. And functional.

From what I've picked up in the developer community lately, there's an increased need for structured work in the new AI landscape. This makes a lot of sense. What surprises me is the conclusion that we should start doing more planning upfront, writing detailed specifications before any code is written. This is what the Plan, Execute, Test sounds to me. I am just misunderstanding, or is this a Modern Waterfall movement?

Plan, execute, test might be the correct workflow for an agent, but not for a human. Planning in the beginning is difficult, because in the beginning we have very little knowledge about the thing to develop. Instead, we could learn what and how to develop something along the way. We can also pick up bits of why along the way too, but it's good to have some understanding about that specific part early in the process.

If the Plan was incorrect we will be 10x, but with 10x waste. Agents produce code fast, and it might not be that big of an issue as before if we need to throw away the result and start over. This is new. The difficult part is throwing away our plan, our design that we've invested in, and start all over again. This drains human energy. Once a plan is set, it can be a too big mental effort to break free from it because things have been decided already. Big planning upfront might sound right, but it is a trap. A vague Jira ticket description to begin with is not necessarily a bad thing.

The challenge as agentic engineers is to 10x the value, and not end up in 10x waste. Essentially making us more product and value focused than before. In short: build the thing right, also build the right thing.

How can we do that? Explore, learn and adapt are words I would like to see as part of the Agentic Engineering definition. Plan a little bit upfront, just enough to get started, but no more than that. Continue exploring, planning and adjust as the work proceeds. Get things out fast so you can collect feedback (logs, errors, usage) and learn what to adjust. That's Agile & Agentic, a Lean and Agentic Engineering workflow.



Top Photo by me, taken at the top of Åreskutan, Jämtland, Sweden.

Saturday, October 25, 2025

Please don't break things

"Does this need to be a breaking change?"

During the years as a Software Developer, I have been part of many teams making a lot of task force style efforts to upgrade third-party dependencies or tools. Far too often it is work that add zero value for us. It adds significant cost, though. As a user of third-party tools, you don't have much choice. Even if you might feel productive as a developer when implementing these forced changes, think of all the other stuff you could do instead to improve your product or platform.

The great tools from the community, most of it Open Source, is something we should be thankful for, and appreciate the efforts made by the people out there. This is a plea to have extra attention when making changes that will affect your users. I am also an Open Source maintainer, and try hard to avoid changes that doesn't add value for the users.

An example from Python: uv

warning: The `tool.uv.dev-dependencies` field (used in `pyproject.toml`) is deprecated and will be removed in a future release; use `dependency-groups.dev` instead

The change itself makes a lot of sense. There's a new PEP standard for how to declare the dependencies only needed for development. Most Package & Dependency management tools out there already had their own implementation of this feature and it is probably a good thing to use the standard. From a user perspective, this only means that we need to make changes in all our Python projects. My suggestion is: why not support both options?

Maintainability vs Value

From a tooling developer perspective it is understandable that you don't want to maintain several ways of solving a problem. What about the Developer Experience of all the users of the tool out there? Imagine the teams maintaining many projects with 10, 40 or even 100 different Microservices and libraries. Each one in its own git repo.

Another Python example: Pydantic

The `dict` method is deprecated; use `model_dump` instead. Deprecated in Pydantic V2.0 to be removed in V3.0.

I like Pydantic, it is a very useful tool with great features. The 2.0 release also came with significant performance improvements. But this change doesn't make sense to me. I understand that it probably fits better within the domain of Pydantic itself.

Does this have to be a breaking change? I would suggest to have the both alternatives there. Yes, it might be a little bit more of maintenance for you as a library developer. More importantly: your users can focus on adding value into their products instead of this mostly zero-added-value work.

Example three: SQLAlchemy

MovedIn20Warning: The ``declarative_base()`` function is now available as sqlalchemy.orm.declarative_base(). (deprecated since: 2.0)

This is probably also correct, from an internal SQLAchemy domain perspective. From a user perspective, this only means that we need to change a lot of existing code. The cost of having the code overlapping in two namespaces is probably low.

I am also a maintainer of tools, and I've also made mistakes, or design choices that turned out to be not that great later on. But I also actively have made the decision to not force users to make the kind of changes that are described in this post. I don't want to break things for users of the tool because of design choices made in the past.

Should the users change their workflows?

The main thing I work on today is Python tooling for Polylith, that is a Monorepo architecture. The changes introduced by uv, Pydantic and SQLAlchemy actually isn't that much work for the developer teams using Polylith today. You'll have only one place in the source code where these changes are needed. This setup is robust, and is ready for any unexpected breaking changes in the tools that are used. Sounds nice, doesn't it?



Top Photo by generated by Dall-E, prompted and modified afterwards by me.

Sunday, May 12, 2024

Pants & Polylith

But who is Luke and who is R2?
"Pants is a fast, scalable, user-friendly build system for codebases of all sizes"
"Polylith helps us build simple, maintainable, testable, and scalable backend systems"

Can we use both? I have tried that out, and here's my notes.

Why?

Because The Developer Experience.

Developer Experience is important, but what does that mean? For me, it is about keeping things simple. The ability to write, try out and reuse code without any context switching. By using one single setup for the REPL and the IDE, you will have everything at your fingertips.

The Polylith Architecture solves this by organizing code into smaller building blocks, or bricks, and separating code from the project-specific configurations. You have all the bricks and configs available in a Monorepo. For Python development, you create one single virtual environment for all your code and dependencies.

There is also tooling support for Polylith that is useful for visualizing the contents of the Monorepo, and for validating the setup. If you already are into Pantsbuild, the Polylith Architecture might be the missing Lego bricks you want to add for a great Developer Experience.

Powerful builds with Pants

Pantsbuild is a powerful build system. The pants tool resolves all the dependencies (by inspecting the source code itself), runs the tests and creates distributions in isolation. The tool also support the common Python tasks such as linting, type checking and formatting. It also has support for creating virtual environments.

Dude, where's my virtual environment?

In the Python Community, there is a convention to name the virtual environment in a certain way, usually .venv, and creating it at the Project root (this will also likely work well with the defaults of your IDE).

The virtual environment created by Pants is placed in a dists folder, and further in a Pants-specific folder structure. I found that the created virtual environment doesn't seem to include custom source paths (I guess that would be what Pants call roots).

Custom source paths is important for an IDE to locate the Python source code. Maybe there are built-in ways in Pantsbuild to solve that already? Package management tools like Poetry, Hatch and PDM have support for configuring custom source paths in the pyproject.toml and also creating virtual environments according to the Python Community conventions.

Note: If you are a PyCharm user, you can mark a folder as a source root manually and it will keep that information in a cache (probably a .pth file).

Example code and custom scripts

I have created an example repository, a monorepo using Pantsbuild and Polylith. You will find Python code and configurations according to the Polylith Architecture and the Pantsbuild configurations making it possible to use both tools. In the example repo I have added a script that adds source paths, based on the output from the pants roots command, to the virtual environment created by Pantsbuild. This is accomplished by adding a .pth file to the site_packages folder. For convenience, the script will also create a symlink to a .venv folder at the root of the repo.

Having the virtual environment properly setup, you can use the REPL (my favorite is IPython) with full access to the entire code base:

source .venv/bin/activate
ipython

With an activated virtual environment, you can also use all of the Polylith commands:

poly create
poly info
poly libs
poly deps
poly diff
poly check
poly sync

Pants & Polylith

Pantsbuild has a different take on building and packaging artifacts compared to other tools I've used. It has support for several languages and setups. Some features overlap with what's available in the well-known tooling in the Python community, such as Poetry. Some parts diverge from the common conventions.

Polylith has a different take on sharing code, and also have some overlapping features. Polylith is a Monorepo Architecture, with tooling support for visualizing the Monorepo. From what I've learned so far, the checks and code inspection features are the things you will find in both Pants and Polylith.

Pants operate on a file level. Polylith on the bricks level.

My gut feeling after learning about it and by experimenting, is that Pantsbuild and Polylith shares the same basic vision of software development in general and I have found them working really well together. There are some things I would like to have been a better fit, such as when selecting contents of the Pants-specific BUILD files vs the content in the project-specific pyproject.toml files.

Maybe I should develop a Pants Polylith plugin to fix that part. 🤔
How does that sound to you?


Resources


Top Photo by Studbee on Unsplash

Saturday, April 13, 2024

Write Less Code, You Must

An aspect of Python Software Development that is often overlooked, is Architecture (or Design) at the namespace, modules & functions level. My thoughts on Software Development in general is that it is important to try hard writing code that is Simple, and Easy to move from one place to another.

When having code written like this, it becomes less important if a feature was added in Service X, but a better fit would be Service Y when looking at it from a high-level Architectural perspective. All you need to do is move the code to the proper place, and you're all good. However, this will require that the actual code is moveable: i.e. having the features logically separated into functions, modules and namespace packages.

Less Problems

There's a lot of different opinions about this, naturally. I've seen it in in several public Python forums, and been surprised about the reactions about Python with (too) few lines of code in it. How is it even possible having too little of code?

My take on this in general is Less code is Less Problems.

An example

def my_something_function():
    # Validation
    
    # if valid 
    # else do something
    ... python code here

    # Checking

    # if this 
    # elif that
    # elif not this or not that
    # else do_something
    ... python code here

    # Data transformation

    # for each thing in the things
    #    do a network call and append to a list
    ... python code here

    # Yay, done
    return the_result

This type of function - when all of those things are processed within the function body - is not very testable. A unit test would likely need a bunch of mocking, patching and additional boilerplate test data code. Especially when there are network calls involved.

My approach on refactoring the code above would be to first identify the different tasks within this controller type of function, and begin by extracting each task into separate functions. Ideally these would be pure functions, accepting input and returning output.

At first, I would put the functions within the same module, close to at hand. Quite quickly, the original function has become a whole lot more testable, because the extracted functions can now easily be patched (my preference is using pytest monkeypatch). This approach would be my interpretation of developing software towards a clean code ideal. There is no need for a Dependency Injection framework or any unnecessary complex OOP-style hierarchy to accomplish it.

In addition to testability, the Python code becomes runnable and REPL-friendly. You can now refactor, develop and test-run the individual functions in the REPL. This is a very fast workflow for a developer. Read more about REPL Driven Development in Python here.

With the features living in separate isolated functions, you will likely begin to identify patterns:

"- Hey, this part does this specific thing & could be put in that namespace"

When moving code into a namespace package, the functions become reusable. Other parts of the application - or, if you have a Monorepo containing several services - can now use one and the same source code. The same rows of code, located in a single place of the repo. You will likely structure the repo with many namespace packages, each one containing one or a couple of modules with functions that ideally do one thing. It kind of sounds like the Unix philosophy, doesn't it?

This is how I try to write code on a daily basis, at work and when developing Open Source things. I use tools like SonarCloud and CodeScene to help me keep going in this direction. I've written about that before. The Open source code that I focus on these days (Polylith) has 0% Code Duplications, 0% Code Smells and about a 9.96 long-term Quality Code Scoring. The 0.04 that is left has been an active decision by me and is because of endpoints having 5+ input arguments. It makes sense for me to keep it like that there, but not in functions within the app itself where an options object is a better choice.

This aspect of Software Development is, from my point of view, very important. Even more important than the common Microservices/Events/REST/CQRS debates when Architecture is the topic of discussion. This was my Saturday afternoon reflections, and I thank you for reading this post. ☀️

Top Photo by Remy Gieling on Unsplash

Wednesday, November 15, 2023

A Coding Copilot

When developing software, I spend most of the time thinking & talking about the problems to solve: the what, the why and the how. The thinking-part works best for me when I'm actually away from the desktop, such as walking outdoors or even when grabbing a cup of coffee & a banana by the office kitchen. 🍌

Talking is a really nice thing, we should try that more often in combination with listening to what others have say. Even when not having any human around to chat with, there is always the rubber duck. Speak to it!

Problem Solving

Mob programming takes the Thinking & Talking to the next level. I am, strangely enough, surprised almost every time how great mob and pair programming is for software development. I tend to forget that. It's probably easy to fall back into old familiar behavior.

When figuring out what to try out, the actual typing is done pretty fast for me. A big part of the productivity boost is inspiration and the joy of solving problems with programming. I think this is valid for most creative and problem-solving work.

Everyday practicing

I try hard every day to write clear & concise code. Practicing, learning ... and walking. I really like the Functional approach to programming: separating data from behavior, actions from calculations. I should probably use GitHub Copilot or ChatGPT more, but haven't yet found the need to go all-in (aren't the AI suggestions a bit verbose, or am I doing things wrong?). Those types of in-editor copilots are cool, definitely, and are for sure here to stay. Currently, I find more value in a different kind of automated guidance.

CodeScene

When working on my Open Source Project, the Python tools for the Polylith Architecture, I am guided by tools like SonarCloud and CodeScene. I guess there are some AI involved quite heavily in there too. I especially appreciate the code reviews & even more the CodeScene long-term analysis about the effects of Tech Debt. It's like having a co-pilot, or even a Teacher, guiding you during the development to make you a better software developer than before.

This is different from the kind of review a team of humans usually do when sharing feedback on Pull Requests or even during mob programming sessions.

Even if I sometimes disagree with things the tools report on being a problem, I go ahead and refactor the code anyway. Then, when doing the refactoring, I quickly realize that the code is actually transforming into something simpler and clearer than before. SonarCloud is more into the low level details, and lets me know about code duplications or code smells. We don't want that, no. Better fix that too.

Coding Style

The feedback from these kind of tools is helping me to get closer to writing the type of code I want to write: minimalistic, readable and functional. A coding style that also is a very good fit for the Polylith Architecture, even if that thing isn't about how the code is written. You are encouraged to write in a readable & functional style by the structuring of code and by having all code at your fingertips, ready to experiment with in the REPL or in a Notebook.

CodeScene, SonarCloud and Polylith: all of them helping me in my journey to be a better Developer. Maybe I'll throw in Copilot in there too eventually.

Top Photo by Jamie Templeton on Unsplash

Saturday, September 30, 2023

Software and Projects

How can we simplify things, to add value as early as possible?

Software Projects is a misconception within Software Development. When organizing work into Projects, one might think that there also is a need to estimate the things to be done. Because the Project itself is by definition something that will end, or more likely be delayed.

From my experience, estimation is only adding anxiety and sometimes actually delaying value. I have experienced the same thing with Projects and fixed release dates.

Instead, we could flip it: how can we simplify, to add value for our users as early as possible?

Flip it!

In a team that I was part of some time ago, the Product Managers challenged us by asking those kind of questions. We (the Developers) were at the beginning intimidated, because we had the idea of building the perfect kind of feature and usually we spent time on figuring out & cover as many scenarios as we could imagine. The not-great thing with that approach is that it will likely increase the cost, because it would take longer time and more effort to deliver value for the users of the product.

Think Different

The Product Management folks kept challenging us to think different, and we begun to find ways of delivering smaller parts of the product within days (instead of months). We wouldn't be able to release an entire feature, of course. Far from it. Instead, it would be something - sometimes just a tiny addition - that people could use to simplify their daily work life. They actually did that, we saw it ourselves. There was value added, within a couple of days of development!

Smaller parts

There was no need for us (the Dev Team) to put any Fibonacci numbers or estimating hours to the tasks we identified should be developed. We stopped doing those stressful Big Bang Releases of huge chunks of code. Instead, we found ways to simplify tasks - splitting them out into several smaller parts - to make it possible to push the work to production within days. In my opinion, Projects, Estimation and Deadlines are rarely adding value. Why are there so many Organizations out there still doing that?

Top photo by Patrick Fore on Unsplash