article: better agencement

This commit is contained in:
Julien Calixte
2025-01-03 18:15:53 +01:00
parent 82d16ef0cc
commit cb3e6acc87
8 changed files with 93 additions and 45 deletions

View File

@@ -18,7 +18,7 @@ import SimulationDashboard from '@/modules/pull-system/simulation/SimulationDash
<!-- <h2>Ekiden (駅伝): long-distance running relay race</h2> -->
<FlowIntro class="text" />
<SeparatorIcon />
<!-- <FlowHypothesis class="text" /> -->
<FlowHypothesis class="text" />
<!-- <SeparatorIcon /> -->
<FlowSetup class="text" />
<FlowDashboard class="above" />

View File

@@ -1,23 +1,40 @@
<script setup lang="ts">
import PullSystemIcon from '@/icons/PullSystemIcon.vue'
</script>
<template>
<div class="flow-conclusion">
<p>
The fact that
<a
target="_blank"
rel="noopener noreferrer"
href="https://journals.aps.org/pre/abstract/10.1103/PhysRevE.96.052303#:~:text=The%20%E2%80%9Cfaster%2Dis%2Dslower,evacuation%20time%20can%20be%20achieved"
>faster is slower</a
>
is counter-intuitive but it is a fact. The more we push the more we are
slowing down the system.
</p>
<p>
When money and pressure are in the game, fear, uncertainty, and doubt
spread out rapidly. So we rush, as fast as we can, and when a team has
nothing to do, it becomes a disaster: money are being burned.
</p>
<p>
Teams will overproduce. They will do every pieces they can as they are
autonomous: product team will pitch their features, designers will design
every pages, developers will rush to code forgetting why the customer
needs this precise feature. They will then struggle to get these pieces to
the very end when they will transfer them to the others teams. So the fear
of having nothing to give to the next team pushes us to produce just in
case. Bugs lead to more bugs that lead to more bugs. Multitasking will
drastically drop the productivity.
Teams will overproduce. They will do every pieces they can as they can:
product team will prepare their features, designers will design every
screens, developers will rush to code. Then, they struggle to get these
pieces to the very end. So the fear of having nothing to give to the next
team pushes us to produce just in case. Bugs lead to more bugs that lead
to more bugs. The productivity drops.
</p>
<p>
But the best way to succeed is to ask: "Is this what you need? How can I
help you?".
So the <PullSystemIcon /> pull system is here to change our priority.
Developpers are the clients of the Designer team, as well as Designers are
the client of the Product team. Focusing on the lead time is asking to the
next team: "Is this what you need? How can we help each other?". This is
the question of team work.
<!-- Just like in Ekiden, handovers are where the real struggles
happen but we're on the same race, together. -->
</p>

View File

@@ -2,7 +2,18 @@
<template>
<div class="flow-hypothesis">
<p>Here our hypothesis:</p>
We need some hypothesis to start with. Here are ours:
<ol>
<li>
The more feature done in parallel, the more it is difficult to focus and
it is more likely to introduce a defect.
</li>
<li>
it takes the same amount of time for each team to complete a task
<span class="meaning">same task time</span>
</li>
</ol>
<!-- <p>Here our hypothesis:</p>
<ol>
<li>
it takes the same amount of time for each team to complete a task
@@ -19,7 +30,7 @@
</li>
<li>release team never fails</li>
<li>there is no limit on how many defects a feature can have.</li>
</ol>
</ol> -->
</div>
</template>

View File

@@ -1,3 +1,8 @@
<script setup lang="ts">
import PullSystemIcon from '@/icons/PullSystemIcon.vue'
import PushSystemIcon from '@/icons/PushSystemIcon.vue'
</script>
<template>
<div class="flow-conclusion">
<!-- TODO: Mettre ici le comportement en pull system et en push system.
@@ -5,20 +10,26 @@
En pull system, on voit petit à petit du danse avec une passation de plus en plus facile.
Il n'empêche que dans les deux systèmes il y ai de la création de défaut -->
<p>
Pull system wins! The fact that
<a
target="_blank"
rel="noopener noreferrer"
href="https://journals.aps.org/pre/abstract/10.1103/PhysRevE.96.052303#:~:text=The%20%E2%80%9Cfaster%2Dis%2Dslower,evacuation%20time%20can%20be%20achieved"
>faster is slower
</a>
is counter-intuitive but it is a fact. The more we push the more we are
slowing down the system.
Not so obvious... So what can we learn? What are the patterns we can
identify?
</p>
<p>
In a primarly <PushSystemIcon /> push system, we see teams struggling and
stuck reworking the same features again and again to finally having all
features live all at once.
</p>
<p>
In a primarly <PullSystemIcon /> pull system however, we see a smoother
flow of work with teams able to pass on features more easily and
continuously, leading to a more steady and predictable delivery. It's not
perfect, but you may have see a balai of features when teams work and
finish at the same time. 💃🏽
<!-- TODO complete this sentence -->
</p>
<p>
Before any conclusion, comparing two simulations is not enough. Let's be
more scientific here and let's generate 200 projects delivering 200
features each and see what happens.
more scientific here and let's generate 200 projects delivering the 20
features of the Newsletter app and see what happens.
</p>
</div>
</template>

