diff options
Diffstat (limited to '2025/05/27/vertical-slicing-practice')
| -rw-r--r-- | 2025/05/27/vertical-slicing-practice/index.html | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/2025/05/27/vertical-slicing-practice/index.html b/2025/05/27/vertical-slicing-practice/index.html new file mode 100644 index 00000000..325c7a76 --- /dev/null +++ b/2025/05/27/vertical-slicing-practice/index.html @@ -0,0 +1,323 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8"> +<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> +<meta http-equiv="X-UA-Compatible" content="ie=edge"> + + <meta name="author" content="韩暮秋"> + + + <meta name="subtitle" content="暮秋小屋"> + + + <meta name="description" content="这里是暮秋小屋,思念和灵感的寄存处"> + + + <meta name="keywords" content="韩暮秋,MuqiuHan,'Muqiu Han', 'muqiu han', muqiuhan"> + + + + + <title> + + Vertical slicing 在开发中的实践探索 | + 暮秋小屋 + </title> + + + + <link rel="icon" href="/favicon.ico"> + + + <style> + @font-face { + font-family: CarroisSong; + src: url('/fonts/CarroisSong.ttf'); + } + </style> + + + + <!-- stylesheets list from _config.yml --> + + <link rel="stylesheet" href="/css/style.css"> + + + + + + <!-- scripts list from _config.yml --> + + <script + src="/js/menu.js"></script> + + + + + + <script + src="https://polyfill.alicdn.com/polyfill.js?features=es6"></script> + <script + id="MathJax-script" + async + src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/mathjax/3.2.0/es5/tex-mml-chtml.js"></script> + + + + + <meta name="generator" content="Hexo 6.3.0"></head> + <body> + <div class="mask-border"> + </div> + + <div class="wrapper"> + + <div class="header"> + <div class="flex-container"> + <div class="header-inner"> + <div class="site-brand-container"> + <a href="/"> + + 暮秋小屋 + + </a> + </div> + <div id="menu-btn" class="menu-btn" onclick="toggleMenu()"> + Menu + </div> + <nav class="site-nav"> + <ul class="menu-list"> + + + <li class="menu-item"> + <a href="/"> + 主页 + </a> + </li> + + + + <li class="menu-item"> + <a href="/categories/gallery/"> + 日记本 + </a> + </li> + + + + <li class="menu-item"> + <a href="/tags/Medicine/"> + 医学 + </a> + </li> + + + + <li class="menu-item"> + <a href="/tags/Technique/"> + 计算机/互联网 + </a> + </li> + + + + <li class="menu-item"> + <a href="/tags/Life/"> + 生活 + </a> + </li> + + + + <li class="menu-item"> + <a href="/archives"> + 全部 + </a> + </li> + + + + <li class="menu-item"> + <a href="/about"> + 关于 + </a> + </li> + + + + <li class="menu-item search-btn"> + <a href="#">Search</a> + </li> + + </ul> + </nav> + </div> + </div> +</div> + + <div class="main"> + <div class="flex-container"> + <article id="post"> + + + <div class="post-head"> + <div class="post-info"> + <div class="tag-list"> + + + <span class="post-tag"> + <a href="/tags/Technique/"> + Technique + </a> + </span> + + + </div> + <div class="post-title"> + + + Vertical slicing 在开发中的实践探索 + + + </div> + <span class="post-date"> + May 27, 2025 + </span> + </div> + <div class="post-img"> + + <div class="h-line-primary"></div> + + </div> +</div> + <div class="post-content"> + <p><strong>垂直切片 (Vertical Slicing)</strong> 是一种在敏捷软件开发中将产品需求(通常是用户故事)拆分为可独立交付的、具有端到端功能的小块的方法。这意味着每个“切片”都包含了从用户界面 (UI) 到底层数据库,以及中间所有业务逻辑层所需的工作。</p> +<p>与水平切片(即按技术分层,如先完成所有 UI,再完成所有后端逻辑)不同,垂直切片的目标是尽快交付一个虽小但完整可用的功能。</p> +<hr> +<p>想象一个蛋糕,垂直切片就像切下一块完整的蛋糕,包含从顶部到底部的每一层。在软件开发中,这意味着一个任务或用户故事的完成会涉及到:</p> +<ul> +<li>**用户界面 (UI)**:用户能看到并与之交互的部分。</li> +<li>**业务逻辑层 (Business Logic Layer)**:处理数据和执行核心功能的部分。</li> +<li>**数据访问层 (Data Access Layer)**:与数据库或其他数据存储交互的部分。</li> +<li>**数据库 (Database)**:存储数据的部分。</li> +</ul> +<p>所以一个垂直切片代表了一个可以独立运行、测试和向用户展示的小功能。</p> +<hr> +<p>在实践中,用垂直切片进行任务拆分或许可以按照如下步骤来实现:</p> +<p>一、**从用户故事开始 (Start with User Stories)**:明确用户需要什么功能以及这个功能为用户带来的价值。例如:“作为一个注册用户,我希望能用我的邮箱和密码登录系统,以便访问我的个人资料。”</p> +<p>二、<strong>识别涉及的技术层面 (Identify Affected Layers)</strong></p> +<p>对于登录功能,需要考虑:</p> +<ul> +<li><strong>UI 层</strong>:登录表单(输入邮箱、密码的地方)、提交按钮、错误提示信息。</li> +<li><strong>API/服务层</strong>:接收登录请求、验证用户凭证的接口。</li> +<li><strong>业务逻辑层</strong>:校验输入格式、查询用户信息、验证密码、生成会话(Session)或令牌(Token)。</li> +<li><strong>数据访问层</strong>:从数据库中读取用户信息。</li> +</ul> +<p>三、<strong>创建可交付的小功能块 (Create Small, Deliverable Chunks)</strong></p> +<p>就是将一个大的用户故事拆分成更小的、但仍然是垂直的、可独立交付的故事。例如,可以将“用户登录”进一步细化:</p> +<p>**切片1 (基础登录)**:用户可以使用正确的邮箱和密码成功登录。这包含了 UI 输入、后端验证和数据库查询。</p> +<p>**切片2 (错误处理)**:用户输入错误的邮箱或密码时,系统给出明确的错误提示。这可能只涉及 UI 和业务逻辑层的少量修改。</p> +<p>**切片3 (“记住我” 功能)**:用户可以选择“记住我”,下次访问时自动登录。这可能涉及 UI、业务逻辑和客户端存储。</p> +<p>四、**确保每个切片都有价值 (Ensure Each Slice Has Value)**:每完成一个切片,都应该为用户或产品带来可感知的价值,并且理想情况下是可以演示给利益相关者看的。</p> +<p>五、**保持切片足够小 (Keep Slices Small Enough)**:每个切片的工作量应该小到可以在一个迭代周期(例如 Sprint)内完成。这有助于团队保持专注,并快速获得反馈。</p> +<hr> +<p>这里有一些拆分技巧:</p> +<ul> +<li><strong>按操作流程拆分</strong>:例如,一个复杂的表单提交可以先实现基本信息的提交,后续再添加高级选项的提交。</li> +<li><strong>按业务规则拆分</strong>:先实现核心的业务规则,再逐步添加次要的或复杂的规则。</li> +<li><strong>按数据类型或参数拆分</strong>:先支持一种数据类型或最常用的参数,再扩展到其他类型。</li> +<li><strong>按用户角色或权限拆分</strong>:先实现某个核心角色的功能,再实现其他角色的特定功能。</li> +<li><strong>简化错误处理或用户体验</strong>:先实现基本功能,再完善错误处理和用户体验细节。</li> +</ul> + +</div> + +<script> + window.onload = detectors(); +</script> + <div class="post-footer"> + <div class="h-line-primary"></div> + <nav class="post-nav"> + <div class="prev-item"> + + </div> + <div class="next-item"> + + <div class="icon arrow-right"></div> + <div class="post-link"> + <a href="/2025/05/12/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E4%BA%94%E6%9C%88%E5%8D%81%E4%BA%8C%E6%97%A5/">Next</a> + </div> + + </div> + </nav> +</div> + + + <div class="post-comment"> + + + + + + + +</div> + + +</article> + </div> + </div> + + <div class="footer"> + <div class="flex-container"> + <div class="footer-text"> + + + 韩暮秋 | + + + 希望路过的人可以添点柴火让这里暖和点 + + </div> + </div> +</div> + + </div> + + + <div class="search-popup"> + <div class="search-popup-overlay"> + </div> + <div class="search-popup-window" > + <div class="search-header"> + <div class="search-input-container"> + <input autocomplete="off" autocapitalize="off" maxlength="80" + placeholder="Search Anything" spellcheck="false" + type="search" class="search-input"> + </div> + <div class="search-close-btn"> + <div class="icon close-btn"></div> + </div> + </div> + <div class="search-result-container"> + </div> + </div> +</div> + +<script> + const searchConfig = { + path : "/search.xml", + top_n_per_article: "1", + unescape : "false", + trigger: "auto", + preload: "false" + } +</script> +<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/search.js"></script> +<script src="/js/search.js"></script> + + + + </body> +</html> |
