[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"portal-settings:stajic:zh":3,"public-menus:all":38,"post:model-view-controller-mvc:zh":205,"related:post:model-view-controller-mvc:zh:1":873},{"statusCode":4,"data":5,"message":37},200,{"tenantId":6,"lang":7,"defaultLang":8,"siteUrl":9,"contactEmail":10,"brandName":11,"logoUrl":12,"siteName":11,"siteDescription":13,"ogImage":10,"robotsIndex":14,"socialLinks":10,"reservedSlugs":10,"seoPolicy":15},"stajic","zh","de","https:\u002F\u002Fstajic.de",null,"Stajic Platform","\u002FLogo_Planet.svg","Stajic Portal",true,{"branding":16,"relatedContent":17,"crossDomainLinks":18},{"logoUrl":12},{"enabled":14},[19,22,25,28,31,34],{"url":20,"label":21,"isActive":14,"showInFooter":14,"includeInSameAs":14},"https:\u002F\u002Ffigure.rocks","figure.rocks",{"url":23,"label":24,"isActive":14,"showInFooter":14,"includeInSameAs":14},"https:\u002F\u002Floving.rocks","loving.rocks",{"url":26,"label":27,"isActive":14,"showInFooter":14,"includeInSameAs":14},"https:\u002F\u002Fbazify.com","bazify.com",{"url":29,"label":30,"isActive":14,"showInFooter":14,"includeInSameAs":14},"https:\u002F\u002Fbazify.de","bazify.de",{"url":32,"label":33,"isActive":14,"showInFooter":14,"includeInSameAs":14},"https:\u002F\u002Fbazify.at","bazify.at",{"url":35,"label":36,"isActive":14,"showInFooter":14,"includeInSameAs":14},"https:\u002F\u002Fbazify.ba","bazify.ba","Portal settings resolved",[39,45],{"id":40,"name":41,"location":42,"isActive":14,"isDefault":43,"items":44},1,"main-navigation","header",false,[],{"id":46,"name":47,"location":48,"isActive":14,"isDefault":14,"items":49},4,"main-menu","sidebar",[50,66,79,93,103,118,133],{"id":51,"title":52,"url":60,"target":61,"icon":62,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":64,"portfolioId":10,"children":65},"item-18",{"de":53,"en":54,"es":55,"fr":56,"it":54,"ru":57,"sr":58,"zh":59},"Startseite","Home","Inicio","Accueil","Главная","Почетна","首页","\u002Ffull-stack-web-developer-munich-performance-seo-and-maintainable-builds","_self","i-lucide-home","page",111,[],{"id":67,"title":68,"url":75,"target":61,"icon":76,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":77,"portfolioId":10,"children":78},"item-22",{"de":69,"en":69,"es":70,"fr":69,"it":71,"ru":72,"sr":73,"zh":74},"Vision","Visión","Visione","Видение","Визија","想象","\u002Fueber-uns-webdesign-muenchen-webaplikation","i-lucide-eye",113,[],{"id":80,"title":81,"url":89,"target":61,"icon":90,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":91,"portfolioId":10,"children":92},"item-19",{"de":82,"en":83,"es":84,"fr":83,"it":85,"ru":86,"sr":87,"zh":88},"Leistungen","Services","Servicios","Servizi","Услуги","Услуге","服务","\u002Fservices-dienstleistungen-muenchen","i-lucide-wrench",116,[],{"id":94,"title":95,"url":99,"target":61,"icon":100,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":101,"portfolioId":10,"children":102},"item-23",{"de":96,"en":96,"es":96,"fr":96,"it":96,"ru":97,"sr":97,"zh":98},"Blog","Блог","博客","\u002Fblog","i-lucide-book-open",112,[],{"id":104,"title":105,"url":114,"target":61,"icon":115,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":116,"portfolioId":10,"children":117},"item-32",{"de":106,"en":107,"es":108,"fr":109,"it":110,"ru":111,"sr":112,"zh":113},"Neue Technologien","New Technologies","Nuevas tecnologías","Nouvelles technologies","Nuove tecnologie","Новые технологии","Нове технологије","新技术！","\u002Fneue-webtechnologien","i-lucide-sparkles",122,[],{"id":119,"title":120,"url":129,"target":61,"icon":130,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":131,"portfolioId":10,"children":132},"item-20",{"de":121,"en":122,"es":123,"fr":124,"it":125,"ru":126,"sr":127,"zh":128},"Kontakt","Contact us!","Contacto","Contact","Contatto","Контакт","Контактирајте нас","联系我们！","\u002Fcontact","i-lucide-mail",115,[],{"id":134,"title":135,"url":144,"target":61,"icon":145,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":146,"portfolioId":10,"children":147},"item-21",{"de":136,"en":137,"es":138,"fr":139,"it":140,"ru":141,"sr":142,"zh":143},"Unsere Arbeit","Our Work","Nuestro trabajo","Nos réalisations","I nostri lavori","Наши работы","Наши радови","文件夹","\u002Fportfolio","i-lucide-briefcase",114,[148,161,175,181,193],{"id":149,"title":150,"url":144,"target":61,"icon":159,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":146,"portfolioId":10,"children":160},"item-24",{"de":151,"en":152,"es":153,"fr":154,"it":155,"ru":156,"sr":157,"zh":158},"Alle Projekte","All Projects","Todos los proyectos","Tous les projets","Tutti i progetti","Все проекты","Сви пројекти","所有项目","i-lucide-grid-3x3",[],{"id":162,"title":163,"url":171,"target":61,"icon":172,"isActive":14,"type":173,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":10,"portfolioId":10,"children":174},"item-29",{"de":164,"en":165,"es":166,"fr":167,"it":168,"ru":169,"sr":170,"zh":143},"Local Roots, Global Reach","Local Roots - Global Reach","Empresa local ","Entreprise locale","Azienda locale","Местная компания","Локално предузеће глобално тржиште","\u002Fportfolio\u002Flocal-roots-global-reach-communication-media-systems-for-modern-business","i-lucide-folder","custom",[],{"id":176,"title":177,"url":179,"target":61,"icon":172,"isActive":14,"type":173,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":10,"portfolioId":10,"children":180},"item-28",{"de":178,"en":178,"es":178,"fr":178,"it":178,"ru":178,"sr":178,"zh":178},"Solr Suggester","\u002Fportfolio\u002Fsolr-fuzzy-suggester-und-solr-infix-suggester-abfrage-ueber-ajax-und-filterung",[],{"id":182,"title":183,"url":191,"target":61,"icon":172,"isActive":14,"type":173,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":10,"portfolioId":10,"children":192},"item-27",{"de":184,"en":185,"es":186,"fr":187,"it":188,"ru":189,"sr":190,"zh":185},"Firmenwebseite SEO","Company Website SEO","Sitio web corporativo SEO","Site web d’entreprise SEO","Sito web aziendale SEO","Корпоративный сайт SEO","Пословна веб-страница SEO","\u002Fportfolio\u002Fseo-sem-branding-mobile-webseite-muenchen",[],{"id":194,"title":195,"url":203,"target":61,"icon":172,"isActive":14,"type":173,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":10,"portfolioId":10,"children":204},"item-31",{"de":196,"en":197,"es":198,"fr":199,"it":200,"ru":201,"sr":202,"zh":197},"Digitalisierungsportal","Digitalization Portal","Portal de digitalización","Portail de numérisation","Portale di digitalizzazione","Портал цифровизации","Портал за дигитализацију","\u002Fportfolio\u002Fdigitalisierungsportal-archiv-museum-bibliothek-ead-lido-mets-mods",[],{"statusCode":4,"data":206,"message":872},{"id":207,"title":208,"slug":209,"content":210,"contentJson":211,"excerpt":457,"featuredImage":458,"featuredImageAlt":459,"featuredImageCaption":10,"featuredImageTitle":10,"featuredImageCopyright":10,"featuredImageAuthor":10,"featuredImageSourceUrl":10,"featuredImageLicense":10,"featuredImageIsAiGenerated":43,"status":460,"publishedAt":461,"createdAt":462,"updatedAt":463,"seoLocalePaths":464,"categories":473,"author":484,"translations":489},"361","模型-视图-控制器（MVC）：现代Web应用的结构支柱","model-view-controller-mvc","\u003Cp>\u003Cb>模型-视图-控制器（MVC）\u003C\u002Fb>模式仍然是Web应用程序架构中最持久的基础之一。它的长寿并非偶然。MVC之所以经久不衰，是因为它解决了一个从未真正消失的问题：如何构建软件，使得增长不会让每一次变更都变成风险。当职责分离良好时，团队可以扩展功能、修改界面、重构内部结构，并以更少的阻力发布变更。\u003C\u002Fp>\n\u003Cp>这就是为什么这个话题自然属于\u003Cb>企业交付操作系统\u003C\u002Fb>。MVC不仅仅是一种编码约定。它是一种结构性规范，影响着平台的可维护性、交付安全性、迁移工作量、测试设计和操作清晰度。在实际工程意义上，MVC之所以有用，是因为它在系统通常变得混乱的地方划定了边界。\u003C\u002Fp>\n\u003Cp>在stajic.de的支柱结构中，最匹配的主要分类是\u003Cb>参考模型 > 数字平台\u003C\u002Fb>。MVC首先是一个架构和平台边界话题。它也与交付和变更、迁移和平台重构、发布控制和交付评估相关，但这些是次要的支持关系，而非主要分类。\u003C\u002Fp>\n\u003Ch2>MVC实际分离了什么\u003C\u002Fh2>\n\u003Cp>MVC将应用程序划分为三个不同的职责领域。\u003Cb>模型\u003C\u002Fb>代表领域状态、不变条件和规则。\u003Cb>视图\u003C\u002Fb>负责呈现和交互输出。\u003Cb>控制器\u003C\u002Fb>接收请求，协调相关用例，并决定如何组装响应。名称很简单，但价值重大：清晰的分离减少了隐藏的耦合。\u003C\u002Fp>\n\u003Cul>\u003Cli>\u003Cb>模型\u003C\u002Fb>拥有领域含义，而不仅仅是存储。\u003C\u002Fli>\u003Cli>\u003Cb>视图\u003C\u002Fb>清晰地呈现信息，不会悄然变成业务层。\u003C\u002Fli>\u003Cli>\u003Cb>控制器\u003C\u002Fb>协调流程，而不是变成一个上帝对象。\u003C\u002Fli>\u003C\u002Ful>\n\u003Cp>一旦这些边界弱化，系统就变得更难理解。业务规则会渗入模板。控制器会因编排、验证和副作用而变得臃肿。模型变成被动的数据库包装器。团队随后会误将框架结构视为架构清晰度，尽管代码库已经纠缠不清。\u003C\u002Fp>\n\u003Ch2>为什么MVC在现代Web技术栈中仍然重要\u003C\u002Fh2>\n\u003Cp>现代框架通常使用不同的语言：组件、可组合项、孤岛、服务器操作、API路由、无头交付和边缘渲染。这些都没有消除分离的需求。它们只是重新分配了分离必须发生的地方。一个严肃的平台仍然需要一个稳定的地方来存放领域规则，一个受控的路径来编排请求，以及一个不秘密拥有策略的呈现层。\u003C\u002Fp>\n\u003Cp>这就是为什么有用的问题不是框架是否自称MVC。有用的问题是平台是否保护了MVC旨在强制执行的相同边界。如果没有，那么技术栈可能看起来很现代，但仍然在积累结构性债务。\u003C\u002Fp>\n\u003Cblockquote class=\"border-l-4 border-gray-300 pl-4 italic\">框架的新颖性并不能取代架构规范。新的语法可以隐藏旧的混乱。\u003Ccite class=\"block mt-2 text-sm\">— 平台架构视角\u003C\u002Fcite>\u003C\u002Fblockquote>\n\u003Ch2>一个最小的请求流程\u003C\u002Fh2>\n\u003Cp>理解MVC最简单的方法是跟踪请求在系统中的流程。用户请求一个页面或触发一个操作。控制器接收请求，将领域工作委托给模型或服务，准备响应结构，并将结果传递给视图。视图渲染输出。这个流程很容易解释，但许多系统在实践中违反了它。\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode>\u002F\u002F 请求进入系统\nGET \u002Fproducts\u002F42 \u002F\u002F 路由器选择控制器操作\nProductController.show(id = 42) \u002F\u002F 控制器协调用例\nproduct = ProductService.getById(42)\nviewModel = ProductPresenter.toViewModel(product) \u002F\u002F 视图渲染输出\nreturn render(&quot;product\u002Fshow&quot;, viewModel)\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>这个例子有意保持最小化。价值不在于语法。价值在于可见性。审查者可以看到请求进入的地方、领域工作发生的地方以及呈现开始的地方。当团队在交付压力下更改实时平台时，这种清晰度变得极其重要。\u003C\u002Fp>\n\u003Ch2>模型真正应该拥有什么\u003C\u002Fh2>\n\u003Cp>在弱实现中，模型变得几乎只是一个ORM实体或数据库记录。这太狭隘了。一个有用的模型保护业务含义。它应该持有无论请求来自Web表单、管理屏幕、公共API、后台工作进程还是CLI作业都必须保持为真的规则。\u003C\u002Fp>\n\u003Cul>\u003Cli>状态转换，例如允许的状态更改\u003C\u002Fli>\u003Cli>在每个接口中都必须保持的不变条件\u003C\u002Fli>\u003Cli>属于业务而非仅属于表单层的领域级验证\u003C\u002Fli>\u003Cli>代表实际业务行为的计算值和决策\u003C\u002Fli>\u003C\u002Ful>\n\u003Cpre class=\"code-block\">\u003Ccode>class Order: def cancel(self, actor): if self.status == &quot;shipped&quot;: raise DomainError(&quot;Shipped orders cannot be cancelled&quot;) if not actor.can(&quot;cancel_order&quot;): raise PermissionError(&quot;Actor may not cancel this order&quot;) self.status = &quot;cancelled&quot;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>这条规则虽小，但教训深刻。如果一条规则重要，它就需要一个稳定的归属地。当这样的逻辑只存在于一个控制器操作或一个UI表单中时，另一条路径最终会绕过它。领域规则应该存在于领域能够真正捍卫它们的地方。\u003C\u002Fp>\n\u003Ch2>视图应该做什么和不应该做什么\u003C\u002Fh2>\n\u003Cp>视图的存在是为了呈现信息、格式化输出和支持交互。它可以包含显示逻辑，但不应该成为重要业务策略的隐藏所有者。一旦模板开始决定谁被允许做什么，系统就会变得更难测试、更难审计，也更容易出错。\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode>&lt;!-- Good: presentation logic --&gt;\n{% if product.stock &gt; 0 %} &lt;button&gt;Add to cart&lt;\u002Fbutton&gt;\n{% else %} &lt;p&gt;Currently unavailable&lt;\u002Fp&gt;\n{% endif %} &lt;!-- Bad: business policy leaking into the template --&gt;\n{% if user.role == &quot;admin&quot; or order.total &lt; 1000 or region == &quot;DE&quot; %} &lt;button&gt;Approve refund&lt;\u002Fbutton&gt;\n{% endif %}\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>视图可以决定如何显示状态。它不应该默默地决定哪些策略是有效的。这种区别在代码审查中看起来很小，但随着时间的推移会变得非常重要。\u003C\u002Fp>\n\u003Ch2>控制器应该协调，而不是积累权力\u003C\u002Fh2>\n\u003Cp>控制器很有用，因为它们为应用程序创建了一个清晰的入口。但它们应该保持专注。一个验证原始输入、调用外部服务、计算领域决策、转换持久化数据并决定最终渲染策略的控制器，不再仅仅是一个控制器。它变成了一个与HTTP焊接在一起的隐藏应用层。\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode>\u002F\u002F Too much responsibility in one controller\nasync function checkout(req, res) { validateCart(req.body) const tax = await taxApi.calculate(req.body.address, req.body.items) const discount = computeDiscount(req.user, req.body.items) const inventory = await reserveItems(req.body.items) const payment = await chargeCard(req.body.card) const order = await db.orders.create({ tax, discount, inventory, payment }) res.render(&quot;checkout\u002Fsuccess&quot;, { order })\n}\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cpre class=\"code-block\">\u003Ccode>\u002F\u002F Better: controller delegates to application services\nasync function checkout(req, res) { const command = CheckoutCommand.fromHttp(req) const result = await checkoutService.execute(command) res.render(&quot;checkout\u002Fsuccess&quot;, CheckoutPresenter.toViewModel(result))\n}\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>这就是MVC与交付质量高度相关的地方。清晰的边界减少了审查范围，缩小了变更影响，并使发布更容易推理。这也是为什么MVC自然地与\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Freference-models\u002Fdelivery-and-change\">交付与变更参考模型\u003C\u002Fa>相关联，该模型专注于通过明确的证据和可衡量的结果安全地交付变更。\u003C\u002Fp>\n\u003Ch2>MVC与平台架构\u003C\u002Fh2>\n\u003Cp>本文最适合的主要参考是\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Freference-models\u002Fdigital-platform\">数字平台参考模型\u003C\u002Fa>。该页面描述了一个与技术无关的结构，用于大规模设计和运营数字平台。MVC适合那里，因为它是团队用来定义真实系统内部边界、职责和变更面的结构词汇的一部分。\u003C\u002Fp>\n\u003Cp>一个内部边界薄弱的平台可能仍在生产环境中运行，但它的演进速度会变慢。新功能需要更长时间。错误变得更难定位。重构被推迟。发布承载着更多未知风险。从这个意义上说，MVC不仅仅是关于代码风格。它是关于保持可变更性。\u003C\u002Fp>\n\u003Ch2>现代框架和无头系统中的MVC\u003C\u002Fh2>\n\u003Cp>并非每个现代技术栈都直接暴露经典的MVC。在SSR框架中，控制器可能表现为路由处理器或服务器操作。在API优先的系统中，视图可能存在于单独的前端。在无头平台中，模型行为可能分布在服务、领域模块和持久化层之间。但对分离的需求并未消失。它只是分散到了更多的移动部件中。\u003C\u002Fp>\n\u003Cul>\u003Cli>SSR框架通常将控制器逻辑移至路由级别的处理器中\u003C\u002Fli>\u003Cli>API优先架构将表示层置于一个独立的前端层\u003C\u002Fli>\u003Cli>无头系统将模型行为分布在服务和领域边界之间\u003C\u002Fli>\u003Cli>基于组件的UI仍然受益于将业务策略排除在视图层之外\u003C\u002Fli>\u003C\u002Ful>\n\u003Cp>因此，更深层次的教训是：即使其经典包装形式消失，MVC仍然有价值。它作为一种设计原则得以存续，因为职责分离仍然是抵御熵增的少数可靠防御手段之一。\u003C\u002Fp>\n\u003Ch2>为何MVC让平台重构更轻松\u003C\u002Fh2>\n\u003Cp>遗留系统迁移常常失败，因为旧平台将所有东西混杂在一起。查询逻辑存在于模板中。状态转换隐藏在辅助文件里。验证逻辑在表单、API和管理工具中重复出现。没人能安全地移动任何部分，因为太多职责被熔合在一起。分离越清晰，迁移路径就越现实。\u003C\u002Fp>\n\u003Cp>这就是为什么MVC对\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Fplaybooks\u002Fmigration-and-replatform\">迁移与平台重构手册\u003C\u002Fa>具有重要的次要相关性。平台重构不仅仅是技术替换练习，更是一项解耦练习。团队必须在迁移变得安全之前，暴露并稳定职责边界。\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode>平台重构安全序列\n1. 将领域规则移出模板和控制器\n2. 将控制器简化为请求映射和编排\n3. 引入展示器或视图模型以建立稳定的输出契约\n4. 将数据访问隔离在服务或仓储之后\n5. 一次迁移一个边界，而非一次性重写所有内容\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>这种重构不会让迁移变得微不足道，但它减少了不确定性。仅此一点就能节省数月的浪费。\u003C\u002Fp>\n\u003Ch2>发布安全、测试与运维信心\u003C\u002Fh2>\n\u003Cp>MVC本身不能保证发布安全，但它让发布安全更容易实现。纤薄的控制器、明确的服务、稳定的视图模型以及受保护的领域规则，使得变更的实际影响范围更加清晰。这提高了代码审查质量，缩小了错误的影响范围，并帮助团队在正确的层级设计测试。\u003C\u002Fp>\n\u003Cul>\u003Cli>模型测试验证不变式和业务规则\u003C\u002Fli>\u003Cli>服务测试验证用例行为\u003C\u002Fli>\u003Cli>控制器测试验证请求映射和响应流程\u003C\u002Fli>\u003Cli>视图测试验证渲染和交互预期\u003C\u002Fli>\u003Cli>端到端测试保护关键用户旅程，而无需承担全部负担\u003C\u002Fli>\u003C\u002Ful>\n\u003Cp>这就是为什么MVC也与\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Frunbooks\u002Frelease-runbook\">发布运行手册\u003C\u002Fa>和\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Fassessments\u002Fdelivery-assessment\">交付评估\u003C\u002Fa>自然连接。一个具有明确结构的平台更容易发布、度量和改进。\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode>发布安全变更模式\n1. 在一个可信位置更新领域规则\n2. 扩展服务或用例测试\n3. 仅在请求契约变更时调整控制器映射\n4. 仅在输出契约变更时更新展示器或视图模型\n5. 验证受影响的界面和API响应\n6. 在具备回滚意识和清晰证据的情况下发布\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>常见的MVC反模式\u003C\u002Fh2>\n\u003Cul>\u003Cli>臃肿的控制器，暗中包含了应用层逻辑\u003C\u002Fli>\u003Cli>被动的模型，缺乏有意义的领域行为\u003C\u002Fli>\u003Cli>做出隐藏策略决策的视图\u003C\u002Fli>\u003Cli>在前端、后端和管理工具中重复的验证逻辑\u003C\u002Fli>\u003Cli>领域与UI之间缺乏稳定的展示器或视图模型边界\u003C\u002Fli>\u003Cli>将框架约定误认为是架构\u003C\u002Fli>\u003C\u002Ful>\n\u003Cp>这些问题通常是逐渐出现的，因此团队会低估它们。一个代码库从外部看可能井井有条，但内部结构依然脆弱。\u003C\u002Fp>\n\u003Cblockquote class=\"border-l-4 border-gray-300 pl-4 italic\">框架可以生成文件夹，但无法生成良好的边界。这些边界仍然需要团队来设计和维护。\u003Ccite class=\"block mt-2 text-sm\">— 企业交付操作系统视角\u003C\u002Fcite>\u003C\u002Fblockquote>\n\u003Ch2>最佳匹配SEO支柱定位\u003C\u002Fh2>\n\u003Cp>在企业交付操作系统结构中，本文属于\u003Cb>参考模型 > 数字平台\u003C\u002Fb>。这是正确的主要定位，因为MVC从根本上关乎平台结构和职责边界。其辅助支持链接属于\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Freference-models\u002Fdelivery-and-change\">交付与变更\u003C\u002Fa>、\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Fplaybooks\u002Fmigration-and-replatform\">迁移与平台重构\u003C\u002Fa>、\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Frunbooks\u002Frelease-runbook\">发布运行手册\u003C\u002Fa>和\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Fassessments\u002Fdelivery-assessment\">交付评估\u003C\u002Fa>。\u003C\u002Fp>\n\u003Cp>这个定位并非表面功夫。它告诉门户、编辑和读者，该主题在结构上属于何处。MVC主要不是一个发布清单，主要不是一个迁移策略，也主要不是一个评估标准。它首先是一个平台设计原则。\u003C\u002Fp>\n\u003Ch2>最终视角\u003C\u002Fh2>\n\u003Cp>模型-视图-控制器模式之所以仍然重要，是因为软件并不会仅仅因为框架更新而变得更简单。团队仍然需要一个稳定的地方来存放领域规则，一个受控的请求处理路径，以及一个不会将策略偷偷带入界面的表示层。如果运用得当，MVC 不仅仅是一个历史模式。它将成为实现更清晰架构、更安全发布、更轻松迁移以及更强长期交付纪律的实用工具。\u003C\u002Fp>\n\u003Cdiv class=\"ce-delimiter cdx-block my-8\">\u003C\u002Fdiv>\n\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\" class=\"editorjs-link-tool block border border-gray-200 dark:border-gray-700 rounded-lg p-4 transition text-gray-900 dark:text-gray-100 hover:border-primary-500 hover:bg-primary-50 dark:hover:bg-gray-900 hover:text-gray-900 dark:hover:text-gray-100\">\u003Cstrong class=\"block font-semibold\">企业交付操作系统\u003C\u002Fstrong>\u003Cp class=\"text-sm text-gray-600 dark:text-gray-400\">面向平台、交付、安全和LLM采用的企业知识库。\u003C\u002Fp>\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Freference-models\u002Fdigital-platform\" class=\"editorjs-link-tool block border border-gray-200 dark:border-gray-700 rounded-lg p-4 transition text-gray-900 dark:text-gray-100 hover:border-primary-500 hover:bg-primary-50 dark:hover:bg-gray-900 hover:text-gray-900 dark:hover:text-gray-100\">\u003Cstrong class=\"block font-semibold\">数字平台参考模型\u003C\u002Fstrong>\u003Cp class=\"text-sm text-gray-600 dark:text-gray-400\">一个与技术无关的结构，用于设计和运营支持大规模产品交付的数字平台。\u003C\u002Fp>\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Freference-models\u002Fdelivery-and-change\" class=\"editorjs-link-tool block border border-gray-200 dark:border-gray-700 rounded-lg p-4 transition text-gray-900 dark:text-gray-100 hover:border-primary-500 hover:bg-primary-50 dark:hover:bg-gray-900 hover:text-gray-900 dark:hover:text-gray-100\">\u003Cstrong class=\"block font-semibold\">交付与变更参考模型\u003C\u002Fstrong>\u003Cp class=\"text-sm text-gray-600 dark:text-gray-400\">该模型定义了如何通过质量门、清晰的证据和可衡量的结果安全地发布变更。\u003C\u002Fp>\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Fplaybooks\u002Fmigration-and-replatform\" class=\"editorjs-link-tool block border border-gray-200 dark:border-gray-700 rounded-lg p-4 transition text-gray-900 dark:text-gray-100 hover:border-primary-500 hover:bg-primary-50 dark:hover:bg-gray-900 hover:text-gray-900 dark:hover:text-gray-100\">\u003Cstrong class=\"block font-semibold\">迁移与平台重构手册\u003C\u002Fstrong>\u003Cp class=\"text-sm text-gray-600 dark:text-gray-400\">用于降低迁移风险并构建更安全的平台重构工作的手册。\u003C\u002Fp>\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Frunbooks\u002Frelease-runbook\" class=\"editorjs-link-tool block border border-gray-200 dark:border-gray-700 rounded-lg p-4 transition text-gray-900 dark:text-gray-100 hover:border-primary-500 hover:bg-primary-50 dark:hover:bg-gray-900 hover:text-gray-900 dark:hover:text-gray-100\">\u003Cstrong class=\"block font-semibold\">发布运行手册\u003C\u002Fstrong>\u003Cp class=\"text-sm text-gray-600 dark:text-gray-400\">用于飞行前检查、发布步骤、验证和发布后审查的运行手册。\u003C\u002Fp>\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Fassessments\u002Fdelivery-assessment\" class=\"editorjs-link-tool block border border-gray-200 dark:border-gray-700 rounded-lg p-4 transition text-gray-900 dark:text-gray-100 hover:border-primary-500 hover:bg-primary-50 dark:hover:bg-gray-900 hover:text-gray-900 dark:hover:text-gray-100\">\u003Cstrong class=\"block font-semibold\">交付能力评估\u003C\u002Fstrong>\u003Cp class=\"text-sm text-gray-600 dark:text-gray-400\">针对交付能力、变更风险和发布纪律的评估。\u003C\u002Fp>\u003C\u002Fa>",{"time":212,"blocks":213,"version":456},1774883846656,[214,218,221,224,228,231,239,242,245,248,251,256,259,262,266,269,272,275,282,285,288,291,294,297,300,303,306,309,312,315,318,321,324,327,330,337,340,343,346,349,352,355,358,361,369,372,375,378,387,390,394,397,400,403,406,409,412,421,428,435,442,449],{"data":215,"type":217},{"text":216},"\u003Cb>模型-视图-控制器（MVC）\u003C\u002Fb>模式仍然是Web应用程序架构中最持久的基础之一。它的长寿并非偶然。MVC之所以经久不衰，是因为它解决了一个从未真正消失的问题：如何构建软件，使得增长不会让每一次变更都变成风险。当职责分离良好时，团队可以扩展功能、修改界面、重构内部结构，并以更少的阻力发布变更。","paragraph",{"data":219,"type":217},{"text":220},"这就是为什么这个话题自然属于\u003Cb>企业交付操作系统\u003C\u002Fb>。MVC不仅仅是一种编码约定。它是一种结构性规范，影响着平台的可维护性、交付安全性、迁移工作量、测试设计和操作清晰度。在实际工程意义上，MVC之所以有用，是因为它在系统通常变得混乱的地方划定了边界。",{"data":222,"type":217},{"text":223},"在stajic.de的支柱结构中，最匹配的主要分类是\u003Cb>参考模型 > 数字平台\u003C\u002Fb>。MVC首先是一个架构和平台边界话题。它也与交付和变更、迁移和平台重构、发布控制和交付评估相关，但这些是次要的支持关系，而非主要分类。",{"data":225,"type":42},{"text":226,"level":227},"MVC实际分离了什么",2,{"data":229,"type":217},{"text":230},"MVC将应用程序划分为三个不同的职责领域。\u003Cb>模型\u003C\u002Fb>代表领域状态、不变条件和规则。\u003Cb>视图\u003C\u002Fb>负责呈现和交互输出。\u003Cb>控制器\u003C\u002Fb>接收请求，协调相关用例，并决定如何组装响应。名称很简单，但价值重大：清晰的分离减少了隐藏的耦合。",{"data":232,"type":238},{"items":233,"style":237},[234,235,236],"\u003Cb>模型\u003C\u002Fb>拥有领域含义，而不仅仅是存储。","\u003Cb>视图\u003C\u002Fb>清晰地呈现信息，不会悄然变成业务层。","\u003Cb>控制器\u003C\u002Fb>协调流程，而不是变成一个上帝对象。","unordered","list",{"data":240,"type":217},{"text":241},"一旦这些边界弱化，系统就变得更难理解。业务规则会渗入模板。控制器会因编排、验证和副作用而变得臃肿。模型变成被动的数据库包装器。团队随后会误将框架结构视为架构清晰度，尽管代码库已经纠缠不清。",{"data":243,"type":42},{"text":244,"level":227},"为什么MVC在现代Web技术栈中仍然重要",{"data":246,"type":217},{"text":247},"现代框架通常使用不同的语言：组件、可组合项、孤岛、服务器操作、API路由、无头交付和边缘渲染。这些都没有消除分离的需求。它们只是重新分配了分离必须发生的地方。一个严肃的平台仍然需要一个稳定的地方来存放领域规则，一个受控的路径来编排请求，以及一个不秘密拥有策略的呈现层。",{"data":249,"type":217},{"text":250},"这就是为什么有用的问题不是框架是否自称MVC。有用的问题是平台是否保护了MVC旨在强制执行的相同边界。如果没有，那么技术栈可能看起来很现代，但仍然在积累结构性债务。",{"data":252,"type":255},{"text":253,"caption":254},"框架的新颖性并不能取代架构规范。新的语法可以隐藏旧的混乱。","平台架构视角","quote",{"data":257,"type":42},{"text":258,"level":227},"一个最小的请求流程",{"data":260,"type":217},{"text":261},"理解MVC最简单的方法是跟踪请求在系统中的流程。用户请求一个页面或触发一个操作。控制器接收请求，将领域工作委托给模型或服务，准备响应结构，并将结果传递给视图。视图渲染输出。这个流程很容易解释，但许多系统在实践中违反了它。",{"data":263,"type":265},{"code":264},"\u002F\u002F 请求进入系统\nGET \u002Fproducts\u002F42 \u002F\u002F 路由器选择控制器操作\nProductController.show(id = 42) \u002F\u002F 控制器协调用例\nproduct = ProductService.getById(42)\nviewModel = ProductPresenter.toViewModel(product) \u002F\u002F 视图渲染输出\nreturn render(\"product\u002Fshow\", viewModel)","code",{"data":267,"type":217},{"text":268},"这个例子有意保持最小化。价值不在于语法。价值在于可见性。审查者可以看到请求进入的地方、领域工作发生的地方以及呈现开始的地方。当团队在交付压力下更改实时平台时，这种清晰度变得极其重要。",{"data":270,"type":42},{"text":271,"level":227},"模型真正应该拥有什么",{"data":273,"type":217},{"text":274},"在弱实现中，模型变得几乎只是一个ORM实体或数据库记录。这太狭隘了。一个有用的模型保护业务含义。它应该持有无论请求来自Web表单、管理屏幕、公共API、后台工作进程还是CLI作业都必须保持为真的规则。",{"data":276,"type":238},{"items":277,"style":237},[278,279,280,281],"状态转换，例如允许的状态更改","在每个接口中都必须保持的不变条件","属于业务而非仅属于表单层的领域级验证","代表实际业务行为的计算值和决策",{"data":283,"type":265},{"code":284},"class Order: def cancel(self, actor): if self.status == \"shipped\": raise DomainError(\"Shipped orders cannot be cancelled\") if not actor.can(\"cancel_order\"): raise PermissionError(\"Actor may not cancel this order\") self.status = \"cancelled\"",{"data":286,"type":217},{"text":287},"这条规则虽小，但教训深刻。如果一条规则重要，它就需要一个稳定的归属地。当这样的逻辑只存在于一个控制器操作或一个UI表单中时，另一条路径最终会绕过它。领域规则应该存在于领域能够真正捍卫它们的地方。",{"data":289,"type":42},{"text":290,"level":227},"视图应该做什么和不应该做什么",{"data":292,"type":217},{"text":293},"视图的存在是为了呈现信息、格式化输出和支持交互。它可以包含显示逻辑，但不应该成为重要业务策略的隐藏所有者。一旦模板开始决定谁被允许做什么，系统就会变得更难测试、更难审计，也更容易出错。",{"data":295,"type":265},{"code":296},"\u003C!-- Good: presentation logic -->\n{% if product.stock > 0 %} \u003Cbutton>Add to cart\u003C\u002Fbutton>\n{% else %} \u003Cp>Currently unavailable\u003C\u002Fp>\n{% endif %} \u003C!-- Bad: business policy leaking into the template -->\n{% if user.role == \"admin\" or order.total \u003C 1000 or region == \"DE\" %} \u003Cbutton>Approve refund\u003C\u002Fbutton>\n{% endif %}",{"data":298,"type":217},{"text":299},"视图可以决定如何显示状态。它不应该默默地决定哪些策略是有效的。这种区别在代码审查中看起来很小，但随着时间的推移会变得非常重要。",{"data":301,"type":42},{"text":302,"level":227},"控制器应该协调，而不是积累权力",{"data":304,"type":217},{"text":305},"控制器很有用，因为它们为应用程序创建了一个清晰的入口。但它们应该保持专注。一个验证原始输入、调用外部服务、计算领域决策、转换持久化数据并决定最终渲染策略的控制器，不再仅仅是一个控制器。它变成了一个与HTTP焊接在一起的隐藏应用层。",{"data":307,"type":265},{"code":308},"\u002F\u002F Too much responsibility in one controller\nasync function checkout(req, res) { validateCart(req.body) const tax = await taxApi.calculate(req.body.address, req.body.items) const discount = computeDiscount(req.user, req.body.items) const inventory = await reserveItems(req.body.items) const payment = await chargeCard(req.body.card) const order = await db.orders.create({ tax, discount, inventory, payment }) res.render(\"checkout\u002Fsuccess\", { order })\n}",{"data":310,"type":265},{"code":311},"\u002F\u002F Better: controller delegates to application services\nasync function checkout(req, res) { const command = CheckoutCommand.fromHttp(req) const result = await checkoutService.execute(command) res.render(\"checkout\u002Fsuccess\", CheckoutPresenter.toViewModel(result))\n}",{"data":313,"type":217},{"text":314},"这就是MVC与交付质量高度相关的地方。清晰的边界减少了审查范围，缩小了变更影响，并使发布更容易推理。这也是为什么MVC自然地与\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Freference-models\u002Fdelivery-and-change\">交付与变更参考模型\u003C\u002Fa>相关联，该模型专注于通过明确的证据和可衡量的结果安全地交付变更。",{"data":316,"type":42},{"text":317,"level":227},"MVC与平台架构",{"data":319,"type":217},{"text":320},"本文最适合的主要参考是\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Freference-models\u002Fdigital-platform\">数字平台参考模型\u003C\u002Fa>。该页面描述了一个与技术无关的结构，用于大规模设计和运营数字平台。MVC适合那里，因为它是团队用来定义真实系统内部边界、职责和变更面的结构词汇的一部分。",{"data":322,"type":217},{"text":323},"一个内部边界薄弱的平台可能仍在生产环境中运行，但它的演进速度会变慢。新功能需要更长时间。错误变得更难定位。重构被推迟。发布承载着更多未知风险。从这个意义上说，MVC不仅仅是关于代码风格。它是关于保持可变更性。",{"data":325,"type":42},{"text":326,"level":227},"现代框架和无头系统中的MVC",{"data":328,"type":217},{"text":329},"并非每个现代技术栈都直接暴露经典的MVC。在SSR框架中，控制器可能表现为路由处理器或服务器操作。在API优先的系统中，视图可能存在于单独的前端。在无头平台中，模型行为可能分布在服务、领域模块和持久化层之间。但对分离的需求并未消失。它只是分散到了更多的移动部件中。",{"data":331,"type":238},{"items":332,"style":237},[333,334,335,336],"SSR框架通常将控制器逻辑移至路由级别的处理器中","API优先架构将表示层置于一个独立的前端层","无头系统将模型行为分布在服务和领域边界之间","基于组件的UI仍然受益于将业务策略排除在视图层之外",{"data":338,"type":217},{"text":339},"因此，更深层次的教训是：即使其经典包装形式消失，MVC仍然有价值。它作为一种设计原则得以存续，因为职责分离仍然是抵御熵增的少数可靠防御手段之一。",{"data":341,"type":42},{"text":342,"level":227},"为何MVC让平台重构更轻松",{"data":344,"type":217},{"text":345},"遗留系统迁移常常失败，因为旧平台将所有东西混杂在一起。查询逻辑存在于模板中。状态转换隐藏在辅助文件里。验证逻辑在表单、API和管理工具中重复出现。没人能安全地移动任何部分，因为太多职责被熔合在一起。分离越清晰，迁移路径就越现实。",{"data":347,"type":217},{"text":348},"这就是为什么MVC对\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Fplaybooks\u002Fmigration-and-replatform\">迁移与平台重构手册\u003C\u002Fa>具有重要的次要相关性。平台重构不仅仅是技术替换练习，更是一项解耦练习。团队必须在迁移变得安全之前，暴露并稳定职责边界。",{"data":350,"type":265},{"code":351},"平台重构安全序列\n1. 将领域规则移出模板和控制器\n2. 将控制器简化为请求映射和编排\n3. 引入展示器或视图模型以建立稳定的输出契约\n4. 将数据访问隔离在服务或仓储之后\n5. 一次迁移一个边界，而非一次性重写所有内容",{"data":353,"type":217},{"text":354},"这种重构不会让迁移变得微不足道，但它减少了不确定性。仅此一点就能节省数月的浪费。",{"data":356,"type":42},{"text":357,"level":227},"发布安全、测试与运维信心",{"data":359,"type":217},{"text":360},"MVC本身不能保证发布安全，但它让发布安全更容易实现。纤薄的控制器、明确的服务、稳定的视图模型以及受保护的领域规则，使得变更的实际影响范围更加清晰。这提高了代码审查质量，缩小了错误的影响范围，并帮助团队在正确的层级设计测试。",{"data":362,"type":238},{"items":363,"style":237},[364,365,366,367,368],"模型测试验证不变式和业务规则","服务测试验证用例行为","控制器测试验证请求映射和响应流程","视图测试验证渲染和交互预期","端到端测试保护关键用户旅程，而无需承担全部负担",{"data":370,"type":217},{"text":371},"这就是为什么MVC也与\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Frunbooks\u002Frelease-runbook\">发布运行手册\u003C\u002Fa>和\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Fassessments\u002Fdelivery-assessment\">交付评估\u003C\u002Fa>自然连接。一个具有明确结构的平台更容易发布、度量和改进。",{"data":373,"type":265},{"code":374},"发布安全变更模式\n1. 在一个可信位置更新领域规则\n2. 扩展服务或用例测试\n3. 仅在请求契约变更时调整控制器映射\n4. 仅在输出契约变更时更新展示器或视图模型\n5. 验证受影响的界面和API响应\n6. 在具备回滚意识和清晰证据的情况下发布",{"data":376,"type":42},{"text":377,"level":227},"常见的MVC反模式",{"data":379,"type":238},{"items":380,"style":237},[381,382,383,384,385,386],"臃肿的控制器，暗中包含了应用层逻辑","被动的模型，缺乏有意义的领域行为","做出隐藏策略决策的视图","在前端、后端和管理工具中重复的验证逻辑","领域与UI之间缺乏稳定的展示器或视图模型边界","将框架约定误认为是架构",{"data":388,"type":217},{"text":389},"这些问题通常是逐渐出现的，因此团队会低估它们。一个代码库从外部看可能井井有条，但内部结构依然脆弱。",{"data":391,"type":255},{"text":392,"caption":393},"框架可以生成文件夹，但无法生成良好的边界。这些边界仍然需要团队来设计和维护。","企业交付操作系统视角",{"data":395,"type":42},{"text":396,"level":227},"最佳匹配SEO支柱定位",{"data":398,"type":217},{"text":399},"在企业交付操作系统结构中，本文属于\u003Cb>参考模型 > 数字平台\u003C\u002Fb>。这是正确的主要定位，因为MVC从根本上关乎平台结构和职责边界。其辅助支持链接属于\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Freference-models\u002Fdelivery-and-change\">交付与变更\u003C\u002Fa>、\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Fplaybooks\u002Fmigration-and-replatform\">迁移与平台重构\u003C\u002Fa>、\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Frunbooks\u002Frelease-runbook\">发布运行手册\u003C\u002Fa>和\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Fassessments\u002Fdelivery-assessment\">交付评估\u003C\u002Fa>。",{"data":401,"type":217},{"text":402},"这个定位并非表面功夫。它告诉门户、编辑和读者，该主题在结构上属于何处。MVC主要不是一个发布清单，主要不是一个迁移策略，也主要不是一个评估标准。它首先是一个平台设计原则。",{"data":404,"type":42},{"text":405,"level":227},"最终视角",{"data":407,"type":217},{"text":408},"模型-视图-控制器模式之所以仍然重要，是因为软件并不会仅仅因为框架更新而变得更简单。团队仍然需要一个稳定的地方来存放领域规则，一个受控的请求处理路径，以及一个不会将策略偷偷带入界面的表示层。如果运用得当，MVC 不仅仅是一个历史模式。它将成为实现更清晰架构、更安全发布、更轻松迁移以及更强长期交付纪律的实用工具。",{"data":410,"type":411},{},"delimiter",{"data":413,"type":420},{"link":414,"meta":415},"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise",{"image":416,"title":418,"description":419},{"url":417},"","企业交付操作系统","面向平台、交付、安全和LLM采用的企业知识库。","linkTool",{"data":422,"type":420},{"link":423,"meta":424},"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Freference-models\u002Fdigital-platform",{"image":425,"title":426,"description":427},{"url":417},"数字平台参考模型","一个与技术无关的结构，用于设计和运营支持大规模产品交付的数字平台。",{"data":429,"type":420},{"link":430,"meta":431},"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Freference-models\u002Fdelivery-and-change",{"image":432,"title":433,"description":434},{"url":417},"交付与变更参考模型","该模型定义了如何通过质量门、清晰的证据和可衡量的结果安全地发布变更。",{"data":436,"type":420},{"link":437,"meta":438},"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Fplaybooks\u002Fmigration-and-replatform",{"image":439,"title":440,"description":441},{"url":417},"迁移与平台重构手册","用于降低迁移风险并构建更安全的平台重构工作的手册。",{"data":443,"type":420},{"link":444,"meta":445},"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Frunbooks\u002Frelease-runbook",{"image":446,"title":447,"description":448},{"url":417},"发布运行手册","用于飞行前检查、发布步骤、验证和发布后审查的运行手册。",{"data":450,"type":420},{"link":451,"meta":452},"https:\u002F\u002Fstajic.de\u002Fzh\u002Fenterprise\u002Fassessments\u002Fdelivery-assessment",{"image":453,"title":454,"description":455},{"url":417},"交付能力评估","针对交付能力、变更风险和发布纪律的评估。","2.31","模型-视图-控制器（通常简称为MVC）依然是软件开发中最经久不衰的架构模式之一。它为团队提供了一种实用的方法，将业务逻辑、展示层和用户交互分离，从而使应用程序更易于构建、扩展、测试和维护。本文阐述了MVC是什么、为何至今仍具重要性、它在当今Web技术栈中的定位，以及它如何与更广泛的平台架构、交付质量、迁移策略和运维成熟度相连接。","\u002Fuploads\u002F2026\u002F03\u002Fmodel-view-controller-mvc-1774872805793-0bjubu.webp","model-view-controller-mvc-1774872805793-0bjubu","PUBLISHED","2023-04-12T12:57:00.000Z","2023-04-12T16:57:01.000Z","2026-03-30T15:17:26.670Z",{"en":465,"de":466,"sr":467,"es":468,"fr":469,"it":470,"ru":471,"zh":472},"\u002Fblog\u002Fmodel-view-controller-mvc","\u002Fde\u002Fblog\u002Fmodel-view-controller-mvc","\u002Fsr\u002Fblog\u002Fmodel-view-controller-mvc","\u002Fes\u002Fblog\u002Fmodel-view-controller-mvc","\u002Ffr\u002Fblog\u002Fmodel-view-controller-mvc","\u002Fit\u002Fblog\u002Fmodel-view-controller-mvc","\u002Fru\u002Fblog\u002Fmodel-view-controller-mvc","\u002Fzh\u002Fblog\u002Fmodel-view-controller-mvc",[474,477,481],{"id":475,"name":418,"slug":476},39,"enterprise",{"id":478,"name":479,"slug":480},44,"参考模型","reference-models",{"id":482,"name":426,"slug":483},45,"digital-platform",{"id":485,"login":486,"email":487,"displayName":488},"20","rooth8233","aleksandar@stajic.de","Aleksandar Stajić",[490,728],{"lang":491,"title":492,"content":493,"contentJson":494,"excerpt":727},"en","Model-View-Controller (MVC): The Structural Backbone of Modern Web Applications","{\"time\":1774828800000,\"blocks\":[{\"type\":\"paragraph\",\"data\":{\"text\":\"The \u003Cb>Model-View-Controller (MVC)\u003C\u002Fb> pattern remains one of the most durable foundations in web application architecture. Its longevity is not an accident. MVC survives because it solves a problem that never really disappears: how to structure software so that growth does not turn every change into risk. When responsibility is separated well, teams can extend features, revise interfaces, refactor internals, and release changes with far less friction.\"}},{\"type\":\"paragraph\",\"data\":{\"text\":\"That is why this topic belongs naturally inside \u003Cb>Enterprise Delivery OS\u003C\u002Fb>. MVC is not just a coding convention. It is a structural discipline that influences platform maintainability, delivery safety, migration effort, test design, and operational clarity. In practical engineering terms, MVC is useful because it draws boundaries where systems usually become tangled.\"}},{\"type\":\"paragraph\",\"data\":{\"text\":\"Within the stajic.de pillar structure, the strongest primary fit is \u003Cb>Reference Models > Digital Platform\u003C\u002Fb>. MVC is first an architecture and platform-boundary topic. It also connects to delivery and change, migration and replatforming, release control, and delivery assessment, but those are secondary supporting relationships rather than the main classification.\"}},{\"type\":\"header\",\"data\":{\"text\":\"What MVC Actually Separates\",\"level\":2}},{\"type\":\"paragraph\",\"data\":{\"text\":\"MVC divides an application into three different areas of responsibility. The \u003Cb>Model\u003C\u002Fb> represents domain state, invariants, and rules. The \u003Cb>View\u003C\u002Fb> is responsible for presentation and interaction output. The \u003Cb>Controller\u003C\u002Fb> receives requests, coordinates the relevant use case, and decides how the response should be assembled. The names are simple, but the value is significant: clean separation reduces hidden coupling.\"}},{\"type\":\"list\",\"data\":{\"style\":\"unordered\",\"items\":[\"The \u003Cb>Model\u003C\u002Fb> owns domain meaning, not just storage.\",\"The \u003Cb>View\u003C\u002Fb> presents information clearly, without quietly becoming the business layer.\",\"The \u003Cb>Controller\u003C\u002Fb> coordinates flow, instead of turning into a god object.\"]}},{\"type\":\"paragraph\",\"data\":{\"text\":\"Once those boundaries weaken, systems become harder to understand. Business rules drift into templates. Controllers become overloaded with orchestration, validation, and side effects. Models become passive database wrappers. Teams then mistake framework structure for architectural clarity, even though the codebase is already entangled.\"}},{\"type\":\"header\",\"data\":{\"text\":\"Why MVC Still Matters in Modern Web Stacks\",\"level\":2}},{\"type\":\"paragraph\",\"data\":{\"text\":\"Modern frameworks often speak a different language: components, composables, islands, server actions, API routes, headless delivery, and edge rendering. None of that removes the need for separation. It only redistributes where separation must happen. A serious platform still needs a stable place for domain rules, a controlled path for request orchestration, and a presentation layer that does not secretly own policy.\"}},{\"type\":\"paragraph\",\"data\":{\"text\":\"That is why the useful question is not whether a framework calls itself MVC. The useful question is whether the platform protects the same boundaries that MVC was designed to enforce. If it does not, then the stack may look modern while still accumulating structural debt.\"}},{\"type\":\"quote\",\"data\":{\"text\":\"Framework novelty does not replace architectural discipline. New syntax can hide old chaos.\",\"caption\":\"Platform architecture perspective\"}},{\"type\":\"header\",\"data\":{\"text\":\"A Minimal Request Flow\",\"level\":2}},{\"type\":\"paragraph\",\"data\":{\"text\":\"The simplest way to understand MVC is to follow a request through the system. A user requests a page or triggers an action. The controller receives the request, delegates domain work to models or services, prepares a response structure, and passes the result to the view. The view renders the output. This flow is easy to explain, but many systems violate it in practice.\"}},{\"type\":\"code\",\"data\":{\"code\":\"\u002F\u002F Request enters the system\\nGET \u002Fproducts\u002F42 \u002F\u002F Router chooses the controller action\\nProductController.show(id = 42) \u002F\u002F Controller coordinates the use case\\nproduct = ProductService.getById(42)\\nviewModel = ProductPresenter.toViewModel(product) \u002F\u002F View renders output\\nreturn render(\\\"product\u002Fshow\\\", viewModel)\"}},{\"type\":\"paragraph\",\"data\":{\"text\":\"This example is intentionally minimal. The value is not the syntax. The value is visibility. A reviewer can see where the request enters, where domain work happens, and where presentation begins. That clarity becomes extremely important when teams are changing a live platform under delivery pressure.\"}},{\"type\":\"header\",\"data\":{\"text\":\"What the Model Should Really Own\",\"level\":2}},{\"type\":\"paragraph\",\"data\":{\"text\":\"In weak implementations, the model becomes little more than an ORM entity or database record. That is too narrow. A useful model protects business meaning. It should hold rules that must remain true regardless of whether the request came from a web form, an admin screen, a public API, a background worker, or a CLI job.\"}},{\"type\":\"list\",\"data\":{\"style\":\"unordered\",\"items\":[\"State transitions such as allowed status changes\",\"Invariants that must hold across every interface\",\"Domain-level validation that belongs to the business, not only to the form layer\",\"Calculated values and decisions that represent actual business behavior\"]}},{\"type\":\"code\",\"data\":{\"code\":\"class Order: def cancel(self, actor): if self.status == \\\"shipped\\\": raise DomainError(\\\"Shipped orders cannot be cancelled\\\") if not actor.can(\\\"cancel_order\\\"): raise PermissionError(\\\"Actor may not cancel this order\\\") self.status = \\\"cancelled\\\"\"}},{\"type\":\"paragraph\",\"data\":{\"text\":\"That rule is small, but the lesson is large. If a rule matters, it needs a stable home. When such logic exists only in one controller action or one UI form, another path will eventually bypass it. Domain rules should live where the domain can actually defend them.\"}},{\"type\":\"header\",\"data\":{\"text\":\"What the View Should and Should Not Do\",\"level\":2}},{\"type\":\"paragraph\",\"data\":{\"text\":\"The view exists to present information, format output, and support interaction. It can contain display logic, but it should not become the hidden owner of important business policy. Once templates start deciding who is allowed to do what, the system becomes harder to test, harder to audit, and easier to break.\"}},{\"type\":\"code\",\"data\":{\"code\":\"\u003C!-- Good: presentation logic -->\\n{% if product.stock > 0 %} \u003Cbutton>Add to cart\u003C\u002Fbutton>\\n{% else %} \u003Cp>Currently unavailable\u003C\u002Fp>\\n{% endif %} \u003C!-- Bad: business policy leaking into the template -->\\n{% if user.role == \\\"admin\\\" or order.total \u003C 1000 or region == \\\"DE\\\" %} \u003Cbutton>Approve refund\u003C\u002Fbutton>\\n{% endif %}\"}},{\"type\":\"paragraph\",\"data\":{\"text\":\"A view may decide how to display a state. It should not silently decide which policies are valid. That distinction looks small in code review, but it becomes huge over time.\"}},{\"type\":\"header\",\"data\":{\"text\":\"Controllers Should Coordinate, Not Accumulate Power\",\"level\":2}},{\"type\":\"paragraph\",\"data\":{\"text\":\"Controllers are useful because they create a clear entrance into the application. But they should stay focused. A controller that validates raw input, calls external services, calculates domain decisions, transforms persistence data, and decides final rendering strategy is no longer just a controller. It becomes a hidden application layer welded to HTTP.\"}},{\"type\":\"code\",\"data\":{\"code\":\"\u002F\u002F Too much responsibility in one controller\\nasync function checkout(req, res) { validateCart(req.body) const tax = await taxApi.calculate(req.body.address, req.body.items) const discount = computeDiscount(req.user, req.body.items) const inventory = await reserveItems(req.body.items) const payment = await chargeCard(req.body.card) const order = await db.orders.create({ tax, discount, inventory, payment }) res.render(\\\"checkout\u002Fsuccess\\\", { order })\\n}\"}},{\"type\":\"code\",\"data\":{\"code\":\"\u002F\u002F Better: controller delegates to application services\\nasync function checkout(req, res) { const command = CheckoutCommand.fromHttp(req) const result = await checkoutService.execute(command) res.render(\\\"checkout\u002Fsuccess\\\", CheckoutPresenter.toViewModel(result))\\n}\"}},{\"type\":\"paragraph\",\"data\":{\"text\":\"This is where MVC becomes strongly relevant to delivery quality. Clear boundaries reduce review scope, shrink change impact, and make releases easier to reason about. That is also why MVC relates naturally to the \u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Freference-models\u002Fdelivery-and-change\\\">Delivery and Change Reference Model\u003C\u002Fa>, which focuses on shipping changes safely with explicit evidence and measurable outcomes.\"}},{\"type\":\"header\",\"data\":{\"text\":\"MVC and Platform Architecture\",\"level\":2}},{\"type\":\"paragraph\",\"data\":{\"text\":\"The best primary fit for this article is the \u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Freference-models\u002Fdigital-platform\\\">Digital Platform Reference Model\u003C\u002Fa>. That page describes a tech-agnostic structure for designing and operating a digital platform at scale. MVC fits there because it is part of the structural vocabulary teams use to define boundaries, responsibilities, and change surfaces inside real systems.\"}},{\"type\":\"paragraph\",\"data\":{\"text\":\"A platform with weak internal boundaries may still run in production, but it becomes slower to evolve. New features take longer. Bugs become harder to localize. Refactoring gets postponed. Releases carry more unknown risk. In that sense, MVC is not merely about code style. It is about preserving changeability.\"}},{\"type\":\"header\",\"data\":{\"text\":\"MVC in Modern Frameworks and Headless Systems\",\"level\":2}},{\"type\":\"paragraph\",\"data\":{\"text\":\"Not every modern stack exposes classic MVC directly. In SSR frameworks, controllers may appear as route handlers or server actions. In API-first systems, the view may live in a separate frontend. In headless platforms, model behavior may be split across services, domain modules, and persistence layers. But the need for separation does not vanish. It simply spreads across more moving parts.\"}},{\"type\":\"list\",\"data\":{\"style\":\"unordered\",\"items\":[\"SSR frameworks often move controller logic into route-level handlers\",\"API-first architectures place presentation in a distinct frontend layer\",\"Headless systems distribute model behavior across service and domain boundaries\",\"Component-based UIs still benefit from keeping business policy out of the view layer\"]}},{\"type\":\"paragraph\",\"data\":{\"text\":\"So the deeper lesson is this: MVC remains valuable even when its classical packaging disappears. It survives as a design principle because responsibility separation remains one of the few reliable defenses against entropy.\"}},{\"type\":\"header\",\"data\":{\"text\":\"Why MVC Makes Replatforming Easier\",\"level\":2}},{\"type\":\"paragraph\",\"data\":{\"text\":\"Legacy migrations often fail because the old platform mixed everything together. Queries live in templates. State transitions hide in helper files. Validation is duplicated in forms, APIs, and admin tools. Nobody can move one part safely because too many responsibilities are fused together. The cleaner the separation, the more realistic the migration path becomes.\"}},{\"type\":\"paragraph\",\"data\":{\"text\":\"That is why MVC has strong secondary relevance for the \u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Fplaybooks\u002Fmigration-and-replatform\\\">Migration and Replatform Playbook\u003C\u002Fa>. Replatforming is not only a technology replacement exercise. It is a disentangling exercise. Teams must expose and stabilize responsibility boundaries before a move can become safe.\"}},{\"type\":\"code\",\"data\":{\"code\":\"Replatform-safe sequence\\n1. Move domain rules out of templates and controllers\\n2. Reduce controllers to request mapping and orchestration\\n3. Introduce presenters or view models for stable output contracts\\n4. Isolate persistence access behind services or repositories\\n5. Migrate one boundary at a time instead of rewriting everything at once\"}},{\"type\":\"paragraph\",\"data\":{\"text\":\"This kind of restructuring does not make migration trivial, but it reduces uncertainty. That alone can save months of waste.\"}},{\"type\":\"header\",\"data\":{\"text\":\"Release Safety, Testing, and Operational Confidence\",\"level\":2}},{\"type\":\"paragraph\",\"data\":{\"text\":\"MVC does not guarantee safe releases by itself, but it makes release safety much easier to achieve. Thin controllers, explicit services, stable view models, and protected domain rules make it clearer where a change really lands. That improves review quality, narrows the blast radius of mistakes, and helps teams design tests at the correct layer.\"}},{\"type\":\"list\",\"data\":{\"style\":\"unordered\",\"items\":[\"Model tests verify invariants and business rules\",\"Service tests verify use-case behavior\",\"Controller tests verify request mapping and response flow\",\"View tests verify rendering and interaction expectations\",\"End-to-end tests protect key user journeys without carrying the entire burden\"]}},{\"type\":\"paragraph\",\"data\":{\"text\":\"This is why MVC also connects naturally to the \u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Frunbooks\u002Frelease-runbook\\\">Release Runbook\u003C\u002Fa> and the \u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Fassessments\u002Fdelivery-assessment\\\">Delivery Assessment\u003C\u002Fa>. A platform with explicit structure is easier to release, easier to measure, and easier to improve.\"}},{\"type\":\"code\",\"data\":{\"code\":\"Release-safe change pattern\\n1. Update the domain rule in one trusted place\\n2. Extend service or use-case tests\\n3. Adjust controller mapping only if the request contract changed\\n4. Update presenter or view model only if the output contract changed\\n5. Verify affected screens and API responses\\n6. Release with rollback awareness and clear evidence\"}},{\"type\":\"header\",\"data\":{\"text\":\"Common MVC Anti-Patterns\",\"level\":2}},{\"type\":\"list\",\"data\":{\"style\":\"unordered\",\"items\":[\"Fat controllers that secretly contain the application layer\",\"Passive models with no meaningful domain behavior\",\"Views that make hidden policy decisions\",\"Duplicated validation across frontend, backend, and admin tools\",\"No stable presenter or view-model boundary between domain and UI\",\"Framework conventions mistaken for architecture\"]}},{\"type\":\"paragraph\",\"data\":{\"text\":\"These problems often appear gradually, which is why teams underestimate them. A codebase can look organized from the outside and still be structurally weak inside.\"}},{\"type\":\"quote\",\"data\":{\"text\":\"A framework can generate folders. It cannot generate good boundaries. Those still have to be designed and defended by the team.\",\"caption\":\"Enterprise Delivery OS perspective\"}},{\"type\":\"header\",\"data\":{\"text\":\"Best-Fit SEO Pillar Placement\",\"level\":2}},{\"type\":\"paragraph\",\"data\":{\"text\":\"Inside the Enterprise Delivery OS structure, this article belongs to \u003Cb>Reference Models > Digital Platform\u003C\u002Fb>. That is the correct primary placement because MVC is fundamentally about platform structure and responsibility boundaries. Its secondary support links belong to \u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Freference-models\u002Fdelivery-and-change\\\">Delivery and Change\u003C\u002Fa>, \u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Fplaybooks\u002Fmigration-and-replatform\\\">Migration and Replatform\u003C\u002Fa>, \u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Frunbooks\u002Frelease-runbook\\\">Release Runbook\u003C\u002Fa>, and \u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Fassessments\u002Fdelivery-assessment\\\">Delivery Assessment\u003C\u002Fa>.\"}},{\"type\":\"paragraph\",\"data\":{\"text\":\"That placement is not cosmetic. It tells the portal, the editor, and the reader where the topic belongs structurally. MVC is not mainly a release checklist, not mainly a migration tactic, and not mainly an assessment rubric. It is first a platform design principle.\"}},{\"type\":\"header\",\"data\":{\"text\":\"Final Perspective\",\"level\":2}},{\"type\":\"paragraph\",\"data\":{\"text\":\"Model-View-Controller remains relevant because software does not become easier merely because frameworks become newer. Teams still need a stable place for domain rules, a controlled path for request handling, and a presentation layer that does not smuggle policy into the interface. Used well, MVC becomes more than a historical pattern. It becomes a practical instrument for cleaner architectures, safer releases, easier migrations, and stronger long-term delivery discipline.\"}},{\"type\":\"delimiter\",\"data\":{}},{\"type\":\"linkTool\",\"data\":{\"link\":\"https:\u002F\u002Fstajic.de\u002Fenterprise\",\"meta\":{\"title\":\"Enterprise Delivery OS\",\"description\":\"Enterprise knowledge base for platform, delivery, security, and LLM adoption.\",\"image\":{\"url\":\"\"}}}},{\"type\":\"linkTool\",\"data\":{\"link\":\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Freference-models\u002Fdigital-platform\",\"meta\":{\"title\":\"Digital Platform Reference Model\",\"description\":\"A tech-agnostic structure for designing and operating a digital platform that supports product delivery at scale.\",\"image\":{\"url\":\"\"}}}},{\"type\":\"linkTool\",\"data\":{\"link\":\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Freference-models\u002Fdelivery-and-change\",\"meta\":{\"title\":\"Delivery and Change Reference Model\",\"description\":\"This model defines how to ship changes safely with quality gates, clear evidence, and measurable outcomes.\",\"image\":{\"url\":\"\"}}}},{\"type\":\"linkTool\",\"data\":{\"link\":\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Fplaybooks\u002Fmigration-and-replatform\",\"meta\":{\"title\":\"Migration and Replatform Playbook\",\"description\":\"Playbook for reducing migration risk and structuring safer replatforming work.\",\"image\":{\"url\":\"\"}}}},{\"type\":\"linkTool\",\"data\":{\"link\":\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Frunbooks\u002Frelease-runbook\",\"meta\":{\"title\":\"Release Runbook\",\"description\":\"Runbook for preflight checks, release steps, verification, and post-release review.\",\"image\":{\"url\":\"\"}}}},{\"type\":\"linkTool\",\"data\":{\"link\":\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Fassessments\u002Fdelivery-assessment\",\"meta\":{\"title\":\"Delivery Assessment\",\"description\":\"Assessment for delivery capability, change risk, and release discipline.\",\"image\":{\"url\":\"\"}}}}],\"version\":\"2.30.8\"}",{"time":495,"blocks":496,"version":726},1774828800000,[497,500,503,506,509,512,518,521,524,527,530,534,537,540,543,546,549,552,559,561,564,567,570,572,575,578,581,583,585,588,591,594,597,600,603,610,613,616,619,622,625,628,631,634,642,645,648,651,660,663,667,670,673,676,679,682,684,691,698,705,712,719],{"data":498,"type":217},{"text":499},"The \u003Cb>Model-View-Controller (MVC)\u003C\u002Fb> pattern remains one of the most durable foundations in web application architecture. Its longevity is not an accident. MVC survives because it solves a problem that never really disappears: how to structure software so that growth does not turn every change into risk. When responsibility is separated well, teams can extend features, revise interfaces, refactor internals, and release changes with far less friction.",{"data":501,"type":217},{"text":502},"That is why this topic belongs naturally inside \u003Cb>Enterprise Delivery OS\u003C\u002Fb>. MVC is not just a coding convention. It is a structural discipline that influences platform maintainability, delivery safety, migration effort, test design, and operational clarity. In practical engineering terms, MVC is useful because it draws boundaries where systems usually become tangled.",{"data":504,"type":217},{"text":505},"Within the stajic.de pillar structure, the strongest primary fit is \u003Cb>Reference Models > Digital Platform\u003C\u002Fb>. MVC is first an architecture and platform-boundary topic. It also connects to delivery and change, migration and replatforming, release control, and delivery assessment, but those are secondary supporting relationships rather than the main classification.",{"data":507,"type":42},{"text":508,"level":227},"What MVC Actually Separates",{"data":510,"type":217},{"text":511},"MVC divides an application into three different areas of responsibility. The \u003Cb>Model\u003C\u002Fb> represents domain state, invariants, and rules. The \u003Cb>View\u003C\u002Fb> is responsible for presentation and interaction output. The \u003Cb>Controller\u003C\u002Fb> receives requests, coordinates the relevant use case, and decides how the response should be assembled. The names are simple, but the value is significant: clean separation reduces hidden coupling.",{"data":513,"type":238},{"items":514,"style":237},[515,516,517],"The \u003Cb>Model\u003C\u002Fb> owns domain meaning, not just storage.","The \u003Cb>View\u003C\u002Fb> presents information clearly, without quietly becoming the business layer.","The \u003Cb>Controller\u003C\u002Fb> coordinates flow, instead of turning into a god object.",{"data":519,"type":217},{"text":520},"Once those boundaries weaken, systems become harder to understand. Business rules drift into templates. Controllers become overloaded with orchestration, validation, and side effects. Models become passive database wrappers. Teams then mistake framework structure for architectural clarity, even though the codebase is already entangled.",{"data":522,"type":42},{"text":523,"level":227},"Why MVC Still Matters in Modern Web Stacks",{"data":525,"type":217},{"text":526},"Modern frameworks often speak a different language: components, composables, islands, server actions, API routes, headless delivery, and edge rendering. None of that removes the need for separation. It only redistributes where separation must happen. A serious platform still needs a stable place for domain rules, a controlled path for request orchestration, and a presentation layer that does not secretly own policy.",{"data":528,"type":217},{"text":529},"That is why the useful question is not whether a framework calls itself MVC. The useful question is whether the platform protects the same boundaries that MVC was designed to enforce. If it does not, then the stack may look modern while still accumulating structural debt.",{"data":531,"type":255},{"text":532,"caption":533},"Framework novelty does not replace architectural discipline. New syntax can hide old chaos.","Platform architecture perspective",{"data":535,"type":42},{"text":536,"level":227},"A Minimal Request Flow",{"data":538,"type":217},{"text":539},"The simplest way to understand MVC is to follow a request through the system. A user requests a page or triggers an action. The controller receives the request, delegates domain work to models or services, prepares a response structure, and passes the result to the view. The view renders the output. This flow is easy to explain, but many systems violate it in practice.",{"data":541,"type":265},{"code":542},"\u002F\u002F Request enters the system\nGET \u002Fproducts\u002F42 \u002F\u002F Router chooses the controller action\nProductController.show(id = 42) \u002F\u002F Controller coordinates the use case\nproduct = ProductService.getById(42)\nviewModel = ProductPresenter.toViewModel(product) \u002F\u002F View renders output\nreturn render(\"product\u002Fshow\", viewModel)",{"data":544,"type":217},{"text":545},"This example is intentionally minimal. The value is not the syntax. The value is visibility. A reviewer can see where the request enters, where domain work happens, and where presentation begins. That clarity becomes extremely important when teams are changing a live platform under delivery pressure.",{"data":547,"type":42},{"text":548,"level":227},"What the Model Should Really Own",{"data":550,"type":217},{"text":551},"In weak implementations, the model becomes little more than an ORM entity or database record. That is too narrow. A useful model protects business meaning. It should hold rules that must remain true regardless of whether the request came from a web form, an admin screen, a public API, a background worker, or a CLI job.",{"data":553,"type":238},{"items":554,"style":237},[555,556,557,558],"State transitions such as allowed status changes","Invariants that must hold across every interface","Domain-level validation that belongs to the business, not only to the form layer","Calculated values and decisions that represent actual business behavior",{"data":560,"type":265},{"code":284},{"data":562,"type":217},{"text":563},"That rule is small, but the lesson is large. If a rule matters, it needs a stable home. When such logic exists only in one controller action or one UI form, another path will eventually bypass it. Domain rules should live where the domain can actually defend them.",{"data":565,"type":42},{"text":566,"level":227},"What the View Should and Should Not Do",{"data":568,"type":217},{"text":569},"The view exists to present information, format output, and support interaction. It can contain display logic, but it should not become the hidden owner of important business policy. Once templates start deciding who is allowed to do what, the system becomes harder to test, harder to audit, and easier to break.",{"data":571,"type":265},{"code":296},{"data":573,"type":217},{"text":574},"A view may decide how to display a state. It should not silently decide which policies are valid. That distinction looks small in code review, but it becomes huge over time.",{"data":576,"type":42},{"text":577,"level":227},"Controllers Should Coordinate, Not Accumulate Power",{"data":579,"type":217},{"text":580},"Controllers are useful because they create a clear entrance into the application. But they should stay focused. A controller that validates raw input, calls external services, calculates domain decisions, transforms persistence data, and decides final rendering strategy is no longer just a controller. It becomes a hidden application layer welded to HTTP.",{"data":582,"type":265},{"code":308},{"data":584,"type":265},{"code":311},{"data":586,"type":217},{"text":587},"This is where MVC becomes strongly relevant to delivery quality. Clear boundaries reduce review scope, shrink change impact, and make releases easier to reason about. That is also why MVC relates naturally to the \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Freference-models\u002Fdelivery-and-change\">Delivery and Change Reference Model\u003C\u002Fa>, which focuses on shipping changes safely with explicit evidence and measurable outcomes.",{"data":589,"type":42},{"text":590,"level":227},"MVC and Platform Architecture",{"data":592,"type":217},{"text":593},"The best primary fit for this article is the \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Freference-models\u002Fdigital-platform\">Digital Platform Reference Model\u003C\u002Fa>. That page describes a tech-agnostic structure for designing and operating a digital platform at scale. MVC fits there because it is part of the structural vocabulary teams use to define boundaries, responsibilities, and change surfaces inside real systems.",{"data":595,"type":217},{"text":596},"A platform with weak internal boundaries may still run in production, but it becomes slower to evolve. New features take longer. Bugs become harder to localize. Refactoring gets postponed. Releases carry more unknown risk. In that sense, MVC is not merely about code style. It is about preserving changeability.",{"data":598,"type":42},{"text":599,"level":227},"MVC in Modern Frameworks and Headless Systems",{"data":601,"type":217},{"text":602},"Not every modern stack exposes classic MVC directly. In SSR frameworks, controllers may appear as route handlers or server actions. In API-first systems, the view may live in a separate frontend. In headless platforms, model behavior may be split across services, domain modules, and persistence layers. But the need for separation does not vanish. It simply spreads across more moving parts.",{"data":604,"type":238},{"items":605,"style":237},[606,607,608,609],"SSR frameworks often move controller logic into route-level handlers","API-first architectures place presentation in a distinct frontend layer","Headless systems distribute model behavior across service and domain boundaries","Component-based UIs still benefit from keeping business policy out of the view layer",{"data":611,"type":217},{"text":612},"So the deeper lesson is this: MVC remains valuable even when its classical packaging disappears. It survives as a design principle because responsibility separation remains one of the few reliable defenses against entropy.",{"data":614,"type":42},{"text":615,"level":227},"Why MVC Makes Replatforming Easier",{"data":617,"type":217},{"text":618},"Legacy migrations often fail because the old platform mixed everything together. Queries live in templates. State transitions hide in helper files. Validation is duplicated in forms, APIs, and admin tools. Nobody can move one part safely because too many responsibilities are fused together. The cleaner the separation, the more realistic the migration path becomes.",{"data":620,"type":217},{"text":621},"That is why MVC has strong secondary relevance for the \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Fplaybooks\u002Fmigration-and-replatform\">Migration and Replatform Playbook\u003C\u002Fa>. Replatforming is not only a technology replacement exercise. It is a disentangling exercise. Teams must expose and stabilize responsibility boundaries before a move can become safe.",{"data":623,"type":265},{"code":624},"Replatform-safe sequence\n1. Move domain rules out of templates and controllers\n2. Reduce controllers to request mapping and orchestration\n3. Introduce presenters or view models for stable output contracts\n4. Isolate persistence access behind services or repositories\n5. Migrate one boundary at a time instead of rewriting everything at once",{"data":626,"type":217},{"text":627},"This kind of restructuring does not make migration trivial, but it reduces uncertainty. That alone can save months of waste.",{"data":629,"type":42},{"text":630,"level":227},"Release Safety, Testing, and Operational Confidence",{"data":632,"type":217},{"text":633},"MVC does not guarantee safe releases by itself, but it makes release safety much easier to achieve. Thin controllers, explicit services, stable view models, and protected domain rules make it clearer where a change really lands. That improves review quality, narrows the blast radius of mistakes, and helps teams design tests at the correct layer.",{"data":635,"type":238},{"items":636,"style":237},[637,638,639,640,641],"Model tests verify invariants and business rules","Service tests verify use-case behavior","Controller tests verify request mapping and response flow","View tests verify rendering and interaction expectations","End-to-end tests protect key user journeys without carrying the entire burden",{"data":643,"type":217},{"text":644},"This is why MVC also connects naturally to the \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Frunbooks\u002Frelease-runbook\">Release Runbook\u003C\u002Fa> and the \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Fassessments\u002Fdelivery-assessment\">Delivery Assessment\u003C\u002Fa>. A platform with explicit structure is easier to release, easier to measure, and easier to improve.",{"data":646,"type":265},{"code":647},"Release-safe change pattern\n1. Update the domain rule in one trusted place\n2. Extend service or use-case tests\n3. Adjust controller mapping only if the request contract changed\n4. Update presenter or view model only if the output contract changed\n5. Verify affected screens and API responses\n6. Release with rollback awareness and clear evidence",{"data":649,"type":42},{"text":650,"level":227},"Common MVC Anti-Patterns",{"data":652,"type":238},{"items":653,"style":237},[654,655,656,657,658,659],"Fat controllers that secretly contain the application layer","Passive models with no meaningful domain behavior","Views that make hidden policy decisions","Duplicated validation across frontend, backend, and admin tools","No stable presenter or view-model boundary between domain and UI","Framework conventions mistaken for architecture",{"data":661,"type":217},{"text":662},"These problems often appear gradually, which is why teams underestimate them. A codebase can look organized from the outside and still be structurally weak inside.",{"data":664,"type":255},{"text":665,"caption":666},"A framework can generate folders. It cannot generate good boundaries. Those still have to be designed and defended by the team.","Enterprise Delivery OS perspective",{"data":668,"type":42},{"text":669,"level":227},"Best-Fit SEO Pillar Placement",{"data":671,"type":217},{"text":672},"Inside the Enterprise Delivery OS structure, this article belongs to \u003Cb>Reference Models > Digital Platform\u003C\u002Fb>. That is the correct primary placement because MVC is fundamentally about platform structure and responsibility boundaries. Its secondary support links belong to \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Freference-models\u002Fdelivery-and-change\">Delivery and Change\u003C\u002Fa>, \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Fplaybooks\u002Fmigration-and-replatform\">Migration and Replatform\u003C\u002Fa>, \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Frunbooks\u002Frelease-runbook\">Release Runbook\u003C\u002Fa>, and \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Fassessments\u002Fdelivery-assessment\">Delivery Assessment\u003C\u002Fa>.",{"data":674,"type":217},{"text":675},"That placement is not cosmetic. It tells the portal, the editor, and the reader where the topic belongs structurally. MVC is not mainly a release checklist, not mainly a migration tactic, and not mainly an assessment rubric. It is first a platform design principle.",{"data":677,"type":42},{"text":678,"level":227},"Final Perspective",{"data":680,"type":217},{"text":681},"Model-View-Controller remains relevant because software does not become easier merely because frameworks become newer. Teams still need a stable place for domain rules, a controlled path for request handling, and a presentation layer that does not smuggle policy into the interface. Used well, MVC becomes more than a historical pattern. It becomes a practical instrument for cleaner architectures, safer releases, easier migrations, and stronger long-term delivery discipline.",{"data":683,"type":411},{},{"data":685,"type":420},{"link":686,"meta":687},"https:\u002F\u002Fstajic.de\u002Fenterprise",{"image":688,"title":689,"description":690},{"url":417},"Enterprise Delivery OS","Enterprise knowledge base for platform, delivery, security, and LLM adoption.",{"data":692,"type":420},{"link":693,"meta":694},"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Freference-models\u002Fdigital-platform",{"image":695,"title":696,"description":697},{"url":417},"Digital Platform Reference Model","A tech-agnostic structure for designing and operating a digital platform that supports product delivery at scale.",{"data":699,"type":420},{"link":700,"meta":701},"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Freference-models\u002Fdelivery-and-change",{"image":702,"title":703,"description":704},{"url":417},"Delivery and Change Reference Model","This model defines how to ship changes safely with quality gates, clear evidence, and measurable outcomes.",{"data":706,"type":420},{"link":707,"meta":708},"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Fplaybooks\u002Fmigration-and-replatform",{"image":709,"title":710,"description":711},{"url":417},"Migration and Replatform Playbook","Playbook for reducing migration risk and structuring safer replatforming work.",{"data":713,"type":420},{"link":714,"meta":715},"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Frunbooks\u002Frelease-runbook",{"image":716,"title":717,"description":718},{"url":417},"Release Runbook","Runbook for preflight checks, release steps, verification, and post-release review.",{"data":720,"type":420},{"link":721,"meta":722},"https:\u002F\u002Fstajic.de\u002Fenterprise\u002Fassessments\u002Fdelivery-assessment",{"image":723,"title":724,"description":725},{"url":417},"Delivery Assessment","Assessment for delivery capability, change risk, and release discipline.","2.30.8","Model-View-Controller, usually shortened to MVC, remains one of the most durable architectural patterns in software development. It gives teams a practical way to separate business logic, presentation, and user interaction so applications stay easier to build, extend, test, and maintain. This article explains what MVC is, why it still matters, where it fits in today’s web stacks, and how it connects to broader platform architecture, delivery quality, migration strategy, and operational maturity.",{"lang":7,"title":208,"content":210,"contentJson":729,"excerpt":457},{"time":212,"blocks":730,"version":456},[731,733,735,737,739,741,744,746,748,750,752,754,756,758,760,762,764,766,769,771,773,775,777,779,781,783,785,787,789,791,793,795,797,799,801,804,806,808,810,812,814,816,818,820,823,825,827,829,832,834,836,838,840,842,844,846,848,852,856,860,864,868],{"data":732,"type":217},{"text":216},{"data":734,"type":217},{"text":220},{"data":736,"type":217},{"text":223},{"data":738,"type":42},{"text":226,"level":227},{"data":740,"type":217},{"text":230},{"data":742,"type":238},{"items":743,"style":237},[234,235,236],{"data":745,"type":217},{"text":241},{"data":747,"type":42},{"text":244,"level":227},{"data":749,"type":217},{"text":247},{"data":751,"type":217},{"text":250},{"data":753,"type":255},{"text":253,"caption":254},{"data":755,"type":42},{"text":258,"level":227},{"data":757,"type":217},{"text":261},{"data":759,"type":265},{"code":264},{"data":761,"type":217},{"text":268},{"data":763,"type":42},{"text":271,"level":227},{"data":765,"type":217},{"text":274},{"data":767,"type":238},{"items":768,"style":237},[278,279,280,281],{"data":770,"type":265},{"code":284},{"data":772,"type":217},{"text":287},{"data":774,"type":42},{"text":290,"level":227},{"data":776,"type":217},{"text":293},{"data":778,"type":265},{"code":296},{"data":780,"type":217},{"text":299},{"data":782,"type":42},{"text":302,"level":227},{"data":784,"type":217},{"text":305},{"data":786,"type":265},{"code":308},{"data":788,"type":265},{"code":311},{"data":790,"type":217},{"text":314},{"data":792,"type":42},{"text":317,"level":227},{"data":794,"type":217},{"text":320},{"data":796,"type":217},{"text":323},{"data":798,"type":42},{"text":326,"level":227},{"data":800,"type":217},{"text":329},{"data":802,"type":238},{"items":803,"style":237},[333,334,335,336],{"data":805,"type":217},{"text":339},{"data":807,"type":42},{"text":342,"level":227},{"data":809,"type":217},{"text":345},{"data":811,"type":217},{"text":348},{"data":813,"type":265},{"code":351},{"data":815,"type":217},{"text":354},{"data":817,"type":42},{"text":357,"level":227},{"data":819,"type":217},{"text":360},{"data":821,"type":238},{"items":822,"style":237},[364,365,366,367,368],{"data":824,"type":217},{"text":371},{"data":826,"type":265},{"code":374},{"data":828,"type":42},{"text":377,"level":227},{"data":830,"type":238},{"items":831,"style":237},[381,382,383,384,385,386],{"data":833,"type":217},{"text":389},{"data":835,"type":255},{"text":392,"caption":393},{"data":837,"type":42},{"text":396,"level":227},{"data":839,"type":217},{"text":399},{"data":841,"type":217},{"text":402},{"data":843,"type":42},{"text":405,"level":227},{"data":845,"type":217},{"text":408},{"data":847,"type":411},{},{"data":849,"type":420},{"link":414,"meta":850},{"image":851,"title":418,"description":419},{"url":417},{"data":853,"type":420},{"link":423,"meta":854},{"image":855,"title":426,"description":427},{"url":417},{"data":857,"type":420},{"link":430,"meta":858},{"image":859,"title":433,"description":434},{"url":417},{"data":861,"type":420},{"link":437,"meta":862},{"image":863,"title":440,"description":441},{"url":417},{"data":865,"type":420},{"link":444,"meta":866},{"image":867,"title":447,"description":448},{"url":417},{"data":869,"type":420},{"link":451,"meta":870},{"image":871,"title":454,"description":455},{"url":417},"Post erfolgreich abgerufen",{"items":874,"source":903,"manualIds":904,"manualMatchedIds":905},[875,882,889,896],{"id":876,"slug":877,"title":878,"excerpt":879,"featuredImage":880,"publishedAt":881},"381","enterprise-grade-multi-tenant-architecture-for-an-international-platform","企业级多租户架构，适用于国际平台","Loving Rocks 是一款企业级婚礼平台，采用真正的多租户架构设计，实现租户间数据库隔离，并内置国际化支持，以确保全球可扩展性、安全性及长期运营稳定性。","\u002Fuploads\u002F2026\u002F01\u002Fenterprise-grade-multi-tenant-architecture-for-an-international-platform-1769789121298-b6v7ak.webp","2026-01-30T12:04:00.000Z",{"id":883,"slug":884,"title":885,"excerpt":886,"featuredImage":887,"publishedAt":888},"445","qwen-3-6-in-production-release-runbook-ai-rollback-and-llmops-versioning","Qwen 3.6 生产环境部署：发布手册、AI 回滚与 LLMOps 版本管理","Qwen 3.6 不仅仅是一次模型升级。它同时是一个发布事件、一个回滚场景和一个版本管理问题。本文通过LLMOps规范、提示词与模型可追溯性、受控发布以及基于证据的回滚准备，阐述了在生产环境中应如何处理Qwen 3.6。","\u002Fuploads\u002F2026\u002F02\u002Fnew-qwen-3-5-plus-1771515512741-dcbi9p.webp","2026-05-04T02:49:00.000Z",{"id":890,"slug":891,"title":892,"excerpt":893,"featuredImage":894,"publishedAt":895},"383","canonical-architecture-url-design-resolver-logic-api-scalability-specification","规范化架构、URL 设计、解析器逻辑、API 与可扩展性规范","面向多租户门户的地理发现架构。定义了规范化 URL、解析器逻辑、缓存策略以及不依赖 CMS 耦合或数据库重构的地理读模型。该设计旨在确保 SEO 稳定性、高可扩展性，并支持未来的功能扩展，例如预订和地图。","\u002Fuploads\u002F2026\u002F01\u002Fcanonical-architecture-url-design-resolver-logic-api-scalability-specification-1769890763607-7rghbp.webp","2026-01-31T06:12:00.000Z",{"id":897,"slug":898,"title":899,"excerpt":900,"featuredImage":901,"publishedAt":902},"459","ollama-is-not-the-product-building-production-ready-open-llm-applications","Ollama 并非产品：构建可投入生产的开源大语言模型应用","使用Ollama运行本地模型很简单。但构建一个可用于生产环境的开源大语言模型（Open-LLM）应用则更具挑战性：它需要RAG（检索增强生成）、访问控制、供应商抽象、评估、日志记录、部署规范，以及围绕模型构建受控的应用层。","\u002Fuploads\u002F2026\u002F06\u002Follama-is-not-the-product-building-production-ready-open-llm-applications-1782679361640-h0usqf.webp","2026-06-28T16:39:00.000Z","fallback",[],[]]