View File

@@ -10,6 +10,20 @@ const featureStore = useFeatureStore()
<div class="flow-dashboard">
<SeparatorIcon />
<div class="row cards">
<div class="card">
Days
<div class="data">
<span class="numeric">{{ featureStore.meta.totalDays }}</span
>d
</div>
</div>
<div class="card">
ETA
<div class="data">
<span class="numeric">{{ featureStore.eta }}</span>
days
</div>
</div>
<div class="card">
Features
<span class="numeric">
@@ -24,10 +38,6 @@ const featureStore = useFeatureStore()
{{ featureStore.meta.teamWorkExperience.toFixed(2) }}
</span>
</div> -->
<div class="card">
Mean complexity
<div class="numeric">{{ featureStore.meanComplexity }}</div>
</div>
<div class="card">
Mean lead time
<div class="data">
@@ -43,18 +53,12 @@ const featureStore = useFeatureStore()
</div>
</div>
<div class="card">
Days
<div class="data">
<span class="numeric">{{ featureStore.meta.totalDays }}</span
>d
</div>
Quality issues
<div class="numeric">{{ featureStore.qualityIssues }}</div>
</div>
<div class="card">
ETA
<div class="data">
<span class="numeric">{{ featureStore.eta }}</span>
days
</div>
Mean complexity
<div class="numeric">{{ featureStore.meanComplexity }}</div>
</div>
</div>
<FlowControls />

View File

@@ -23,11 +23,11 @@ const HARD_STOP = 5000
const getQualityIssue = ({
complexity,
tasksInParallel,
featuresInParallel,
teamWorkExperience
}: {
complexity: number
tasksInParallel: number
featuresInParallel: number
teamWorkExperience: number
}): boolean => {
const qualityProbability = getQualityProbability(
@@ -35,7 +35,7 @@ const getQualityIssue = ({
teamWorkExperience
)
const multiplicator = getOverburdenMultiplicator(tasksInParallel)
const multiplicator = getOverburdenMultiplicator(featuresInParallel)
const quality = randomFloat(0, 1)
return quality > qualityProbability / multiplicator
@@ -91,7 +91,7 @@ export const initBoard = (
initialFeatures.forEach((feature) => {
const step = pickRandomElement(steps)
feature.status = pickRandomElement(['doing', 'done'])
feature.step = Math.max(step.stepIndex, 1)
feature.step = step.stepIndex
feature.qualityIssue = 0
})
@@ -141,7 +141,7 @@ export const getFeaturesForNextDay = ({
const hasQualityIssue = getQualityIssue({
complexity: feature.complexity,
tasksInParallel: features.filter(
featuresInParallel: features.filter(
(f) => f.status === 'doing' && f.step === feature.step
).length,
teamWorkExperience

View File

@@ -37,7 +37,10 @@ export const useFeatureStore = defineStore('feature', {
async initBoard(type: 'bird' | 'mobile-app', limit?: number) {
this.backlog = newBacklog(type, limit)
this.steps = featureSteps
this.features = initBoard(this.steps, this.backlog)
const initialSteps = featureSteps.filter(
(step) => step.title !== 'Release' && step.title !== 'Development'
)
this.features = initBoard(initialSteps, this.backlog)
this.backlog = this.backlog.filter(
(l) => !this.features.find((f) => f.name === l.name)
@@ -56,6 +59,8 @@ export const useFeatureStore = defineStore('feature', {
isProjectFinished: (state) => isProjectFinished(state.features),
meanComplexity: (state) => getMeanComplexity(state.features),
meanLeadTime: (state) => getMeanLeadTime(state.features),
qualityIssues: (state) =>
state.features.map((f) => f.qualityIssue).reduce((a, b) => a + b, 0),
meanQualityIssue: (state) => getMeanQualityIssue(state.features),
taktTime: (state): string => {
const taktTime = (

View File

@@ -66,7 +66,7 @@ export const useSimulationStore = defineStore('dashboard', {
actions: {
async simulate(strategy: Strategy) {
const steps = featureSteps
const backlog = await instance.newBacklog('bird')
const backlog = await instance.newBacklog('mobile-app')
const features = await instance.initBoard(steps, backlog)
const newState = await instance.simulate(