diff --git a/LEVIT_REVIEW.md b/LEVIT_REVIEW.md new file mode 100644 index 0000000..81f37de --- /dev/null +++ b/LEVIT_REVIEW.md @@ -0,0 +1,78 @@ +# Levit Framework Review + +**Reviewer Persona:** Senior Flutter Developer (Riverpod/Functional Programming advocate). +**Date:** 2026-01-29 + +## Executive Summary + +Levit is a fascinating "anti-Riverpod" in many ways. While Riverpod chases compile-time safety, immutability, and explicit graphs, Levit doubles down on **runtime performance**, **mutability**, and **implicit "magic" (Observation by Access)**. + +It feels like a modern, highly optimized re-imagining of GetX/MobX, stripping away the bloat and focusing purely on speed and clean syntax. + +**Verdict:** It is dangerous but incredibly fast. It trades safety for velocity and raw performance. + +--- + +## 1. DX (Developer Experience) + +### The Good +* **Zero Code Gen:** This is the killer feature. Riverpod's `riverpod_generator` is great, but the build runner lag is real. Levit gives you a similar "concise" feel (`0.lx`) without the build step. +* **Syntax:** `.lx` extensions and `LWatch` are clean. Writing `count.value++` is undeniably faster than `ref.read(provider.notifier).state++`. +* **Async Pattern Matching:** The `LxStatus` sealed class usage in Dart 3 is beautiful. It feels even more idiomatic than `AsyncValue.when` because it uses standard switch expressions. +* **LWatch:** The "hooks-like" behavior without the "rules of hooks" is a massive DX win. You just use the value, and the widget rebuilds. No `ref.watch` dance. + +### The Bad +* **Runtime Dependency Injection:** This is my biggest gripe as a Riverpod user. `Ls.find()` throws at *runtime*. Riverpod providers are compile-time safe constants. In a large team, Levit requires strict discipline to avoid "Service Not Found" crashes. +* **Hidden Dependencies:** In Riverpod, looking at a Provider's signature tells you what it needs (via `ref`). In Levit (and GetX), dependencies are pulled from the ether (`Ls.find`). This makes unit testing harder because you have to mock the global scope, rather than just passing arguments. +* **Mutable State:** Mutability is the root of many bugs. Levit embraces it. While it offers "transactional" batching, it still lacks the time-travel debugging and strict state history that immutable state (Freezed/Riverpod) offers by default. + +### The Verdict on DX +**8/10.** Faster to write than Riverpod, but "looser" and less safe. It feels like driving a sports car without a seatbelt. + +--- + +## 2. Performance + +### Analysis +I dug into `levit_reactive` and the implementation is **impressive**. +* **Fast Paths:** The code is riddled with "Fast Path" checks. If you aren't using middleware, it skips entire blocks of logic. +* **Deduplication:** The "diamond problem" handling in the graph propagation is mathematically correct and optimized. +* **Batching:** The `Lx.batch` implementation is solid. + +### Benchmarks +The provided benchmarks claim Levit is ~15x faster than Riverpod in rapid mutations. This checks out conceptually: +* Riverpod: Immutable Copy -> Notify -> Check Families -> Rebuild. +* Levit: Mutate value -> Mark Dirty -> (Batch) -> Notify. +Direct mutation will always beat immutable copy chains in micro-benchmarks. + +### The Verdict on Performance +**10/10.** This is clearly designed for 120fps. It might be overkill for a Todo app, but for a high-frequency trading app or a complex dashboard, this engine is a beast. + +--- + +## 3. Will I try it in a new project? + +**Yes, but with conditions.** + +* **For a personal side project or a rapid prototype:** **Absolutely.** The speed of development without code-gen is intoxicating. +* **For a high-performance visualizer/game UI:** **Yes.** The granular rebuilds (`LWatch`) and raw mutation speed make it perfect for this. +* **For a large-scale Enterprise Banking App:** **No.** I would stick to Riverpod. The compile-time safety, explicit dependency graph, and immutability are non-negotiable when 20 developers are touching the codebase. I need the compiler to yell at them, not a runtime exception in production. + +--- + +## 4. Will I be interested in contributing to it? + +**Yes.** + +The codebase is clean, modular, and respectful of computer science principles (Topological sort, Graph theory). It's not "hacky" like some other state management solutions in the ecosystem. + +**Areas of interest:** +1. **DevTools:** Riverpod has world-class DevTools. Levit needs a visualization of the dependency graph to mitigate the "hidden dependency" issue. +2. **Testing Utilities:** `levit_test` package to make mocking scopes easier would be a huge value add. +3. **Strict Mode:** A compile-time analyzer plugin (custom_lint) to warn about missing `LWatch` or invalid `Ls.find` calls would bridge the safety gap. + +--- + +## Final Thoughts + +Levit is the "Un-Riverpod". It is the chaotic good to Riverpod's lawful good. It proves that you can have extremely ergonomic, high-performance state management in Dart without code generation, provided you accept the trade-offs of mutability and runtime scoping.