《架构整洁之道》:Part2. STARTING WITH THE BRICKS: PROGRAMMING PARADIGMS 从基础构件开始:编程范式

Software architecture begins with the code—and so we will begin our discussion of architecture by looking at what we’ve learned about code since code was first written. 任何软件架构的实现都离不开具体的代码,所以我们对软件架构的讨论应该从第一行被写下的代码开始。 In 1938, Alan Turing laid the foundations of what was to become computer programming. He was not the first to conceive of a programmable machine, but he was the first to understand that programs were simply data. By 1945, Turing was writing real programs on real computers in code that we would recognize (if we squinted enough). Those programs used loops, branches, assignment, subroutines, stacks, and other familiar structures. Turing’s language was binary. ...

March 4, 2024

《架构整洁之道》:Chap2. A TALE OF TWO VALUES 两个价值维度

Every software system provides two different values to the stakeholders: behavior and structure. Software developers are responsible for ensuring that both those values remain high. Unfortunately, they often focus on one to the exclusion of the other. Even more unfortunately, they often focus on the lesser of the two values, leaving the software system eventually valueless. 对于每个软件系统,我们都对以通过行为和架构两个维度来休现它的实际价值。软件研发人员应该确保自己的系统在这两个维度上的实际价值都能长时间维持在很高的状态。不幸的是,他们往往只关注一个维度,而忽视了另外一个维度。更不幸的是,他们常常关注的还是错误的维度,这导致了系统的价值最终趋降为零。 BEHAVIOR 行为价值 The first value of software is its behavior. Programmers are hired to make machines behave in a way that makes or saves money for the stakeholders. We do this by helping the stakeholders develop a functional specification, or requirements document. Then we write the code that causes the stakeholder’s machines to satisfy those requirements. ...

March 3, 2024

《架构整洁之道》:Chap1. WHAT IS DESIGN AND ARCHITECTURE? 设计与架构到底是什么

There has been a lot of confusion about design and architecture over the years. What is design? What is architecture? What are the differences between the two? 一直以来,设计(Design)与架构(Architecture)这两个概念让大多数人十分迷惑——什么是设计?什么是架构?二者究竟有什么区别? One of the goals of this book is to cut through all that confusion and to define, once and for all, what design and architecture are. For starters, I’ll assert that there is no difference between them. None at all. 本书的一个重要的目标就是要清晰、明确地对二者进行定义。首先我要明确地说,二者没有任何区别。一丁点区别都没有! The word “architecture” is often used in the context of something at a high level that is divorced from the lower-level details, whereas “design” more often seems to imply structures and decisions at a lower level. But this usage is nonsensical when you look at what a real architect does. ...

March 2, 2024

《架构整洁之道》:AFTERWORD 后序

My professional career as a software developer began in the 1990s, at a time when the dinosaurs of Big Architecture ruled the world. To get ahead, you had to learn about objects and components, about design patterns, and about the Unified Modeling Language (and its precursors). 我的软件工程师生涯开始于 20 世纪 90 年代,那是一个恐龙级大型架构统治世界的时代。要想在那样的时代获得一席之地,我们必须学会对象及其组件、设计模式、统一建模语言(包括其前身)的相关知识。 Projects—and boy, should we rue the day when we decided to call them that?—started with long design phases, where detailed blueprints for our systems were laid out by “senior” programmers for more “junior” programmers to follow. Which, of course, they didn’t. Ever. ...

March 1, 2024

OrchardCore实现模块化核心原理分析

