网站建设怎么骗人,wordpress 新浪微博,seo如何分析网站,wordpress异地登录到现在#xff0c;我们已经将 Gin 集成到框架 hade 中#xff0c;同时又引入了服务容器和服务提供者#xff0c;明确框架的核心思想是面向服务编程#xff0c;一切皆服务#xff0c;所有服务都是基于协议。后续也会以服务的形式#xff0c;封装一个个的服务#xff0c;让…到现在我们已经将 Gin 集成到框架 hade 中同时又引入了服务容器和服务提供者明确框架的核心思想是面向服务编程一切皆服务所有服务都是基于协议。后续也会以服务的形式封装一个个的服务让我们的框架越来越丰富。
框架和业务区分
业务代码的目录结构是一种工程化的规范。所谓工程化简单来说就是希望不管是谁在一个工程项目中都按照一种做法来完成某个事情。而目录结构就是项目工程化的一个起点。
在一个公司或者一个部门中如果有架构团队基本上要做的第一个事情就是规范公司或者部门的代码目录结构。整体目录结构不仅仅代表着分层、归纳也包含着很多架构的思想。
而对于 hade 框架而言因为目标是将框架应用于实际生产工程化使用所以对业务的目录结构制定最小化的工程化规范并且提供默认的整体目录结构是很有必要的。
不过请注意这里是希望制定最小化的工程化规范就是说对于这个框架规范某些最小化的功能性目录是必要的如果没有这些功能性目录我们会认为目录设计是不合理的。
如何设计
在制定具体的目录结构之前我们要明确一点业务的目录结构也是一个服务是一个应用目录服务。在这个服务中我们制定框架要求的最小化的工程化规范即框架要求业务至少有哪些目录结构。
而在其他服务中一旦需要用到某个目录我们能从目录结构服务中查找出对应的结构。比如后续要创建配置服务它需要去某个配置目录文件中读取配置而去哪个配置目录呢只需要去服务容器中获取这个应用目录服务就能知道了。 (就是说目录的设置也是一个服务也要注入到框架中)
所以按照面向接口编程的思想先为“应用目录服务”定义一下服务接口协议也就是应用要提供哪些接口。
在今后的章节中我们会定义许多框架级别的基础服务这些服务我们都存放在框架目录中。服务的接口协议统一放在框架目录下的 framework/contract 中而对应的服务提供者和服务实现统一存放在框架目录下的 framework/provider 中。
这里将所有框架级别的接口协议放在 framework/contract 中的设计有两个好处 一是框架协议的关键字我希望使用 contract.xxx 这个语义来区分比如 App 服务的接口为 contract.App、日志服务的接口为 contract.Log它们的 namespace 都是 contract这样在使用的时候记忆成本会比较低。另外将框架提供的所有接口协议都放在一个文件夹中在阅读框架提供哪些服务的时候也更清晰明了。
以“应用目录服务”为例我们在 framework/contract 目录中创建 app.go 存放服务协议。在 framework/contract/app.go 中我们定义应用目录服务接口名称为 App代表整个应用。它对应的服务字符串凭证为“hade:app”。 (还有非应用的目录服务吗)
这个接口的抽象我们按照创建应用需要哪些目录的顺序来思考。
首先创建一个应用需要明确应用所在的根目录这个就是根目录 BaseFolder其次我们需要一个目录保存配置文件所以要有一个配置文件的目录 ConfigFolder应用要输出日志日志输出的存放路径也是需要设置的所以我们再创建一个 LogFolder 来设置日志存放。
再考虑下业务的服务提供者和对应接口需要有一个地方存放我们将其命名为 ProviderFolder。同时我们业务也有可能创建自己的中间件所以需要有个 MiddlewareFolder 来存放中间件。
在后续的章节中我们预计让框架支持命令行命令并且使用命令行来控制进程的运行时状态所以需要有个 CommandFolder 来存放各种命令行命令、一个 RuntimeFolder 来存放运行时的进程 ID 等信息。
最后当然了还需要有一个文件来存放单元测试信息比如单元测试的初始化和终止的一些默认操作等所以我们有一个 TestFolder 目录。
按照目前能想到的需求可以将目录先分为这些文件夹后续在开发模块的过程中遇到需要增加的目录我们还可以继续迭代修改 App 接口。
按照以上的分析我们在框架的 framework/contract/app.go 中定义了一个 App 的服务接口 package contract
// AppKey 定义字符串凭证
const AppKey hade:app
// App 定义接口
type App interface {// Version 定义当前版本Version() string//BaseFolder 定义项目基础地址BaseFolder() string// ConfigFolder 定义了配置文件的路径ConfigFolder() string// LogFolder 定义了日志所在路径LogFolder() string// ProviderFolder 定义业务自己的服务提供者地址ProviderFolder() string// MiddlewareFolder 定义业务自己定义的中间件MiddlewareFolder() string// CommandFolder 定义业务定义的命令CommandFolder() string// RuntimeFolder 定义业务的运行中间态信息RuntimeFolder() string// TestFolder 存放测试所需要的信息TestFolder() string
}定义默认目录结构
定义好了应用目录服务接口我们再来思考它的实现也就是设计使用这个 hade 框架的应用的默认目录。
PHP 目前最火的应用框架 Laravel它的目录设计非常值得我们学习和参考很合理地将各个功能模块放在各自的文件并且文件定义清晰、无歧义。所以有了下面这个默认目录结构我们来解释下对应的每个目录。 在根目录下有五个文件app、framework、config、storage、test我们一个个描述功能看看下面都应该怎么划分。
app目录
一个业务就是一个 App和业务代码相关的比如所有的请求、控制台命令、控制器、服务提供者等都放在这个目录中而业务逻辑代码之外的比如配置文件、缓存、日志等都放在外面。这样能把**“业务逻辑”和“非业务逻辑”**区分得更清晰。
我们继续看业务逻辑目录 app 下有哪些子目录。 第一层有三个目录console、http、provider。因为业务除了提供 Web 服务也提供控制台进程所以在 app 目录下有两个子目录一个是 console业务中所有的控制台进程逻辑都放在这里而另一个就是 http 目录所有 Web 服务的逻辑都存放在里面。
同时这两者有很多逻辑是通用的比如有可能用到同一个服务提供者所以我们将两者通用的服务提供者的代码 provider 目录也放在 app 目录下。
再看第二层的细分目录。
首先是 app 目录下的 console存放的是所有命令行工具的逻辑代码。
控制台命令设计为多级命令比如在命令 ./hade task info 中hade 是命令行工具task 为一级命令info 为二级命令。所以在 console 目录下我们要创建一个 command 目录并且 command 目录下按照一级、二级……递归保存。关于命令行工具的更多详细设计和实现我们在下节课实现。
提供 Web 服务的 http 目录还有更细的层级。
HTTP 服务一般会按照模块划分比如一个图书馆业务我们会分为注册模块、图书模块、用户模块等所以我们在 http 目录下定义了一个 module 目录这个 module 目录下每个子目录代表一个模块服务。而 Web 服务特有的通用中间件我们使用 http 目录下的 middleware 目录来保存。
app 下的 provider 目录提供的是定义一个服务需要的文件。
在 provider 目录中每个子目录就代表一个业务服务。而按照上一节课描述的每个服务都需要有三个文件代表服务协议的 contract.go 文件、代表服务提供者的 provider.go 文件以及代表具体服务实现的 service.go 文件。
这里要强调是这个 provider 目录存放业务提供的服务而框架提供的服务我们会放在 framework 目录下。
framework目录
framework 目录就是我们这个框架所有的代码。在这个目录里除了之前引入了 Gin 框架有的 gin 目录还有一些子目录command、contract、middleware、provider、util。 这几个目录的功能也比较好理解。command 提供的是框架自带的命令行工具middleware 存放框架为 Web 服务提供的中间件contract 存放框架默认提供的服务协议而对应服务协议的具体实现以及服务提供者我们存放在 provider 目录下util 目录则存放在框架研发过程中通用的一些函数。
不难发现provider 和 command 的服务在业务app 目录和框架framework 目录层面都有相同的目录区别就是一个是业务提供的一个是框架提供的。
我们这个项目为了演示框架开发的全过程把框架和业务合并在一起但是因为最终版框架在开源发布的时候framework 目录是会剥离出去作为一个单独的 git 项目的。所以你在开发的时候要时刻明确哪些是框架提供的命令行工具和服务哪些是业务提供的命令行和服务。框架的内容需要放在 framework 目录下业务的就要放在 framework 外。
config、storage、test 目录
在应用根目录下还剩 config 、storage、test 目录。config 这个目录存放的是配置文件至于不同环境的配置文件如何存放和组织我们后面会统一探讨整体的配置文件存放机制。test 目录存放的是测试相关的信息比如测试用例或者测试数据等信息。
应用根目录下的 storage 存放应用运行过程中产生的内容。首先是日志日志是应用运行过程中必然产生的信息在 storage 下的 log 子目录里保存其次是运行的进程 ID 等信息这些都会存放在 storage 下的 runtime 目录中。
好目录结构讲完了我们整理下从应用根目录开始分为 5 个子目录 app、framework、config、storage、test其中
app 按应用的使用方式和通用性分为 console 和 http以及通用的 provider 目录。framework 根据框架需要提供的功能分为 command、contract、gin、middleware、provider 和 util 6 个子目录。config 和 test 分别保存配置和测试相关的信息storage 目录保存应用运行产生的信息分为 log 和 runtime 两个目录。
默认目录的实现
最开始我们说了目录结构也是一个服务其他服务想要使用目录结构的时候可以通过服务容器来获取目录结构服务实例。而现在我们有了想要创建的默认目录结构那么下面就要实现这个目录结构服务实例了。
我们定义一个 HadeApp 来实现这个目录结构服务接口这个 HadeApp 结构的元素除了服务实例之外只需要一个项目的基础路径 basePath。因为我们设计的默认目录结构只要有了这个 basePath就可以按照设计找出其余的所有目录了。
在 framework/provider/app/service.go 中定义 HadeApp 结构
// HadeApp 代表 hade 框架的 App 实现
type HadeApp struct {container framework.Container // 服务容器baseFolder string // 基础路径
}BaseFolder 是获取项目的基础路径所以我们可以提供一种方式在注册服务提供者的时候实现 BaseFolder 的设置。来看代码设置 hade 框架默认的 App 服务提供者为 HadeAppProvider它带有一个可以设置的属性 BaseFolder这个属性作为参数传入给服务实例初始化函数。
我们在 framework/provider/app/provider.go 中定义 HadeAppProvider 结构和方法 // HadeAppProvider 提供 App 的具体实现方法
type HadeAppProvider struct {BaseFolder string
}...// Params 获取初始化参数
func (h *HadeAppProvider) Params(container framework.Container) []interface{} {return []interface{}{container, h.BaseFolder}
}
...// NewHadeApp 初始化 HadeApp
func NewHadeApp(params ...interface{}) (interface{}, error) {if len(params) ! 2 {return nil, errors.New(param error)}// 有两个参数一个是容器一个是 baseFoldercontainer : params[0].(framework.Container)baseFolder : params[1].(string)return HadeApp{baseFolder: baseFolder, container: container}, nil
}这样在业务目录的 main.go 中注册 App 服务的时候就可以创建指定我们的 BaseFolder func main() {// 创建 engine 结构core : gin.New()// 指定 BaseFoldercore.Bind(app.HadeAppProvider{BaseFolder: /tmp})...
}但是刚才的实现在每次注册服务的时候都需要设置一遍为了提高易用性我们希望这个 BaseFolder 能自动设置。怎么办
在业务场景中这个 BaseFolder 代表业务的开发路径即业务代码所在的目录另一个运行场景中框架开发的业务需要去现网也就是生产环境中运行只需要二进制文件、配置文件、日志文件即可因为这时候的 BaseFolder 其实是会根据项目部署地址变化的。
【小结】
程序目录app、config、framework、storage、test把目录结构作为一个服务也注册到框架容器中