lucidarch / lucid
可扩展软件架构。
Requires
- ext-dom: *
- mockery/mockery: *
- symfony/console: *
- symfony/filesystem: *
- symfony/finder: *
- symfony/process: *
README
- 网站: https://lucidarch.dev
- 文档: https://docs.lucidarch.dev
- 社交: 我们分享更新和来自网络的有趣内容
- Twitter: @lucid_arch & #lucidarch
- Reddit: /r/lucidarch
目录
关于Lucid
Lucid是构建可扩展Laravel项目的软件架构。它核心集成了命令总线
和领域驱动设计
,在其基础上构建目录和类的堆栈以组织业务逻辑。它还从SOA(面向服务架构)
中吸取了在服务内封装功能的概念,并在此基础上增加了服务不仅仅是类的概念。
使用Lucid来
- 轻松编写干净的代码
- 保护您的代码免受时间退化
- 以通常所需时间的几分之一审查代码
- 在您的应用程序中结合经过验证的实践和模式
- 在代码之间导航并在代码库之间移动而不会感到陌生
概念
这种架构是最佳实践、设计模式和验证方法的融合。
- 命令总线:分发工作单元。在Lucid术语中,这些单元将是
功能
、作业
或操作
。 - 领域驱动设计:通过将工作单元按其所属的主题进行分类来组织它们。
- 面向服务架构:封装和管理具有相同目的的功能及其所需资源(路由、控制器、视图、数据库迁移等)。
如果您更喜欢视频,请观看2016年Laracon EU的公告
目录
定位
在一个典型的MVC应用程序中,Lucid将是应用程序入口点和执行工作的工作单元之间的纽带,确保代码不会走向歧途
堆栈
简而言之...
框架
提供“内核”以执行繁琐工作,如请求/响应生命周期、依赖注入和其他核心功能。
基础
扩展框架以提供适用于应用程序的高级抽象,这些抽象可以在整个堆栈中共享,而不是特定于情况。
可以放入基础的一些示例
DateTime
:用于常见日期和时间功能的支持类JsonSerializableInterface
:用于标识应从JSON格式进行序列化和反序列化的对象
域
提供分离以分类属于同一主题的工作和相应的类别。一个领域独立于其他领域运行,并通过Lucid作业仅向特性和操作公开其功能。
以下是一个示例,说明领域可能的样子。
app/Domains/GitHub
├── GitHubClient
├── Jobs
│ ├── FetchGitHubRepoInfoJob
│ └── LoginWithGitHubJob
├── Exceptions
│ ├── InvalidTokenException
│ └── RepositoryNotFoundException
└── Tests
└── GitHubClientTest
└── Jobs
├── FetchGitHubReposJobTest
└── LoginWithGitHubJobTest
文档包含了更多关于处理领域的详细信息。
服务
目录具有丰富的功能,用于将[单体]({{<ref "/micro-vs-monolith/#monolith">}})分离为多用途应用程序中的关注区域。
以一个应用程序为例,我们输入食物食谱并希望我们的成员在论坛中进行讨论,我们会有两个服务:1) 厨房,2) 论坛,其中厨房将管理所有与食谱相关的,而论坛很明显。
app/Services
├── Forum
└── Kitchen
以下是单个服务的结构,突出显示了Lucid特定的目录
app/Services/Forum ├── Console │ └── Commands ├── Features ├── Operations ├── Http │ ├── Controllers │ └── Middleware ├── Providers │ ├── KitchenServiceProvider │ ├── BroadcastServiceProvider │ └── RouteServiceProvider ├── Tests │ └── Features │ └── Operations ├── database │ ├── factories │ ├── migrations │ └── seeds ├── resources │ ├── lang │ └── views └── routes ├── api ├── channels ├── console └── web
文档提供了更多关于服务和其内容的示例。
功能
在类中表示可读性应用程序功能。它包含实现功能的逻辑,但详细程度最小,通过从领域和应用程序或服务级别运行作业。
控制器方法(在MVC中)中仅有一行是服务于功能类,从而实现了最薄的控制器形式。
class AddRecipeFeature extends Feature { public function handle(AddRecipe $request) { $price = $this->run(CalculateRecipePriceOperation::class, [ 'ingredients' => $request->input('ingredients'), ]); $this->run(SaveRecipeJob::class, [ 'price' => $price, 'user' => Auth::user(), 'title' => $request->input('title'), 'ingredients' => $request->input('ingredients'), 'instructions' => $request->input('instructions'), ]); return $this->run(RedirectBackJob::class); } }
关于功能文档扩展了如何将它们作为类从任何地方提供。
操作
它们的目的是通过将作业拼接在一起来提高代码重用度,从而提供来自各个领域的组合功能。
class NotifySubscribersOperation extends Operation { private int $authorId; public function __construct(int $authorId) { $this->authorId = $authorId; } /** * Sends notifications to subscribers. * * @return int Number of notification jobs enqueued. */ public function handle(): int { $author = $this->run(GetAuthorByIDJob::class, [ 'id' => $this->authorId, ]); do { $result = $this->run(PaginateSubscribersJob::class, [ 'authorId' => $this->authorId, ]); if ($result->subscribers->isNotEmpty()) { // it's a queueable job so it will be enqueued, no waiting time $this->run(SendNotificationJob::class, [ 'from' => $author, 'to' => $result->subscribers, 'notification' => 'article.published', ]); } } while ($result->hasMorePages()); return $result->total; } }
关于操作的文档介绍了这个简单而强大的概念。
数据
对于一组可扩展的相互关联的数据元素,我们在app/Data
中为它们创建了空间,因为随着时间的推移,在应用程序中编写可能需要比模型更多的数据,例如存储库、值对象、集合等。
app/Data
├── Models
├── Values
├── Collections
└── Repositories
好处
过度工程可能看似有价值,但确实有宝贵的优势。
组织
- 在审查代码时,系统变化的可预测影响
- 由于我们将应用程序划分为独立的关注区域(分而治之),因此调试时间减少
- 在单体中,我们的每个服务都可以有自己的版本控制系统(例如,API服务在v1而聊天在v2.3,但它们仍然位于同一代码库中)
重用和替换
通过将我们的应用程序分解成小的代码构建块——即单元——我们立即打开了在应用程序中实现高度代码共享的大门,与数据和领域一起,以及以最少的摩擦和技术债务进行替换。
边界
通过设置边界,您已经迈出了保护应用程序代码免于不堪重负地增长并向新开发者快速入职迈出的一步。最重要的是,您将技术债务降至最低,这样您就不必用错误和失眠来支付;代码不是由好意或愿望运行的。
多租户
当我们的应用程序扩展时,我们通常会在不同的位置运行许多其实例,在某个时候,我们希望在某些区域激活我们的代码库的某些部分,关闭其他部分。
以下是一个运行同一应用程序的Api、Back Office和Web App实例的谦卑示例,在Lucid术语中,这些是服务,它们通过数据和领域共享功能。
贡献
错误和问题报告
为了鼓励积极合作,Lucid强烈鼓励通过pull requests进行贡献。“错误报告”可以在问题中搜索或创建,或以包含失败测试或重现错误步骤的pull request的形式发送。
如果您提交了一个错误报告,您的报告应该包含一个标题和对问题的清晰描述。您还应包括尽可能多的相关信息和一个演示问题的代码示例。错误报告的目的是让您和其他人能够轻松地复现错误并开发解决方案。
⏱️ PRs 和问题通常每周检查大约三次,因此您的报告很快就会被处理。
Lucid Architecture 的源代码位于 GitHub 上的 lucidarch/lucid。
支持问题
Lucid Architecture 的 GitHub 问题跟踪器不旨在提供帮助或支持。相反,请使用以下渠道之一
- 讨论区 是大多数对话发生的地方
- 如果您想要聊天,请在我们的官方 Slack 工作空间 的
#support
频道联系我们 - 如果您喜欢在 StackOverflow 上发布问题,可以使用 #lucidarch 为它们添加标签
核心开发讨论
您可以在 Lucid 讨论区 中提出新的功能或改进现有 Lucid Architecture 行为的建议。如果您提出一个新功能,请准备好实施至少一些完成该功能所需的代码,或者在此期间参与活跃的构思。
关于错误、新功能和现有功能的实现的非正式讨论发生在 Lucid Slack 工作空间 的 #internals
频道中。Abed Halawi,Lucid 的维护者,通常在工作日的上午8点至下午5点(东欧夏令时)在该频道中,其他时间偶尔出现。
哪个分支?如何贡献
主分支包含最新的实时版本,并且是发布版本。
- 分叉此仓库
- 将分叉的仓库克隆到您将编辑代码的位置
- 为您的编辑创建一个分支(例如
feature/queueable-units
,fix/issue-31
) - 使用有意义的简短消息提交您的更改及其测试(如果适用)
- 推送您的分支
git push origin feature/queueable-units
- 向主分支打开一个 PR,这将运行您的编辑的测试
⏱️ PRs 和问题通常每周检查大约三次。
开发设置
以下是设置 Lucid 开发的步骤
假设我们在
~/dev
目录...
- 克隆分叉的仓库
[你的用户名]/lucid
,这将创建一个lucid
文件夹在~/dev/lucid
- 创建一个 Laravel 项目以在其中测试您的实现
composer create-project laravel/laravel myproject
- 将创建的 Laravel 项目连接到本地 Lucid 安装;在 Laravel 项目的
composer.json
"require": { "...": "", "lucidarch/lucid": "@dev" }, "repositories": [ { "type": "path", "url": "~/dev/lucid", "options": { "symlink": true } } ], "minimum-stability": "dev",
确保将
url
改为您的目录的绝对路径
- 运行
composer update
以创建符号链接
现在,您在 lucid 目录中的所有更改将自动在项目中生效。
安全漏洞
如果您在 Lucid 中发现安全漏洞,请向 Abed Halawi 发送电子邮件至 halawi.abed@gmail.com。所有安全漏洞都将得到及时解决。
编码风格
Lucid Architecture 遵循 PSR-2 编码标准和 PSR-4 自动加载标准。
PHPDoc
下面是一个有效的 Lucid Architecture 文档块的示例。请注意,@param
属性后面跟着两个空格,参数类型,再跟两个空格,最后是变量名
/** * Register a binding with the container. * * @param string|array $abstract * @param \Closure|string|null $concrete * @param bool $shared * @return void * * @throws \Exception */ public function bind($abstract, $concrete = null, $shared = false) { // }
行为准则
Lucid Architecture 的行为准则源自 Laravel 的行为准则。任何违反行为准则的行为都可以报告给 Abed Halawi(halawi.abed@gmail.com)
- 参与者应对不同观点保持宽容。
- 参与者必须确保他们的言语和行为不包含人身攻击和诋毁性的个人言论。
- 在解释他人的言语和行为时,参与者应始终假设对方有善意。
- 任何可以合理认为是骚扰的行为都将不被容忍。