若改造项目,也因历史遗留问题,数据库表设计也可能存在不合理,此时从头开始再搭建如此庞大的架子,感觉会有点虚空,同时也要考虑团队内部情况,不是那么容易上手,反而可能会违背初心,花更多时间和精力在各种模型理解上 我们完全可以为后续做铺垫,先搭建出底层基本设施,再基于此做灵活扩展即可,每个公司项目具体情况都不一样,比如仓储模式可能需要结合项目进行对应 改造,仓储只是提供了一种基本思想,若真将网上普遍流传的模式照搬可能并不是那么好用,可能会认为仓储莫不是一种反模式 .NET Core模块化插件 .NET Core内置提供了AssemblyLoadContext加载dll插件方式实现模块化,然后将其进行注册 var mvcBuilder = services.AddMvc(); foreach (var module in modules) { // Register controller from modules mvcBuilder.AddApplicationPart(module.Assembly); } 这种方式虽可行,在我看来只能作为一种临时解决方案并不利于长期,因为需额外创建一个新的项目,然后加载所生成dll,由于没有底层设施做支撑,所以极易引起版本不一致问题,而且手动被迫性质太强,实现模块化方案最终的目标则只需关注业务逻辑实现,我们来看看OrchardCore如何实现模块化。 OrchardCore模块化思想 这里我们并不讨论和ABP vNext二者谁更强大,没有任何意义,比如需结合现有项目情况、项目大小、是否为多租户、实施难度等等多方面考虑才能得出基本结论,而不是一味追求当前主流 比如我们只是想实现模块化方案,建议选择OrchardCore来实施,因为很简单,我们可将其剥离为我所用,而后结合项目情况是否考虑利用ABP vNext来进行分层处理。借鉴核心思想、才能保证一切可在控制范围内 首先我们先从整体上对OrchardCore做个认识,细枝末节暂不考虑:基于ASP.NET Core多租户模块化应用框架。 版本管理:无论是底层设施、基本框架、模块都通过包管理,同时框架和包版本基本(包管理走框架包版本)可以统一管理(对于版本升级很重要) 核心思想:模块实现模块特性,通过MSBuild构建主程序所添加实现模块特性的模块包,底层设施扫描模块特性将其注册到容器中,当然模块和模块特性都可进行基本信息描述 OrchardCore模块化原理 整个项目架构如下图所示 OrchardCore:底层设施以及可能需要添加的组件(比如本地化、日志、文件存储、缓存、Lucene等) OrchardCore.Frameworks:MVC框架 OrchardCore.Modules:模块化包(比如邮件服务、后台作业服务、第三方集成等等) OrchardCore.Modules.Cms:Cms模块包 OrchardCore.Themes:主题管理 OrchardCore.Cms.Web:主程序 我以内置所提供示例程序给大家讲解整个详细流程,而后有需要更细致了解的童鞋就可以很快上手了,如下示例主程序加载示例模块,主程序直接采用引用该示例模块(实际则是通过nuget下载该模块) 正常情况下我们通过nuget直接下载的是程序包,而OrchardCore对于入口则是利用MSBuild加载targets文件(其他组件则直接下载对应包),而targets引用对应包,通过这种中转方式根据我的理解主要解决了两个问题,其一则是可以屏蔽底层设施包(一次性下载),最重要的是通过targets文件可自动添加主程序程序集所加载模块包特性 是不是感觉有点懵,那到底是如何加载模块包特性的呢?来,请看如下图,我们以实际操作从头再来做一个完整梳理(注意:为排版美观,如下都将省略OrchardCore前缀) 【1】创建Mvc.Web程序,在nuget上下载Application.Mvc.Targets包 【2】创建Mvc.HelloWorld模块,在nuget上下载引用Module.Targets包 【3】Mvc.Web主程序引用我们所使用的Mvc.HelloWorld模块 【4】Application.Mvc.Targets包引用Application.Targets(引入底层设施)和MVC.Core(引入MVC框架) 【5】示例模块引入模块包,该包中存在模块特性(Module类) 【6】Application.Targets包下存在Application.Targets.targets文件,由于主程序引用了该包,添加所引用实现模块特性的包程序集信息到主程序集 到这里我们已经研究完主程序如何识别模块包,接下来则是如何加载模块包以及对应注册服务信息 OrcharCore核心在于OrchardCore和OrchardCore.Abstractions这两个底层设施包 归根到底,其底层设施源码一部分可能从官方源码拷贝过来(自我猜测),为实现多租户模式,势必要构建租户的容器和路由中间件,这中间就涉及在容器中需要维护每一个租户上下文(ShellContext),并且也要跟踪每个租户的状态。 ModularTenantContainerMiddleware作为创建租户容器中间件 ModularTenantRouterMiddleware作为租户路由中间件

January 10, 2024

OrchardCore入门指南:创建Orchard Core CMS网站

在本指南中,您将使用项目模板将Orchard Core设置为内容管理系统。 您需要什么 .NET SDK的当前版本。您可以从以下网址下载它:https://dotnet.microsoft.com/download. 文本编辑器和终端,您可以在其中键入 dotnet 命令。 创建项目 有多种创建Orchard Core网站和模块的方法。您可以在这里了解更多信息。 在本指南中,我们将使用“代码生成模板”。您可以使用此命令安装最新稳定版本的模板: dotnet new install OrchardCore.ProjectTemplates::1.5.0-* 注意 要使用模板的开发分支,请添加 –nuget-source https://nuget.cloudsmith.io/orchardcore/preview/v3/index.json 创建一个空文件夹来存放你的网站。打开终端,进入该文件夹并运行以下命令: dotnet new occms -n MySite 这样就在一个名为 MySite 的文件夹中创建了一个新的Orchard Core CMS项目。 设置站点 应用程序已经由模板创建,但尚未设置。 通过执行以下命令启动应用程序: dotnet run –project .\MySite\MySite.csproj Note 如果你正在使用模板的开发分支,请在运行应用程序之前运行dotnet restore .\MySite\MySite.csproj –source https://nuget.cloudsmith.io/orchardcore/preview/v3/index.json。 现在您的应用程序应该正在运行,并监听以下端口: 现在监听 on: https://localhost:5001 和 on: http://localhost:5000。应用已经启动,按 Ctrl+C 可以关闭应用。 在浏览器中打开 https://localhost:5001 可以显示设置屏幕。 为了演示的目的,我们将使用 Blog 配方创建网站。Blog 配方是 Orchard Core 的 入门配方之一,其中包含一系列功能和配置 Orchard Core 网站的步骤。 完成设置表单,选择 Blog 配方和 SQLite 数据库。 提交表单后,几秒钟后您将可以看到一个博客站点。 为了配置并开始编写内容,您可以转到 https://localhost:5001/admin。 概要 ...

June 30, 2023

OrchardCore入门指南:创建一个模块化的 ASP.NET Core 应用程序

你将要构建什么 您将创建一个模块化的 ASP.NET Core MVC 网络应用程序,类似于包含在 Orchard Core 中的 “Hello World” 应用程序示例。它包括一个网络应用程序和一个模块。网络应用程序提供了布局,而模块注册了路由并响应首页请求。您可以参考 Orchard Core 中的以下项目以获取更多信息。 src/OrchardCore.Mvc.Web src/OrchardCore.Modules/OrchardCore.Mvc.HelloWorld 所需材料 当前版本的 .NET SDK。您可以从此处下载: https://dotnet.microsoft.com/download. 一个文本编辑器和一个终端,您可以在其中运行 dotnet CLI 命令。 创建 Orchard Core 网站和模块 有不同的方法可以为 Orchard Core 创建网站和模块。您可以在 此处 了解更多信息。 在本指南中,我们将使用我们的代码生成模板。您可以使用以下命令安装模板的最新稳定版本: dotnet new install OrchardCore.ProjectTemplates::1.5.0-* Note 如果想使用模板的开发分支,请添加 –nuget-source https://nuget.cloudsmith.io/orchardcore/preview/v3/index.json 创建一个名为OrchardCore.Mvc的空文件夹,它将包含我们的项目。打开一个终端,进入该文件夹并运行以下命令来创建Web应用程序: dotnet new ocmvc -n OrchardCore.Mvc.Web 接下来,创建“ Hello World”模块。 dotnet new ocmodulemvc -n OrchardCore.Mvc.HelloWorld 将Web应用程序中指向该模块的项目引用添加到其中。 dotnet add OrchardCore.Mvc.Web reference OrchardCore.Mvc.HelloWorld 可选地,您可以添加一个解决方案文件,该文件引用了Web应用程序和模块,以便在Visual Studio中打开解决方案。 dotnet new sln -n OrchardCore.Mvc dotnet sln add OrchardCore.Mvc.Web\OrchardCore.Mvc.Web.csproj dotnet sln add OrchardCore.Mvc.HelloWorld\OrchardCore.Mvc.HelloWorld.csproj 测试生成的应用程序 从包含两个项目的OrchardCore.Mvc根文件夹中运行以下命令启动Web应用程序: ...

June 30, 2023

OrchardCore入门指南

指南 无论你在构建什么,这些指南旨在让你尽快使用最新的Orchard Core项目版本和Orchard团队推荐的技术,进入工作状态。 入门指南 这些指南旨在在15-30分钟内完成,提供快速的、实践操作的指令,用于使用Orchard Core构建任何开发任务的“Hello World”。在大多数情况下,唯一的先决条件是一个.NET SDK和一个文本编辑器。 创建一个模块化的ASP.NET Core应用程序 在启动时运行代码 自定义编码设置 Orchard Core CMS指南 这些指南专门针对Orchard Core CMS: 创建Orchard Core CMS网站 向管理导航添加菜单项 安装本地化文件 如何使用资产转码器/绑定器/缩小器管道- 集成 Facebook 插件 实现全文检索 将 AzureAD 集成为外部提供程序 教程 这些教程旨在在2-3小时内完成,提供更深入、上下文探讨企业应用程序开发主题,并让您准备实现现实世界的解决方案。 使用 Razor Pages 构建解耦的网站 构建一个来自 Web 模板的网站(待定) 实施自助式 SaaS 解决方案(待定)

June 20, 2023

基于ASP.NET Core的整洁架构

干净体系结构将业务逻辑和应用程序模型置于应用程序的中心。 而不是让业务逻辑依赖于数据访问或其他基础设施,此依赖关系被倒置:基础结构和实现细节依赖于应用程序内核。 此功能是通过在应用程序核心中定义抽象或接口来实现的,然后通过基础设施层中定义的类型实现。 将此体系结构可视化的常用方法是使用一系列同心圆,类似于洋葱。 遵循依赖倒置原则以及域驱动设计原则 (DDD) 的应用程序倾向于达到类似的体系结构。 多年来,这种体系结构有多种名称。 最初的名称之一是六边形体系结构,然后是端口 - 适配器。 最近,它被称为洋葱体系结构或干净体系结构。 此电子书中将后一种名称“干净体系结构”用作此体系结构的名称。 在此关系图中,依赖关系流向最里面的圆。 “应用程序内核”因其位于此关系图的核心位置而得名。 从关系图上可见,该应用程序内核在其他应用程序层上没有任何依赖项。 应用程序的实体和接口位于正中心。 在外圈但仍在应用程序核心中的是域服务,它通常实现内圈中定义的接口。 在应用程序内核外面,UI 和基础结构层均依赖于应用程序内核,但不一定彼此依赖。

June 7, 2023

Entity Framework Core 创建DbContext的两种方法

最近创建基于firstcode的开发模式,整理了一下如何使用Entity Framework Core 创建DbContext。 1、第一种重写DbContext的OnConfiguring方法,每次生成一个DbContext的方法的时候就会重新来这个方法这里读一下配置。 这种情况下,首先尝试通过调用 Program.CreateHostBuilder()、调用 Build(),然后访问 Services 属性来获取服务提供程序。 public class Program { public static void Main(string[] args) => CreateHostBuilder(args).Build().Run(); // EF Core uses this method at design time to access the DbContext public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults( webBuilder => webBuilder.UseStartup<Startup>()); } public class Startup { public void ConfigureServices(IServiceCollection services) => services.AddDbContext<ApplicationDbContext>(); public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { } } public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } } 2、使用不带参数的构造函数 ...

May 8, 2023