article: better agencement
This commit is contained in:
@@ -18,7 +18,7 @@ import SimulationDashboard from '@/modules/pull-system/simulation/SimulationDash
|
|||||||
<!-- <h2>Ekiden (駅伝): long-distance running relay race</h2> -->
|
<!-- <h2>Ekiden (駅伝): long-distance running relay race</h2> -->
|
||||||
<FlowIntro class="text" />
|
<FlowIntro class="text" />
|
||||||
<SeparatorIcon />
|
<SeparatorIcon />
|
||||||
<!-- <FlowHypothesis class="text" /> -->
|
<FlowHypothesis class="text" />
|
||||||
<!-- <SeparatorIcon /> -->
|
<!-- <SeparatorIcon /> -->
|
||||||
<FlowSetup class="text" />
|
<FlowSetup class="text" />
|
||||||
<FlowDashboard class="above" />
|
<FlowDashboard class="above" />
|
||||||
|
|||||||
@@ -1,23 +1,40 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import PullSystemIcon from '@/icons/PullSystemIcon.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flow-conclusion">
|
<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>
|
<p>
|
||||||
When money and pressure are in the game, fear, uncertainty, and doubt
|
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
|
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.
|
nothing to do, it becomes a disaster: money are being burned.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Teams will overproduce. They will do every pieces they can as they are
|
Teams will overproduce. They will do every pieces they can as they can:
|
||||||
autonomous: product team will pitch their features, designers will design
|
product team will prepare their features, designers will design every
|
||||||
every pages, developers will rush to code forgetting why the customer
|
screens, developers will rush to code. Then, they struggle to get these
|
||||||
needs this precise feature. They will then struggle to get these pieces to
|
pieces to the very end. So the fear of having nothing to give to the next
|
||||||
the very end when they will transfer them to the others teams. So the fear
|
team pushes us to produce just in case. Bugs lead to more bugs that lead
|
||||||
of having nothing to give to the next team pushes us to produce just in
|
to more bugs. The productivity drops.
|
||||||
case. Bugs lead to more bugs that lead to more bugs. Multitasking will
|
|
||||||
drastically drop the productivity.
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
But the best way to succeed is to ask: "Is this what you need? How can I
|
So the <PullSystemIcon /> pull system is here to change our priority.
|
||||||
help you?".
|
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
|
<!-- Just like in Ekiden, handovers are where the real struggles
|
||||||
happen but we're on the same race, together. -->
|
happen but we're on the same race, together. -->
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -2,7 +2,18 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flow-hypothesis">
|
<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>
|
<ol>
|
||||||
<li>
|
<li>
|
||||||
it takes the same amount of time for each team to complete a task
|
it takes the same amount of time for each team to complete a task
|
||||||
@@ -19,7 +30,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li>release team never fails</li>
|
<li>release team never fails</li>
|
||||||
<li>there is no limit on how many defects a feature can have.</li>
|
<li>there is no limit on how many defects a feature can have.</li>
|
||||||
</ol>
|
</ol> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import PullSystemIcon from '@/icons/PullSystemIcon.vue'
|
||||||
|
import PushSystemIcon from '@/icons/PushSystemIcon.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flow-conclusion">
|
<div class="flow-conclusion">
|
||||||
<!-- TODO: Mettre ici le comportement en pull system et en push system.
|
<!-- 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.
|
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 -->
|
Il n'empêche que dans les deux systèmes il y ai de la création de défaut -->
|
||||||
<p>
|
<p>
|
||||||
Pull system wins! The fact that
|
Not so obvious... So what can we learn? What are the patterns we can
|
||||||
<a
|
identify?
|
||||||
target="_blank"
|
</p>
|
||||||
rel="noopener noreferrer"
|
<p>
|
||||||
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"
|
In a primarly <PushSystemIcon /> push system, we see teams struggling and
|
||||||
>faster is slower
|
stuck reworking the same features again and again to finally having all
|
||||||
</a>
|
features live all at once.
|
||||||
is counter-intuitive but it is a fact. The more we push the more we are
|
</p>
|
||||||
slowing down the system.
|
<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>
|
||||||
<p>
|
<p>
|
||||||
Before any conclusion, comparing two simulations is not enough. Let's be
|
Before any conclusion, comparing two simulations is not enough. Let's be
|
||||||
more scientific here and let's generate 200 projects delivering 200
|
more scientific here and let's generate 200 projects delivering the 20
|
||||||
features each and see what happens.
|
features of the Newsletter app and see what happens.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -10,6 +10,20 @@ const featureStore = useFeatureStore()
|
|||||||
<div class="flow-dashboard">
|
<div class="flow-dashboard">
|
||||||
<SeparatorIcon />
|
<SeparatorIcon />
|
||||||
<div class="row cards">
|
<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">
|
<div class="card">
|
||||||
Features
|
Features
|
||||||
<span class="numeric">
|
<span class="numeric">
|
||||||
@@ -24,10 +38,6 @@ const featureStore = useFeatureStore()
|
|||||||
{{ featureStore.meta.teamWorkExperience.toFixed(2) }}
|
{{ featureStore.meta.teamWorkExperience.toFixed(2) }}
|
||||||
</span>
|
</span>
|
||||||
</div> -->
|
</div> -->
|
||||||
<div class="card">
|
|
||||||
Mean complexity
|
|
||||||
<div class="numeric">{{ featureStore.meanComplexity }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
Mean lead time
|
Mean lead time
|
||||||
<div class="data">
|
<div class="data">
|
||||||
@@ -43,18 +53,12 @@ const featureStore = useFeatureStore()
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
Days
|
Quality issues
|
||||||
<div class="data">
|
<div class="numeric">{{ featureStore.qualityIssues }}</div>
|
||||||
<span class="numeric">{{ featureStore.meta.totalDays }}</span
|
|
||||||
>d
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
ETA
|
Mean complexity
|
||||||
<div class="data">
|
<div class="numeric">{{ featureStore.meanComplexity }}</div>
|
||||||
<span class="numeric">{{ featureStore.eta }}</span>
|
|
||||||
days
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<FlowControls />
|
<FlowControls />
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ const HARD_STOP = 5000
|
|||||||
|
|
||||||
const getQualityIssue = ({
|
const getQualityIssue = ({
|
||||||
complexity,
|
complexity,
|
||||||
tasksInParallel,
|
featuresInParallel,
|
||||||
teamWorkExperience
|
teamWorkExperience
|
||||||
}: {
|
}: {
|
||||||
complexity: number
|
complexity: number
|
||||||
tasksInParallel: number
|
featuresInParallel: number
|
||||||
teamWorkExperience: number
|
teamWorkExperience: number
|
||||||
}): boolean => {
|
}): boolean => {
|
||||||
const qualityProbability = getQualityProbability(
|
const qualityProbability = getQualityProbability(
|
||||||
@@ -35,7 +35,7 @@ const getQualityIssue = ({
|
|||||||
teamWorkExperience
|
teamWorkExperience
|
||||||
)
|
)
|
||||||
|
|
||||||
const multiplicator = getOverburdenMultiplicator(tasksInParallel)
|
const multiplicator = getOverburdenMultiplicator(featuresInParallel)
|
||||||
const quality = randomFloat(0, 1)
|
const quality = randomFloat(0, 1)
|
||||||
|
|
||||||
return quality > qualityProbability / multiplicator
|
return quality > qualityProbability / multiplicator
|
||||||
@@ -91,7 +91,7 @@ export const initBoard = (
|
|||||||
initialFeatures.forEach((feature) => {
|
initialFeatures.forEach((feature) => {
|
||||||
const step = pickRandomElement(steps)
|
const step = pickRandomElement(steps)
|
||||||
feature.status = pickRandomElement(['doing', 'done'])
|
feature.status = pickRandomElement(['doing', 'done'])
|
||||||
feature.step = Math.max(step.stepIndex, 1)
|
feature.step = step.stepIndex
|
||||||
feature.qualityIssue = 0
|
feature.qualityIssue = 0
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ export const getFeaturesForNextDay = ({
|
|||||||
|
|
||||||
const hasQualityIssue = getQualityIssue({
|
const hasQualityIssue = getQualityIssue({
|
||||||
complexity: feature.complexity,
|
complexity: feature.complexity,
|
||||||
tasksInParallel: features.filter(
|
featuresInParallel: features.filter(
|
||||||
(f) => f.status === 'doing' && f.step === feature.step
|
(f) => f.status === 'doing' && f.step === feature.step
|
||||||
).length,
|
).length,
|
||||||
teamWorkExperience
|
teamWorkExperience
|
||||||
|
|||||||
@@ -37,7 +37,10 @@ export const useFeatureStore = defineStore('feature', {
|
|||||||
async initBoard(type: 'bird' | 'mobile-app', limit?: number) {
|
async initBoard(type: 'bird' | 'mobile-app', limit?: number) {
|
||||||
this.backlog = newBacklog(type, limit)
|
this.backlog = newBacklog(type, limit)
|
||||||
this.steps = featureSteps
|
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(
|
this.backlog = this.backlog.filter(
|
||||||
(l) => !this.features.find((f) => f.name === l.name)
|
(l) => !this.features.find((f) => f.name === l.name)
|
||||||
@@ -56,6 +59,8 @@ export const useFeatureStore = defineStore('feature', {
|
|||||||
isProjectFinished: (state) => isProjectFinished(state.features),
|
isProjectFinished: (state) => isProjectFinished(state.features),
|
||||||
meanComplexity: (state) => getMeanComplexity(state.features),
|
meanComplexity: (state) => getMeanComplexity(state.features),
|
||||||
meanLeadTime: (state) => getMeanLeadTime(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),
|
meanQualityIssue: (state) => getMeanQualityIssue(state.features),
|
||||||
taktTime: (state): string => {
|
taktTime: (state): string => {
|
||||||
const taktTime = (
|
const taktTime = (
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export const useSimulationStore = defineStore('dashboard', {
|
|||||||
actions: {
|
actions: {
|
||||||
async simulate(strategy: Strategy) {
|
async simulate(strategy: Strategy) {
|
||||||
const steps = featureSteps
|
const steps = featureSteps
|
||||||
const backlog = await instance.newBacklog('bird')
|
const backlog = await instance.newBacklog('mobile-app')
|
||||||
const features = await instance.initBoard(steps, backlog)
|
const features = await instance.initBoard(steps, backlog)
|
||||||
|
|
||||||
const newState = await instance.simulate(
|
const newState = await instance.simulate(
|
||||||
|
|||||||
Reference in New Issue
Block a user