Pipeline Design
:::info Why Pipeline?
- A choice made by senior team members.
- Pipeline's advantage: it allows
VSeedto independently control the execution flow for each chart type. With good design, each chart type's implementation is both decoupled and locally reusable, giving each chart type perfect control over every detail — this is what Pipeline brings, and exactly whatVSeedneeds most. - The downsides of the Pipeline pattern can all be avoided at design time — by keeping individual
Pipesizes small and minimizing dependencies betweenPipes. - After four generations of Pipeline design and optimization, this is the fifth version — the pitfalls have already been navigated. :::
What is a Pipeline?
Pipeline is a powerful abstraction and engineering practice that decomposes a complex task into a series of connected, sequentially executed smaller steps. Its design philosophy is deeply influenced by the core ideas of functional programming (FP).
Pipeline Advantages:
- Modularity: Atomic implementation — compose atoms into modules.
- Automation: Simply define the input to automatically get the output, without worrying about internal implementation.
- Pure functions: Given a specified input, the expected output is always produced — a characteristic of pure functions.
- Parallelism: Naturally supports concurrency.
- Reusability: Every module can be reused.
- Testability: In theory, every module is independent and can be tested individually to ensure quality.
- Traceability: Clear inputs and outputs at each stage make it easy to locate issues and monitor process state.
- Cacheability: In theory, the output of individual
Pipes can be cached, avoiding redundant computation and improving efficiency.
Pipeline Disadvantages:
- Sequential dependencies: When Pipes have ordering dependencies, the cognitive cost increases — you need to understand earlier stages to understand later ones. Deep overall understanding is needed to quickly locate issues.
- Debugging cost: Since Pipeline executes sequentially, a failure at any stage causes the entire Pipeline to fail. This makes debugging harder, as you need to locate the failing stage and fix it.
- Performance: Since Pipeline executes sequentially, each stage's output must wait for the previous stage to complete, which can cause performance issues — especially when one stage takes a long time.
- Functional programming: Requires learning new concepts, which carries some onboarding cost. As a result, design principles and implementation details need to be documented in the contribution guide for other developers.
How to Write Pipelines in VSeed?
Pipe Composition Pattern
Multiple functional Pipes can be composed into a larger functional Pipe, or combined into a more complex Pipeline.
In VSeed, a complete Pipeline corresponds to the implementation of one chart type. By describing the composition of Pipes, different chart types can be created. During the Pipeline composition phase, you don't need to worry about each pipe's specific implementation.
Composition for Differences
Example:
Line charts and area charts share many reusable features — labels, legends, axes, etc. — but area charts have area mark styles while line charts don't. The pipeline resolves this difference through functional Pipe composition, with no if statements needed.
Pipe Adapter Pattern
Beyond composition, building Pipes often involves conditions. To handle different conditional Pipe combinations, VSeed makes heavy use of Pipe adapters.
Conditional Composition
Example:
Line charts support pivot mode — without pivot, rendered by VChart (output VChart spec); with pivot, rendered by VTable (output VTable spec).
Pivot line charts need to reuse most basic line chart features (labels, legends, axes, etc.), so the adapter pattern adapts regular line chart Pipes into pivot line chart Pipes.
In summary, each adapter is essentially an if-else — hidden conditions inside a pipe are abstracted into an adapter, pushing the if-else to the top level. This results in a Pipeline with clearer dependencies and lower maintenance cost.
The Most Basic Unit: Functional Pipe
VSeed expects all chart types to use features as the most basic unit, providing sufficient reusability and extensibility — building a chart type's pipeline bottom-up. Each functional Pipe should be an independent, testable, and reusable module.
The most critical point: abstract differences into different Pipes (write fewer if-else statements), rather than writing one large, all-in-one Pipe.
Flat Functional Pipes
Example:
Bar, column, line, area, and scatter charts all have X and Y axes — similar but slightly different. If you write one large axes pipe, it might look like this:
The better approach is to abstract the differences into separate Pipes and compose them at the pipeline level:
All chart type divergences should occur above the Pipeline level. Unless absolutely necessary, Pipelines should not branch based on chart type.
This composition approach aligns with VSeed's design philosophy: use a flatter composition of functional Pipes instead of if-else conditions in a single large Pipe.