(lean) add pull system

This commit is contained in:
Julien Calixte
2023-07-23 21:08:46 +02:00
parent 48733ab131
commit eaec93c071
6 changed files with 71 additions and 20 deletions

View File

@@ -18,8 +18,8 @@ const featuresDone = computed(() =>
.sort((a, b) => (a.leadTime > b.leadTime ? -1 : 1)) .sort((a, b) => (a.leadTime > b.leadTime ? -1 : 1))
) )
const remainingBlueBuckets = computed(() => const remainingBlueBins = computed(() =>
Math.max(0, props.step.blueBuckets - featuresDone.value.length) Math.max(0, props.step.blueBins - featuresDone.value.length)
) )
const hasFeaturesInProgress = computed( const hasFeaturesInProgress = computed(
() => featuresInProgress.value.length > 0 () => featuresInProgress.value.length > 0
@@ -48,10 +48,10 @@ const isLive = computed(
<section class="done"> <section class="done">
<h5>📝 [{{ featuresDone.length }}]</h5> <h5>📝 [{{ featuresDone.length }}]</h5>
<div> <div>
<div class="blue-bin-container"> <div v-if="!isLive" class="blue-bin-container">
<div <div
v-for="blueBucket in remainingBlueBuckets" v-for="blueBin in remainingBlueBins"
:key="blueBucket" :key="blueBin"
class="bin blue-bin" class="bin blue-bin"
> >
Blue bucket Blue bucket

View File

@@ -17,9 +17,8 @@ onMounted(() => featureStore.initBoard())
{{ featureStore.meanLeadTime }} days {{ featureStore.meanLeadTime }} days
</div> </div>
<div> <div>
<button @click="featureStore.nextDay('push')"> <button @click="featureStore.nextDay('push')">push system</button>
add feature and next day <button @click="featureStore.nextDay('pull')">pull system</button>
</button>
<button @click="featureStore.nextDay('turn-off')"> <button @click="featureStore.nextDay('turn-off')">
next day without new feature next day without new feature
</button> </button>

View File

@@ -75,10 +75,12 @@ export const nextDay = ({
backlog, backlog,
features, features,
initialStep, initialStep,
steps,
strategy strategy
}: { }: {
backlog: Feature[] backlog: Feature[]
features: Feature[] features: Feature[]
steps: FeatureStep[]
initialStep: number initialStep: number
strategy: Strategy strategy: Strategy
}): Feature[] => { }): Feature[] => {
@@ -95,7 +97,27 @@ export const nextDay = ({
feature.status = 'done' feature.status = 'done'
break break
case 'done': case 'done':
if (strategy === 'pull') {
const nextStep = steps.find(
(step) => step.stepIndex === feature.step - 1
)
if (!nextStep) {
break
}
const hasBlueBinAvailableNextStep =
nextStep.blueBins -
features.filter(
(f) => f.step === feature.step - 1 && f.status === 'done'
).length >
0
if (hasBlueBinAvailableNextStep) {
feature.status = 'doing' feature.status = 'doing'
}
} else {
feature.status = 'doing'
}
if ( if (
hasQualityIssue( hasQualityIssue(
@@ -114,13 +136,41 @@ export const nextDay = ({
} }
}) })
if (strategy === 'push' && features.length < MAX_FEATURES) { if (features.length < MAX_FEATURES) {
switch (strategy) {
case 'push': {
const [newFeature] = popNElement(backlog, 1)
if (newFeature) {
features.push({ ...newFeature, step: initialStep })
}
break
}
case 'pull': {
const firstStep = steps.find((step) => step.stepIndex === initialStep)
if (!firstStep) {
break
}
const hasBlueBinAvailableOnFirstStep =
firstStep.blueBins -
features.filter(
(f) => f.step === initialStep && f.status === 'done'
).length >
0
if (hasBlueBinAvailableOnFirstStep) {
const [newFeature] = popNElement(backlog, 1) const [newFeature] = popNElement(backlog, 1)
if (newFeature) { if (newFeature) {
features.push({ ...newFeature, step: initialStep }) features.push({ ...newFeature, step: initialStep })
} }
} }
}
case 'turn-off':
break
}
}
return features return features
} }

View File

@@ -1,6 +1,6 @@
export type FeatureStep = { export type FeatureStep = {
title: string title: string
blueBuckets: number blueBins: number
stepIndex: number stepIndex: number
} }
@@ -8,26 +8,26 @@ export const featureSteps: FeatureStep[] = [
{ {
title: 'Product', title: 'Product',
stepIndex: 4, stepIndex: 4,
blueBuckets: 2 blueBins: 2
}, },
{ {
title: 'Design', title: 'Design',
stepIndex: 3, stepIndex: 3,
blueBuckets: 2 blueBins: 2
}, },
{ {
title: 'Development', title: 'Development',
stepIndex: 2, stepIndex: 2,
blueBuckets: 2 blueBins: 2
}, },
{ {
title: 'Test', title: 'Test',
stepIndex: 1, stepIndex: 1,
blueBuckets: 2 blueBins: 2
}, },
{ {
title: 'Release', title: 'Release',
stepIndex: 0, stepIndex: 0,
blueBuckets: 0 blueBins: Infinity
} }
] ]

View File

@@ -19,6 +19,7 @@ const resetMeta = (): State['meta'] => ({
totalDays: 0, totalDays: 0,
strategy: { strategy: {
push: 0, push: 0,
pull: 0,
'turn-off': 0 'turn-off': 0
} }
}) })
@@ -41,6 +42,7 @@ export const useFeatureStore = defineStore('feature', {
this.features = nextDay({ this.features = nextDay({
backlog: this.backlog, backlog: this.backlog,
features: this.features, features: this.features,
steps: this.steps,
initialStep: this.steps[0].stepIndex, initialStep: this.steps[0].stepIndex,
strategy strategy
}) })

View File

@@ -1 +1 @@
export type Strategy = 'push' | 'turn-off' export type Strategy = 'push' | 'pull' | 'turn-off'