语言和框架
Go语言
- 64 次浏览
【Go语言】Go 1.18 中的新功能
Go 1.18 中的新功能
泛型、测试模糊、AMD64 优化、工作区模式等
又到了一年中的那个时候:一个新的 Go 版本即将发布。 Go 团队刚刚发布了 Go 1.18 候选版本 1 (go1.18rc1),预计在 2022 年 2 月之前发布 Go 1.18。
Go 1.18 是长期以来最受期待的 Go 版本之一,这是有充分理由的。 Go 1.18 实现了对泛型类型和函数的初步支持,这是 Go 社区最想要的——也许也是最有争议的——特性。
除了泛型之外,Go 1.18 还包含许多其他强大的功能,例如支持测试 fuzzing、微架构支持和 AMD64 CPU 的优化、对 go 工具的更改,包括对“工作区”模式的支持、对核心库的一些更新,以及许多错误修复和标准库的小更新。
让我们来看看一些主要的更新。
支持泛型
泛型是此版本中最受期待的功能。根据泛型提案,Go 1.18 支持泛型类型和函数的初始实现。有了这个新增功能,该语言支持声明参数化类型和函数,这些类型和函数可以在以后使用不同的参数类型进行实例化。
泛型的使用允许您将具有相似实现但对不同输入类型进行操作的函数或类型集合并到更易于测试和维护的单个实体中,从而提高了通用代码的可重用性。
例如,某些库的代码类似于以下内容是很常见的:
func SumInt(a, b int) int { return a + b }func SumFloat32(a, b float32) float32 { return a + b }func SumFloat64(a, b float64) float64 { return a + b }//func sum...
通过使用泛型函数,您可以将所有这些函数合并为一个函数:
func Sum[T constraints.Ordered] (a, b T) T {
return a + b
}
因为这是语言的重大变化,而且它是一个全新的功能,所以存在一些限制,可能会影响性能,并且可能存在未知问题。在生产中部署通用代码时要注意这些不确定性。
有关泛型的更多信息,请查看发行说明和更新的语言规范。
测试模糊
Go 1.18 的另一个受欢迎的补充是对测试模糊测试的支持。 Fuzzing 是一种软件测试策略,它涉及向被测试的代码提供大量随机输入参数,包括许多边缘情况,目的是捕捉错误、暴露错误、触发异常和发现人类难以发现的漏洞探测。
Go test fuzzing 在测试包 testing.F 中增加了一种新的类型,并扩展了 Go 目前的特性和策略,例如 Table Driven Testing。在此版本之前,您可以使用外部库来执行测试模糊测试,但在标准工具中添加模糊测试将为更多开发人员提供更好的支持和更轻松的访问。
🌟 请注意——Go 团队提醒我们当前的 fuzzing 实现使用了大量系统资源,并且可能会在执行期间影响系统的性能。
有关更多详细信息,请参阅 Go Fuzzing 文档。
AMD64 CPU 的微架构优化
Go 1.18 为 AMD64 处理器引入了微架构优化。您现在可以使用新的 Go 环境变量 GOAMD64 来选择四个微架构目标 v1、v2、v3 或 v4 之一,以指示编译器针对特定 CPU 功能优化生成的二进制文件。它导致优化的二进制指令与不具有这些功能的处理器不兼容。
变量 GOAMD64=v1 的默认值导致二进制指令与所有 64 位 x86 处理器兼容。
有关此功能的更多详细信息,请参阅最低要求页面的架构部分。
进入工作区模式
最后,对于最后一个突出显示的更新,Go 1.18 为 go 命令引入了新的工作区模式支持,它允许您同时处理多个模块。以前,使用多个模块并不容易,并且可能会导致工具和 IDE 出现问题。这个新功能解决了这些问题,对其他工具(例如 gopls)进行了更改,以简化对多个模块的工作。
通过此更改,如果 go 命令或工具在当前目录或父目录中找到名为 go.work 的文件,它将以工作空间感知模式运行。然后它使用这个文件的内容来确定使用哪些模块来解决依赖关系,而不是使用 go.mod 文件。
在 Go 1.18 中,您可以使用 go work 命令创建和管理 go.work 文件。有关更多信息,请参阅其文档。
有关工作区功能的更详细说明以及许多其他 Go 1.18 改进的概要,请查看 Go Time 播客的第 217 集。
下一步是什么?
本文简要总结了 Go 1.18 的主要更新,但还有许多额外的错误修复和对工具、编译器和标准库的小改进。如需完整列表,请查看 Go 1.18 发行说明。
如果您等不及几周后的最终版本,并且想立即开始测试 Go 1.18 而不在您的机器上安装它,请访问 Go Playground 并从 Go 发布下拉列表中选择 Go Dev Branch。您也可以使用 Podman 或 Docker 将其作为容器运行。
如果您希望将其安装在您的机器上以便您可以使用一些代码进行测试,请按照下载页面上的说明将 Go 1.18 RC1 下载到您的本地机器。
原文:https://medium.com/pragmatic-programmers/whats-new-in-go-1-18-e7773a110…
- 63 次浏览
Javascript开发
- 24 次浏览
【JavaScript 开发】2022 年 JavaScript 面试题
JavaScript 面试题
注意:在进行 JS 面试问题之前,请详细阅读以下 JS 主题:
- 面向对象的 JavaScript (OOP)
- JavaScript 如何在屏幕后面运行
- 1. ES6 中有哪些新的 JS 特性?
- https://github.com/lukehoban/es6features
- 2. JS是sync还是Async?
- JavaScript 始终是同步和单线程的。如果您在页面上执行 JavaScript 代码块,则当前不会执行该页面上的其他 JavaScript。
- 3.JS 中的 Sync 和 Async 有什么区别?
- 异步代码在主程序流程之外获取语句,允许异步调用之后的代码立即执行而无需等待。
- 链接 — https://rowanmanning.com/posts/javascript-for-beginners-async/
- 4.如何优化JS代码的性能?
- 5.什么是备忘( memoization)。实现用于记忆的 JS 代码。
- 6.什么是绑定?为绑定实现 pollyfill。
- 7.为:map、reduce、filter、promise 编写 polyfill
- 8.什么是纯函数?
- 9.shim 和 polyfill 有什么区别?
- https://2ality.com/2011/12/shim-vs-polyfill.html
- 10.什么是 IIFE(立即调用函数表达式)( (Immediately Invoked Function Expressions))?
- 11.JavaScript 中的强制(Coercion )是什么?
- https://developer.mozilla.org/en-US/docs/Glossary/Type_coercion
- 12.高阶函数的定义是什么?
- 13.什么时候使用绑定功能?
- 14.什么是柯里化(Currying)?
- https://www.tutorialspoint.com/what-is-currying-in-javascript
- 15.你能举一个咖喱(curry )函数的例子吗?为什么这种语法有优势?
- 16.解释 Javascript 中的提升(Hoisting )是什么?
- JavaScript 提升是指编译器在执行代码之前为变量和函数声明分配内存的过程。使用 var 进行的声明使用默认值 undefined 进行初始化。使用 let 和 const 进行的声明不会作为提升的一部分进行初始化。
- 17.解释原型(Prototype )设计模式?
- 18.比较 Async/Await 和 Generators 的使用以实现相同的功能?
- https://medium.com/dailyjs/a-simple-guide-to-understanding-javascript-e…
- 19.await 关键字和 yield 关键字有什么区别?
- 20.是否可以将 ECMAScript 6 生成器重置为其初始状态?
- 21.如何在 JavaScript 中深度冻结(deep-freeze)对象?
我们可以使用 JavaScript 提供的 Object.freeze() 方法来防止通过更新和删除现有属性来添加新属性。
链接——https://www.geeksforgeeks.org/how-to-deep-freeze-an-object-in-javascrip…
- 22. JavaScript 是按引用传递还是按值传递语言?
- JavaScript 总是按值传递,所以改变变量的值永远不会改变底层的原语(字符串或数字)。然而,当一个变量引用一个包含数组的对象时,该值就是对该对象的引用。
https://medium.com/nodesimplified/javascript-pass-by-value-and-pass-by-…
- 23. 什么是 JS 中的 JIT 和事件循环?
事件循环有一项简单的工作——监控调用堆栈和回调队列。如果调用堆栈为空,事件循环将从队列中取出第一个事件并将其推送到调用堆栈,调用堆栈有效地运行它。
链接——https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-r…
- 24.JS 中的闭包是什么?
闭包是捆绑在一起(封闭)的函数与对其周围状态(词法环境)的引用的组合。换句话说,闭包让你可以从内部函数访问外部函数的作用域。在 JavaScript 中,每次创建函数时都会在创建函数时创建闭包。
Question Link — https://dev.to/levimeahan/closures-scope-and-the-settimeout-for-loop-question-5bl6
- https://coderbyte.com/algorithm/3-common-javascript-closure-questions#
- 25.使用箭头函数有什么好处?
- 26.JS 中的数组和字符串方法及其参数?
- 27.windows.onload 与 onDocumentReady 有什么区别?
- 28.ForEach() 和 map() 的区别?
- 29.JS中的回调函数是什么?
- 30.什么是回调地狱?
- 31.什么是承诺(promises )以及承诺(promises )如何运作?
- 32.事件冒泡和事件捕获之间的区别?
- 33.js中2+‘2’和2-‘2’的输出?
https://www.toptal.com/javascript/interview-questions
https://www.interviewbit.com/javascript-interview-questions/#coding-pro…
- 34. JS中set方法和map方法的区别?
- Map 是元素的集合,其中每个元素都存储为键、值对。 Map 对象可以同时保存对象和原始值作为键或值。当我们遍历 map 对象时,它以与插入相同的顺序返回键值对
- JavaScript map set() 方法用于添加或更新元素以映射具有特定键值对的对象。每个值都必须有一个唯一的键。
- 35. 软件开发模型——KISS、SOLID、POC、DRY、MVP 等
- 36. 什么是 javascript 中的 debounce 和 throttling?
- 37. JS中SetTimeout和SetInterval的区别?
- 38、如何使用ClearInterval & ClearTimeout?
- 39. 为什么在 JS 中引入了 let 和 const?
- 40. NaN 和 undefined 有什么区别?
- 41. 阅读逻辑与 (&&) 和逻辑或 (||) -> 短路评估
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_OR
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND
# 请按以下顺序阅读以下主题:
- 1.‘this’关键字
链接——https://www.w3schools.com/js/js_this.asp
- 2. Call、Apply 和 Bind 方法及其与 ‘this’ 关键字的使用
- 3. JS 中的闭包
闭包是函数和声明该函数的词法环境的组合。该环境由创建闭包时在范围内的任何局部变量组成。
闭包是捆绑在一起(封闭)的函数与对其周围状态(词法环境)的引用的组合。换句话说,闭包让你可以从内部函数访问外部函数的作用域。在 JavaScript 中,每次创建函数时都会在创建函数时创建闭包。
链接 — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
- 4. JS 中的柯里化(Currying )
https://www.tutorialspoint.com/what-is-currying-in-javascript
- 5. 编写 sum(1)(2)(3) 和 sum(1,2,3) 的柯里化代码
- 6. 为什么需要Bind、调用和应用?
# Devesh JS 采访资料:https://devesh-kr-sri.medium.com/javascript-3497a26e5e5a
# 重要话题:
- 1. 高级 JavaScript 实践
- 2. 面向对象编程
- 3. 函数式编程
- 4. 范围和执行上下文
- 5. 继承+原型链
- 6、最新特性:ES6、ES7、ES8、ES9、ES10、ES2020
- 7. 闭包
- 8. 异步 JavaScript + 事件循环
- 9. JavaScript 模块
- 10.`this`关键字
- 11. JavaScript 引擎和运行时
- 12. 错误处理
- 13. 堆栈溢出
- 14. 内存泄漏
- 15. 组合与继承
- 16.类型强制
- 17. 按引用传递与按值传递
- 18. 高阶函数
- 19. IIFE
- 20. .call()、.apply()、.bind()
- 21.解释器/编译器/ JIT编译器
- 22. 垃圾收集
- 23. 吊装
- 24. JavaScript 最佳实践
# 数组方法:https://www.freecodecamp.org/news/the-javascript-array-handbook/
#LinkedIn 技能评估测验 — https://github.com/Ebazhanov/linkedin-skill-assessments-quizzes
Promise Example:
function GetUserDetails() {
return new Promise(function(resolve, reject) {
console.log(“Fetching data, Please wait…..”);
setTimeout(() = >{
fetch(“https: //jsonplaceholder.typicode.com/todos/1")
.then(response = >response.json())
// .then(json => console.log(json))
// .catch(error => console.log(error));
.then(json = >resolve(json)).
catch(error = >reject(error));
},
3000);
});
}
原文:https://medium.com/@abhishekbhatti89/javascript-interview-questions-202…
- 89 次浏览
【JavaScript开发】每个 Web 开发人员都应该知道的 12 个重要的 JavaScript 函数
在本文中,我将为每个 Web 开发人员展示 12 个重要的 JavaScript 函数。 您在这里学到的一切都将加速您的开发并节省您宝贵的时间!
1.缩短控制台日志
您是否厌倦了在代码中一次又一次地编写 console.log() ? 这个简单的脚本使用 bind 来缩短控制台日志以加快开发过程(这可以通过每个函数来完成)。
2.将两个数组合并为一个
如果要将两个任意大小的数组合并为一个数组,可以使用 concate JavaScript 函数。
3. 将两个对象合并为一个
如果您使用对象,您可以使用这个简单的技巧将它们合并在一起。
4. 缩短数组
Web 开发人员有一种简单的方法来缩短数组。 您需要使用长度方法并传递一个小于实际数组大小的数字。
5. 随机排列数组
有时您希望随机化数组中的值。 为此,您可以使用带有随机 compareFunction 的 Array.sort 函数。
6.使用isNum验证一个数字
使用此函数,您可以检查值或变量是否为数字(int、float 等)。
7. 使用 isStr 验证字符串
使用此功能,您可以检查值或变量是否为字符串格式。
8. 使用 isNull
检查结果或数据是否为空通常很有用。
9.计算一个函数的性能
如果你想检查一个函数运行了多长时间,你可以在你的程序中使用这种方法
10.从数组中删除重复项
我们经常会遇到一个包含重复数据的数组,并使用循环来删除这些重复数据。 此功能可以在不使用循环的情况下以简单的方式删除重复项。
11. 对条件使用逻辑 AND/OR
您可以使用逻辑 AND/OR,而不是使用 if 条件。 这可以在执行命令的函数中使用
或用于赋值
12. 三元运算符
三元运算符很酷。 您可以使用三元运算符避免看起来不好的嵌套条件 if..elseif..elseif。
结语
我希望你觉得这篇文章有帮助! 如果您也有好的 JavaScript 函数可以分享,请随时在此处发表评论并与其他开发人员分享。 快乐的 JavaScript 编码。
原文:https://javascript.plainenglish.io/12-important-javascript-functions-ev…
本文:
- 19 次浏览
Java开发
- 201 次浏览
AssertJ 介绍:java的流畅断言
AssertJ是一个Java库,它为断言提供了一个流畅的接口,这使得在测试代码中传递意图变得很容易。AssertJ提供可读的错误消息、软断言以及改进的集合和异常支持。我们的许多团队选择AssertJ作为默认的断言库,而不是将JUnit与Java Hamcrest结合使用。
AssertJ核心网站已转移到https://assertj.github.io/doc/
丰富和易于使用
AssertJ提供了一组丰富的断言,真正有用的错误消息,提高了测试代码的可读性,并被设计为在您喜欢的IDE中非常容易使用。
马上开始一分钟的入门指南,看看AssertJ的一些伟大的功能或保持最新的发布。
如果您相信AssertJ,您可以自动将JUnit断言转换为AssertJ。
可扩展的
您可以轻松地为自己的类编写断言,这将使您的测试断言反映领域,并且是在测试中使用通用语言的一种方法!
我们提供了一个断言生成器来快速创建域模型类的断言。
社区驱动的
AssertJ的存在只是为了帮助开发社区。我们倾听用户的想法,提供最有用的断言。
AssertJ是不再维护的great Fest Assert库的一个分支。
AssertJ将永远保持开放和自由。
AssertJ为流行的库提供断言
Guava
为类似于Multimap, Table, Optional or ByteSource.的Guava类型提供断言。
检查AssertJ Guava断言的最新消息和文档。
Joda Time
为诸如DateTime和LocalDateTime之类的Joda时间类型提供断言。以后会有更多的,欢迎投稿!
检查AssertJ Joda时间断言最新的新闻和文档。
Neo4J
为节点、路径和关系等Neo4J类型提供断言。
检查AssertJ Neo4J断言的最新消息和文档。
Neo4J断言是由Florent Biville开发的。
原文:http://joel-costigliola.github.io/assertj/index.html
- 64 次浏览
【Java开发】使用 Spring Boot 的优缺点
介绍
由于附加功能的建立,Spring 框架的结构在过去几年中变得明显更加复杂。现在,开始一个新的 Spring 项目需要一个漫长的设置过程。 Spring Boot 的发明是为了节省时间并避免在每个新项目中从头开始配置这个框架。
什么是 Spring 框架
Spring 是用于开发企业应用程序的最广泛使用的框架之一,它提供了健壮的编程和配置模型。这个框架的创建是为了简化 Oracle 流行的 Java EE 技术堆栈上的应用程序开发,当时该技术非常复杂且难以使用。
与其他框架不同,Spring 专注于应用程序功能的几个领域,并为它们提供了广泛的附加功能。
Spring Framework 的主要优点之一是它使用了依赖注入模式。 DI 使实现应用程序所需的功能变得更加容易,并允许开发松散耦合、更通用的类。
Spring框架的优点
让我们看一下 Spring Framework 的一些优点:
Spring Framework 可用于 Web 应用程序开发中使用的所有架构层;
- 编写类时使用非常轻量级的POJO模型;
- 允许您自由链接模块并轻松测试它们;
- 支持声明式编程;
- 消除了独立创建工厂和单例类的需要;
- 支持多种配置方式;
- 提供中间件级别的服务。
尽管 Spring Framework 有许多优点,但配置它所涉及的冗长准备过程促成了 Spring Boot 的创建。
用于应用程序开发的 Spring Boot
尽管 Spring Framework 具有优势,但作者决定为开发人员提供一些实用程序,这些实用程序可以自动执行配置过程并加快创建和部署 Spring 应用程序的过程。这些实用程序以 Spring Boot 的通用名称组合在一起。
虽然 Spring Framework 专注于提供灵活性,但 Spring Boot 旨在减少代码长度并简化 Web 应用程序开发。通过利用注释和样板配置,Spring Boot 减少了开发应用程序所需的时间。此功能可帮助您以较少或几乎没有配置开销创建独立应用程序。
易于依赖管理
为了加快依赖管理过程,Spring Boot 为每类基于 Spring 的应用程序隐式打包所需的第三方依赖,并通过所谓的启动包(spring-boot-starter-web、spring-boot-starter-数据-jpa 等)。
入门包是可以包含在应用程序中的方便依赖描述符的集合。它们允许您获得所有 Spring 相关技术的通用解决方案,无需搜索代码示例并从中加载所需的依赖项描述符。
例如,如果您想开始使用 Spring Data JPA 访问您的数据库,只需在项目中包含 spring-boot-starter-data-jpa 依赖项即可完成(无需寻找兼容的 Hibernate 数据库驱动程序和图书馆)。
如果你想创建一个 Spring Web 应用,只需要添加 spring-boot-starter-web 依赖,它会将开发 Spring MVC 应用所需的所有库拉到你的项目中,例如 spring-webmvc、jackson-json、validation -api 和 Tomcat。
简而言之,Spring Boot 是用来做什么的,它收集所有常见的依赖项并将它们定义在一个地方,这使开发人员可以立即开始工作,而不是每次创建新应用程序时都重新发明轮子。
因此,在 Spring Boot 中使用时 pom.xml 文件包含的行数比在常规 Spring 中少得多。
自动配置
Spring Boot 的优点之一,值得一提的是应用程序的自动配置。
选择合适的启动包后,Spring Boot 将尝试根据您添加的 jar 依赖项自动配置您的 Spring 应用程序。例如,如果添加 Spring-boot-starter-web,Spring Boot 会自动配置已注册的 bean,例如 DispatcherServlet、ResourceHandlers 和 MessageSource。
如果您使用的是 spring-boot-starter-jdbc,Spring Boot 会自动注册 DataSource、EntityManagerFactory 和 TransactionManager bean,并从 application.properties 文件中读取数据库连接信息。如果您不打算使用数据库并且不提供任何有关手动连接的详细信息,Spring Boot 将自动在内存中配置数据库,而无需您进行任何额外配置(如果您有 H2 或 HSQL 库)。使用用户首选项可以随时完全覆盖自动配置。
对应用服务器的原生支持——Servlet 容器
每个 Spring Boot 应用程序都包含一个嵌入式 Web 服务器。开发人员不再需要担心设置 servlet 容器并将应用程序部署到其中。应用程序现在可以使用内置服务器将自身作为可执行 jar 文件运行。如果您需要使用单独的 HTTP 服务器,只需排除默认依赖项即可。 Spring Boot 为不同的 HTTP 服务器提供了单独的启动包。
使用嵌入式服务器构建独立的 Web 应用程序,不仅方便开发,而且是企业级应用程序的有效解决方案;更重要的是,它在微服务领域变得越来越有用。将整个服务(例如用户身份验证)快速打包到独立且完全可部署的工件中的能力,该工件还提供 API,这使得安装和部署应用程序变得更加容易。
Spring Boot 是下一代工具的一部分,可简化 Spring 应用程序的配置过程。它不是自动生成代码的工具,而是项目构建自动化系统的插件(支持 Maven 和 Gradle)。
该插件提供了测试和部署 Spring 应用程序的功能。 mvn spring-boot:run 命令在端口 8080 上运行您的应用程序。此外,Spring Boot 允许您将应用程序打包到一个单独的 jar 文件中,并嵌入完整的 Tomcat 容器。这种方法是从 Play 框架的应用程序部署模型中借用的(不过,Spring Boot 也可以创建传统的 war 文件)。
Spring Boot 的主要优势之一是基于类路径的内容配置资源。当涉及到默认配置时,Spring Boot 非常直观。您可能并不总是同意它的设置选择,但至少它会为您提供一个工作模块。这是一种非常有用的方法,尤其是对于新手开发人员,他们可以从默认设置开始并在他们以后探索替代方案时对其进行更改。这比每次开始一个新项目时回答一堆难题要好得多。此外,Spring Boot 的官方网页上还有许多成熟的教程。这些将帮助您在初始阶段快速理解并实际实施所有主要类型的项目。
Spring Boot 还处于起步阶段,自然要经过多次蜕变才能完全稳定。用它来构建严肃的系统可能还为时过早,但它非常适合执行各种个人、培训和测试项目,以防你想消除大量无关的非生产性日常工作创造有用的功能。
就 Spring Boot 成长为一个严肃的开发工具的潜力而言,可接受的技术文档的存在看起来非常令人鼓舞。
现在让我们仔细看看使用 Spring Boot 的优缺点。
Spring Boot 应用程序的优点
Spring Boot 旨在使 Spring Framework 更易于使用。 Spring 提供了一个松散耦合的应用程序,这本身就是一个很棒的特性。然而,当涉及到几个松散耦合的块时,跟踪它们就变成了一项乏味且吃力不讨好的任务。这就是 Spring Boot 的用武之地,它通过以下功能帮助您保持简单:
- 快速轻松地开发基于 Spring 的应用程序;
- 无需部署war文件;
- 创建独立应用程序的能力;
- 帮助将 Tomcat、Jetty 或 Undertow 直接嵌入到应用程序中;
- 无需XML配置;
- 减少源代码数量;
- 额外的开箱即用功能;
- 轻松启动;
- 简单的设置和管理;
- 大型社区和许多培训计划,以促进熟悉期。
借助自动配置等功能,Spring Boot 为您省去了编码和不必要配置的麻烦。 Spring 框架不仅为您提供依赖注入或事务处理等功能,它还充当其他 Spring 框架的基础。最好的例子是 Spring Boot。 Spring Boot 使用 Spring Framework 作为其基础。它简化了 Spring 依赖项并直接从命令行运行应用程序。它也不需要外部应用程序容器。 Spring Boot 有助于在外部控制和自定义应用程序组件。
Spring Boot 的缺点
尽管 Spring Boot 有很多优点,但它仍然有一些缺点需要牢记:
- 缺乏控制。 Spring Boot 会创建大量未使用的依赖项,导致部署文件很大;
- 将遗留或现有 Spring 项目转换为 Spring Boot 应用程序的复杂且耗时的过程;
- 不适合大型项目。 尽管它非常适合使用微服务,但许多开发人员声称 Spring Boot 不适合构建单体应用程序。
原文:https://bambooagile.eu/insights/pros-and-cons-of-using-spring-boot/
- 510 次浏览
【Java架构】Jakarta EE没有javax:世界不会在这个时候结束
这篇冗长的文章讨论了Eclipse Foundation和Oracle之间关于命名空间和商标权的争议。
如果您在2017年错过了新闻,那么Oracle就会将Java EE规范捐赠给Eclipse基金会。这个决定在规范过程中进行了相当长时间的休眠,人们理所当然地怀疑Oracle对Java EE失去了战略兴趣。起初,Java EE和更广泛的Java社区很好地满足了捐赠规范的决定。如果没有Oracle放慢流程,那些参与Java EE的人可能会再次尝试关闭非标准化的API。直到今天,由于甲骨文和Eclipse基金会对捐赠的几个细节存在分歧,捐赠过程仍未完成。
在转换所有知识产权的同时,Oracle在规范的新家中使用其Java品牌时并不那么慷慨。当然,Java EE确实包含Oracle拥有的开源且受商标保护的平台的名称。这会在法律背景下产生问题:如果您授予第三方使用您的品牌名称,您将来有权限制它。更糟糕的是,当谈到有关您品牌的诉讼时,您可能会削弱您在法庭上的地位。随着甲骨文和谷歌多年来争论Java许可的历史,人们可以预见到品牌化将成为一个困难的讨论点。并且不假装对国际商标法有多少了解,有人告诉我更多参与者“使用它或失去它”对于理解这种分歧的一般格言是一个足够好的近似。因此,第一个结果是,规范从Java EE重命名为Jakarta EE,以避免利益冲突。
然而,新成立的雅加达EE社区的真正震惊还未到来。经过几个月的讨论捐赠手续,Eclipse基金会了解到它无法承担托管Java EE中定义的API的当前javax命名空间的所有权。相反,此命名空间现在计划为所有捐赠的API休眠。因此,任何将在Jakarta EE的规范过程中创建的新API都应该托管在新的命名空间中,以避免侵犯Oracle的商标。
在这一点上,澄清这意味着什么很重要。不禁止Jakarta EE和Eclipse Foundation使用javax命名空间或实现其API。也不会删除当前存在的API。但是,在新形成的Jakarta EE规范过程中创建或更新的任何API都需要存在于新的命名空间中,该命名空间最有可能模仿现有的命名空间,但使用jakarta作为其前缀而不是javax。例如,如果要将新方法添加到javax.servlet.Servlet接口,则下一版本的servlet规范需要发布名为jakarta.servlet.Servlet的新接口,而不是将此方法添加到现有API中。
我不是Java EE用户。我为什么要关心?
正如大多数人所知,Java平台正式分为两部分。第一部分是Java SE,其中所有API都在以java为前缀的包中定义。除此之外,Java EE还在javax命名空间中指定扩展API。这些API并不意味着特定的实现,而只是定义由不同Java EE兼容组件供应商实现的行为。
在这种情况下,Java EE是几个不依赖于彼此的API规范的总称。例如,Java消息传递规范(JMS)定义了用于与消息队列交互的API,而Java servlet规范定义了用于将调用分派给Web服务器的API。实际上,我所知道的Java EE应用程序运行时没有实现Java EE规范过程中定义的整个API。一些Java框架甚至专注于实现单一规范。例如,Jetty Web服务器仅实现Java servlet规范。因此,如果您通过Spring Boot使用Jetty,即使您没有直接与规范交互或认为自己是Java EE用户,您也正式成为Java EE的用户。
尽管存在这种形式上的区别,但即使您只编写了vanilla Java而没有包含任何外部依赖项,您也可能遇到过Java EE及其javax命名空间。这是因为选择的Java EE API与JVM的标准映像捆绑在一起。除了API之外,JVM还提供了此API的默认实现,以便用户无需任何额外工作即可轻松解决常见任务。例如,JAXP是一个Java EE规范,它定义了一个用于在Java中处理XML的API。由于XML处理是一项常见任务,特别是在面向企业的Java平台上,因此将其包含在内是一个合理的选择。对于JAXP,它假定的常见用法在今天仍然是事实,但其他JVM捆绑的Java EE规范并没有同样好的老化。例如,SOAP消息传递不再是大多数Java开发人员的首选,因此JVM捆绑的JAX-WS实现对于大多数用户来说已经变得非常重要。为了减少JVM的占用空间,并且在Java 9中引入了Java模块系统,一些Java EE API被移至已弃用的模块,这些模块计划在将来的版本中删除。当然,这并不意味着模块的API本身已被弃用。 JAX-WS仍然活跃并被许多人积极使用。但是由于这个模块被弃用,JAX-WS需要被那些想要在未来的Java版本中继续使用它的人添加为显式依赖。
在我们在虚拟化硬件上运行微服务的时代,减少JVM占用空间已成为演进JVM的明显目标。但是从基础JVM映像中删除Java EE API还有另一个优点。通过要求用户包含对Java EE API的显式依赖,升级Java运行时和Java EE不再捆绑在一起。在Java 8之前,管理这种版本的相互依赖性一直很乏味。如果您不控制要部署应用程序的JVM的确切版本,则尤其如此。在Java 8之前,JVM只允许您通过将JAR文件放入JVM的扩展文件夹来覆盖隐式Java EE依赖项。但是,当您与其他也会受到影响的Java进程共享JVM安装时,这当然是有问题的。此外,您仍然需要对正在使用的JVM安装进行一些控制。为了解决这个问题,默认情况下,Java模块系统不再解析已弃用的Java EE模块,这样可以在JVM中包含显式版本,尽管可以继续按需捆绑,同时还提供了一种激活旧版兼容性的简单方法。
为了使事情变得更加复杂,一小部分Java EE API以不允许简单分离的方式发展为Java SE。例如,JDBC规范分为“客户端”和“服务器端”需求,前者正式属于Java SE,后者则是Java EE的一部分。这种区别来自最初的Java哲学,其中人们将Java SE用于面向用户的桌面应用程序,而Java EE用于多个并发用户使用的服务器应用程序。本着这种精神,JDBC Connection接口例如在java.sql包中定义。毕竟,桌面用户当然可能想要连接到数据库。另一方面,JDBC DataSource接口在javax.sql包中定义,因为连接池仅被视为多线程服务器应用程序的要求。从今天的角度来看,这种分离当然不再有意义,但命名空间和形式上的区别在今天仍然存在。
当然,让JDBC API在由OpenJDK项目管理的Java SE和现在由Eclipse Foundation管理的Jakarta EE中单独发展是没有意义的。因此,并非Java EE规范的所有部分都捐赠给Eclipse,因此将为JDBC API保留javax.sql命名空间,该API现在被认为是仅Java SE的一部分。此类API保留的其他示例是JMX API,它严重依赖于本机JVM支持。当然,所有其他始终被认为是Java SE的一部分的API,例如最终在Java扩展名称空间中的Swing API,仍将保留在其原始包中。
那么向后兼容性怎么样?
需要记住的重要一点是,现在或将来,现有的javax API都不会消失。就个人而言,我还希望现在雅加达EE的一部分规范能够在未来许多年内支持javax命名空间。事实上,处理多个名称空间对于大多数Java EE实现来说并不是什么新鲜事,但它始终是一个需要处理的重要主题。例如,Hibernate库在逐渐用JPA规范定义的注释替换自己的注释时已经成功完成了类似的迁移。在另一个示例中,Spring框架支持与其本机注释并行的Java EE CDI规范。这样做,例如,可以通过使用javax.inject.Inject批注或Spring的本机Autowired批注来请求bean注入。一旦Inject注释转移到jakarta包,我就会期望Spring框架同时支持Java EE和Jakarta EE命名空间,因为我也期望它来自Java企业API的其他实现者。
由于Jakarta EE是Java EE的继承者,我不希望这种支持的实现或维护成本过高,因为应用服务器供应商可以简单地实现委托给现在过时的Java EE API的Jakarta EE包装器类。例如,通过定义类似于以下内容的包装类,可以在内部将Java EE servlet视为Jakarta EE servlet:
public class LegacyServlet implements jakarta.servlet.Servlet {private final javax.servlet.Servlet delegate;public LegacyServlet(javax.servlet.Servlet delegate) {this.delegate = delegate;}@Overridepublic void service(jakarta.servlet.ServletRequest req, jakarta.servlet.ServletResponse resp) {delegate.service(new LegacyServletRequest(req), new LegacyServletResponse(resp));}}
如果Jakarta EE以(逻辑)向后兼容当前规范和API为目标,这应该相当简单。如果遵循这一原则,这也将要求API的用户仅更新到Jakarta命名空间,以防他们想要使用已经需要代码更改的新功能。因此,我希望更改的命名空间不会过多地影响未来的Jakarta EE用户,但主要是那些实现其API的人的关注。回顾过去对Java平台的其他更基本的变化,例如,引入Java模块系统时也是如此,这主要涉及库和框架开发人员,但很少是Java的最终用户。
当然,对两个命名空间的支持永远不会是通用的,特别是从长远来看,因此Java EE API的用户最终需要对转换作出反应。鉴于规范保留了其API的二进制兼容性并排除了名称空间前缀的变化,我相信移植软件应该易于克服,甚至应该是可自动化的。任何Java类都在每个类文件的常量池中引用其导入的类型。使用新的jakarta前缀修补工件的所有常量池中的所有相关类型引用的工具将是微不足道的。这样做,Java EE的旧用户可以避免在被动维护下为其应用程序更改源代码,并且仅在编译后应用此类更改,甚至在部署期间修补工件。
什么驱动Oracle?
我当然是一名软件顾问,而不是国际商标管辖权的专家。我对甲骨文的决策过程也没有任何见解。因此,请将这最后一节作为有根据的推测与我的个人意见相混合而不是事实摘要。
Java社区中的一些声音目前正在指责Oracle通过限制javax命名空间的使用来反对Java及其用户的兴趣。 Eclipse基金会中也有激烈的争论,以至于有人建议以这种方式捐赠Java EE可能会被拒绝,因为它与组织的目标和价值观不相容。
鉴于这种变化确实给Java用户带来了重大的工作,当然可以很快得出这个观点。但是,我无法想象甲骨文会轻易做出这个决定。 Oracle已经并且一直在Java平台上进行大量投资 - Java很少像现在这样活跃 - 但它也改变了它的战略方向。对我而言,Oracle在进行这些投资时“不关心”Java社区的想法根本不合适。
那么我认为如何推动这一决定呢?对我而言,限制与Java EE几乎没有关系,而是关于Oracle保护其对Java SE的兴趣。在一天结束时,甲骨文正在投资Java以获取利润。通过允许使用其商标,甲骨文将放弃对其品牌的控制权,从而使这一目标陷入危险境地。当然,Oracle依靠Java来生产自己的产品,并因此保留了它。但与此同时,该公司正在尝试创建一个战略模型,证明为数百名从事Java工作的全职和高素质员工提供资金。
甲骨文显然正在推动销售云解决方案,鉴于该公司目前在运营时和数据库方面的主导地位,除了雄厚的资金外,我相信他们在这一领域获得重要市场份额的机会要好于许多人的预期。 Oracle的另一个迹象是它对Graal VM及其编译器的投资,它还在资源受限的环境(如容器)中为Java语言提供了更广泛的应用范围。
但在投资某些领域的同时,甲骨文肯定也在研究削减成本的方法,例如终止不再具有战略利益或盈利能力不足的企业。虽然让用户(包括我自己)感到悲伤,但像Java飞行记录器这样的成功项目团队被解雇了,但考虑到绝大多数Java开发人员都没有要求这样的工具,这是有道理的。我认为Java EE不符合Oracle的平台计划或成本,并遭遇了类似的命运。.
有鉴于此,甲骨文可能考虑在放弃规范与捐赠给其他人维护之间进行权衡。虽然捐赠Java EE的选择似乎没有成本,但甲骨文当然会通过捐赠来承担风险。通过允许竞争组织继续他们在Java EE中的努力,这些努力也可能增强他们在Java SE领域与Oracle竞争的能力。对于红帽和IBM来说尤其如此 - 它们也在云解决方案市场上竞争。通过保护其品牌权,Oracle的目标只是降低Java EE被竞争对手武器化以在未来争夺Java SE市场份额的风险。公平地说,Oracle为Eclipse基金会提供了一种继续使用javax命名空间的方法。但是,这需要基础来限制自己将其产品与JVM的Java SE认证实现捆绑在一起,而不是例如它自己的IBM捐赠的OpenJ9。这样做,甲骨文将保留对其品牌的充分控制,但与此同时,签署如此广泛的协议不符合基金会的利益是非常可以理解的。它本来就没有意义,从这个角度来看,人们甚至认为Eclipse首先是接受Java EE捐赠的错误选择。
接下来是什么?
在开源社区,我们经常讨论我们的工作资金不足。虽然缺乏盈利能力对于个人开发者来说是个问题,但对于大型企业来说当然也是一个问题,无论是甲骨文还是参与当前讨论的任何其他公司。在我看来,通过Oracle捐赠Java EE的知识产权,Java社区已经交付了规范中最重要的部分,我们应该专注于我们拥有的东西,而不是被附加的字符串过度分散注意力。就个人而言,如果Oracle对Java品牌失去兴趣而不是采取立场,我会更担心Java的未来。
至于Jakarta EE,我不认为即将发生的命名空间迁移是规范面临的最大问题。许多开发人员甚至在最近的停滞期之前就对Java EE的尘埃感到沮丧。在我看来,问题是这个过程的一部分。实际上,Java EE规范通常源自领先框架的实现。如果另一个框架想要重新发明如何通过更好的API解决同样的问题,它需要面对不遵守标准的不断批评。这一切尽管这个标准通常只是以前最佳实践的快照。出于这个原因,我希望雅加达EE能够专注于它的发展,而不是过分坚持它的过去。通过提供最先进的API的引人注目的产品,我不会太担心调整我的代码,如果它让我免于实现最小化jakarta.servlet.Servlet API的迭代。
原文:https://dzone.com/articles/jakarta-ee-without-javax-the-world-wont-end-this-time-either
本文:http://pub.intelligentx.net/jakarta-ee-without-javax-world-wont-end-time-either
讨论:请加入知识星球或者小红圈【首席架构师圈】
- 70 次浏览
【Java框架】2022 年 17 个流行的 Java 框架:优缺点等
视频号
微信公众号
知识星球
进入 2022 年,Java 仍然是世界上第三大最受欢迎的编程语言。它包含一个庞大的生态系统和全球超过 900 万的 Java 开发人员。 Java有很多优点;最重要的是,它是一种独立于平台的语言(一次编写,随处运行),遵循面向对象的编程范式,易于理解、编写和调试。
由于该语言的成熟和流行,您不必从头开始编写 Java 程序。有许多优秀的 Java 框架可以编写在 Java 虚拟机上运行的 Web 和移动应用程序、微服务和 REST API。
在本深入指南中,我们将研究 17 个主要用于 Web 开发的流行 Java 框架。
什么是 Java 框架?
Java 框架是为使构建 Java 应用程序更容易和更快而创建的软件库。它们由预先编写的代码、类、模板、组件和其他结构组成,您可以将它们用作 Java 应用程序的基础。
最好的 Java 框架经过充分测试,并强制使用编码最佳实践。它们让您专注于应用程序的业务逻辑,而不是编写基本功能,例如建立数据库连接或处理异常。
但是,并非所有 Java 框架都具有相同的目的,因此在它们之间进行选择不仅仅是偏好问题。有些允许您创建全栈 Java Web 应用程序,而另一些则专注于前端或后端,还有一些框架用于处理数据库操作等额外任务。在某些情况下,您可能希望同时使用多个框架,因此了解这些 Java 框架如何相互比较和集成非常重要。
前 17 个 Java 框架
我们选择按字母顺序列出我们排名前 17 的 Java 框架,而不是按“质量”排名,因为它们的结构和用途不同。
我们包含了允许您创建视图层的 Java 前端框架、允许您与数据库交互的 ORM 和持久性框架、有助于创建微服务和 REST API 的 Java 后端框架、构建在其他 Java 框架之上的 Java 框架,和更多。
本文重点介绍 Web 开发,因此需要注意的是,这并不是一个详尽的列表,还有其他类型的 Java 框架,例如日志框架。
让我们从 B for Blade 开始。
Blade:占用空间最小的简单应用程序框架
Blade:占用空间最小的简单应用程序框架
Blade 是一个轻量级的高性能 Java 框架,它允许您以高效的方式构建快速的 Web 应用程序。创建者的目标是让用户在一天内了解整个框架。为了实现这一点,Blade 专注于简单和优雅。
Blade 框架遵循 MVC(模型-视图-控制器)软件设计模式。它具有易于理解的设计,不依赖任何第三方库或引入太多层。 Blade基于Java 8,框架内置Netty Web服务器和模板引擎。它占地面积小;源代码总共不到 500kb。
使用 Blade,您可以访问 RESTful 样式的路由接口,并且可以将您的应用程序部署为基本的 Maven 或 Gradle 项目。 Blade 也有内置的安全功能;例如,它带有 CSRF(Cross-Site Request Forgery)和 XSS(Cross-Site Scripting)防御。它是一个多功能框架,支持插件扩展和 webjar 资源。
优点: - 无依赖关系 - 易于部署 - 小型轻量级框架
- 嵌入式网络服务器 - 模板引擎支持 - 平坦的学习曲线
缺点: - 教程和示例项目不多 - 现在开发活动不太活跃
Dropwizard:生产就绪的 RESTful Web 服务
Dropwizard:生产就绪的 RESTful Web 服务
Dropwizard 是一个高性能但简单的 Java 框架,用于快速开发 RESTful Web 服务。它特别适合创建 Java 微服务。
Dropwizard 框架汇集了几个完善的 Java 库,为您提供快速且无干扰的开发平台。它带有嵌入式 Jetty 服务器、Google Guava、Logback、Hibernate Validator、Joda Time 和许多其他流行的 Java 库。 Dropwizard 还包含可用于构建 RESTful Web 服务的 Jersey 和用于处理 JSON 的 Jackson。您可以将 Dropwizard 视为一个单独的生态系统,其中包含捆绑到单个包中的所有上述依赖项。
如果您选择 Dropwizard,则不必在辅助功能上花费太多时间,例如必须为配置、指标或日志记录编写代码。相反,您可以专注于应用程序的主要业务逻辑并实现最大生产力。这就是为什么 Dropwizard 通常被称为操作友好的 Java 框架的原因。
优点: - 易于设置和开始 - 轻量级 - 由成熟的 Java 库组成 - 良好的约定 - 可扩展 - 大量文档
缺点: - 你可能会觉得它有点太自以为是了
Grails:基于 Groovy 的 Web 应用程序框架
Grails 是一个使用 Groovy 编程语言的 Web 应用程序框架。 Groovy 是一种面向对象的 Java 平台语言,旨在提高开发人员的工作效率。它的语法与 Java 兼容,并编译为 JVM(Java 虚拟机)字节码。
尽管您必须在 Groovy 中编写代码,但 Grails 可以很好地与其他 Java 相关技术(例如 Java Development Kit、Java EE 容器、Hibernate 或 Spring)配合使用。在底层,Grails 构建在 Spring Boot 之上,以利用其生产力友好的特性,例如 Spring 的依赖注入。 Grails 最好的一点是,您可以用更少的代码实现相同的结果——这要归功于 Groovy 语言的强大功能。
Grails 遵循一些现代软件开发原则,例如约定优于配置、固执己见的 API 以强制执行最佳实践以及合理的默认值。它也对开发人员非常友好,因为它带有详细且易于阅读的文档、分步指南和广泛的插件库。您还可以构建自己的插件并利用 Grails 对 Eclipse、Sublime、Textmate、IntelliJ IDEA 和其他平台的 IDE 支持。
优点: - 建立在 Spring Boot 之上(见下文,作为 Spring 框架的一部分) - 与 Java 库和工具的无缝集成 - 约定优于配置(具有合理的默认值) - 异步功能 - 用于 React 和 Angular 的应用程序配置文件 - 高质量文档和大量的学习资料
缺点: - 你需要了解 Groovy 才能编写 Grails 应用程序
GWT:Google Web Toolkit:部署为 JavaScript 的客户端 Java 应用程序
GWT 或 Google Web Toolkit 是由 Google 创建的 Web 框架。您可以使用它为 Web 快速构建 Java 应用程序,因为它允许您编写客户端 Java 代码并将其部署为浏览器的 JavaScript。
GWT(读作“gwit”)是一个稳定且维护良好的 Java 框架。没有什么比它出现在 AdWords、AdSense、Blogger 和 Google Wallet 等多种 Google 产品中更能说明这一点了。 Google Web Toolkit 还有一个信息量很大的网站,其中包含教程、开发人员指南和入门应用程序。
使用 GWT,您无需成为 JavaScript 优化或响应式设计等前端技术专家即可构建基于浏览器的应用程序。 GWT 提供了许多高级功能,例如国际化、跨浏览器可移植性、UI 抽象、书签和历史管理。
优点: - 处理浏览器兼容性(包括移动浏览器) - 集成调试功能 - 代码优化功能 - 允许您对前端代码进行单元测试 - 平坦的学习曲线(适用于 Java 开发人员)
缺点: - 无法控制您的 JavaScript 或前端代码 - 生成非语义 HTML 代码
Hibernate:用于更好的数据库通信的对象关系映射框架
Hibernate:用于更好的数据库通信的对象关系映射框架
Hibernate 是一个稳定的对象-关系映射框架,它可以在 Java 编程语言和关系数据库管理系统 (RDBMS) 之间实现更好的通信。
当您使用 Java 等面向对象 (OO) 语言时,您会遇到一个称为 Object-Relational Impedance Mismatch(有时也称为 Paradigm Mismatch)的问题。 OO 语言和 RDBMS 处理数据的方式不同,这可能导致不匹配问题。 OO 语言将数据构造为对象的层次结构,而关系数据库则以表格格式表示数据。这些不匹配问题之一是当对象模型的类多于关系数据库中可用表的数量时。
Hibernate 为您提供了一个克服 Java 不匹配问题的框架。它旨在实现持久性,这意味着应用程序创建/使用的数据应该比生成它的过程更长。虽然 Hibernate 是为关系数据库构建的,但其较新版本也提供对 NoSQL 数据存储的支持。它还拥有出色的开发人员工具,例如映射编辑器、Hibernate 控制台和数据库逆向工程工具。
优点: - 面向对象的接口(不需要 SQL 接口) - 使任何类或数据结构都可以持久化 - 支持多种获取策略 - 自动版本控制和时间戳 - 可扩展性良好 - 高度可扩展和可配置
缺点: - 复杂查询的性能较低 - 学习曲线陡峭
Jakarta Server Faces (JSF):基于组件的 UI 框架
Jakarta Server Faces (JSF),以前称为 JavaServer Faces,由 Oracle 开发,作为为基于 Java 的 Web 应用程序构建用户界面的规范。它也是 Java Community Process (JCP) 倡议的官方标准。
Jakarta Server Faces 的第一个版本于 2004 年发布,因此它是一个稳定的框架。它遵循 MVC 软件设计模式,并具有基于组件的架构。使用 Jakarta Server Faces,您可以构建由可重用组件组成的用户界面,管理组件的状态,将它们连接到数据源,并将用户生成的事件绑定到服务器端的事件处理程序。
JSF 的默认模板系统是为项目显式创建的 Facelets。使用 Facelets,您可以使用 XML 而不是 Java 来处理视图。但是,您也可以使用 XUL(XML 用户界面语言)和纯 Java 等其他技术创建视图。使用 Jakarta Server Faces 创建的 Web 应用程序可以跨不同的 Jakarta (Java) EE 应用程序服务器移植。
优点: - 可靠性(由 Oracle 开发和维护的代码) - 建立在 Servlet API 之上 - 跨浏览器兼容性 - 自动状态管理 - 支持优雅降级和多种输出格式 - 相对较低的学习曲线(适用于 Java 开发人员)
缺点: - 难以调试 - 教程或学习材料不多
JHipster:使用 Spring Boot 和 Angular/React 的 Web 应用程序和微服务
JHipster 将 Spring Boot 和流行的前端框架(Vue、Angular、React 等)结合在一个方便的 Web 应用程序生成器中。它被 Adobe、西门子、博世、HBO 和谷歌等领先品牌使用。使用 JHipster,您可以快速创建基于 Java 的现代 Web 应用程序和微服务。
Spring Boot 允许您创建以最少配置工作的生产级基于 Spring 的应用程序(请参阅下面有关 Spring 框架的更多信息)。 JHipster 将其与客户端的 Angular、React、Vue 和 Bootstrap 相结合,为您提供全栈架构。如果您想了解 JHipster 应用程序在现实生活中的样子,请查看由 JHipster 团队创建的 Angular、React 和 Vue 示例应用程序。
JHipster 允许您在两种架构风格之间进行选择。您可以选择将前端和后端组合成一个应用程序的单体架构。或者,您可以使用分离前端和后端的微服务架构。 JHipster 还集成了多种工具,并为客户端和服务器端编码、捆绑和不同的 DevOps 任务提供了大量选项。
优点: - 显着加快开发速度 - 支持许多前端框架和技术 - 支持移动应用程序开发(Ionic 和 React Native) - 构建在 Spring Boot 之上(因此您可以使用依赖注入和 Spring Boot 的其他功能) - 多个部署选项 - 活跃的社区和包含示例项目的大量文档
缺点: - 大量自动生成的代码可能会让初学者感到困惑
MyBatis:用于更轻松 SQL 管理的持久性框架
MyBatis 是一个用于 Java 应用程序的持久性框架,它使使用关系 (SQL) 数据库变得更加容易和快捷。该框架充当应用程序和数据库之间的中间件,并解决了源自其不同架构的问题。
您可以将 MyBatis 视为应用程序的 Java 代码和底层 SQL 数据库之间的抽象层。默认情况下,您需要使用 JDBC(Java 数据库连接)API 从您的 Java 代码访问数据源,例如关系数据库或电子表格。 MyBatis 简化了这个过程,让你用更少的代码与关系数据库进行交互。例如,您可以只用一行代码执行 SQL 语句。
MyBatis 类似于 Hibernate 框架,都旨在改善应用层和数据库之间的通信。然而,MyBatis 并不像 Hibernate 那样将 Java 对象映射到数据库表,而是将 Java 方法链接到 SQL 语句。因此,当您使用 MyBatis 框架时,SQL 是可见的,并且您仍然可以控制 SQL 的执行(另一方面,您需要自己编写 SQL 语句并设置映射) .
优点: - 易于使用和学习(适用于 Java 开发人员) - 轻量级 - 快速开发 - 与 Spring 框架兼容 - 简单获取的出色解决方案 - 可移植性 - 数据库独立接口 - 能够构建动态 SQL 查询
缺点: - 高度依赖 SQL - 难以调试 - 不如 Hibernate 灵活
Play:用于高度可扩展的 Java 应用程序的响应式 Web 和移动框架
Play 框架使构建用于桌面和移动设备的轻量级和网络友好的 Java 和 Scala 应用程序成为可能。 Play 是一个非常流行的框架,被 LinkedIn、三星、沃尔玛、卫报、Verizon 等公司使用。
Play 经常被比作其他编程语言的强大 Web 框架,例如 Ruby on Rails 的 Ruby 或 Django 的 Python。与大多数 Java 框架不同,它不依赖于 Jakarta EE 标准。它旨在消除传统 Java Web 开发的不便,例如开发周期慢和配置过多。因此它更类似于脚本语言(PHP、Python、Ruby 等)的 Web 框架。
在底层,Play 构建在 Akka 工具包之上,该工具包简化了在 Java 虚拟机上创建并发和分布式应用程序。因此,Play 使用了完全异步的模型,可以带来更好的可扩展性,特别是因为它还遵循无状态原则。
Play 框架通过热代码重新加载、约定优于配置和浏览器中的错误消息等功能将开发人员的生产力放在首位。此外,它是一个响应式系统,遵循现代系统架构(响应式、弹性、弹性和消息驱动),以实现更灵活和容错的结果。
优点: - 轻量级 - 高可扩展性 - 异步核心 - 支持 Web 技术(REST、JSON、Web 套接字等) - 强大的开发人员工具 - 许多云部署选项 - 广泛的文档和活跃的社区
缺点:
向后兼容性问题(Play 1.x 与 Play 2.x 不兼容,而且 Play 2.x 的次要版本之间可能存在较小的兼容性问题)
PrimeFaces:Jakarta EE 和 Jakarta Server Faces 的 UI 框架
PrimeFaces 是一个流行的 Web 框架,用于为 Jakarta EE 和 Jakarta Server Faces(见上文)应用程序创建轻量级用户界面。许多财富 500 强公司、政府实体和教育机构都在使用它。
PrimeFaces 库是真正轻量级的。它被打包为单个 JAR 文件,需要零配置,并且没有任何依赖项。它允许您使用一组丰富的组件、内置的皮肤框架以及预先设计的主题和布局为 Java 应用程序创建用户界面。由于 PrimeFaces 建立在 Jakarta Server Faces 之上,因此它继承了其特性,例如快速应用程序开发。您还可以将框架添加到任何 Java 项目中。
在 PrimeFaces 网站上,您可以找到所有 PrimeFaces 组件、模板和主题的精彩展示。这些组件带有相关的代码片段,您可以快速复制/粘贴到您的应用程序中 - 或在必要时对其进行调整。例如,这是一个水平的巨型菜单,可让您一起显示根项目的子菜单。
PrimeFaces 还有一个主题设计器,它是一个基于 Sass 的主题引擎,具有 500 多个变量、一个示例主题和字体图标。如果您不想自己构建主题,您还可以下载社区主题或从 PrimeFaces 主题库购买高级主题。
优点: - 易于上手 - 稳定性(建立在 JSF 之上) - 支持移动功能(例如触摸优化组件) - 流行前端库的现成 UI 组件(例如,用于 Angular 的 PrimeNG、用于 React 的 PrimeReact 和 PrimeVue Vue)——预先设计的前端布局和模板(但是,不是免费的——价格从 39 美元起)
- 活跃的社区
缺点: - 掌握它需要时间(您需要了解 Jakarta Server Faces 才能正确使用 PrimeFaces)
Spark 框架:Web 应用程序和 REST API 的微框架
Spark 框架是用于 Java 和 Kotlin 编程语言的微框架和特定领域的语言。 Kotlin 在 Java 虚拟机上运行,并且与 Java 100% 可互操作。 Spark 可帮助您开发基于 Java 的 Web 应用程序、微服务和 REST API。
微框架首先出现在 Ruby 和 PHP 等脚本语言中,并由于其专注于开发速度和简单性而迅速获得关注。 Spark 的灵感来自 Ruby 的 Sinatra Web 应用程序框架,并于 2011 年首次发布。它不是 MVC 框架,但可以让您按照自己的方式构建应用程序。与大多数微框架一样,它的代码库很小,需要最少的配置,并且不需要您编写太多的样板代码。
您可以在几分钟内启动并运行 Spark 框架。默认情况下,它在嵌入到框架中的 Jetty Web 服务器上运行。但是,您也可以将它与其他 Java Web 服务器一起使用。根据 Spark 自己的调查,超过 50% 的用户使用该框架创建 REST API,这是其最受欢迎的用例。 Spark 还为每天为超过 10,000 名用户提供服务的高流量 Web 应用程序提供支持。
请注意,Spark 框架与 Apache Spark 不同,后者是用于大数据处理的分析引擎。
优点: - 轻量级 - 允许快速开发 - 需要很少的样板代码 - 声明性和表达性语法 - 无主见(您可以根据需要构建应用程序)
缺点: - 这些天开发不太活跃 - 教程和学习材料不多
Spring Framework:企业级Java应用框架
Spring 框架可能是最知名和最流行的 Java 框架,拥有庞大的生态系统和活跃的社区。它允许您构建企业级 Java 应用程序、Web 服务和微服务。
Spring 框架最初是一个依赖注入工具,但多年来它已经发展成为一个完整的应用程序框架。它为您提供了一个包罗万象的编程和配置模型,支持建立数据库连接和处理异常等通用任务。除了 Java,您还可以将框架与运行在 Java 虚拟机上的 Kotlin 和 Groovy 一起使用。
Spring 框架利用控制反转 (IoC) 软件设计原则,框架根据该原则控制自定义编写的代码(与传统编程相反,传统编程中自定义代码调用处理通用任务的其他库)。因此,您可以为 Spring 应用程序创建松散耦合的模块。
虽然 Spring 框架非常适合构建企业级 Java 应用程序,但它确实有一个陡峭的学习曲线。这是因为它是一个广泛的框架,旨在为可能出现企业级应用程序的每项任务提供解决方案,并且还支持许多不同的平台。因此,配置、设置、构建和部署过程都需要您可能不想处理的多个步骤,尤其是在您处理较小的项目时。 Spring Boot(Spring 框架的一个扩展)是解决这个问题的一个解决方案,因为它允许您更快地设置您的 Spring 应用程序,并且配置少得多。
优点: - 非常流行且非常稳定的框架 - 灵活的配置 - 松散耦合(由于依赖注入) - 易于测试应用程序(由于依赖注入) - 使用 POJO(普通旧 Java 对象) - 广泛的文档 - 活跃的社区
缺点: - 复杂性(高学习曲线) - 需要编写大量样板代码(除非您使用 Spring Boot)
Struts:用于企业级 Java 应用程序的 MVC 框架
Struts 是一个较旧的框架,仍然被许多开发人员使用。它是由 Apache Software Foundation 维护和开发的全功能 Java Web 应用程序框架。它是一个拥有庞大社区的可靠平台,通常与 Spring 框架相比。 Struts 允许您创建随着时间的推移易于维护的企业级 Java 应用程序。
它遵循 MVC 软件设计模式,并具有基于插件的架构。插件可以扩展框架以适应不同的项目需求。 Struts 插件是基本的 JAR 包,因此它们是可移植的,您也可以将它们添加到应用程序的类路径中。一些插件与框架捆绑在一起(JSON 插件、REST 插件、配置浏览器插件等),而您可以从第三方来源添加其他插件。
您可以将 Struts 与其他 Java 框架集成以执行未内置于平台中的任务。例如,您可以使用 Spring 插件进行依赖注入或使用 Hibernate 插件进行对象关系映射。 Struts 还允许您使用不同的客户端技术(例如 Jakarta Server Pages)来构建应用程序的前端。
但是,如果您想创建可以在前端渲染的服务器端组件,Struts 可能不是最好的选择。相反,您应该研究具有不同架构的框架,例如 Tapestry 或 Wicket(见下文)。
优点: - 稳定和成熟的框架 - 约定优于配置 - 可扩展(通过插件) - 易于与其他 Java 框架和工具集成 - 支持 Web 技术(REST、AJAX、JSON)
缺点: - 不提供任何安全机制(请参阅您需要自己申请的安全提示)
Tapestry:面向组件的高度可扩展应用程序框架
Tapestry 是一个基于组件的 Java 框架,您可以使用它创建可扩展的 Web 应用程序。它对可重用组件的关注使其在架构上类似于 Jakarta Server Faces 和 Wicket 框架。与 Struts 一样,Tapestry 也是 Apache 软件基金会的一个项目。
您可以将 Tapestry 页面和组件编写为普通的旧 Java 对象 (POJO),因此您可以从框架访问整个 Java 生态系统。除了 Java,Tapestry 还支持 Groovy 和 Scala,并与 Hibernate 和 Spring 等其他 Java 框架集成。 Tapestry 的构建考虑了性能;因此,它为您提供了诸如实时类重新加载、异常报告、Ajax 支持以及内置组件和模板等功能。
Tapestry 也是一个对开发人员友好的框架。它具有促进测试驱动开发 (TDD) 的内置实用程序,并支持 Selenium 测试框架。 Tapestry 在单个服务器和服务器集群上都可以很好地扩展。使用 Tapestry 构建的应用程序可以在浏览器中快速运行,因为它遵循客户端缓存、支持并发线程、JavaScript 聚合和压缩、集成 GZip 内容压缩等最佳实践。
优点: - 可扩展 - 易于测试 - 约定优于配置 - 组件是纯 Java 对象 - 带有预制组件 - 出色的异常报告
缺点: - 很难找到教程和学习材料
Vaadin:专注于 UX、可访问性和移动的 Web 应用程序框架
Vaadin 为简化的 Java 开发提供了一个平台。它允许您构建专注于性能、用户体验和可访问性的可定制组件的 Web 应用程序。
Vaadin 10+ 以全新的方式处理 Web 应用程序开发:它让开发人员可以直接从 Java 虚拟机访问 DOM(文档对象模型)。在新版本中,Vaadin 团队将以前的单一框架分成了两部分。它有一个名为 Vaadin Flow 的轻量级 Java 框架,用于处理路由和服务器-客户端通信,以及一组在用户浏览器中运行的 UI 组件。
这些组件是移动优先的,并遵循最新的网络和可访问性标准;它们是基于 Web Components 标准构建的。您可以将 Vaadin 组件与任何前端框架(例如 React、Angular 或 Vue)一起使用。创建者还推荐它们作为渐进式 Web 应用程序的构建块。您可以基于 Vaadin 组件构建自己的主题,也可以使用 Vaadin 的两个预制主题:Lumo(默认)和 Material。
Vaadin Flow 提供高级 Java API 来管理应用程序的所有技术方面,从服务器-客户端自动通信到 WebSocket 再到数据绑定。由于 Flow 在 JVM 上运行,您可以访问整个 Java 生态系统,例如,您可以使用 Spring Boot 运行您的应用程序。 Flow 还允许您使用 Kotlin 或 Scala 编写应用程序。
优点: - 使用独特的编程模型 - 遵循 Web 标准 - 适合移动设备的组件 - 可扩展(参见 Vaadin 目录) - 与 Spring 框架无缝集成 - Java 应用程序的预制主题(免费提供)
缺点: - Vaadin 是一家营利性公司,因此您需要为专业组件、工具和支持付费(参见定价)。
Vert.x:用于 Java 虚拟机的多语言事件驱动应用程序框架
Vert.x 是一个运行在 Java 虚拟机上的多语言框架。它允许您使用 Java、JavaScript、Groovy、Ruby、Scala 和 Kotlin 等编程语言编写应用程序。它的事件驱动架构使应用程序即使在硬件资源最少的情况下也能很好地扩展。
Vert.x 由 Eclipse 基金会开发和维护,其最著名的项目是 Eclipse IDE。 Vert.x 中的“x”指的是它的多语言特性,这意味着您可以用几种不同的语言编写有效的代码。它为每种受支持的编程语言提供惯用的 API。
由于 Vert.x 是一个事件驱动的非阻塞框架,它可以只使用最少数量的线程来处理大量并发。 Vert.x 也非常轻量级,核心框架仅重约 650 KB。它具有模块化架构,允许您仅使用所需的模块,以便您的应用程序尽可能保持流畅。如果您想构建轻量级、高度可扩展的微服务,Vert.x 是一个理想的选择。
优点: - 加载速度快 - 模块化架构 - 可扩展 - 不拘一格(您可以根据需要构建应用程序) - 易于使用的应用程序生成器 - 大量文档
缺点: - 高学习曲线(更多的是高级工具包而不是框架,因此您需要自己做出很多决定)
Wicket:面向纯粹主义者的基于组件的 Web 应用程序框架
Wicket 是一个基于组件的 Web 应用程序框架,类似于 Jakarta Server Faces 和 Tapestry。它允许您使用纯 Java 和 HTML 代码编写优雅、用户友好的应用程序。该框架由 Apache Software Foundation 维护,类似于 Struts 和 Tapestry。
由于 Wicket 是一个基于组件的框架,因此应用程序由可重用的页面和组件组成,例如图像、按钮、链接、表单等。它使用 POJO 数据模型,因此 Wicket 组件是普通的 Java 对象。组件被捆绑为可重用的包,因此您可以向它们添加自定义 CSS 和 JavaScript。
Wicket 通过为超过 25 种语言提供开箱即用的支持,让您的应用程序、页面和组件国际化。内置的 Ajax 功能允许您实时更新页面的某些部分,而无需编写任何 JavaScript 代码。 Wicket 也关注安全的 URL 处理。组件路径是会话相关的,并且 URL 不会泄露任何敏感信息。如果您想了解 Wicket 在现实生活中的工作原理,请查看使用 Apache Wicket 构建的博客,您可以在其中看到一些不错的示例。
优点: - 分离标记和逻辑 - 不需要 JavaScript 或 XML 配置文件 - 与标准 HTML 无缝集成 - 简单的状态管理(组件是 Java 对象维护它们的状态) - 您可以对前端代码进行单元测试
缺点: - 相对较小的社区;教程或学习资料不多
下一步
这是我们对 Java 框架比较的总结。由于这些框架中的每一个都有不同的用途,因此在为您的特定 Java 项目选择一个或多个框架之前,了解它们的优缺点和功能至关重要。
要选择正确的框架,您需要考虑您的目标(您想要构建什么?)、您的预算和团队的知识,以及其他因素。
- 5256 次浏览
【Java编程】JDK18:Java18中的新特性
Java开发工具包(JDK)18定于2022年3月22日发布。标准Java的新版本将有九个新特性,特性集已于12月9日冻结。
自1月20日起,该版本进入了第二个降级阶段,此前上个月开始了第一个降级阶段。标准Java的升级每六个月发布一次,最新的JDK17将于9月份发布。
OpenJDK页面列出了以下正式针对JDK 18的功能:服务提供商接口、简单web服务器、向量API、代码片段、核心反射的重新实现、UTF-8字符集、外部函数和内存API的第二个孵化器、switch语句模式匹配的第二个预览、,以及最后一次添加的对Finalization 的反对。
JDK18的候选版本将于2月10日和2月24日发布。虽然JDK 17是一个长期支持(LTS)版本,将获得Oracle至少八年的支持,但JDK 18将是一个短期功能版本,支持期为六个月。JDK18的早期访问版本可以在java上找到,用于Linux、Windows和MacOS。网
JDK 18提案的具体内容包括:
- finalization在将来的版本中被删除(Deprecate finalization for removal in a future release)。Finalizer 的缺陷会在安全性、性能、可靠性和可维护性方面造成重大的现实问题。它还有一个困难的编程模型。默认情况下,目前已启用Finalization ,但可以禁用以便于早期测试。默认情况下,它将在功能版本中禁用,并在以后的版本中完全删除。该提案要求使用命令行选项来禁用标准JavaAPI中所有Finalizer 和Finalization 方法的Finalization 和弃用。该提案的目标包括帮助开发人员理解定稿的危险,为最终删除定稿做好准备,并提供简单的工具来帮助检测对定稿的依赖。在Java1.0中引入的Finalization 旨在帮助避免资源泄漏。类可以声明Finalizer (受保护的void finalize()方法),其主体释放任何底层资源。垃圾收集器将在回收对象内存之前,计划调用不可访问对象的Finalizer ;反过来,finalize方法可以执行诸如调用对象的close之类的操作。这似乎是防止资源泄漏的有效安全网,但存在缺陷,包括不可预测的延迟,从对象变得不可访问到调用其Finalizer 的时间间隔很长;不受约束的行为,Finalizer 代码可以执行任何操作,包括恢复对象并使其再次可访问;Finalizer 始终处于启用状态,没有明确的注册机制;Finalizer 可以在未指定的线程上以任意顺序运行。考虑到Finalization 的问题,建议开发人员使用其他技术来避免资源泄漏,即尝试使用resources语句和Cleaner。(有关详细信息,请参阅JDK增强方案421。)
- 对于Internet地址解析SPI,建议为主机和名称地址解析定义一个SPI,以便
Inet.Address
可以使用平台内置解析器以外的解析器。这项工作的动机包括更好地支持ProjectLowe、Java中的并发性和新编程模型,以及集成新的网络协议、定制和启用测试。该提案不涉及为JDK开发替代解析器。 - switch模式匹配的第二个预览,其中Java语言将通过switch表达式和语句的模式匹配以及模式语言的扩展得到增强。这是在JDK 17中预览的。通过将模式匹配扩展到switch,可以针对多个模式测试表达式,每个模式都有一个特定的操作,因此可以简洁而安全地表达复杂的面向数据的查询。
- 使用方法句柄重新实现核心反射将重新实现lang.reflect。方法、构造函数和位于java之上的字段。调用方法句柄。将方法句柄用作反射的底层机制将降低java和java的维护和开发成本。lang.reflect和java。lang.invoke API。
- 使用简单的web服务器方案,将提供一个命令行工具来启动一个只提供静态文件的最小web服务器。没有CGI或类似servlet的功能可用。该工具将有助于原型设计、特殊编码和测试,特别是在教育环境中。该计划的目标包括提供一个开箱即用的静态HTTP文件服务器,具有简单的设置和最少的功能,减少开发人员的激活能量,使JDK更容易接近,并通过命令行提供一个默认实现,以及一个用于编程创建和定制的小API。提供功能丰富的或商业级服务器不是本提案的目标。
- 外部函数和内存API的第二个孵化,其中引入了一个API,通过该API,Java程序可以在Java运行时之外与代码和数据进行互操作。通过调用外部函数(JVM外部的代码)和安全访问外部内存(JVM不管理的内存),API允许Java程序调用本机库并处理本机数据,而不会出现JNI(Java本机接口)的脆弱性和危险性。其目的是用一个优秀的纯Java开发模型取代JNI。这个API是在JDK 17中培育出来的。对于JDK18,将根据反馈进行改进,例如支持更多载体,如内存访问变量句柄中的布尔和MemoryAddress,以及在内存段之间复制Java数组的新API。
- 向量API将在JDK 18中第三次孵化,之前在JDK 16和JDK 17中孵化过。该方案将在运行时编译的向量计算表示为支持的CPU架构上的最佳向量指令,实现优于等效标量计算的性能。向量操作表示一定程度的并行化,使更多的工作可以在单个CPU周期内完成,从而显著提高性能。平台无关矢量API旨在提供一种用Java编写复杂算法的方法,使用现有的热点自动矢量器,但使用一种用户模型,使矢量化更可预测。JDK18还将增加对ARM标量向量扩展平台的支持,并改进向量操作的性能,这些向量操作在支持硬件掩蔽的体系结构上接受掩蔽。
- 将UTF-8指定为标准JavaAPI的默认字符集。UTF-8是一种用于电子通信的可变宽度字符编码,被认为是web的标准字符集。字符集是一种字符编码,能够对web上的所有字符进行编码。通过此更改,依赖于默认字符集的API将在所有实现、操作系统、区域设置和配置中保持一致。该提案并不打算定义新的Java标准或JDK特定的API。该提案的支持者预计,Java选择UTF-8不会对许多环境中的应用程序产生影响,因为MacOS、许多Linux发行版和许多服务器应用程序已经支持UTF-8。但是,在其他环境中也存在风险,最明显的是,依赖默认字符集的应用程序在处理未指定默认字符集时生成的数据时会表现不正确。数据损坏可能会悄然发生。预计主要影响将落在亚洲地区Windows系统的用户身上,可能还会落在亚洲和其他地区的某些服务器环境上。
- JavaAPI文档中的代码片段,包括为JavaDoc的标准Doclet引入@snippet标记,以简化API文档中示例源代码的包含。该计划的目标之一是通过提供对源代码片段的API访问来促进源代码片段的验证。虽然正确性是作者的责任,但JavaDoc和相关工具中增强的支持可以使其更容易实现。其他目标包括启用现代样式,如语法突出显示,以及名称与声明的自动链接,以及更好地支持IDE创建和编辑代码段。该提案指出,API文档的作者经常在文档注释中包含源代码片段。
原文:https://www.infoworld.com/article/3630510/jdk-18-the-new-features-in-ja…
- 92 次浏览
Python开发
【Django 框架】Django 框架死了吗?
了解 Django 是否适合您的 Web 开发需求。
我已经学习了一些 JavaScript 和 Python,并且计划学习一个后端框架。我不知道我应该选择基于 Node.js 的框架还是基于 Django 的框架。我看到很多基于 Node.js 的框架得到了很多炒作。 Django 框架现在死了吗?
不,不是。 Django 被 StackOverflow 开发者调查选为 2021 年最受欢迎的 Web 开发框架,这意味着它在 2022 年具有巨大的潜力。我有很多 Django 开发者朋友,他们作为自由开发者或全职开发者做得很好。
如果你想知道 Django 是否适合你,你可以使用这些参数。
为什么使用 Django?
- 可扩展性:Django 因其缓存选项和代码可重用特性而具有可扩展性,使 Django 应用程序有效地处理流量需求。
- 安全性:默认情况下,Django 帮助开发人员避免许多安全问题,例如 SQL 注入、CSRF 攻击和 XSS。
- Added Battery:由于这个特殊功能,开发人员可以利用包来包含功能,而不是从一开始就编写代码。它节省时间,开发人员可以专注于其他应用程序领域。
- 异步编程:根据模型-视图-模板架构,基于 Python 的 Django 可以在任何地方运行,并支持反应式和异步编程。
- SEO 优化:基于 Django 的应用程序易于优化且对 SEO 友好,因为您可以通过 URL 而不是 IP 地址在服务器上维护它们。
- 快速开发:Django 使开发人员能够同时利用多个元素。您不必为任何新功能编写单独的代码。此外,它有助于快速创建 MVP。
- 更大的社区支持:Django 拥有一个拥有超过 2000 名开发人员的广泛社区。有了这样的帮助,您可以比以往更快地为您的问题找到最佳解决方案。
- 多功能用例:Django 提供了创建所有类型网站的范围,从 CMS(内容管理系统)到社交网络和新闻网站。
为什么不使用 Django?
- 您的项目/应用程序非常庞大,您无法将所有内容都保存在一个代码库中。
- 您可能希望将您的应用程序分解为微服务。每一层都可能由专门的团队和流程更好地处理。最好为每个用例使用不同的技术。 Django 可能会在某些特定的用例中有所帮助,但使用 Django(或单独的任何其他框架)开发所有东西可能并不明智。
- 你需要构建一个非常基本的应用程序,它不需要数据库、文件操作,甚至任何远程复杂的东西。
- 微框架更适合这些用例。 Flask 是用 Python 编写的最流行的微框架之一。类似的微框架可用于其他技术,例如。 PHP 中的 Slim、Java 中的 Apache Spark、Node.js 中的 Express.js 等。
- 如果您想从头开始构建所有内容,并且您知道自己在做什么。
- 您或您的团队成员根本不熟悉 Django/Python,而且您无法投入时间和资源来收集所需的技能。在这种情况下,最好的解决方案是使用您最了解的内容。如果你采用新的技术或框架,把事情搞砸的机会会增加很多倍。
所以…
Django 框架死了吗?
从来没有,我想它永远不会死。许多受欢迎的公司,如 Instagram、国家地理、Mozilla、Spotify、Pinterest、Disqus、Bitbucket 和 Eventbrite 都在使用 Django。相反,我会越来越受欢迎。
这里有一些 Django Web 开发领域可以帮助你快速完成项目……
我对使用 Django 的建议
但是,我再次告诉您,即使您想制作小型应用程序或非常基本的 Web 应用程序,也要选择 Django。 Django 开箱即用地完成了大部分工作。我们要做的任务是建模、查看和一些渲染。所以,Django 适合那些珍惜时间的人。
原文:https://python.plainenglish.io/is-the-django-framework-dead-591f9a533ba
- 57 次浏览
【Django 框架】关于 Django 4.0 你需要知道的 10 件事
Django 4.0 于 2021 年 12 月 7 日发布
Python 兼容性
Django 4.0 支持 Python 3.8、3.9 和 3.10。强烈推荐,并且仅官方支持每个系列的最新版本。
注意力:
Django 3.2.x 系列是最后一个支持 Python 3.6 和 3.7
关于 Django 4.0 你需要知道的那些事
1-您可以使用 Scrypt 密码哈希
新的 scrypt 密码散列器比 PBKDF2 更安全,推荐使用。但是,它不是默认设置,因为它需要 OpenSSL 1.1+ 和更多内存。
scrypt 与 PBKDF2 和 bcrypt 类似,它利用一定数量的迭代来减缓暴力攻击。但是,由于 PBKDF2 和 bcrypt 不需要大量内存,因此资源充足的攻击者可以发起大规模并行攻击,以加快攻击进程。与其他基于密码的密钥派生函数相比,scrypt 专门设计为使用更多内存,以限制攻击者可以使用的并行量。
要使用 scrypt 作为您的默认存储算法,
修改 PASSWORD_HASHERS 以首先列出 ScryptPasswordHasher。也就是说,在您的设置文件中:
PASSWORD_HASHERS = [ 'django.contrib.auth.hashers.ScryptPasswordHasher', 'django.contrib.auth.hashers.PBKDF2PasswordHasher', 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', 'django.contrib.auth.hashers.Argon2PasswordHasher', 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', ]
2-请求和响应
SecurityMiddleware 现在添加了值为 'same-origin' 的 Cross-Origin Opener Policy 标头,以防止跨域弹出窗口共享相同的浏览上下文。您可以通过将 SECURE_CROSS_ORIGIN_OPENER_POLICY 设置设置为 None 来防止添加此标头。
3- SecurityMiddleware 不再设置 X-XSS-Production 标头
如果 SECURE_BROWSER_XSS_FILTER 设置为 True,SecurityMiddleware 不再设置 X-XSS-Protection 标头。该设置被删除。
大多数现代浏览器不支持 X-XSS-Protection HTTP 标头。您可以使用 Content-Security-Policy 而不允许使用“不安全内联”脚本。
如果您想支持旧版浏览器并设置标头,请在自定义中间件中使用此行:
response.headers.setdefault('X-XSS-Protection', '1; mode=block')
4- CSRF-TOKEN
CSRF 保护现在会参考 Origin 标头(如果存在)。为此,需要对 CSRF_TRUSTED_ORIGINS 设置进行一些更改。
5- 通用视图
DeleteView 现在使用 FormMixin 来处理 POST 请求。因此,delete() 处理程序中的任何自定义删除逻辑都应移至 form_valid() 或共享辅助方法(如果需要)。
6- 表格
ModelChoiceField 现在包括在引发的 ValidationError 的 params 参数中为 invalid_choice 错误消息提供的值。这允许自定义错误消息使用 %(value)s 占位符。
BaseFormSet 现在使用额外的非形式类呈现非形式错误,以帮助将它们与特定于表单的错误区分开来。
BaseFormSet 现在允许自定义通过 can_delete 删除表单时使用的小部件,方法是设置 delete_widget 属性或覆盖 get_deletion_widget() 方法。
7-模型
新的 QuerySet.contains(obj) 方法返回查询集是否包含给定对象。这试图以最简单和最快的方式执行查询。
Round() 数据库函数的新精度参数允许指定舍入后的小数位数。
QuerySet.bulk_create() 现在在使用 SQLite 3.35+ 时设置对象的主键。
DurationField 现在支持 SQLite 上的标量值乘除。
QuerySet.bulk_update() 现在返回更新的对象数。
新的 Expression.empty_result_set_value 属性允许指定在函数用于空结果集时要返回的值。
MariaDB 10.6+ 现在允许使用 QuerySet.select_for_update() 的 skip_locked 参数。
查找表达式现在可以在 QuerySet 注释、聚合中使用,也可以直接在过滤器中使用。
内置聚合的新默认参数允许指定在查询集(或分组)不包含条目时返回的值,而不是 None。
8- 功能独特的约束
UniqueConstraint() 的新 *expressions 位置参数允许在表达式和数据库函数上创建功能唯一约束。例如:
from django.db import models from django.db.models import UniqueConstraint from django.db.models.functions import Lower class MyModel(models.Model): first_name = models.CharField(max_length=255) last_name = models.CharField(max_length=255) class Meta: constraints = [ UniqueConstraint( Lower('first_name'), Lower('last_name').desc(), name='first_last_name_unique', ), ]
使用 Meta.constraints 选项将功能唯一约束添加到模型中。
9- 模板
基于模板的表单渲染
现在使用模板引擎呈现 Forms、Formsets 和 ErrorList 以增强自定义。请参见 Formset 的新 render()、get_context() 和 template_name 和 Formset 渲染。
floatformat 模板过滤器现在允许使用 u 后缀来强制禁用本地化。
10-管理命令
runserver 管理命令现在支持 --skip-checks 选项。
在 PostgreSQL 上,dbshell 现在支持指定密码文件。
shell 命令现在在启动时尊重 sys.__interactivehook__。这允许在交互式会话之间加载 shell 历史记录。因此,如果在隔离模式下运行,则不再加载 readline。
新的 BaseCommand.suppressed_base_arguments 属性允许在帮助输出中抑制不支持的默认命令选项。
新的 startapp --exclude 和 startproject --exclude 选项允许从模板中排除目录。
原文:https://aliarefwriorr.medium.com/top-10-things-you-need-to-know-about-d…
本文:https://jiagoushi.pro/top-10-things-you-need-know-about-django-40
- 26 次浏览
【Python 开发】2022 年开始使用的 3 个 Python 包
1.Mito
Mito 是 Python 的电子表格界面——你可以在你的 Python 环境中调用 Mito,你在电子表格中所做的每次编辑都会在下面的代码单元格中生成等效的 Python。 想象一下,如果你在 Excel 中所做的一切都可以生成 Python 代码——那就是 Mito。
为 Mito 安装命令:
python -m pip install mitoinstaller python -m mitoinstaller install
然后打开 Jupyter Lab 并调用 Mitosheet
import mitosheet mitosheet.sheet()
完整的说明可以在 Mito 网站的“docs”下找到。
Mito 是一种快速完成数据科学任务的快速方法,无需完美的语法——Mito 为您编写代码。
功能包括:
- 绘图
- 数据透视表
- 过滤器
- 合并
- 排序
- 汇总统计
- 导入和导出 Excel 文件
- 去重
- 添加和删除列
- 编辑特定单元格
- 和更多!
2. Plotly
Plotly 是 Python 的开源图形库。 他们的图表涵盖了一些特定领域的领域,例如金融和地理——这将它们与像 Matplotlib 这样的包区分开来。 Plotly 专注于允许用户创建交互式图表。 这些图表不仅允许创建者从数据中展示他们的见解,而且还允许查看者做出自己的见解。
您可以使用以下命令安装 Plotly:
$ pip install plotly==5.5.0
这是最简单的 Plotly 图表之一的示例:
import plotly.express as px fig = px.bar(x=["a", "b", "c"], y=[1, 3, 2]) fig.show()
在图像中很难看到,但在笔记本中,如果您将鼠标悬停在此图表上,您将有许多选项与此图表进行交互,包括放大数据和导出为 PNG。
从下面的示例中可以看出,Plotly 提供了各种易于使用但功能强大的图表。
3.Streamlit
Streamlit 旨在快速构建数据应用程序。 近年来,将“应用程序”作为内部和外部业务工具的想法广受欢迎(我可以为此写一个完整的博客!)。 似乎它们的崛起与 Mito 和 Plotly 等低代码/无代码工具的兴起同步并可能受到了刺激,这些工具允许较少技术用户进入数据科学领域。
这是来自 Data Professor 的关于 Streamlit 的演示。
要导入 Streamlit,请运行以下命令:
import streamlit as st
Streamlit 还具有“组件”,它们是可用于您的应用程序和仪表板的第三方功能。 例如,您可以在 Streamlit 中使用 AGgrid、Bokeh 或 Pandas Profiling。
以下是他们网站上的一些 Streamlit 应用程序示例:
您可以在 Github 上为 Streamlit 加注星标,请点击此处。
我希望这些软件包对您有所帮助。 他们三人的共同点是,他们都明白数据科学和 Python 在传统数据科学团队之外的应用越来越广泛。 营销人员、销售专家、运营专家、财务专家以及介于两者之间的每个人都已经在与数据科学工作流程进行交互。 这些工具可帮助技术和非技术受众聚集在一起,共同推动数据科学向前发展 :)
原文:https://medium.com/trymito/3-python-packages-to-start-using-in-2022-42f…
本文:
- 30 次浏览
【Python开发】Python 3.10 发布——你应该知道的 5 大新特性
Python 已经在市场上出现了很长一段时间,作为一名 Python 开发人员,我很高兴能与大家分享 Python 正在逐步更新并随着每个新版本的发布而改进。
Python 的最新版本 3.10 有一些重大改进,我将在此处列出这些更新。 我在下面捆绑了与这个新版本的 Python 一起发布的前 5 个新更新。
1.改进的错误信息
这个很大。 对于 Python 开发人员,当您编写代码并遇到错误时,错误消息可以帮助您找出代码中的错误。 与使用以前的 Python 版本相比,改进的错误消息使您的生活更加轻松。
例如,考虑以下代码,其中第二行末尾没有括号:
# I am coding in Python and this is first line ;) my_list = ["Hello", "Python!" print(my_list)
在以前的版本中——Python3.9 和更早的版本,你会看到如下错误——
File "my_precious.py", line 3 print(my_list) ^ SyntaxError: invalid syntax
嗯,语法无效! 现在,作为开发人员,您从这个错误消息中理解了什么? 好吧,就我个人而言,除了在第 3 行的某处添加了错误的语法这一事实之外,我什么都不明白。
但是,错误真的在第 3 行吗?
Python 3.10 是这种情况下的救星,它的最新更新。 对于同一段代码,Python 3.10 将抛出以下错误消息——
File "my_precious.py", line 2 news = ["Hello", "Python!" ^ SyntaxError: '[' was never closed
呜呼! 行号和非常具体的错误消息将允许您直接进入,修复错误并继续编码!
我个人尝试查看错误消息是否足够清晰的另一个示例 -
# missing_comma.py dc_characters = { 1: "Superman" # Comma missing 2: "Batman", 3: "Joker" }.... Output: File "dc_characters.py", line 4 10: "October" ^^^^^^^^^ SyntaxError: invalid syntax. Perhaps you forgot a comma?
这确实是 Python 3.10 版本中的一个很酷的更新,请在本文的评论部分分享您的想法。
2. 更简单的联合类型语法
Typing 模块用于向 Python 添加静态类型。 在过去的 Python 版本中,更多的工具已经从类型转移到内置功能,以避免每次都必须导入静态类型。
现在让我们看看这里到底发生了什么变化——
# Before Python 3.10 Release from typing import Union def f(list: List[Union[int, str]], param: Optional[int]): pass# In Python 3.10 Release def f(list: List[int | str], param: int | None): pass# Calling the function f([1, "abc"], None)
在 Python 3.10 中,现在您可以使用管道运算符 (|) 来指定类型联合,而不是从类型模块中导入联合。
此外,现有的 typing.Union 和 | 语法应该与下面的比较相同 -
int | str == typing.Union[int, str] typing.Union[int, int] == int int | int == int
3. 跨多行使用多个 `with` 语句
Python 确实通过使用反斜杠 (\) 来支持多行语句,但是 Python 中的一些结构不应该要求使用斜杠来编写多行语句。 其中之一是具有多行 with() 语句的上下文管理器。 例如 -
# Before Python 3.10 Releasewith (open("a_really_long_foo") as foo, open("a_really_long_bar") as bar): pass Traceback (most recent call last): File "<input>", line 1, in <module> File "demo.py", line 19 with (open("a_really_long_foo") as foo, ^ SyntaxError: invalid syntax
是的,这看起来不像是一项功能,但它是对先前版本的一项重大改进,因为您可能遇到过使用多行上下文管理器的用例,但由于上述错误而无法做到这一点。
如果您仍然感到困惑,让我们举更多示例来说明您可以在 Python 3.10 版本中使用上下文管理器做什么——
# After Python 3.10 Releasefrom contextlib import contextmanager @contextmanager def f(x): try: yield x finally: pass# Example 1 with f('c') as a, f('a') as b: pass# Example 2 with f('c') as a, f('a') as b, f('a') as c: pass
您现在可以拥有多行上下文管理器语句,而无需使用反斜杠。 很棒吧?
4. 更好的类型别名
类型别名允许您快速定义可以为复杂类型声明创建的新别名。 例如 -
# Before Python 3.10 UserInfo = tuple[str, int]
这通常可以正常工作。 但是,类型检查器通常不可能知道这样的语句是类型别名还是只是常规全局变量的定义。
# In Python 3.10from typing import TypeAlias Card: TypeAlias = tuple[str, str] Deck: TypeAlias = list[Card]
上面的 python 代码为 tuple[str, str] 声明了一个别名 UserInfo,因为它是一种组合了多种类型值的数据类型。 在我们的例子中,它是一个字符串和一个整数。 此外,添加 TypeAlias 注释可以澄清意图,无论是对类型检查器还是对任何阅读您的代码的人。
5. 更严格的序列压缩
zip() 是 Python 中的一个内置函数,您可能在组合多个列表/序列时使用过它。 Python3.10 引入了新的 strict 参数,它添加了一个运行时测试来检查所有被压缩的序列是否具有相同的长度。
例如 -
# Before Python 3.10 names = ["Tom", "Harry", "Jessica", "Robert", "Kevin"] numbers = ["21024", "75978", "92176", "75192", "34323"]
zip() 可用于并行迭代这三个列表:
list(zip(names, numbers))..... Output: [(Tom, 21024), (Harry, 75978), (Jessica, 92176), (Robert, 75192), (Kevin, 34323)]
让我们再次使用上面显示的这两个序列的名称和编号。 现在,这些序列之间的唯一区别是数字与序列名称的长度不同,如下所示 -
# Before Python 3.10 names = ["Tom", "Harry", "Jessica", "Robert"] # Kevin is missing numbers = ["21024", "75978", "92176", "75192", "34323"]# Zipping using zip() list(zip(names, numbers))...... Output [(Tom, 21024), (Harry, 75978), (Jessica, 92176), (Robert, 75192)]
请注意,关于名字的所有信息——凯文消失了!
如果您的数据集更大,则很难发现此类错误。 即使你发现有问题,诊断和修复也并不总是那么容易。
被压缩的序列将具有相同长度的假设不仅可以帮助您避免这种差异。
在 Python 3.10 中,strict 参数可以帮助您在一开始就避免这种情况——
# In Python 3.10 names = ["Tom", "Harry", "Jessica", "Robert"] # Kevin is missing # Zipping using zip() with additional Parameter strict=True numbers = ["21024", "75978", "92176", "75192", "34323"] list(zip(names, numbers, strict=True)).... Output: Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: zip() argument 2 is shorter than argument 1
虽然 strict 并没有真正为 zip() 添加任何新功能,但它可以帮助您避免那些难以发现的错误。
Python 3.10 中的其他更新
这个版本有很多错误修复和一些其他小更新,如果您有兴趣,可以在官方发布页面上找到
原文:https://blog.varunsingh.in/python-3-10-released-top-5-new-features-you-…
- 26 次浏览
【Python开发】Python中的多处理
- Why Python Multiprocessing
- 在 Python 中,单 CPU 使用是由全局解释器锁 (GIL) 引起的,它在任何给定时间只允许一个线程携带 Python 解释器。实现 GIL 是为了处理内存管理问题,但因此,Python 仅限于使用单个处理器。
- 模块的多处理允许程序员充分利用给定机器上的多个处理器。使用的 API 类似于经典的线程模块。它提供本地和远程并发。
- 多处理模块通过使用子进程而不是线程来避免全局解释器锁 (GIL) 的限制。多处理代码的执行顺序与串行代码不同。不能保证第一个创建的进程将是第一个完成的。
为什么多处理有用?
计算从 1 到 1000 的所有数字的最快方法是什么?
- Python 一次只使用一个内核来工作。想想在解决一个简单的数学问题时做什么更快。
- 通过将结果一一相加,并以递增方式将总和相加(1+2=3、3+3=6,6+4=1000,依此类推)。一个核心正在处理这项任务。
- 预先将值拆分为单独的块,然后先将那里的值相加(1 到 300、301 到 600 和 601 到 1000)。三个核心将同时工作(最后一步是将收到的三个值相加)。
一个好的起点是了解 Python 中的多处理库是如何工作的。
你应该使用什么?
- 如果你的代码有很多 I/O 或网络使用:多线程是你最好的选择,因为它的开销很低
- 如果你有一个 GUI:多线程,这样你的 UI 线程就不会被锁定
- 如果您的代码受 CPU 限制:您应该使用多处理(如果您的机器有多个内核)
多处理示例
- Multiprocessing 是一个使用类似于 threading 模块的 API 支持生成进程的包。
- multiprocessing 包提供本地和远程并发,通过使用子进程而不是线程来有效地避开全局解释器锁。
- 因此,模块的多处理允许程序员充分利用给定机器上的多个处理器。 它可以在 Unix 和 Windows 上运行。
- 这个使用 Pool 的数据并行的基本示例,
from multiprocessing import Pool def f(x): return x*x if __name__ == '__main__': with Pool(5) as p: print(p.map(f, [1, 2, 3]))
将打印到标准输出:
[1, 4, 9]
进程类
在多处理中,进程是通过创建一个 Process 对象然后调用它的 start() 方法来产生的。 进程遵循threading.Thread的API。 多进程程序的一个简单示例是
from multiprocessing import Process def f(name): print('hello', name) if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() p.join()
为了显示所涉及的各个进程 ID,这是一个扩展示例:
from multiprocessing import Process import os def info(title): print(title) print('module name:', __name__) print('parent process:', os.getppid()) print('process id:', os.getpid()) def f(name): info('function f') print('hello', name) if __name__ == '__main__': info('main line') p = Process(target=f, args=('bob',)) p.start() p.join()
过程和例外:
- run():方法代表进程的活动。
- start():启动进程的活动。
- join([timeout]):如果可选参数 timeout 为 None(默认值),则该方法将阻塞,直到调用该方法的 join() 的进程终止。
- 名称:进程的名称。该名称是一个仅用于识别目的的字符串。
- is_alive():返回进程是否存活。
- terminate():终止进程
- kill():与 terminate() 相同,但在 Unix 上使用 SIGKILL 信号。
- close():关闭 Process 对象,释放与之相关的所有资源。
- 异常 multiprocessing.ProcessError:所有多处理异常的基类。
- 异常 multiprocessing.BufferTooShort:当提供的缓冲区对象太小而无法读取消息时,Connection.recv_bytes_into() 会引发异常。
- 异常 multiprocessing.AuthenticationError:出现身份验证错误时引发
- 异常 multiprocessing.TimeoutError:超时到期时由具有超时的方法引发
管道和队列
当使用多个进程时,通常使用消息传递来进行进程之间的通信,并避免使用任何同步原语,如锁。
对于传递消息,可以使用 Pipe()(用于两个进程之间的连接)或队列(允许多个生产者和消费者)。
结论
- 如果没有多处理,Python 程序会因为 GIL(全局解释器锁)而无法最大化系统的规格。
- 多处理允许您创建可以同时运行的程序(绕过 GIL)并使用整个 CPU 内核。 虽然它与线程库根本不同,但语法非常相似。 多处理库为每个进程提供了自己的 Python 解释器和自己的 GIL。
- 因此,与线程相关的常见问题(例如数据损坏和死锁)不再是问题。 由于进程不共享内存,因此它们不能同时修改相同的内存。
谢谢阅读。 如果您觉得这篇文章有用,请不要忘记鼓掌并与您的朋友和同事分享。 如果您有任何问题,请随时与我联系。
原文:https://hiteshmishra708.medium.com/multiprocessing-in-python-c6735fa70f…
- 29 次浏览
【Python架构】在 Python 中使用架构模式管理复杂性
你的源代码是不是感觉像一个大泥球?依赖项是否在您的代码库中交织在一起,以至于改变感觉很危险或不可能?
随着业务的增长和领域模型(您在应用程序中解决的业务问题)变得更加复杂,我们如何在不从头开始重新编写所有内容的情况下解开我们创建的混乱?更好的是,我们如何避免一开始就陷入混乱?
鸟瞰图
以下是 Python 架构模式中介绍的技术的简要总结:
分层架构
- 单一职责
- 视图 vs 服务 vs 存储库 vs ORM vs 域
- 依赖倒置
- 高级与低级模块
- 抽象
领域驱动设计
- 先说“业务上下文”
- 领域建模(事件风暴等)
- 实体 vs ValueObjects vs 域服务
- 数据类
测试驱动开发
- 什么是TDD
- 在服务层进行高速测试
- 在域中进行低速测试
设计模式
- 存储库模式
- 服务层模式
- 工作单元模式
- 聚合模式
事件驱动架构
- 活动
- 消息总线
- 事件处理程序作为服务层
- 时间解耦
- 队列和代理
- 幂等性、故障和监控
- 命令
- CQRS
- 简单读取与复杂命令
- 非规范化、缓存和最终一致性
我将简要介绍这些主题中的每一个,但我不会在这篇博文中重新打印这本书。这些将是我自己的话和我的解释,所以如果你想要“真正的交易”,我建议你去源头找一本这本书:)
分层架构
A simplified summary of Layered Architecture
- SOLID 原则大量存在于良好的设计中。简而言之,如果您不知道,我将解释这些是什么。 S,Single Responsibility,意味着代码应该有一个改变的理由,而且只有一个理由。 O,对于 Open-Closed,意味着您的代码应该对扩展开放但对修改关闭。 L,对于 Liskov Substitution,意味着子类的实例可以在不改变行为的情况下替换其父类的用法。我,对于接口隔离,意味着你的代码不应该被迫实现它不使用的行为。最后,D,表示依赖倒置,意味着一种松散耦合。
- 单一职责是分层架构背后的动机。也就是说,您的 Django 视图负责处理 HTTP 事务——获取输入、发送输出和状态码。这些视图应该委托给编排业务逻辑的服务。服务实现用例并且应该依赖于围绕低级细节的抽象,这些抽象可以包括存储库(用于存储抽象)和工作单元(用于事务或原子操作管理)。
- 这些层(视图、服务、存储库/UoW)从您的业务与特定用例/端点/网页相关的高层开始。然后他们使用抽象层直到我们写入数据库(在存储库中)或与其他系统通信等的低级操作。这就是依赖倒置的原理。
- 依赖倒置原则有两个部分。首先,高级模块不应该依赖于低级模块,两者都应该依赖于抽象。其次,抽象不应该依赖于细节,而细节应该依赖于抽象。因为这是一个如此复杂的话题,我不会详述它,如果你有兴趣,我建议你在这里、这里、甚至在本书中找到更好的阅读材料!
领域驱动设计
source: https://pixabay.com/photos/engineer-engineering-4941336/
也称为 DDD。成为您领域的主人!什么是域?好吧,实际上,这取决于您要解决的业务问题!不,我不是在开玩笑。这实际上取决于 - 域的定义是您要解决的业务问题!
也就是说,如果您在一家航运公司工作,那么当您为您的域建模时,您会发现您可能有“ShippingContainers”和“Ships”或“Trucks”等。您可能有“SalesReports”和“PackingManifests” ”。但是,如果你要为一家软件公司工作,那么这些域对象就没有多大意义,你将拥有一个完全不同的域模型。
找出你的领域模型的过程被称为……“领域建模”。您可以为此使用几种不同的技术,我最喜欢的技术之一是“事件风暴”(https://eventstorming.com/)。不过,基本上,TLDR 是您需要与利益相关者(需要解决问题的人)坐下来弄清楚他们使用的语言。写下名词和动词,将它们连接在一起,并弄清楚你的领域是如何工作的。做对了,它会使剩下的过程变得更容易。
然后,您需要将此域模型转换为实际代码。出于我们的目的,我们专注于“实体”和“值对象”——区别在于实体具有永久身份(例如 ID 字段),而值对象根据其……嗯……值……来改变身份。例如,“用户”将有一个 ID 字段,您可以在不更改实际用户的情况下更改用户的电子邮件。然而,ValueObject 类似于地址。如果你改变地址的值,你就有了一个新的地址!看看它是如何工作的?
你可以很简单地使用“@dataclass”在 python 中表示你的域模型,它为你设置了你的构造函数和其他一些简洁的东西。这可以为您提供一个非常简单的对象,该对象仅用于存储特定属性(例如,城市、州、zip 或名字、姓氏等)。然后您可以从您的存储库中返回这些对象,并且您将有一个一致的结构来传递您的应用程序。让您的领域模型通过 ID 相互引用并根据需要进行水合,可选择存储在缓存中,然后您就可以参加比赛了。
测试驱动开发
The “Testing Pyramid” with explanations
对于某些人来说,TDD 是一个有争议的话题。如果你不熟悉,TDD 的基本前提是只有三个规则:
- 除非您的测试失败,否则您不得编写任何代码。
- 你一次只能写一个测试用例,它应该开始失败。
- 一旦你有一个失败的测试,你应该只写足够的代码来使测试通过。
而已。然后你重复。人们说这个完整的循环是一个 30 秒的过程——我怀疑他们练习它的时间比我多一点。这也被称为“进攻性”测试,而不是我们都习惯的“防御性”测试——也就是说,防御性测试是在事后编写测试以“保护”自己。防御性测试可以为您提供一些保护,但要获得高覆盖率要困难得多。进攻性测试为您提供 100% 的覆盖率,并*迫使*您使用抽象等编写可测试的代码。
也就是说,TDD 不是灵丹妙药。它不是一种宗教。有(很少)TDD 不起作用的情况。 TDD 也不会阻止您编写错误或编写糟糕的代码(您仍然也可以编写糟糕的测试)。考虑到这一点,重要的是通过在可能时以“高速档”进行测试并在必要时以“低速档”进行测试,从而最大限度地提高测试的价值。
高速档与低速档测试是本书中讨论的一个概念。总而言之,“高级”是指您在服务层或使用其他高级模块编写测试(参见上面的“分层架构”)。它们往往涵盖更多代码,并且最适合添加新功能或修复简单错误。 “低档”测试是在域级别和其他低级别模块。当面临特别困难的错误或进行非常大的重构时,低档是最好的。
设计模式
A simple layout of the design patterns we talk about
有很多设计模式值得了解。其他一些书籍,如“设计模式:可重用面向对象软件的元素”涵盖了其中的几本。 Python 中的架构模式特别关注四种模式:存储库模式、服务层模式、工作单元模式和聚合模式。
存储库是围绕您的存储机制的抽象。您可以为 Redis、CSV 文件、数据库等创建一个存储库。它们都可以满足一个通用接口,如果您真的愿意,您可以将一个交换为另一个。目标是抽象出低级细节,以便您的高级模块不依赖于低级细节。这对于分层架构很重要,这也是本书广泛使用存储库模式的原因。
服务层只是您的业务逻辑的编排。当您第一次开始编写 API 端点时,倾向于将所有业务逻辑放在一个处理 API 请求的函数中。这违反了单一职责原则,因为 API 端点处理程序现在负责管理 HTTP 输入、响应以及业务逻辑的所有各个方面,如创建用户、验证输入、登录等。这些较低级别(尽管不是最低级别)任务可以委托给每个用例都有方法的服务。也就是说,该服务将具有注册用户、登录用户等的方法。这些方法将调用存储库并接收回域对象。
工作单元用于原子操作。想想“数据库事务”和“锁”,通常封装相关的操作。如果您需要“预订酒店房间”,那么您可以有一个包含此逻辑的“工作单元”。如果在查找可用房间并将房间分配给某人并处理此人的付款信息期间发生某种错误,那么工作单元将很好地为您回滚所有这些逻辑。您可以依赖低级别的数据库事务(并且您的工作单元可能在后台执行此操作),但是在您的服务函数中内联该逻辑开始混淆您的代码。使用工作单元来处理这些原子操作提供了一个干净的接口,可以利用 Python 强大的“with”语句并根据需要在您之后自动清理。
聚合是具有共同一致性边界的领域对象的集合。购物车之类的东西可以是一个聚合体——购物车内有几个领域对象,甚至购物车内可能还有其他聚合体。但是,在结账时,将购物车视为一个单元是很有用的。您可以将聚合视为对象树,并且可以通过根来引用聚合。
关于聚合的另一个注意事项是每个存储库应该有一个聚合。换句话说,您不应该拥有不是聚合的域对象的存储库。这样,聚合就形成了领域模型的“公共”API。
事件驱动架构
Simplified overview of Event Driven Architecture and CQRS
简而言之,EDA 就是您使用“事件”作为系统的输入。事件(或领域事件)是一个 ValueObject,您可以有内部和外部事件。内部事件永远不会离开您的系统,通常由消息总线(将事件映射到事件处理程序的简单路由器)之类的东西处理。外部事件被发送到其他系统并且非常适合“时间解耦”——您可以向消息代理发出事件,该消息代理异步管理一系列队列工作程序。
所有事件都可能失败,我们如何处理失败很重要。我们需要监控以了解事件何时失败以及哪些事件失败。我们还需要我们的事件处理程序是幂等的,所以当我们重试事件时,不会发生任何意外。常规事件可以在不影响整体操作的情况下安全地失败,这是事件和命令之间的重要区别。
命令是一种特殊类型的事件。一个常规事件可以有多个处理程序,而一个命令只有一个处理程序。一个命令,当它失败时,应该将异常重新抛出堆栈,而当一个事件失败时,应该有一些优雅的异常处理。命令通常会修改数据并触发副作用,将其与“返回数据”操作分开是 CQRS(Command/Query Responsibility Segregation)的目标。
CQRS 背后的主要动机是命令昂贵且复杂,通常需要一定程度的原子性以及即时一致性。另一方面,查询是简单的读取操作。查询通常不依赖于域(业务逻辑),而命令通常依赖于域。可以针对只读副本执行查询,其中命令通常最好针对主数据存储执行。查询还可以利用非规范化数据和最终一致性。这很好,因为查询通常比命令多几个数量级,这有助于系统更好地扩展。
应用所有这些
总而言之,重要的是逐个进行。您无需一次完成所有这些操作。如果您对尝试工作单元犹豫不决,或者您没有立即使用聚合,或者您甚至没有领域模型,那没关系!您可以从使用分层架构开始的最简单和最有效的事情之一 - 看看您是否可以使用服务将较低级别的模块与较高级别的模块解耦。看看您是否可以将您的存储逻辑隔离到您的服务使用的存储库中。如果您还可以绘制一些简单的数据类来表示您的域对象并让您的 ORM 依赖于这些,那就更好了。
如果您将依赖于自身的逻辑组合在一起,并使用抽象将模块分开,那么您将成为其中的一部分。查看接缝的位置并开始将代码拆分为可测试的块。有关这方面的一些优秀示例,请查看“有效地使用遗留代码”,这本书既是一本好书,又被“Python 中的架构模式”引用。
哦,如果您还没有阅读“Python 中的架构模式”,请特别注意结尾部分!这将为您提供更多关于我上面提到的所有内容的背景信息。我用大约 5 页总结了一本 300 多页的书,所以肯定有一些东西我遗漏了 :)
原文:https://klaviyo.tech/managing-complexity-with-architecture-patterns-in-…
- 270 次浏览
【数据科学家】无需花费一分钱即可成为数据科学家的完整路线图
今天我想分享一下我是如何在 16 岁成为一名专业的数据科学家的。我的旅程长达两年,但这篇文章并不能结束我的整个旅程。
在这篇文章中,我将分享我的旅程以及我在此过程中犯的所有错误,这样你就不会再犯那些错误了
学习基础
第 1 步:学习 Python
有人说你应该学习数据科学所需的数学。但我建议你应该先学习一门编程语言(如 Python、R)。我现在不会说为什么。不过后面会讲。
为什么选择 Python?:我建议学习 Python,因为它比 R 更广泛使用。
我使用的资源:
学习 Python — 初学者完整课程 [教程]
这是我用来学习Python的。我之所以更喜欢 Mike Dane 的教程,是因为他解释得非常清楚,而且风格惊人。
但我很快会在我的频道 DataBeast 中发布一个完整的初学者教程(即使是小孩子)
但是仅仅通过这个不会帮助你学到很多python,你应该练习它。有一个网站叫做 HackerRank。解决其中的问题。这就是你学习 Python 的全部内容
第 2 步:学习数学
您需要学习几个主题。我知道对某些人来说“数学刺痛”。但不要担心,尽可能多地学习。但它并不比我们想象的要难。主要是统计,概率,有时是线性代数和微积分。但我敢打赌这会很容易。
以下是我比较喜欢的课程:
如果您是青少年或不太了解这些主题的基础知识,我更喜欢您使用可汗学院,您可以在那里学习所有基础知识。然后我更喜欢采取:
- 概率与统计:概率与统计:到 p 还是不到 p? coursera 中的课程。我知道这门课程是付费的,但只有在您需要证书时才付费。我负担不起价格,所以我只是审核课程(您不必为此花一分钱)
- 线性代数:线性代数 - 完整的大学课程 - YouTube
- 微积分:来自 coursera 的微积分入门。这是一个了不起的课程。它几乎教会了你很多你需要的东西。那么你需要参加这门课程。
- 机器学习数学:多元微积分
我的学习建议是用 Python 编写你学到的东西(数学)。
我将很快发布我自己的教程,从基础到高等数学。
为此,请点击 Medium 以及我的 YouTube 频道 DataBeast 上的订阅按钮。启用通知铃以查看我何时发布视频
这是我犯第一个错误的地方:我没有给予太多关注。但有时它非常重要。
数据科学基础
第 3 步:用于数据科学的 Python 库
Python 有一些用于数据科学的库,称为 NumPy、Pandas 等……。我们也需要熟悉它们
用于数据科学的 Python |伟大的学习
这是我个人喜欢的教程之一。她从基础开始涵盖每一个概念
第 4 步:数据科学工具
这是我的第二个错误 我并不真正关心这些人
- SQL:SQL 教程 - 面向初学者的完整数据库课程
- MongoDB:MongoDB 初学者教程 |完整课程
第 5 步:机器学习
ML 是不需要任何介绍的东西。 ML 是数据科学中最重要的部分之一,也是研究人员中最热门的研究课题,因此每年都会在这方面取得新的进展。
这是我认为最适合机器学习的唯一课程:机器学习(Coursera,审核课程不会花费您,但不会获得证书)。这门课程很棒,并提供了扎实的基础知识。但是所有这些都是在MATLAB上学的,所以你需要在python中做
所以我更愿意再次参加这门课程:免费 10 小时机器学习课程 - freeCodeCamp
这是您需要开始练习的时期。
我建议在 Kaggle 上创建一个帐户并开始练习。
Kaggle 有很多数据集,拿走这些数据集,操作后应该洗手。通过一些机器学习来运行它
第 6 步:深度学习
事情变得有趣起来。深度学习是我在整个旅程中学到的最喜欢的东西。这绝对是辉煌的。您真正使用以前学过的数学的地方。
我强烈建议参加斯坦福的 CS230 讲座。在我看来,这让我们的手很脏。但是您需要学习如何更专业地编码。有两个流行的深度学习框架,名为 TensorFlow 和 PyTorch。我个人更喜欢学习 PyTorch,因为它更动态,而且 PyTorch 代码比 TensorFlow 更容易为更难的问题编写代码。
要学习 PyTorch,我更喜欢这门课程:PyTorch for Deep Learning — Full Course / Tutorial — YouTube
在此之后开始做 Kaggle 比赛。第一次获胜会非常困难,但如果你输掉比赛并从他们的解决方案中学习,你就能获胜。
原文:https://medium.com/@mrizin2013/a-complete-roadmap-to-become-a-data-scie…
- 63 次浏览
【编程语言】Python不是未来的编程语言
由于它在过去的十年中越来越受欢迎,人们可以想象它是一种语言,它是在这个千年的同一开始开发的。 事实并非如此:它的起源可以追溯到 1980 年代中期,当时它首次被引入。 Guus van Rossum 是 CWI(荷兰政府赞助的研究中心)的一名研究人员,同意在 1989 年 12 月推出该项目,作为一项业余爱好,他开发了一个 工作。 该项目的实施于当月开始。
它因范罗苏姆对巨蟒喜剧团的钦佩而得名,其设计的重点是使其易于使用和理解,同时不影响其特性和功能。 可供公众使用的硬件资源稀缺是其在推出时缺乏知名度的主要原因。
硬件技术的进步为产品的普及提供了必要的保障。但是,随着人工智能、数据学习、数据科学学习以及数据科学的发展,来自不同来源的大数据的大量增加,作为员工的一个新的体验,已经完全改变了数据科学。
许多工具已经出现,并且是由数据科学和机器学习科学所使用的,它们都是用Python编写的,或者是用Python之类的语言编写的,以便与thém进行交互,使thém更容易与thém一起工作。
让我们分析一下为什么Python现在很流行
Python不是一种新的编程语言,它可能被编程人员“使用”。它是一种理所当然的通用编程语言,被许多公司所使用。g、 Googlíe、Facíe book、Instagram、Spotify和Nétflix等。实际上,Instagram对Python的整合比平台的增长更重要。
为什么Python的扩展速度如此之快?
这种编程语言有一个由编程人员组成的社区,但它是一种软件,这在学习如何编程时是至关重要的,它允许您快速学习曲线。这可能是流行语言出现的部分原因。
另一方面,Rust是统计单位中薪酬最高的编程语言,平均工资超过19万美元,其次是Go,平均工资为18.5万美元,Scala的平均工资为18万美元,它最流行的编程语言经常以每年135000美元的价格进行比较,这一数字大大增加了165000美元。
你认为机器维修的rts费用为146000美元,而生锈的情况比国家的汽车要严重得多。
事实上,受欢迎并不总是与收入挂钩;例如,如果一种程序编程很受欢迎,很可能会导致véryoné的员工数量不足,从而导致salariés的专业水平不高。
来自 O'Reilly 最新的 2021 Data 和 Ai Pay Survey 的数据特别有趣,因为它揭示了程序编程是最受欢迎的,甚至根据他们的平均工资排名。
根据 Rust 编程语言开发人员的说法,一些薪酬最高的职位包括游戏引擎程序员的角色和软件工程师、后端工程师和区块链工程师的职责。
就游戏引擎程序员而言,英国的平均工资约为每年 60,000 欧元; 软件工程师在英国的平均年薪为 45,000 欧元; 后端工程师的平均年薪为 70,000 美元; 区块链工程师每年的平均收入为 55,000 欧元。
正因为如此,锈菌的数量正在快速增长。如果你想要一个光明的未来和一个新的发展,你可能会考虑除掉蟒蛇之外的锈菌,这在标记t中变得越来越重要。
结论
我们可能认为Python是一种复杂的语言,拥有一个由开发人员、文档和标准生产应用程序组成的社区。
在很大程度上,像语言这样的东西在使用中的必要开发是机器学习和数据挖掘的技术开发,其中,语言以及其他编程语言是主要的语言。
R、 另一方面,是一种高度专业化的语言,它起源于统计学。Python来自另一方面,是一种具有广泛应用范围的通用编程语言。
另一个非常重要的指标,主要基于Googl上编程流行程度的théPYPL,将Python列为第二大最流行的编程语言,其流行程度比其他五种语言高10%。
特殊情况下,当它与数据域通信时,其相似性更具灾难性。Googl拥有的统计机器学习平台,可以随时进行研究,在该平台上可以获取有关数据中rts倾斜的信息。
在这组数据中有一个非常重要的信息:对以下问题的回应:您建议新手数据科学家首先学习哪个计算机程序? 超过 63% 的响应者选择 Python 作为解决方案
原文:https://blog.devgenius.io/why-python-is-not-the-programming-language-of…
本文:
- 20 次浏览
Rust语言
- 184 次浏览
【Rust开发】Java 比优化后的 Rust 程序更快
视频号
微信公众号
知识星球
你好。 起初,我是一名 Rust 程序员,并为它编写了一些项目和一个框架,在听说动态编译技术后,JVM 对我很有吸引力,我在 rust 中编写了一个带有许多优化标志的程序,以便编译器获得最佳性能 ,并在java中编写实例。
经过热身时间后,我看到了 JVM 的惊人性能,它是一头野兽,可以在性能上击败 Rust,
Rust result: 10,648 _ 6,678 _ 8,274
Java result: 8,661 _ 9,608 _ 6,302
12次基准的平均值:
Rust: 9,948
Java: 8,693
Java 代码:
public static void main(String[] args) { for (int q = 0; q < 1001; q++) { long tInit = System.nanoTime(); ArrayList<CClass> arr = new ArrayList<CClass>(100); for (int i = 0; i < 100 ; i++) { arr.add(new CClass("fname", "lname", i % 30)); } for (int i = 0; i < 100 ; i++) { CClass cls = arr.get(i); cls.validation(); } if (q > 997) { System.out.println(System.nanoTime() - tInit); } } }
Rust Code :
fn main() { for _ in 0..3 { let now = std::time::Instant::now(); // =============================================== let mut v = Vec::with_capacity(100); for i in 0..100 { v.push(Class::new("fname", "fname", i % 30)); } for i in 0..100 { let cls = v.get(i).unwrap(); cls.validation(); } // =============================================== let now2 = std::time::Instant::now(); println!("==> {}", now2.duration_since(now).as_nanos()); } }
我使用一些 rust 编译器标志来最大化性能:
[build] rustflags=[“-C”, “target-cpu=native”] [profile.dev] lto = true opt-level = 3
最后,我越来越喜欢 JVM,java/Scala
伟大的语言,庞大的生态系统和惊人的性能,
阿里巴巴、Linkedin、Twitter、亚马逊使用 80% 的后端工作在 JVM 上,
这不仅仅是为了 JVM 的独立性或生产力
它具有惊人的性能和惊人的稳定性
精彩评论1
Java(和 JVM)一点也不慢。 不知道是什么给了你这样的印象。
例如,现代 JavaScript 引擎和现代 JVM 一样快。
当您只对非常简单的循环代码进行计时时尤其如此,这些代码大多会生成相同的程序集。 而且,正如一条评论所说,您可以通过迭代器优化 Rust 的边界检查,这应该会使其更快。
抱怨 Java 和 JavaScript 等不是因为它们很慢,而是因为 GC(垃圾收集)而_偶尔_慢。 并且需要占用大量运行时间(因此需要大量 RAM)。
在您的示例中,您既不会使用大量内存,也不会导致任何 GC。 因此,我希望 Java 速度与 Rust 速度相似,因为没有理由不应该这样。
评论2
当您比较不同的分配器时有点不公平。 Java 预先分配内存并为每个分配请求移动一个指针,rust 实际上向系统分配器请求内存。 这是托管 Vs 本机语言的一个已知位,它与 c# 和 c++ 或其他任何语言相同。 如果将分配移到时区之外会发生什么?
评论3
jvm 通过分析程序和找出热路径来调整优化。 一个公平的比较将根据性能配置文件对 rust 程序进行分析和重新优化
评论4
Java 性能的主要问题是它的 GC,它会增加延迟,最重要的是会使请求处理的延迟变得难以预测。 内存管理的可预测性是没有 GC 的语言的优势之一。 当然,我过于简单化了,因为性能是一个相当复杂的领域
评论5
是的,谢谢,我们可以运行一个 10K rps 的 java 服务器,内存使用率很高
但实际上与 Rust Instance 的区别是,Java 使用 2GB,Rust 使用 10MB。
是的 GC 是数据库软件的问题,但不是没有 ZGC 的 Web 服务器,
但是云托管服务器2GB的钱不算什么
但是时间很昂贵,而且经过良好测试的库更重要,
例如 Akka-grpc 在多核服务器上比 Rust-Tonic 更快
因为库经过了很好的测试,但在 Rust 社区中不存在某些东西,例如我们社区中有 Sqlx (Async orm) 和 Diesel(Sync orm) 是关于哪个更好的战争!!。
不存在直接的解决方案 这个问题也存在于 cassandra 驱动程序中,并且文档是旧的并且与新版本不同。
这对我来说很痛苦。
但是在 jvm 中几乎所有东西都直接存在
评论6
这是正确的。 如果您的环境可以使用 2GB 的内存并且 Java 的 GC 对您来说不是问题,那么您应该使用适合您的目的的最佳技术。
对于某些人来说,例如在嵌入式环境中,您没有使用 2GB 的奢侈,并且您无法维持 GC 暂停,那么您可能会选择 Rust。
原文:https://towardsdev.com/java-is-faster-than-optimize-rust-program-bd0d17…
本文:
- 103 次浏览
【Rust开发】Rust 一年后
好吧,距离我上次写已经有几个月了,但是时间过得真快🕊️
所以这是我在 Rust 进行微服务 Web 开发一年后的小日记,主要是一些想法的集合。
学习曲线
我有时听说使用 Rust 需要 1 个月才能获得生产力。
好吧,我不是计算机科学专业的毕业生(实际上我的专业更侧重于项目管理),但我仍然在这个领域工作了 13 年以上,对此我不太同意。 也许它对以前的系统程序员来说更容易,或者也许有些人比其他人学得更快。
仅作为一个比较:据我所知,JavaScript 花了我 1 个月的时间来适应,而在 6 个月内就可以高效地完成任何编码任务。
Rust 是……不同的。
而且我学习它的背景也不同:我以前也是唯一的 Rust 知识可以追溯到 2019 年初,当时我终于彻底阅读了 Rust 书。我非常简单地尝试设置对 websocket 的基本客户端请求。说我理解了那里的所有概念,或者说我在 2020 年记得它们,那将是一个公然的谎言。刚签下新合同,我应该接受 Rust 的培训。事实证明,就像经常发生的那样,我必须自己学习,同时仍然必须在截止日期内交付功能。谢天谢地,合理的那些给了我足够的时间来改进,但还不足以正确地阅读文档、观看学习资源、进行实验等等。大多数情况下,这必须在我的空闲时间完成,我做了很多。老实说,这是令人筋疲力尽的一年。
我想说的是,在第一个月之后,我能够编写 Rust 代码,而无需每隔 2 分钟左右就对编译器的错误感到惊讶。到那时我已经习惯了它们中的大多数,并且已经习惯了基础知识。熟悉编译器的错误是必要的:这意味着你了解编译器想要你做什么。
不知何故,漫长而广泛的特征仍然会让我目瞪口呆,例如这个:
那么这是什么?您可以将其称为另一种语言的“界面”。
它在这里描述了一个中间件,它将对其请求强制超时。
它接受一个通用请求,并将在将来的某个时间(也就是说,异步)返回一个通用响应或一个通用错误。
首先,这里有趣的是,只要此代码在范围内,此 Timeout 将自动为您的库、标准库或任何在 Rust 中创建或将要创建的库中的任何类型实现。
注意到这个淘气的 T::Error 了吗?它需要任何可以转换为指向动态大小错误的指针(其大小在编译时未知,基本上允许您自由传递任何类型的错误)装箱在堆上的某处(哦,这个指针也是顺便说一句,保证是非空的,但这是另一个话题)。这个“错误”对于线程之间的发送和同步(或共享,如果您愿意)也是安全的(以便运行时可以在多个线程上正确调度任务,如果认为合适的话)。两种响应变体都必须在内存中存在足够长的时间才能完成异步调用,这就是“静态”在这种情况下所表示的。
Rust 语言确实过于表达。
但是一旦你开始理解它,它就是美丽的。
3 个月后,我终于熟悉了它们,编写自定义实现有时很乏味,但最终还是完成了。
我也借此机会感谢整个 Rust 社区,尤其是 tokio 和 tonic 的贡献者和维护者。他们总是不遗余力地提供提示并善意地为我指明正确的方向。不管我的问题多么愚蠢,有时。
作为我自己故事的旁注,如果我可以说的话,Rust 有“很多方面”。其中之一是元编程,或称为宏。它基本上是允许您生成代码的代码。我很晚才开始和他们一起玩,主要是事先没有时间,并意识到它可以让我免去繁琐和耗时的样板。
这是一个指标,除其他外,我有时也“错误地学习”了 Rust,后来意识到它实际上可以更容易地完成。所以我对此的看法是:最好通过适当的时间和反思来学习 Rust。通常我不建议走和我一样的路,除非你喜欢挑战。
我想说的是,在那之后,大部分的实际学习都是生态系统本身。作为一种非常有表现力的语言,Rust crates 作者设计了使用他们的代码的“方法”,有时它会很自然,有时需要一段时间才能习惯它们。但是你对它们了解得越多,你就越能理解为什么它们是这样设计的。
时间已经过去了,我最终想分享的是,Rust 需要适当的时间、反思和思维方式的转变。 几个月前您甚至看不到一些深刻的好处,这绝对是正常的。 没有神奇的快进学习按钮。 对于经验丰富的开发人员来说,这甚至比新手更难,因为我们都从以前的语言(在我的例子中是 ActionScript、PHP、Java 和 JavaScript / TypeScript)中带来了以前的习惯。
但是,一个显着的区别在于可用的学习资源:至少可以说,当我开始时,教程和文档通常很少。 到目前为止,我看到越来越多的内容可供新手使用,更准确的文档和书籍,每周都会出现新的教程。
这是一件非常好的事情。
这值得你花时间吗?
剧透警报:确实如此😉
让我们看看为什么!
“I’m late! I’m late for a very important date! No time to say “Hello”, goodbye! I’m late, I’m late, I’m late!” ― White Rabbit
一次编写,到处构建⚙️
我们以前听说过,对吧?
但这一次也许是真的。
当然,我一开始一直在挣扎,有时我仍然在使用 Rust 时认知精疲力尽,但最后,它从未让我失望:超过编译器要求,在 Rust 中从来没有“你不能那样做”的时刻。
在您的这个特定用例中,生态系统可能还不成熟,它可能很难、压倒性或只是为时过早?当然。它需要你大量的阅读和实验吗?确实。
但最终一切都可以完成。
仅仅是因为 Rust 可以在各种平台上编译为本机代码,并且对 FFI 具有一流的支持,这意味着它可以与大多数语言(如果不是任何其他语言)对话。
我知道只要付出时间和精力,它就可以帮助我构建任何东西。
设置整个服务器基础架构?当然。
编写自定义 Flutter 插件、原生 Nodejs 模块或诸如此类的东西?是的。
甚至构建一个视频游戏、一个嵌入式设备......你的名字!
可能甚至建造一个连接到月球的烤面包机,谁知道呢。
编译时错误和安全☔
仅仅是因为,默认情况下,Rust 中根本不存在大量错误。
它的核心支柱之一是所有权和借用模型:编译器基本上会在任何时候强制您的变量被正确分配、在函数中传递、引用和使用。
它在细节上非常微妙,但本质上非常简单:您只能一次在一个地方改变一个变量,或者一次从多个地方读取,但永远不要同时做这两个。
因此,当变量超出范围时,可以自动释放内存,而无需垃圾收集器。
悬空指针、释放后使用、双释放、空指针异常等也一去不复返了。
在使用 Rust 一年多一点的时间里,我的 Web 服务几乎没有运行时错误。 很少有不同的,我可能可以用手指数数,认真的。
一旦编译,通常它就可以工作了™。
类似于 C 和 C++ ⚡ 的性能
Photo by Marc-Olivier Jodoin on Unsplash
简单地说:它快得离谱。
这意味着,例如,来自 Nodejs,在 Rust 中,即使我过度分配内存(克隆它直到你成功®)或编写优化不足的代码,它仍然平均比精心设计的速度快 5 到 20 倍 和优化的 JavaScript 代码。 为了降低内存消耗。
小轶事:我第一次查看数据反序列化吞吐量(使用 serde)时,我以为我在控制台输出中打错了,因为我的输入是一大块数据,结果显示在……以纳秒为单位。 我一遍又一遍地检查并运行它,直到我意识到一切都很好。 这就是它的速度。
“谁去那里? 是敌是友?” 问哨兵🎭
- 照片由 @huanshi 在 Unsplash 上拍摄
和编译器?在最初的几周内会感到很烦人。
这绝对是几个月的障碍(我会说是对自己的生产力)。但最终成为某种最好的朋友。
编译器错误描述性过强,以至于它通常提供直接复制和粘贴解决方案,并附有解释。
每当我疲倦而遗漏某事或做事不当时:
编译器在那里努力提醒我。
同样由于 Rust 的严格性,我应该提到我现在花更多的时间编写断言实际业务逻辑的测试,而不是断言我对语言行为方式的假设的测试。
在其他语言中,作为开发人员,我们实际上自己持有不变量。必须记住这种方法在这种情况下不能正常工作,记住这种变量类型在与另一种类型相比时表现得非常狂野。在 Rust 中,一切都是无聊的类型。默认情况下,除了让它正确之外别无他法。
它勾起了你的好奇心?
看一看阿莫斯的这篇优秀文章以获得更深入的解释👇
混乱中的宁静🤸♂️
重构是一种幸福。 简直是小菜一碟🍰。
大多数时候它只是遵循编译器的指令。
由于大多数错误发生在 Rust 的编译时,因此一旦编译,任何东西都不太可能发生中断或倒退。
对于我使用过的其他语言,我不能完全肯定。 我什至知道我在说什么吗? 问问我以前的队友谁是“RefactoMan”。
没有工具的工匠什么都不是🧰
- 谷仓图片在 Unsplash 上的照片
工具也是 Rust 感觉舒适、高效和实用的地方:例如,单元测试、文档生成、代码格式化程序和 linter 是内置的。
默认情况下它就在这里。
而且还有很多很多的工具可供使用。
举些例子:
- - see generated assembly code for your program ? 👉 cargo-asm
- - fuzz your tests ? 👉 cargo-fuzz
- - timely compare 2 scripts execution ? 👉 hyperfine
- - profile your code ? 👉 flamegraph
- - enforce valid SQL queries at compile time ? 👉 sqlx
- - enforce valid HTML template at compile time ? 👉 yarte
- - use advanced tracing and telemetry ? 👉 opentelemetry
etc …
心态转变💭
不仅如此,我个人觉得今年我对计算机科学的了解比以往任何时候都多。 并不是特别是它以前不可用或记录不足。 它总是触手可及。 这只是因为,在大多数其他语言中,低级细节被抽象掉了,所以没有真正的动力去深入挖掘。
Rust 需要满足如此多的要求来编译代码的好处是它促使你修改你的基础知识。 美妙的V8黑盒不再处理事情了。
好吧,为了清楚起见,让我在这里重新表述一下:Rust 不会强迫你了解每一个潜在的细节,但它会让你非常了解它们。
此外,您将在 Rust 旅程中学到的有关内存安全的所有内容都与语言无关:因此它将对您之后使用的所有其他语言有用。
挑战极限⚗️
我特别喜欢的是 Rust 周围的热情。
许多人正在重新审视或创新以前很难用其他语言正确完成的领域,如果不是不可能的话。
鉴于编译器永远不会让你编译不是内存安全的代码,它提供了一个“安全网”上下文来试验疯狂的东西(尤其是多线程的)。
一个很好的例子是 rayon,这是一个 crate,它允许您通过简单地更改一行代码来并行化 CPU 密集型任务的迭代。
快速成长
想一想:
9 年前:由 Mozilla Research 孵化。
7 年前:它达到了第一个稳定版本。
4 年前:它正式开始支持 async-await 语法。
今天:它已经提供了成熟的生产就绪服务器解决方案。
好吧,我不了解你,但我不记得有一个编程语言生态系统发展得如此之快,除了当时的 JavaScript。
有趣的事实是,您实际上可能已经使用了一些,甚至没有意识到它。例如,您是否知道一些 Rust 已经进入:Dropbox、Figma、NPM、Microsoft、CloudFlare、Facebook、Amazon、Discord 和 Linux 内核?
生态系统仍有很多需要改进的地方:
本周 Rust 和 crates.io 是测量温度的好方法。
哦,还有一些网站跟踪它的演变,通常标记为:arewegameyet、areweguiyet、arewewebyet 等。
这可以很好地让您了解 Rust 是否已为您的下一个项目做好准备,或者需要一些额外的成熟度。
生产力🏃
所以一般来说,我将其总结为一个整体的方式:
值得花时间提前吗?
尤其是在最初的几个月里,在 Rust 中执行日常任务可能会花费通常执行它们的时间的三倍。随着一项改进,差距最终缩小了:例如,现在我可以像使用 Nodejs 一样快地使用 Rust 设置一个成熟的 REST API。只是花了更长的时间才到达那里。
它基本上是在编译时预先交易时间,
您最终会在运行时节省调试费用。
到目前为止,我个人更喜欢这种方法。
还记得那个导致你的脚本异常失败的小错误吗?还记得你花在调试上的时间吗?几天,几周?
问问自己,您是否愿意在前期投入更多时间。
这也是 Rust 的全部意义所在。
所以让我们总结一下我的收获
对于今天想开始 Rust 的人:
- 不要急于求成:按照自己的节奏学习,适当的时间和反思。
- 摒弃以前的习惯,避免系统地与其他语言进行比较:这需要转变思维方式。
- 不要与编译器对抗:尽早接受它的建议。
- 不要试图过早地进行过度优化:写一些先编译的东西,然后再提高它的效率。
- 从小处着手,随着时间的推移而成长:找到您喜欢的主题的教程,这些教程可以让您快速入门,并在您的旅程中阅读 Rust 书籍。
- 不要让你的生活变得复杂:a.k.a 在没有经验的情况下使用它来为一个期望很高但期限很短的客户使用它。
- 玩得开心,实验!
结束语💬
既然你做到了最后,
谢谢你的时间,我希望你喜欢这个阅读🙂
我实际上有几篇关于实际 Rust 编程的文章,
我希望尽快交付。
直到下一次,大家保重!
原文:https://romain-kelifa.medium.com/after-one-year-of-rust-7cef608fef68
- 218 次浏览
【Rust架构】Rust web框架比较
目录
- 服务器框架
- 过时的服务器框架
- 客户框架
- 过时的客户框架
- 前端框架(WASM)
- 补充库
- WebSocket
- 模板
- 对照
- 高级框架
- 低级框架
- 前端框架
- 中间件和插件
- Websocket库
- 资源
- 博客文章
- 演示
- 使用Rust的真实世界Web项目
- JS&asm.js&WASM
Server frameworks
使用Rust构建Web应用程序有几个有趣的框架:
- actix-web (homepage / repository / documentation / user guide)
- gotham (homepage / repository / documentation / examples)
- iron (homepage / repository / documentation)
- nickel (homepage / repository / documentation)
- rocket (homepage / repository / documentation)
- rouille ( - / repository / documentation)
- Thruster ( - / repository / documentation / examples)
- Tide ( - / repository / documentation / examples)
- tower-web ( - / repository / documentation / examples)
- warp ( - / repository / documentation / examples)
如果您需要更低级别的控件,可以在这些库之间进行选择:
- hyper (homepage / repository / documentation)
- tiny-http ( - / repository) / documentation)
- tk-http ( - / repository / - )
- h2 ( - / repository / - )
过时的服务器框架
Client frameworks
To build web clients with Rust, you can choose between these libraries:
- actix-web (homepage / repository / api docs)
- reqwest (- / repository / documentation)
- hyper (homepage / repository / documentation)
- jsonrpc (- / repository / documentation)
Outdated client frameworks
Frontend frameworks (WASM)
Since WASM support is available in most browsers we can use Rust to build web applications :)
- stdweb ( - / repository / documentation ) A standard library for the client-side Web
- yew ( - / repository / documentation ) - A frontend framework inspired by Elm and React (based on stdweb)
- percy ( homepage / repository / - ) - A modular toolkit for building isomorphic web apps
- seed ( homepage / repository / - ) - A Rust framework for creating web apps
- draco ( - / repository / documentation ) - A frontend framework inpired by Redux and Elm
- smithy ( - / repository / - documentation ) - A front-end framework
- squark ( - / repository / documentation ) - Rust frontend framework, for web browser and more.
- ruukh ( - / repository / documentation ) - A frontend framework inspired by Vue and React
- willow ( homepage - / repository / - ) - A frontend framework inspired by Elm
- dodrio ( - / repository / documentation ) - A fast, bump-allocated virtual DOM library.
- sauron ( - / repository / documentation - Sauron is an html web framework for building web-apps. It is heavily inspired by elm.
Supplemental libraries
Websocket
- websocket (homepage / repository / documentation)
- ws-rs (homepage / repository / documentation)
- tungstenite ( - / repository / documentation)
- tk-http ( - / repository / - )
- actix-web (homepage / repository / documentation)
Templating
- tera (homepage / repository / documentation)
- mustache (- / repository / documentation)
- liquid (- / repository / - )
- handlebars (- / repository / documentation)
- horrorshow (- / repository / documentation)
- maud (homepage / repository / documentation)
- askama (- / repository / - )
- stpl (- / repository / - )
- ructe (- / repository / documentation )
- typed-html (- / repository / documentation )
对照
高级框架
Low-Level Frameworks
Name | hyper | h2 | tiny-http | tk-http |
---|---|---|---|---|
License | ||||
Github Stars | ||||
Contributors | ||||
Server | yes | yes | yes | yes |
Client | yes | yes | ? | yes |
HTTPS support | yes | no | yes | yes |
HTTP/2 support | solicit | yes | ? | no |
Async | yes | yes | yes |
Frontend Frameworks
Middleware & Plugins
Name | iron | gotham | nickel | rouille | actix-web |
---|---|---|---|---|---|
Static File Serving | yes | no^ | yes | n/a | yes |
Mounting | yes | yes | yes | n/a | yes |
Logging | yes | yes | no | n/a | yes |
JSON-Body-Parsing | yes | yes | yes | n/a | yes |
Sessions | yes | yes | ? | n/a | yes |
Cookies | yes | yes | ? | n/a | yes |
PostgreSQL middleware | ? | no^ | yes | n/a | yes |
SQLite middleware | ? | no^ | yes | n/a | yes |
Redis middleware | ? | no^ | yes | n/a | yes |
MySQL middleware | ? | no^ | yes | n/a | yes |
(^ Planned in current roadmap)
Websocket Libraries
Examples
To compile or run the examples use Cargo. First clone this repo
git clone https://github.com/flosse/rust-web-framework-comparison
cd rust-web-framework-comparison/
and change to the desired frameworkd directory (e.g. cd iron/
) and type
cargo run --example hello_world
Then visit http://localhost:3000
to see the result.
Resources
Blog posts
2018
- Lessons learned on writing web applications completely in Rust
- Introducing Ruukh Framework
- Baby’s First Rust+WebAssembly module: Say hi to JSConf EU!
- Mix Rust Code (WebAssembly) with Vue Component
- Wicked Fast Web Servers in Rust
- Migrating to Actix Web from Rocket for Stability
- Creating a Rusty Rocket fuelled with Diesel
Until 2017
- Dose Response ported to WebAssembly!
- Rust and the case for WebAssembly in 2018
- wasm32-unknown-unknown landed & enabled
- How to Deploy a Rocket Application to Heroku
- Rust to WebAssembly, Made Easy
- Rust for the web
- Rocket on Fedora
- Announcing Gotham - A flexible web framework for stable Rust that does not sacrifice safety, security or speed.
- Announcing cargonauts - A Rust async web framework
- Writing a GitHub webhook with Rust! Part 1: Rocket
- Hello, Botket! (Rocket)
- Launching a URL Shortener in Rust using Rocket
- Rocket + sodiumoxide = ♥
- The Path to Rust on the Web
- Rendering Vector Map Tiles (Rust + asm.js demo)
- Compiling to the web with Rust and emscripten
- Basic 2FA in Rocket
- Building high performance REST APIs with Rust and Rocket
- Rocket Rocks! Using FromFormValue Traits to protect your website
- Building an Asynchronous Hyper Server
- JWT & Access Roles in Rocket
- Writing a basic JSON response web server in Rust using Iron
- Diesel Powered Rocket
- Using Stainless with Rocket
- Integration testing a service written in Rust and Iron
- Actually using Iron: A grumpy introduction to web development in Rust
- Using Rust for Webdev as a Hobby Programmer
- My adventures in Rust webdev
- Rust’s Iron Framework: First impressions
- Rust for Node.js developers
- A Rust-powered public web page in 5 minutes
- Rust and Rest
- Shipping forgettable microservices with Rust
- Writing a simple REST app in Rust
- Getting started with Rust
- Let's Build a Web Server in Rust
- Creating a basic webservice in Rust
- Iron on uWSGI
- Deploying a Rust App to Google App Engine
- async hyper
- Trying Rust for web services
- Are we web yet?
- Reimplementing ashurbanipal.web in Rust
- A web app with Nickel: From first line to Heroku deployment
- What features Iron does not have compared to a web server like nginx?
- Build an API in Rust with JWT Authentication using Nickel.rs
- Selective Middleware for Iron
- Rust for the Web - RESTful API in Rust, impressions
- Rust for Node developers
Demos
- exoskeleton - Iron
- Example webapp using React + Webpack - Iron
- rustwebapp - Iron and Postgres (r2d2)
- webrust - Iron and Postgres (r2d2)
- httptest - Iron
- nickel-todo-backend - Nickel and Postgres (r2d2)
- rust-playground - Iron
- rust-web-example - Iron + Diesel (r2d2) + Serde
- websocket chat - Actix: Browser Websocket + tcp chat
- diesel - Actix + Diesel
- json - Actix + serde_json or json_rust
Real-world web projects using Rust
- paste.rs - Rocket
- Portier - Iron and Redis
- yaus - Iron and SQLite
- racerd - Iron
- rust-passivetotal - Hyper
- mars - Hyper
- openfairdb - Rocket and Neo4j (r2d2)
- ruma - Iron and Posgres (diesel + r2d2)
- html2pdf - Iron
JS & asm.js & WASM
- hellorust.com - a website with news, resources and demos
Examples
- rust-webapp-template - Template project for Rust web app using stdweb
- rust-todomvc - an example application build with webplatform
- wasm-experiments - experiments with
wasm32-unknown-unknown
Benchmark
- TechEmpower Web Framework Benchmarks
- benchmarks - Rust web frameworks benchmarks
- which_is_the_fastest - Measuring response times (routing times) for each framework (middleware). Each framework has to have two features; routing and parsing path parameters.
- 3413 次浏览
【Rust编程】在Rust中使用C库
使用bindgen的FFI实用指南(第1部分,共2部分)
今天我想深入探讨一下我们在尝试用Rust重写IoT Python代码时遇到的一个困难:具体地说是FFI,或者“外文函数接口”(Foreign Function Interface)——允许Rust与其他语言交互的位。一年前,当我试图编写与C库集成的Rust代码时,现有的文档和指南常常给出相互矛盾的建议,我不得不自己一个人跌跌撞撞地完成这个过程。本指南旨在帮助将来的rustacean完成将C库移植到Rust的过程,并使读者熟悉在进行同样操作时遇到的最常见问题。
在本指南中,我们将讨论如何使用bindgen使C库函数暴露为Rust。我们还将讨论一下这个自动工具集的局限性,以及如何检查您的工作。公平警告:正确实施外国金融机构是非常困难的模式。如果你是新手,请不要从这里开始。仔细阅读这本书,写一些练习代码,在完全熟悉借阅检查器之后再回来。
动机
为了证明这一点,我需要解释一下为什么我们德韦洛一开始就需要这么做。
对于我们的重写项目,我们希望与供应商提供的C库集成,该库负责通过标准供应商指定的协议通过串行端口与我们的Z-Wave芯片进行通信。这种串行通信协议很复杂,很难正确实现,而且还受到严格的时间限制——发送到串行端口的字节基本上是通过无线电直接传输的。在错误的时间发送错误的字节可能会完全挂起无线电芯片。有一个长达几百页的参考文档,包含传输和确认、重传逻辑、错误处理、定时间隔等的规范。最初的Python代码从零开始(错误地)实现了这个协议,这个实现代表了遗留堆栈中相当大的一部分bug。除此之外,无线芯片组供应商正在推迟认证,除非我们能够证明我们正确地实现了协议。巧合的是,提供的参考库(用C实现)被保证符合规范。很明显,供应商C代码似乎是商业成功的最短路径。
Rust本机支持链接C库并直接调用它们的函数。当然,因此导入的任何函数都需要实际调用unsafe关键字(因为Rust不能保证其不变量或正确性),但这给我们带来了不便,我们可以稍后再使用。
Rust Nomicon将告诉您,只要名称和签名完全对齐,就可以通过在extern块中声明来导入函数定义或其他全局符号。这在技术上是正确的,但不是很有帮助。手工输入函数定义是完全愚蠢的,而且当我们有一组非常好的包含声明的头文件时就没有意义了。相反,我们将使用一个工具从库的C头文件生成锈迹签名。然后我们将运行一些测试代码来验证它是否正常工作,调整一些东西直到看起来正确为止,最后将整个东西烘焙到一个Rust的板条箱中。我们开始吧。
宾根(Bindgen)
最常用的工具是bindgen,它可以从C头生成锈迹签名。我们的目标是创造一个绑定.rs表示库的公共API(其公共函数、结构、枚举等)的文件。我们将配置板条箱以包含该文件。一旦构建了板条箱,我们就可以将该板条箱导入到任何项目中,以调用C库的函数。
您需要:
- 正常工作的货物装置。我假设如果你编译的是Rust代码,你就有这个。
- 一个正在运行的C编译器和pkg配置,用于依赖项解析。
- 与要使用的库函数对应的头文件。
- 如果您有很好的源代码,本例假设您是从源代码构建库。否则,如果链接到的静态或动态库不在系统路径中,则需要该库的路径。
- 与库的API大小相对应的耐心程度。
安装命令行bindgen工具非常简单:
cargo install bindgen
在我的Debian笔记本电脑上,我还需要手动安装clang,尽管您的里程数可能会有所不同。
设置你的板条箱(crate)
我们的新库板条箱将包含肮脏的业务建设和出口本机C库的不安全功能。同样,将所有安全的包装器留给另一个板条箱—这不仅加快了编译速度,而且还使其他板条箱作者能够最少地导入和使用原始的c绑定。FFI板条箱的标准Rust命名约定为lib<XXXX>-sys。
我们要创造一个内部版本.rs将与cc板条箱一起使用的文件,用于编译和链接我们的bindgen导出。让我们将库源代码放在一个名为src的子目录中,并将相关的include文件放在一个名为include的子目录中。接下来,让我们确定货物.toml已设置:
[package] name = "libfoo-sys" version = "0.1.0" links = "foo" build = "build.rs" edition = "2018"[dependencies] libc = "0.2"[build-dependencies] cc = { version = "1.0", features = ["parallel"] } pkg-config = "0.3"
接下来我们将填充内部版本.rs文件。下面看起来有点奇怪-我们正在编写一个Rust程序,它将输出一个脚本到stdout;cargo将直接使用这个脚本来构建我们的板条箱。
如果你链接的是一个已经编译过的库,保证在系统路径中,你的内部版本.rs可能就这么简单:
fn main() {
println!("cargo:rustc-link-lib=foo");
}
不过,大多数情况下,您至少需要使用某种包配置来确保库已实际安装并且链接器可以找到它。在许多情况下,您的库足够小,可以由cargo本身构建为静态库。pkg配置板条箱有助于库和依赖项配置,cc处理从cargo内部构建C代码的脏活。两个板条箱在输出货物所需的行之前都运行配置和构建步骤。在我们的示例中,我们的源代码使用zlib,因此我们使用pkg config来查找和导入适当的版本。下面的示例代码还显示了如何添加编译器标志和预处理器定义。
fn main() { pkg_config::Config::new() .atleast_version("1.2") .probe("z") .unwrap(); let src = [ "src/file1.c", "src/otherfile.c", ]; let mut builder = cc::Build::new(); let build = builder .files(src.iter()) .include("include") .flag("-Wno-unused-parameter") .define("USE_ZLIB", None); build.compile("foo"); }
最后,你需要一个src/自由卢比文件来编译我们的绑定。在这里,我们将禁用与Rust不一致的C命名约定的警告,然后只包含生成的文件:
#![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)]use libc::*;include!("./bindings.rs");
生成绑定
而bindgen用户指南似乎指导您在其中动态生成绑定rs,实际上,您需要在将生成的输出释放到板条箱之前对其进行编辑。通过命令行生成一个或多个文件,并将输出提交到存储库,这将为您提供最大的控制。
最初的生成尝试可能如下所示:
bindgen include/foo_api.h -o src/bindings.rs
对于一个包含多个API调用的真正头,不幸的是,这将生成比我们想要或需要的更多的定义。生成部分绑定.rs因为我们在德韦洛的项目更接近于此:
bindgen include/foo_api.h -o src/bindings.rs '.*' --whitelist-function '^foo_.*' --whitelist-var '^FOO_.*' -- -DUSE_ZLIB
说服生成器只提供所需的内容,而不吐在未定义的符号上,这是一个反复试验的过程。考虑分阶段生成并连接结果。
它很强大,但并不完美
当您将头传递给bindgen时,它将调用Clang预处理器,然后贪婪地转换它能看到的每个符号定义。您需要在命令行进行调整,并重构结果输出。
原始Makefile/CMake extras
在bindgen命令行上的--之后,您可以添加在针对库构建时通常添加到编译器的任何标志。有时,这些将是额外的include路径,有时,当标头具有#ifdef保护的定义时,它们将是必需的。对于我们的供应商库,未能定义OS\u LINUX隐藏了一堆我们需要的符号。(什么,你认为遗留代码会使用标准的编译器定义,比如linux,而不是编造东西吗?抱歉,喜剧时间在楼下和楼上。)如果您生成的输出神秘地缺少函数,请检查您的定义。
包含标准标头的标头
Bindgen非常积极地为预处理器输出中的每个可用符号生成定义,甚至为不需要的可传递的系统特定依赖项生成定义。这意味着如果你的头文件包含stddef.h或time.h(或者包含另一个包含stddef.h或time.h的头文件),你将在生成的输出中得到一堆额外的垃圾。编译C++代码时更糟,因为C++编译器显然必须导出STD中使用的每个符号,即使它不是必需的或需要的。
您的板条箱应该只公开库API中的内容,而不是系统头文件或生成代码的标准库中的内容。这是一个痛苦,特别是如果您的库的函数和常量不遵循任何类型的命名约定。唯一的解决方法是使用白名单regex和大量的尝试和错误。
预处理器#defines
#define FOO_ANIMAL_UNDEFINED 0 #define FOO_ANIMAL_WALRUS 1 #define FOO_ANIMAL_DROP_BEAR 2/* Argument should be one of FOO_ANIMAL_XXX */ void feed(uint8_t animal);
这看起来是人为的,但这是一个模糊版本的模式,在我们的供应商C库中很普遍。
在C语言中,这样做很好,因为当您将头文件包含到源代码中时,当函数调用它时,您可以直接使用FOO\u ANIMAL\u WALRUS之类的东西。C编译器会隐式地将文字1转换为uint8\t,代码就可以运行了。当然,为了清晰起见,最初的作者应该创建一个enum typedef并使用它,但是他们没有,这仍然是我们必须处理的合法C代码。
pub const FOO_ANIMAL_UNDEFINED: u32 = 0; pub const FOO_ANIMAL_WALRUS: u32 = 1; pub const FOO_ANIMAL_DROP_BEAR: u32 = 2;extern "C" { pub fn feed(animal: u8); }
尽管bindgen足够聪明,可以将符号识别为常量,但仍然存在一些问题。首先,bindgen必须猜测每个FOO\u ANIMAL\u XXX的类型。在这种情况下,显然是猜测了u32(它不仅与我们的函数参数不匹配,而且在技术上也是错误的)。这导致了另一个问题:在调用feed时,Rust将要求我们显式地将FOO\u ANIMAL\u WALRUS转换为u8。不是很符合人体工程学,是吗?要解决这个问题,我们需要更改生成的常量的类型以匹配函数定义。稍后我们将在安全包装中修复枚举问题。
有些结构应该是不透明的
我们的vendored库为除初始化之外的几乎所有函数传递一个指向上下文对象的指针。(现在我们称之为foo\u ctx\t)这是一种广泛使用的模式,非常合理。但是由于一个实现缺陷,我们的头文件定义了foo\u ctx\u t而不是向前声明它。不幸的是,这泄漏了foo\u ctx\t的内部结构,然后这种泄漏会间接地迫使我们知道并定义一堆我们不关心的其他依赖类型。
Rust实际上不允许对结构进行单独的声明和定义。与C不同,我们不能在Rust中声明foo\u ctx\t而不为其提供定义,而且Rust编译器必须识别foo\u ctx\t名称,以便将指向它的指针用作函数arg。但是我们可以使用变通方法来避免完全定义它。两者都不是完美的,但在撰写本文时,有两种选择至少在实践中起作用。
我们可以将结构定义替换为没有变量的枚举类型,如果您不小心尝试构造它或将它用作指针目标以外的任何对象,则很容易出现编译错误。这让类型纯粹主义者感到不安,因为从技术上讲,我们在对编译器撒谎,但它确实有效:
pub enum foo_ctx_t {}
或者我们可以用一个私有的零大小类型字段替换它的内部。这是bindgen默认的功能,只要不依赖mem::size\u of:
pub struct foo_ctx_t {
_unused: [u8; 0],
}
常量正确性
Bindgen将C常量指针转换为Rust常量*,将未修饰的C指针转换为mut*。如果原始代码是const correct,那么这个结果就很好了。如果没有,它可能会导致头痛以后当试图创建安全的包装。如果可能,修复库。
下面的例子可以很容易地用在一个Rust不安全的块中,对时间的正常(不变)引用和对tm的可变引用:
// Generated from <time.h>
extern "C" {
pub fn gmtime_r(_t: *const time_t, _tp: *mut tm) -> *mut tm;
}
从技术上讲,您不必修改C库来更改外部定义中指向const*的指针。事实上,C库的符号表甚至没有参数列表,所以Rust的链接器根本无法确认函数参数是否正确(这是C++符号的情况,谢天谢地)。如果您确实修改了Rust指针类型,那么您将负责验证const指针的不变量对于库实际上是正确的。
锋利的边缘
如果您的函数有错误的返回值,请现在帮自己一个忙,确保每个函数都附加了#[must_use]注释。如果调用者忘记检查返回值是否有错误,这至少会给出一些指示,并且在以后将所有内容包装到安全层时会有所帮助。
写一个自述文件.md详细说明如何调用bindgen的文件,并将其提交到存储库。相信我,等你意识到有东西不见了你会想要这个的。
添加几个单元测试来测试是否正常,然后尝试运行cargo测试。Bindgen创建了一些自己的测试,以确保生成的结构对齐是正确的。您还可以运行cargo doc——在您的板条箱上打开,以获得您正在输出的内容的高级视图,并再次检查您是否无意中暴露了错误的内容。
尽管如此,这些手动步骤是必要的,因为bindgen正在尽其所能地利用它所拥有的信息。生成过程将暴露C库中的每个小结构问题。
当您全部完成时,希望您将留下一个不太令人讨厌的Rust包,它通过不安全的Rust暴露您的原始库API。你已经成功了一半!接下来,我们将讨论如何使用这些绑定,并在符合人体工程学和安全的包装器后面保护它们,以便我们的应用程序代码不会错误地使用它们。
原文:https://medium.com/dwelo-r-d/using-c-libraries-in-rust-13961948c72a
本文:http://jiagoushi.pro/node/1450
讨论:请加入知识星球【全栈和低代码开发】或者微信【it_training】或者QQ群【11107767】
- 272 次浏览
【Rust编程】用Rust包装不安全的C库
一个实用的指南,以FFI不让你的指节流血(第2部分,共2)
在第1部分中,我们探讨了如何获取一个C库并为它编写一箱不安全的Rust绑定。使用这个板条箱可以通过“不安全”直接访问库中的函数和其他符号,但必须在应用程序代码中的任何地方使用不安全的块并不是很符合人体工程学的。我们需要一些办法来阻止这种疯狂。
在本文中,我们将探讨如何包装这些函数,并使它们能够安全地正常使用。我们将讨论如何定义处理初始化和清理的包装器结构,并描述一些特性,这些特性描述了应用程序开发人员如何安全地将库与线程一起使用。我们还将讨论如何将函数的随机整数返回转换为符合人体工程学的类型检查结果,如何将字符串和数组与C世界进行转换,以及如何将从C返回的原始指针转换为具有继承生存期的作用域对象。
这一步的总体目标是深入研究C库的文档,并使每个函数的内部假设明确化。例如,文档可能会说函数返回指向内部只读数据结构的指针。该指针在程序生命周期内有效吗?它被限定在某个范围内还是被初始化了?最后,我们将有一套包装器,使这些假设对Rust可见。然后,我们将能够依靠Rust的借阅检查器和强制错误处理来确保每个人都正确地使用库,即使是在多个线程中。
添加枚举
在上一篇文章中,我们讨论了一个以枚举类型作为参数的示例函数。这是清理过的bindings.rs代码:
pub const FOO_ANIMAL_UNDEFINED: u8 = 0; pub const FOO_ANIMAL_WALRUS: u8 = 1; pub const FOO_ANIMAL_DROP_BEAR: u8 = 2;extern "C" { /// Argument should be one of FOO_ANIMAL_XXX pub fn feed(animal: u8); }
等一下。函数签名说它需要一个u8,但是文档说参数应该是FOO\u ANIMAL\u XXX中的一个(为了我们自己的理智,假设它可以安全地处理未定义的情况)。如果我们让我们的安全代码以任意的u8作为输入运行,这不仅令人困惑,而且有潜在的危险。听起来我们的安全包装应该采取动物枚举和转换它。
我们可以手工写这个枚举。但是让我们使用enum_原语板条箱来给我们一些额外的灵活性。(为了简洁起见,我省略了rustdoc字符串,不过您应该在实际代码中包含它们):
use enum_primitive::*;enum_from_primitive! { #[derive(Debug, Copy, Clone, PartialEq)] #[repr(u8)] pub enum Animal { Undefined = FOO_ANIMAL_UNDEFINED, Walrus = FOO_ANIMAL_WALRUS, DropBear = FOO_ANIMAL_DROP_BEAR, } }
因为我们将结构标记为“representable as a u8”,所以一个简单的cast就足以将动物转换成u8。现在我们可以这样写我们的安全包装:
pub fn feed(animal: Animal) {
unsafe { libfoo_sys::feed(animal as u8) }
}
enum_primitive板条箱还为我们提供了一些有用的样板函数,用于将u8转换为选项<Animal>。如果函数返回实际应视为枚举类型的u8值,则可能需要这样做。有一个问题:如果提供的数字与枚举值不匹配,则从数字类型的转换可能会失败。这取决于您的代码是否立即展开并惊慌失措,是否用默认值替换None(“Unknown”如果存在可以使用,如果不存在可以添加),或者只是返回选项并让调用者处理它。
返回指针的初始值设定项
在接下来的几个示例中,我将使用一个非常著名和非常粗糙的库作为示例:OpenSSL。(请不要自己为OpenSSL实现绑定;有人已经实现了,而且做得更好。这只是一个很熟悉的例子。)
在使用OpenSSL加密或解密数据之前,首先需要调用一个函数来分配和初始化一些上下文。在我们的示例中,这个初始化是通过调用SSL\u CTX\u new来执行的。执行任何操作的每个函数都会获取一个指向此上下文的指针。当我们使用完这个上下文后,需要使用SSL\u CTX\u free清理和销毁上下文数据。
我们将创建一个结构来包装此上下文的生存期。我们将添加一个名为new的函数,它为我们进行初始化并返回这个结构。所有需要上下文指针的C库函数都将包装为trust函数taking&self并在结构上实现。最后,当我们的结构超出范围时,我们希望锈迹能自动清除。希望这应该是一个熟悉的软件模式:它是RAII。
我们的示例可能如下所示:
use failure::{bail, Error}; use openssl_sys as ffi;pub struct OpenSSL { // This pointer must never be allowed to leave the struct ctx: *mut ffi::SSL_CTX, }impl OpenSSL { pub fn new() -> Result<Self, Error> { let method = unsafe { ffi::TLS_method() }; // Manually handle null pointer returns if method.is_null() { bail!("TLS_method() failed"); } let ctx = unsafe { ffi::SSL_CTX_new(method) }; // Manually handle null pointer returns here if ctx.is_null() { bail!("SSL_CTX_new() failed"); } Ok(OpenSSL { ctx }) } }
我将ffi后面的C库调用命名为namespacking,以便更清楚地了解我们导入的内容与我们在包装器中定义的内容。我也作弊了一点,并使用保释失败板条箱-在真正的代码中,你会想定义一个错误类型,并使用它。是的,它看起来有点恶心,因为我们没有从我们的回报拆解选项类型的细节。我们必须手动检查一切。
请记住:包装不安全函数意味着您正在进行验证空指针和检查错误的艰苦工作。这正是包装器必须正确处理的类型。早期的恐慌远胜于默默地传递空指针或无效指针。我们也不能允许ctx指针从结构中复制出来,因为我们只能保证它在结构仍然存在时是有效的。
通过impl Drop的析构函数
另一端是清理。铁锈中的毁灭者是通过下降特性来处理的。我们可以为我们的结构实现Drop,这样铁锈就可以适当地破坏我们的句柄:
impl Drop for OpenSSL {
fn drop(&mut self) {
unsafe { ffi::SSL_CTX_free(self.ctx) }
}
}
Rust还可以防止drop被直接调用或两次调用,因此您不必玩一些技巧,比如在释放ctx之后手动将其置空。而且,与C++不同,析构函数不会因为隐形拷贝被创建和删除而被无形调用。
发送和同步
现在有了一个包含指针元素的结构。但是默认情况下,Rust会对如何在线程上下文中使用struct设置一些限制。为什么语言会这样做,为什么这很重要?
默认情况下,Rust假设原始指针不能在线程之间移动(!发送),并且不能在线程之间共享(!同步)。因为你的结构包含一个原始指针,所以它既不发送也不同步。这种保守的假设有助于防止外部C代码在crust提供的那些可爱的线程安全保证上到处乱跑。
如果你的对象没有被发送,那么你在线程程序中处理它的能力就会受到很大的限制——甚至无法将它包装在互斥锁中并在线程之间传递引用。但可能外部文档或对源代码的巧妙检查表明返回的上下文指针在线程之间移动是安全的。它还可以指示使用此上下文指针的函数在线程上下文中使用是否安全,即函数本身是线程安全的。Rust无法为您做出这些决定,因为它看不到库使用这些指针做了什么。
如果你能断言你的每一次使用(内部私有!)指针遵守这两条规则中的任何一条,你都可以直截了当地告诉我。正确地做出这种断言是困难的,如果不是危险的,并且灌输给你适当数量的恐惧Rust需要你使用不安全的关键字。
unsafe impl Send for MyStruct {}
unsafe impl Sync for MyStruct {}
假设您不允许以某种方式(通过访问器方法或通过标记结构成员pub)对指针进行外部访问,那么如果您可以做出以下断言,则可以安全地执行以下操作:
- 如果取消引用指针的C代码从未使用线程本地存储或线程本地锁定,则可以标记struct Send。许多库都是这样。
- 如果所有能够取消引用指针的C代码总是以线程安全的方式(即与safe-Rust一致)取消引用,则可以标记结构同步。大多数遵循此规则的库都会在文档中告诉您,并且它们在内部使用互斥锁来保护每个库调用。
返回指针的函数
假设我们已经用新的和drop实现建立了结构。我们很高兴地翻阅了接受这个上下文指针的函数列表,对于我们想要公开的每一个函数,我们正在针对我们的结构实现一个安全版本,它接受&self。然后我们遇到了这样的事情(为了简单起见是虚构的,但不远):
// Always returns valid data, never fails
SSL_CIPHER *SSL_CTX_get_cipher(const SSL_CTX *ctx);
我们显然不想从包装器中返回原始指针,这不太符合人体工程学。这样做的目的是确保库用户不必使用不安全的软件。
阅读文档后,我们发现SSL\u CIPHER是一个结构,只要SSL\u CTX没有被释放,返回的指针就有效。嘿,听起来像是一辈子的事。所以我们的第一种方法可能是这样的:
pub fn get_cipher(&self) -> &ffi::SSL_CIPHER {
unsafe {
let cipher = ffi::SSL_CTX_get_cipher(self.ctx);
// Dereference the pointer, then turn it into a reference.
// Remember: derefing a pointer is unsafe!
&*cipher
}
}
取消引用然后立即获取指针的地址会创建一个所谓的无限生存期。这不是我们想要的,所以我们立即通过返回类型来约束生存期。我们没有明确指定生存期,但是让我们回顾一下Rust手册中关于生存期省略的规则。在这种情况下,返回值的生存期将被默认约束为与&self的生存期相同。这是一个合理的界限,所以这个实现看起来是安全的。
但我们可以更进一步。SSL\u密码通常用作上下文指针,并具有自己的关联函数。实际上,让我们的安全代码返回对C结构的引用根本不符合人体工程学。我们要返回的是一个Rust结构,它自身的关联行为与C库匹配。但我们也应该保留生存期关联:“只有从中获取密码的OpenSSL对象仍然存在,这个密码对象才有效。”
因此,假设我们已经完成了创建一个密码结构来包装指针的工作,并且我们想告诉Rust这个结构有某种依赖于OpenSSL对象的生存期:
pub fn get_cipher<'a>(&'a self) -> Cipher<'a> { unsafe { let cipher = ffi::SSL_CTX_get_cipher(self.ctx); Cipher::from(&self, cipher) } }// Something is missing here... pub struct Cipher<'a> { cipher: *const ffi::SSL_CIPHER, }fn from<'a>(_: &'a OpenSSL, cipher: *const ffi::SSL_CIPHER) -> Cipher<'a> { Cipher { cipher } }
不幸的是,这不会编译,因为Rust说“嘿,你声明了一个与你的结构相关联的生存期,但是它没有在任何地方使用!“所以我们需要以某种方式声明,是的,内部依赖于一个我们不能立即看到的引用。
use std::marker::PhantomData;pub struct Cipher<'a> { cipher: *const ffi::SSL_CIPHER, phantom: PhantomData<&'a OpenSSL>, }fn from<'a>(_: &'a OpenSSL, cipher: *const ffi::SSL_CIPHER) -> Cipher<'a> { Cipher { cipher, phantom: PhantomData } }
您可以将其视为对编译器说:“将此结构视为包含对OpenSSL的引用,其生存期为'a'。这一生从何而来?当我们打电话给我们的发件人时,我们会提供它。
幻影数据实际上并不占用任何空间,它会在编译代码中消失。但它允许编译器对生存期的正确性进行推理。现在,我们的包装器用户不能在释放其父级OpenSSL后意外地持有密码。
可能返回错误的函数
考虑以下C函数:
int foo_get_widget(const foo_ctx_t*, widget_struct*);
我们需要传递一个指针,函数将填充它。如果此函数返回0,则一切正常,我们可以相信输出已正确填充。否则,我们需要返回一个错误。
更符合人体工程学的做法是返回一个拥有数据的结构,而不是要求调用方创建一个可变结构并传递一个mut引用(尽管如果这样做有意义的话,您可以同时提供这两个结构)。
在下面的示例中,我假设自定义错误类型是在其他地方定义的,并且允许从适当的类型进行转换。
use std::mem::MaybeUninit;pub fn get_widget(&self) -> Result<widget_struct, GetError> { let mut widget = MaybeUninit::uninit(); unsafe { match foo_get_widget(self.context, widget.as_mut_ptr()) { 0 => Ok(widget.assume_init()), x => Err(GetError::from(x)), } } }
Ed:感谢reddit/u/Cocalus指出mem::uninitialized()已被弃用。希望我能修好!
上面,widget_struct不实现Default,因为“Default”和零化构造函数都没有意义。相反,我们告诉Rust不要初始化结构内存,因此我们断言外部函数负责正确初始化结构的每个字段。
有些函数不返回任何有用的信息,但仍然可能出错。
int foo_update(const foo_ctx_t*);
您可能会尝试将整数值转换为枚举类型,然后使用它。别那么做!正确编写的代码会在出现故障时返回结果,您也应该这样做。但是“成功”的价值观呢?为此,我们应该使用()告诉调用者没有返回数据。但是调用者仍然需要打开包装或者处理错误。
update(&self) -> Result<(), UpdateError> {
match unsafe { foo_update(self.context) } {
0 => Ok(()),
x => Err(UpdateError::from(x)),
}
}
FFI中的字符串
Rust不像C那样将字符串存储为以null结尾的char缓冲区;它在内部存储缓冲区和长度。因为类型并没有完全对齐,这意味着从Rust字符串的世界移到C char数组,再移回来需要一些技巧。谢天谢地,有一些内置类型可以帮助管理它,但是它们附带了很多字符串。有些转换分配(因为它们需要改变字符串表示或添加终止null),有些则不分配。有时不做拷贝就可以安全地逃脱,有时则不然。文档确实解释了哪个是哪个,但是有很多东西需要通读。这是执行摘要。
如果您以某种方式生成了一个Rust字符串,并且需要将它作为临时const*c\u char传递给c代码(这样它就可以制作一个字符串的副本供自己使用),那么您可以将它转换为CString,然后作为\u ptr调用。如果包装器签名借用了&str,则首先转换为&CStr,然后作为\u ptr调用。这两种情况下的指针只有在Rust引用正常有效时才有效。原始指针剥离了借用检查器的安全性,并要求我们自己维护这个不变量。如果你搞砸了,铁锈帮不了你。
对于从C函数中获取const char*并希望将其转换为Rust可以使用的内容的情况,需要确保它不为null,然后将其转换为具有适当生存期的&CStr。如果你不知道如何表达一个合适的生命周期,最安全的方法就是立即将它转换成一个拥有的字符串!
需要注意的其他事项:
- CString::因为ptr有一把手枪,很难正确使用。阅读文档中标记为WARNING的部分,并确保CString在C代码返回之前一直在作用域中。
- trust字符串可以合法地在中间有一个空的\0字节,但是C字符串不能(因为它会终止字符串)。因此,尝试将&str转换为&CStr或将字符串转换为CString可能会失败。你的代码需要处理这个问题。
- 一旦将原始C指针转换为&CStr,在将其用作本机safe Rust中的&str之前,仍然需要执行(或不安全地跳过)一些验证。C使用任意字符串编码,而Rust字符串总是UTF-8。现在大多数C库都返回有效的UTF-8字符串(ASCII是一个子集,所以即使是传统的应用程序也可以)。允许分配的函数(如CStr::to \u str \u lossy)将在必要时用UTF“替换字符”替换无效字符,而其他函数如CStr::to \u str将只返回一个结果。阅读文档,并根据需要选择正确的函数。
- 如果库返回路径,请在包装器中使用OsString和&OsStr,而不是String和&str。
数组和长度
如果库接受指向T的指针和长度,那么很容易实现一个包装器,该包装器接受一个切片并将其分解为指针和长度。但反过来呢?原来还有一个库函数。请记住检查null,确保大小是元素数,并再次检查返回生存期是否正确。同样,如果不能保证生存期的正确性,只需返回一个拥有的集合,比如Vec。
回调
回调签名通常作为bindgen中的选项<unsafe extern“C”fn…>生成。因此,当您使用Rust编写回调时,显然需要使用不安全的extern“C”来装饰它们(它们不需要是pub),然后当您将它们传递到C库时,只需将名称包装在一些文件中。很简单。
问题是,在C代码中释放恐慌是…好吧,我们就说它是坏的。理论上,恐慌几乎可以发生在Rust代码的任何地方。所以为了安全起见,我们需要把我们的身体包在里面。通常情况下,抓住恐慌是不明智或理智的,但这是例外。没有双关语。
unsafe extern "C" fn foo_fn_cb_wrapper() {
if let Err(e) = catch_unwind(|| {
// callback body goes here
}) {
// Code here must be panic-free.
// Sane things to do:
// log failure and/or kill the program
eprintln!("{:?}", e);
// Abort is safe because it doesn't unwind.
std::process::abort();
}
}
常见模式
在编写这些包装器时,您可能会遇到一些可以在函数或宏中轻松表达的模式。例如,库函数可能总是返回一个int,它总是表示同一组非零错误。编写一个调用不安全代码并将返回结果强制转换为Result<()、LibraryError>的私有宏可以节省大量样板文件。注意这些构造,通过一点重构,您可以节省自己几个小时的工作。
我不会撒谎的。正确地做这件事需要做很多工作。但是正确的操作会产生无bug的代码。如果您的C库是实心的,并且包装层是正确的,那么您将不会看到一个分段错误或缓冲区溢出。您将立即看到任何错误。当你在应用程序代码中犯了以前的指针错误时,它根本不会编译;当应用程序代码编译时,它只会工作。
原文:https://medium.com/dwelo-r-d/wrapping-unsafe-c-libraries-in-rust-d75aeb283c65
本文:http://jiagoushi.pro/node/1451
讨论:请加入知识星球【全栈和低代码开发】或者微信【it_training】或者QQ群【11107767】
- 57 次浏览
【编程语言】Rust 1.50到Rust 1.58.1的新增功能
与 C、C++、Go 和您可能使用的其他语言相比,Rust 编程语言的独特方法可以生成更好的代码,并且妥协更少。 它还会定期更新,通常是每月更新一次。
在哪里下载最新的 Rust 版本
如果您已经通过 rustup 安装了以前版本的 Rust,您可以通过以下命令访问最新版本:
$ rustup update stable
Rust 1.58.1 中的新功能
该版本于 2022 年 1 月 20 日发布,就在 Rust 1.58 之后的几天,修复了 std::fs::remove_dir_all 标准库函数中的竞争条件。此漏洞在 CVE-2022-21658 中进行了跟踪,并发布了公告。攻击者可以利用此安全问题诱使特权程序删除攻击者无法访问或删除的文件和目录。 Rust 1.0 到 1.58 版本受此漏洞影响。建议用户更新他们的工具链并使用更新的编译器构建程序。
Rust 1.58.1 还解决了 Rust 1.58 中引入的诊断和工具中的几个回归问题:
- non_send_fields_in_send_ty Clippy lint 被发现误报过多,已被移至名为“nursery”的实验性 lints 组。
- useless_format Clippy lint 已更新以处理格式字符串中捕获的标识符,这是在 Rust 1.58 中引入的。
- 修复了 Rustfmt 中的回归,防止生成的文件在通过标准输入时被格式化。
- rustc 在某些情况下显示的错误消息已得到修复。
Rust 1.58 中的新功能
1 月 13 日宣布的 Rust 1.58 具有以格式字符串捕获的标识符。有了这个功能,格式字符串现在可以通过在字符串中写入 {ident} 来捕获参数。格式早已接受位置参数和命名参数,例如:
println!("Hello, {}!", get_person()); // implicit position println!("Hello, {0}!", get_person()); // explicit index println!("Hello, {person}!", person = get_person()); // named
现在,命名参数也可以从周围的范围中捕获。
Rust 1.58 中的另一个新功能:在 Windows 目标上,std::process::Command 将不再在当前目录中搜索可执行文件,这是 win32 CreateProcess API 历史行为的影响。 这修复了在处理不受信任的目录时搜索可能导致意外行为或恶意结果的情况。
Rust 1.58 还在标准库中引入了更多的#[must_use]。 #[must use] 属性可以应用于类型或函数,如果没有明确考虑它们或者它们的输出几乎可以肯定是一个错误。 Rust 1.58 还具有稳定的 API,例如 Metadata::is_symlinkcode 和 Path::is_symlink。
Rust 1.57 中的新功能
12 月 2 日发布的 Rust 1.57 带来了恐慌! (用于终止处于不可恢复状态的程序)到 const 上下文。以前,恐慌!宏在 const fn 和其他编译时上下文中不可用。现在这已经稳定下来。随着 panic! 的稳定化,其他几个标准库现在可以在 const 中使用,例如 assert!。但这种稳定性还不包括完整的格式化基础设施。恐慌!必须使用静态字符串或要与 {} 一起使用的单个插值来调用宏。预计这种支持将在未来扩大。
Rust 1.57 中的其他新功能和改进:
- Cargo 增加了对任意命名配置文件的支持。
- 对于 Vec、String、HashMap、HashSet 和 VecDeque,try_reserve 已经稳定。此 API 使调用者能够错误地为这些类型分配后备存储。
- 其他多个 API 已稳定,包括 [T; N]::as_mut_slice 和 [T; N]::as_slice。
- 宏属性现在可以跟随#derive 并且将看到原始输入。
Rust 1.56 中的新功能
10 月 21 日宣布,Rust 1.56 是支持 Rust 2021 版本的语言的第一个版本。 Rust 2021 版允许 Rust crate 作者选择中断语言更改,使 Rust 更易于使用和更一致。 crates 可以随时选择加入,并保持与旧版本中的 crates 的互操作性。 Rust 编译器支持该语言的所有三个版本:2015、2018 和 2021。
Rust 1.56 中的其他新功能包括:
- 闭包中的不相交捕获,以简化闭包的编写。
- Cargo.toml 现在支持 [package] [rust-version] 字段来指定 crate 支持的最低 Rust 版本,如果不满足,Cargo 将退出并出现早期错误。虽然目前这不会影响依赖解析器,但其目的是在兼容性问题变成隐秘的编译器错误之前捕获它们。
- 支持 binding@pattern 中的新绑定。 Rust 模式匹配可以使用绑定整个值的单个标识符编写,然后是 @ 和更完善的结构模式,但直到现在才允许在该模式中进行其他绑定。此功能在 Rust 1.0 之前已被允许,但由于不健全而被删除。编译器团队现在已经确定这种模式在稳定的 Rust 中是安全且允许的。
- 恐慌宏现在总是需要格式字符串,就像 printlin!()。
- 许多 API 已经稳定,包括 std::os::unix::fs::chroot 和 UnsafeCell::raw_get。
Rust 1.55 中的新功能
2021 年 9 月 9 日宣布,Rust 1.55 提供更快、更正确的浮点解析。浮点解析的标准库实现已更新为使用 Eisel-Lemire 算法,这带来了速度和正确性的改进。以前,某些边缘情况无法解析,但现在已修复。
同样在 Rust 1.55 中:
- 模式中开放范围的使用已经稳定。
- 许多方法和特征实现已经稳定,包括 Bound::cloned 和 Drain::as_str。
- Cargo 现在对编译器错误进行重复数据删除,并在编译结束时打印报告。以前,当运行 cargo test、cargo check ---所有目标或在多个配置中构建相同 Rust crate 的类似命令时,错误和警告可能会重复出现,因为 rustc 执行并行运行并显示相同的警告。
Rust 1.54 中的新功能
7 月 29 日发布,Rust 1.54 支持在属性中调用类似函数的宏。类函数宏可以是基于宏规则的宏!或者它们可以是过程宏,像宏一样调用!(…)。一个值得注意的用例是将其他文件中的文档包含到 Rust 文档注释中。
Rust 1.54 中的其他新特性:
- wasm32 平台的一些内在函数已经稳定。这些可以访问 WebAssembly 中的 SIMD 指令。
- 默认情况下重新启用增量编译。它在 Rust 1.52.1 中默认被禁用。在 Rust 1.52 中,在从磁盘缓存加载增量编译时添加了额外的验证,导致在验证将这些静默错误变为内部编译器错误 (ICE) 时发现了预先存在的潜在健全性问题。从那时起,已经完成了解决这些问题的工作,一些修复在 Rust 1.53 中登陆,大多数修复在 Rust 1.54 中。可能导致 ICE 的剩余问题在实践中被认为是罕见的。
- 多种方法和特征实现已经稳定。
- 编译器输出已针对调试 C++ 的 Windows MSVC 平台上的枚举进行了改进。
Rust 1.54 紧随 6 月 17 日发布的 Rust 1.53,其中包含语言和库功能,包括数组的 IntoIterator 实现。
Rust 1.52 中的新功能
在 5 月 6 日推出的 Rust 1.52 是通过对 Clippy 工具支持的增强来领导的,Clippy 是用于查找错误和改进 Rust 代码的 lint 集合。以前,运行 cargo check 后跟 cargo clippy 实际上不会运行 Clippy,Cargo 中的构建缓存不会区分两者。这已在 Rust 1.52 中修复。同样在 1.52 版本中,稳定了以下方法:
Arguments::as_str
char::MAX
char::REPLACEMENT_CHARACTER
char::UNICODE_VERSION
char::decode_utf16
char::from_digit
char::from_u32_unchecked
char::from_u32
slice::partition_point
str::rsplit_once
str::split_once
几个以前稳定的 API,包括 char::len_utf8 和 u8LLeq_ignore_ascii_case,现在都是 const。 对于编译器,默认 LLVM 已升级到 LLVM 12。该语言的后续版本 Rust 1.52.1 于 5 月 10 日发布,为增量编译中的错误提供了一种解决方法,该错误在 Rust 1.52 中成为编译器错误 .0. Rust 构建者建议升级到 1.52.1 或禁用增量编译。
Rust 1.51.0 中的新功能
发布于 2021 年 3 月 25 日,Rust 1.51.0 版本是相当长一段时间以来对语言和 Cargo 包管理器的最大补充之一,它稳定了 const 泛型的 MVP(最小可行产品)实现和新的功能解析器 货运是亮点之一。 其他亮点:
-
使用 const generics MVP,为库设计者添加了一个用于开发编译时安全 API 的工具。一个备受期待的特性,const 泛型是泛型参数,其范围是常量值,而不是类型或生命周期。例如,这允许类型通过整数参数化。计划是逐步引入 const 泛型,因此目前唯一可以用作 const 泛型参数的类型是整数类型,包括 size、usize、char 和 bool。
-
除了 const 泛型,还稳定了一个使用它的新 API,std::array::IntoIter,它允许开发人员在任何数组上创建按值迭代器。
-
对于 Cargo,新的特征解析器引入了一种用于计算包特征的算法,以帮助避免与当前解析器的一些不必要的统一。
-
改进了 MacOS 上的编译时间,改进了包含调试信息的构建速度并减少了使用的磁盘空间量。
-
除了类型和生命周期之外,函数、特征和结构等项目还可以通过常量值进行参数化。
-
稳定的 API,包括稳定切片和 Peekable 等类型的 18 种新方法。
Rust 1.50.0 中的新功能
发布于 2021 年 2 月 11 日,Rust 1.50.0 改进了数组索引,扩展了对联合字段的安全访问,并添加到标准库中。具体改进包括:
-
对于 const 泛型数组索引,此版本继续向稳定的 const 泛型发展,为数组添加 ops::Index 和 IndexMut 的实现 [T; N] 对于任何长度的 Const N。索引运算符 [ ] 已经通过编译器对数组起作用,但在类型级别,数组直到现在才真正实现库特征。此外,正式承认在数组重复中稳定使用 const 值。
-
允许对 ManuallyDrop<T> 联合字段进行安全分配。
-
现在允许在 Unix 平台上使用 File。有了这个特性,Rust 中的某些类型对什么是有效值有限制,这可能无法涵盖可能的内存值范围。任何剩余的有效值都称为利基,该空间可用于类型布局优化。在 Unix 平台上,Rust 的 File 由系统的文件整数描述符组成;这恰好有一个可能的利基,因为它不能是-1!返回文件描述符的系统调用使用 -1 来指示发生了错误,因此 -1 永远不可能是真正的文件描述符。从 Rust 1.50 开始,它被添加到类型定义中,因此它也可以用于布局优化。因此,Option<File> 现在将具有与 File 相同的大小。
-
对于 Cargo,添加了一个 [rustc-workspace-wrapper] 选项,以设置一个包装器来执行而不是 rustc,仅适用于工作区成员。此外,在 cargo update 命令中添加了 --workspace 标志。
-
库中添加了九个新的稳定函数:bool::then、btree_map::Entry::or_insert_with_key、f32::clamp、f64::clamp、hash_map::Entry::or_insert_with_key、Ord::clamp、RefCell::take 、 slice::fill 和 UnsafeCell::get_mut。
-
同样在库中,几个现有函数被设为 const:IpAddr::is_ipv4、IpAddr::is_ipv6、Layout::size、Layout::align、Layout::from_size_align、pow 用于所有整数类型、checked_pow 用于所有整数类型、saturating_pow对于所有整数类型,wrapping_pow 对于所有整数类型,next_power_of_two 对于所有无符号整数类型,checked_power_of_two 对于所有无符号整数类型。
原文:https://www.infoworld.com/article/3267624/whats-new-in-the-rust-language.html
本文:https://jiagoushi.pro/node/1811
- 32 次浏览
TypeScript开发
TypeScript 是由 Microsoft 开发和维护的免费开源编程语言。 它是 JavaScript 的严格语法超集,并为该语言添加了可选的静态类型。 它专为开发大型应用程序和转译为 JavaScript 而设计。 由于它是 JavaScript 的超集,现有的 JavaScript 程序也是有效的 TypeScript 程序。
TypeScript 可用于开发用于客户端和服务器端执行的 JavaScript 应用程序(与 Node.js 或 Deno 一样)。 有多个选项可用于转译。 可以使用默认的 TypeScript 编译器, 或调用 Babel 编译器将 TypeScript 转换为 JavaScript。
TypeScript 支持可以包含现有 JavaScript 库类型信息的定义文件,很像 C++ 头文件可以描述现有对象文件的结构。 这使其他程序能够使用文件中定义的值,就好像它们是静态类型的 TypeScript 实体一样。 jQuery、MongoDB 和 D3.js 等流行库都有第三方头文件。 Node.js 库模块的 TypeScript 标头也可用,允许在 TypeScript 中开发 Node.js 程序。
TypeScript 编译器本身用 TypeScript 编写并编译为 JavaScript。 它根据 Apache License 2.0 获得许可。 Anders Hejlsberg 是 C# 的首席架构师,也是 Delphi 和 Turbo Pascal 的创建者,他一直致力于 TypeScript 的开发。
历史
经过两年的 Microsoft 内部开发,TypeScript 于 2012 年 10 月向公众发布了 0.8 版。在最初的公开发布后不久,Miguel de Icaza 称赞了语言本身,但批评了除了当时在 Linux 和 OS X 上不可用的 Microsoft Visual Studio 之外缺乏成熟的 IDE 支持。截至 2021 年 4 月,其他 IDE 和文本编辑器都支持,包括 Emacs、Vim、WebStorm、Atom 和微软自己的 Visual Studio Code。2013 年发布的 TypeScript 0.9 增加了对泛型的支持。
TypeScript 1.0 于 2014 年在微软的 Build 开发者大会上发布。 Visual Studio 2013 Update 2 提供了对 TypeScript 的内置支持。 2014 年 7 月,开发团队宣布了一个新的 TypeScript 编译器,并声称其性能提高了五倍,进一步改进。 同时,最初托管在 CodePlex 上的源代码已移至 GitHub。
2016 年 9 月 22 日,TypeScript 2.0 发布,引入了多项功能,包括程序员可选择强制执行空安全的能力, 有时被称为十亿美元的错误。
TypeScript 3.0 于 2018 年 7 月 30 日发布, 带来了许多语言添加,例如剩余参数和展开表达式中的元组、具有元组类型的剩余参数、通用剩余参数等。
TypeScript 4.0 于 2020 年 8 月 20 日发布。虽然 4.0 没有引入任何重大变化,但它添加了语言特性,例如自定义 JSX 工厂和可变元组类型。
设计
TypeScript 起源于 JavaScript 在 Microsoft 及其外部客户中用于开发大型应用程序的缺点。 [26] 处理复杂 JavaScript 代码的挑战导致了对自定义工具的需求,以简化语言中组件的开发。
TypeScript 开发人员寻求一种不会破坏与标准及其跨平台支持的兼容性的解决方案。 知道当前的 ECMAScript 标准提案承诺未来支持基于类的编程,TypeScript 就基于该提案。 这导致了一个带有一组语法语言扩展的 JavaScript 编译器,一个基于提案的超集,它将扩展转换为常规 JavaScript。 从这个意义上说,TypeScript 的类特性是对 ECMAScript 2015 的预期的预览。提案中没有但添加到 TypeScript 的一个独特方面是可选的静态类型(也称为渐进类型),它支持静态语言分析以促进 工具和 IDE 支持。
ECMAScript 2015 支持
主条目:ECMAScript § 6th Edition - ECMAScript 2015
TypeScript 添加了对 ECMAScript 2015 标准中定义的类、模块和箭头函数语法等功能的支持。
特征
TypeScript 是一种语言扩展,它为 ECMAScript 6 添加了功能。其他功能包括:
- 类型注释和编译时类型检查
- 类型推断
- 类型擦除
- 接口
- 枚举类型
- 泛型
- 命名空间
- 元组
- 异步/等待
以下功能是从 ECMAScript 2015 向后移植的:
- 类
- 模块
- 匿名函数的缩写“箭头”语法
- 可选参数和默认参数
在句法上,TypeScript 与 JScript .NET 非常相似,后者是 ECMA-262 语言标准的另一种 Microsoft 实现,它增加了对静态类型和经典的面向对象语言功能(如类、继承、接口和命名空间)的支持。
与 JavaScript 的兼容性
TypeScript 是 ECMAScript 2015 的严格超集,ECMAScript 2015 本身是 ECMAScript 5 的超集,通常称为 JavaScript。 因此,JavaScript 程序也是有效的 TypeScript 程序,并且 TypeScript 程序可以无缝地使用 JavaScript。 默认情况下,编译器以当前流行的标准 ECMAScript 5 为目标,但也能够生成 ECMAScript 3 或 2015 中使用的结构。
使用 TypeScript,可以使用现有的 JavaScript 代码,合并流行的 JavaScript 库,并从其他 JavaScript 调用 TypeScript 生成的代码。 [30] 这些库的类型声明随源代码一起提供。
类型注解
TypeScript 通过类型注释提供静态类型,以在编译时启用类型检查。 这是可选的,可以忽略以使用 JavaScript 的常规动态类型。
function add(left: number, right: number): number { return left + right; }
基本类型的注释是数字、布尔值和字符串。 Typescript 还支持具有以下注释的数据类型 Array、Enums、void。
其他数据类型有:Tuple、Union、never 和 any。 在每个索引处具有预定义数据类型的数组是元组类型。 保存不止一种类型数据的变量是 Union 类型。 当您确定某事永远不会发生时,您可以使用 never type。 弱类型或动态类型的结构是任何类型。
可以将类型注释导出到单独的声明文件,以便使用已编译到 JavaScript 中的类型为 TypeScript 脚本提供类型信息。 可以为现有的 JavaScript 库声明注释,就像对 Node.js 和 jQuery 所做的那样。
TypeScript 编译器在未给出类型时使用类型推断来推断类型。 例如,即使没有提供返回类型注释,上面代码中的 add 方法也会被推断为返回一个数字。 这是基于 left 和 right 的静态类型是数字,并且编译器知道两个数字相加的结果始终是一个数字。 但是,显式声明返回类型允许编译器验证正确性。
如果由于缺少声明而无法推断出任何类型,则它默认为动态任意类型。 any 类型的值支持与 JavaScript 中的值相同的操作,并且对任何值的操作执行最少的静态类型检查。
声明文件
编译 TypeScript 脚本时,可以选择生成一个声明文件(扩展名为 .d.ts),该文件用作已编译 JavaScript 中组件的接口。 在此过程中,编译器剥离所有函数和方法体,仅保留导出类型的签名。 当第三方开发人员从 TypeScript 使用它时,生成的声明文件可用于描述 JavaScript 库或模块的导出虚拟 TypeScript 类型。
声明文件的概念类似于 C/C++ 中的头文件的概念。
declare namespace arithmetics { add(left: number, right: number): number; subtract(left: number, right: number): number; multiply(left: number, right: number): number; divide(left: number, right: number): number; }
可以为现有的 JavaScript 库手动编写类型声明文件,就像 jQuery 和 Node.js 所做的那样。
流行 JavaScript 库的大量声明文件托管在 GitHub 上的 DefinitelyTyped 中。
类
TypeScript 支持集成可选类型注释支持的 ECMAScript 2015 类。
class Person { private name: string; private age: number; private salary: number; constructor(name: string, age: number, salary: number) { this.name = name; this.age = age; this.salary = salary; } toString(): string { return `${this.name} (${this.age}) (${this.salary})`; // As of version 1.4 } }
泛型
TypeScript 支持泛型编程。下面是身份函数的一个例子。 [34]
function id<T>(x: T): T { return x; }
联盟类型
本节摘自 Union type § TypeScript。[编辑]
TypeScript 支持联合类型。 这些值被语言隐式地“标记”为类型,并且可以通过“typeof()”检索。
function successor(n: number | bigint): number | bigint { return ++n }
模块和命名空间
TypeScript 区分模块和命名空间。 TypeScript 中的两个特性都支持将类、接口、函数和变量封装到容器中。 命名空间(以前称为内部模块)利用 JavaScript 的立即调用函数表达式来封装代码,而模块(以前称为外部模块)利用 JavaScript 库模式(AMD 或 CommonJS)来封装代码。
开发工具
编译器
名为 tsc 的 TypeScript 编译器是用 TypeScript 编写的。 因此,它可以被编译成常规的 JavaScript,然后可以在任何 JavaScript 引擎(例如浏览器)中执行。 编译器包捆绑了一个可以执行编译器的脚本宿主。 它也可以作为使用 Node.js 作为主机的 Node.js 包使用。
当前版本的编译器默认支持 ECMAScript 5。 允许一个选项以 ECMAScript 2015 为目标,以使用该版本独有的语言功能(例如生成器)。 尽管类是 ECMAScript 2015 标准的一部分,但在两种模式下都可用。
IDE 和编辑器支持
- Microsoft 为 Visual Studio 2012 和 WebMatrix 提供插件,在 Visual Studio 2013、Visual Studio 2015 中提供全面集成支持,并为 Emacs 和 Vim 提供基本的文本编辑器支持。
- Visual Studio Code 是微软基于 Electron 开发的(大部分)开源、跨平台的源代码编辑器。 除了其他几种语言外,它还支持 TypeScript,并提供调试和智能代码完成等功能。
- alm.tools 是一个用于 TypeScript 的开源云 IDE,使用 TypeScript、ReactJS 和 TypeStyle 构建。
- JetBrains 在其基于 IntelliJ 平台构建的 IDE(例如 PhpStorm 6、WebStorm 6 和 IntelliJ IDEA)及其 Visual Studio 插件和扩展 ReSharper 8.1中通过代码完成、重构和调试支持 TypeScript。 ]
- Atom 有一个 TypeScript 插件,支持代码完成、导航、格式化和快速编译。
- 在线 Cloud9 IDE 和 Codenvy 支持 TypeScript。
- NetBeans IDE 有一个插件可用。
- 一个插件可用于 Eclipse IDE(Kepler 版本)
- TypEcs 可用于 Eclipse IDE。
- 跨平台云 IDE Codeanywhere 支持 TypeScript。
- Webclipse 一个 Eclipse 插件,旨在开发 TypeScript 和 Angular 2。
- Angular IDE 一个独立的 IDE,可通过 npm 用于开发 TypeScript 和 Angular 2 应用程序,具有集成的终端支持。
- Tide – Emacs 的 TypeScript 交互式开发环境。
与构建自动化工具集成
使用插件,TypeScript 可以与构建自动化工具集成,包括 Grunt (grunt-ts)、Apache Maven (TypeScript Maven Plugin)、Gulp (gulp-typescript) 和 Gradle (TypeScript Gradle 插件 )。
linting 工具
TSLint扫描 TypeScript 代码是否符合一组标准和指南。 ESLint 是一种标准的 JavaScript linter,它还通过社区插件为 TypeScript 提供了一些支持。 然而,ESLint 无法利用 TypeScript 的语言服务,因此排除了某些形式的语义检查和程序范围的分析。2019 年初,TSLint 团队宣布弃用 linter,转而使用 typescript-eslint,这是 TSLint、ESLint 和 TypeScript 团队的共同努力,旨在将 linting 整合到 ESLint 保护伞下,以提高性能、社区团结和开发人员可访问性。
- 53 次浏览
【NestJS 】NestJS 及其对后端开发人员的优势
NestJS 是一个框架,用于构建高效且可扩展的 Node.js 服务器端应用程序,该应用程序由 TypeScript 构建并完全支持。它使用强大的 HTTP 服务器框架,如 Express 或 Fastify。 Nest 在常见的 Node.js 框架之上提供了一个抽象级别,并将其 API 公开给开发人员。这为使用第三方模块提供了很大的自由。
选择 NestJS 而不是 ExpressJS(最流行的 Node.js 框架之一)的一个很好的理由是,当 Node.js 中的一个新项目启动时,它是一个基于几个简单组件(控制器、模块和提供程序)的清晰架构)。这很容易将应用程序拆分为微服务。
您想知道为什么选择 NestJS 作为您的后端框架吗?继续阅读。
什么是 NestJS?
如前所述,NestJS 是一个开源、可扩展、通用、渐进的 Node.js 框架,用于创建引人注目且要求苛刻的后端系统。它是目前 TypeScript 中增长最快的 Node.js 框架。
NestJS 用于编写可扩展、可测试和松耦合的应用程序。它将可扩展的 Node.js 服务器提升到了一个全新的水平。它支持 PostgreSQL、MongoDB、MySQL 等数据库。 NestJS 深受 Angular、React 和 Vue 的影响,并提供开箱即用的依赖注入。
截至 2022 年 1 月,它拥有超过 44k 的 GitHub 星,其每周 npm 下载率接近 180k。它鼓励开发人员尝试、学习和使用一些著名的软件开发范例,其文档包含大量示例、配方和代码源。
NestJS 易于扩展,因为它可以与其他库一起使用;由于其自适应的成熟生态系统和渐进式,带来了 JavaScript 功能和设计模式,因此具有多功能性。
NestJS 的构建块
- 模块:用于组织代码并将功能拆分为逻辑可重用单元。分组的 TypeScript 文件用“@Module”装饰器装饰,它提供了 Nest 用来组织应用程序结构的元数据。
- 提供者:也称为服务,旨在抽象任何形式的复杂性和逻辑。可以创建提供程序并将其注入控制器或其他提供程序。
- 控制器:负责处理传入的请求并将适当的响应返回到应用程序的客户端(例如对 API 的调用)。
NestJS 令人难以置信的功能
最近,NestJS 框架因其令人难以置信的特性而获得了极大的欢迎。他们之中有一些是:
- 它利用 TypeScript——强类型语言,它是 JavaScript 的超集
- 易于使用、学习和掌握
- 强大的命令行界面 (CLI) 可提高生产力并简化开发
- 详细且维护良好的文档
- 主动代码库开发和维护
- 它是开源的(MIT 许可证)
- 支持数十个特定于Nest的模块,可帮助您轻松与 TypeORM、Mongoose、GraphQL、日志记录、验证、缓存、WebSockets 等常见技术和概念集成
- 简单的单元测试应用程序
- 为单体和微服务创建(文档中有关 NestJS 应用程序的微服务类型以及技术和配方的完整部分
为什么选择 NestJS
Java 作为一种编程语言已有 20 多年的历史。多年来,它是创建业务应用程序的主要框架,但最近,焦点转移到了 Node.js。由于它的速度,Node.js 席卷了开发人员世界,让他们可以享受 JavaScript 的所有好处,并用相同的编程语言编写前端和后端。由于 NestJS 是 Node.js 中增长最快的框架,让我们谈谈为什么选择 NestJS 而不是您当前的框架的原因?
- 快速高效的开发过程。
- 高度可扩展且易于维护的应用程序。
- 过去 3 年来增长最快的 Node.js 框架。
- 大型社区和支持系统。
- Nest 将自己定位在前端和中端开发的独特十字路口,这是许多语言难以找到的。
- TypeScript 的使用有助于确保 Nest 在快速变化的 JavaScript 环境中保持相关性,并为开发人员提供更少的上下文切换。
- 很棒的文档。
- 简单的单元测试。
- 专为大型企业应用程序而构建。
- Nest 提供了一个开箱即用的应用程序架构,允许开发人员和团队创建高度可测试、可扩展、松散耦合和易于维护的应用程序。
- 使用 NestJS,您可以构建 Rest API、MVC 应用程序、微服务、GraphQL 应用程序、Web Sockets 或 CLI 和 CRON 作业。
- 它使用最好的 Node.js、TypeScript 和防弹架构模式。
- Nest 中的应用程序结构很大程度上基于 Angular。结构非常简单,可以更多地关注端点及其消费者的设计,而不是应用程序结构。
- NestJS 通过引入类似 Angular 的模块、服务和控制器来强制开发人员使用特定架构,确保应用程序具有可扩展性、高度可测试性和松散耦合,这与其他 Node.js 框架(如 Express 或 Koa)相反关于架构的项目可能会花费很多时间来重构代码库。
原文:https://blog.devgenius.io/nestjs-and-its-advantages-for-backend-develop…
- 459 次浏览
【.Net框架】什么是.NET Framework?
视频号
微信公众号
知识星球
NET Framework是一个用于在Windows上构建和运行应用程序的软件开发框架。
.NET Framework是.NET平台的一部分,.NET平台是一组用于构建Linux、macOS、Windows、iOS、Android等应用程序的技术。
.NET and .NET Framework
.NET is a developer platform made up of tools, programming languages, and libraries for building many different types of applications.
There are various implementations of .NET. Each implementation allows .NET code to execute in different places—Linux, macOS, Windows, iOS, Android, and many more.
- .NET Framework is the original implementation of .NET. It supports running websites, services, desktop apps, and more on Windows.
- .NET is a cross-platform implementation for running websites, services, and console apps on Windows, Linux, and macOS. .NET is open source on GitHub. .NET was previously called .NET Core.
- Xamarin/Mono is a .NET implementation for running apps on all the major mobile operating systems, including iOS and Android.
.NET Standard is a formal specification of the APIs that are common across .NET implementations. This allows the same code and libraries to run on different implementations.
.NET框架的体系结构
.NET Framework的两个主要组件是公共语言运行库和.NET Framework类库。
- 公共语言运行库(CLR)是处理正在运行的应用程序的执行引擎。它提供诸如线程管理、垃圾收集、类型安全、异常处理等服务。
- 类库为通用功能提供了一组API和类型。它提供字符串、日期、数字等的类型。类库包括用于读写文件、连接数据库、绘图等的API。
.NET应用程序是用C#、F#或Visual Basic编程语言编写的。代码被编译成与语言无关的通用中间语言(CIL)。编译后的代码存储在程序集中——文件扩展名为.dll或.exe的文件。
当应用程序运行时,CLR获取程序集,并使用实时编译器(JIT)将其转换为可以在其运行的计算机的特定体系结构上执行的机器代码。
Read more: What is the .NET Framework
Release history
Version | Release date | End of support |
---|---|---|
.NET Framework 4.8.1 | August 9, 2022 | |
.NET Framework 4.8 | April 18, 2019 | |
.NET Framework 4.7.2 | April 30, 2018 | |
.NET Framework 4.7.1 | October 17, 2017 | |
.NET Framework 4.7 | April 5, 2017 | |
.NET Framework 4.6.2 | August 2, 2016 | |
.NET Framework 3.5 SP1 | November 18, 2008 | January 9, 2029 |
.NET Framework FAQ
What is .NET Framework used for?
.NET Framework is used to create and run software applications. .NET apps can run on many operating systems, using different implementations of .NET. .NET Framework is used for running .NET apps on Windows.
Who uses .NET Framework?
Software developers and the users of their applications both use .NET Framework:
- Users of applications built with the .NET Framework need to have .NET Framework installed. In most cases, .NET Framework is already installed with Windows. If needed, you can download .NET Framework.
- Software developers use .NET Framework to build many different types of applications—websites, services, desktop apps, and more with Visual Studio. Visual Studio is an integrated development environment (IDE) that provides development productivity tools and debugging capabilities. See the .NET customer showcase for examples of what people are building with .NET.
Why do I need .NET Framework?
You need .NET Framework installed to run applications on Windows that were created using .NET Framework. It's already included in many versions of Windows. You only need to download and install .NET Framework if prompted to do so.
How does .NET Framework work?
.NET Framework applications are written in C#, F#, or Visual Basic and compiled to Common Intermediate Language (CIL). The Common Language Runtime (CLR) runs .NET applications on a given machine, converting the CIL to machine code. See Architecture of .NET Framework for more info.
What are the main components/features of .NET Framework?
The two major components of .NET Framework are the Common Language Runtime (CLR) and the .NET Framework Class Library. The CLR is the execution engine that handles running applications. The Class Library provides a set of APIs and types for common functionality. See Architecture of .NET Framework for more info.
What is the difference between .NET and .NET Framework?
.NET and .NET Framework share many of the same components and you can share code across the two. Some key differences include:
- .NET is cross-platform and runs on Linux, macOS, and Windows. .NET Framework only runs on Windows.
- .NET is open-source and accepts contributions from the community. The .NET Framework source code is available but doesn't take direct contributions.
- All of the innovation happens in .NET.
- .NET Framework is included in Windows and automatically updated machine-wide by Windows Update. .NET is shipped independently.
See .NET vs. .NET Framework for server apps for more details.
Can you have multiple .NET Frameworks installed?
Some versions of .NET Framework are installed side-by-side, while others will upgrade an existing version (known as an in-place update). In-place updates occur when two .NET Framework versions share the same CLR version.
For example, installing .NET Framework 4.8 on a machine with .NET Framework 4.7.2 and 3.5 installed will perform an in-place update of the 4.7.2 installation and leave 3.5 installed separately.
.NET Framework version | CLR version |
---|---|
.NET Framework 4.x | 4.0 |
.NET Framework 2.x and 3.x | 2.0 |
.NET Framework 1.1 | 1.1 |
.NET Framework 1.0 | 1.0 |
How much does .NET Framework cost?
.NET Framework is free, like the rest of the .NET platform. There are no fees or licensing costs, including for commercial use. See .NET is free for more details.
Which version of .NET Framework should I use?
In most cases, you should use the latest stable release. Currently, that's .NET Framework 4.8.1 .
Applications that were created with any 4.x version of .NET Framework will run on .NET Framework 4.8.1 . To run an application that was created for an earlier version (for example, .NET Framework 3.5), you should install that version. See Download .NET Framework for a complete list.
What is the support policy for .NET Framework?
.NET Framework 4.8.1 is the latest version of .NET Framework and will continue to be distributed with future releases of Windows. As long as it is installed on a supported version of Windows, .NET Framework 4.8.1 will continue to also be supported.
- 26 次浏览
【编程语言】编程语言InfoQ趋势报告—2019年10月
关键的要点
- Elixir已进入趋势报告的创新者采用阶段。它是运行在Erlang虚拟机上的一种函数式、并发的通用编程语言。
- 我们看到人们对基础设施或特定于云的语言、dsl和sdk(如Ballerina和Pulumi)的兴趣和创新有所增加。
- 我们相信Rust已经从革新者阶段过渡到早期采用者阶段,这主要是由于它在基础设施和网络数据平面空间(例如,Habitat和Linkerd 2.0)中的应用。
- Python继续受到人们的欢迎,这主要归功于它在数据科学和教学中的作用。
- 由于iOS作为移动应用程序运行时的流行,iOS的开发已经向早期主流发展。虽然在JVM趋势报告中单独跟踪了Kotlin,但在Android应用程序开发方面,他也看到了类似的早期主流趋势。
- 对于.net,我们看到很多人对.net Core很感兴趣,而随着.net Core 3的到来,我们希望这种情况能够继续下去。
2019年及以后的编程语言趋势是什么?本报告旨在帮助技术领导者做出中长期的技术投资决策,并帮助个别开发人员识别流行的编程语言,并选择将他们宝贵的时间和资源投入到哪些新的编程语言学习和技能开发方面。
该报告总结了InfoQ编辑团队目前是如何看待编程语言领域中技术的采用和新兴趋势的,而不包括单独报告的Java / JVM和JavaScript / Web开发。这是一篇观点文章,由我们的编辑(他们本身也是活跃的软件工程师)与我们进行广泛的内部讨论,对外部公共调查结果的审查,以及对内部或私有调查和分析结果的审查形成。各种编辑谈话的摘录可以在下面找到。
InfoQ和QCon都关注我们认为属于革新者、早期采用者和早期主流阶段的主题。我们试图做的是找出符合杰弗里·摩尔(Geoffrey Moore)所说的“早期市场”的想法,在这个市场里,“客户基础是由技术爱好者和有远见的人组成的,他们要么想抓住机会,要么想解决迫在眉睫的问题。”我们还在寻找可能“跨越鸿沟”、被更广泛采纳的想法。值得指出的是,在这种情况下,技术在采用曲线上的确切位置可能不同。例如,Rust目前可能在旧金山湾区的公司中被广泛采用,但在其他地方可能不太被广泛采用。
自从我们发布了2018年内部编程趋势报告以来,发生了显著的变化,包括增加了几种语言,如Python、Ruby和PHP,这些语言虽然很流行,但我们并没有公开跟踪采用曲线。尽管与这些语言相关的技术和因素正在内部讨论,我们现在已经纠正了它们在趋势图上的缺失。
移动中的编程语言:Elixir、Rust和Swift
Elixir——一种函数式、并发的、通用编程语言——已经进入了创新者采用阶段的趋势报告。Elixir构建在Erlang之上(我们将其归入早期采用者类别),并运行在Erlang虚拟机上。Elixir和Erlang共享用于构建分布式容错应用程序的相同抽象。
我们认为,Rust已经从创新者转变为早期采用者,这主要是由于它在基础设施和网络数据平面空间(例如,Habitat和Linkerd 2.0)中的应用。这种语言也逐渐成为WebAssembly的天然合作伙伴,帮助提高人们的认识。此外,我们注意到Facebook选择使用Rust实现其Libra加密货币。
由于iOS作为移动应用程序运行时的流行,iOS的开发已经向早期主流发展。虽然我们没有在这个趋势类别中跟踪Kotlin,但是InfoQ Java和JVM趋势报告发现Kotlin越来越受欢迎,因为它现在是开发Android应用程序的默认语言。
基础设施的语言:芭蕾舞女,普鲁米,黑暗(Ballerina, Pulumi, Dark)
我们看到人们对基础设施/云目标语言、dsl以及类似Ballerina和Pulumi这样的sdk的兴趣越来越浓厚。我们也在追踪Dark,它目前处于内测阶段,所以还没有进入图表。这类技术目前正牢牢地扎根于创新者采用阶段,但我们正在密切关注这一阶段,并将于11月在旧金山的QCon上推出一个专门讨论“基础设施语言”的专题。
以下是我们2018年下半年的内部主题图。2019年的版本在文章的顶部。
2018年的编程语言
.net 2019年第三季度
对于。net,我们看到很多人对。net Core很感兴趣,而随着。net Core 3的到来,我们希望这种情况能够继续下去。我们把。net Core在图上分成了2x和3x两个分支,因为它们在采用上是不同的。关于。net语言,我们期待c# 8能很快被采用。我们继续对f#感兴趣,但是我们认为,f#的复杂性和缺乏来自微软的强大支持意味着它不太可能得到更广泛的采用。
我们有ASP。网芯早在多数。在这一点上,我们相信大多数新的web工作是在ASP上完成的。NET核心,但不一定是。NET核心。一些现有的应用程序正在被移植,但大多数不会。WCF在企业中仍然非常重要,但是MS在。net Core中并不能很好地支持它。我们已经把Visual Basic移到了落后的地方,并且在这一点上,我们真的把它看作是一种业余爱好者的语言。
以下是一系列经过简单编辑和汇总的内容,摘自InfoQ几个编辑团队的内部对话,为我们推荐的采用图的定位提供了更多的上下文环境。
Timisoara技术大学计算机与自动化学院助理教授Abel Avram和InfoQ编辑:
JetBrains发布了他们的2019年开发者生态系统状态,调查了7000名开发者,得出了以下结论:
- Java——最流行的初级编程语言
- JavaScript -使用最多的整体编程语言
- Go——最有前途的编程语言
- Python是被研究最多的语言
Go最初在2017年的市场份额是8%,现在已经达到了18%。此外,大多数开发人员(13%)选择Go作为他们希望采用或迁移的语言。
StackOverflow今年曾这样评价Python:“Python是增长最快的主要编程语言,在我们的调查中再次跻身编程语言的行列,今年超过了Java,成为第二受欢迎的语言(仅次于Rust)。”
Arthur Casals,在人工智能/多智能体系统领域工作的计算机科学研究员:
从我最近看到/读到的情况来看,Rust似乎正在加快采用它的速度。尽管如此,它仍然是(某种程度上)小众的,被视为“c++的替代品”。然而,随着可用库数量的增加和主要参与者的采用,我认为这是“早期采用者”的一个好选择。
Elixir似乎获得了一些势头,尤其是在巴西——事实上,这种语言的创造者是巴西人,至少有一个新的独角兽(Movile)正在公开使用它(与其他流行的公司,如Quero,在教育)。
我最近看到了一些关于Elixir的讨论——特别是在Quero的一个专家讲述了他们如何从一开始就采用Elixir的故事之后,等等。还有一个来自于的工程师的很好的用例,他们最近写了关于使用Rust和Elixir结合起来为1100万并发用户提供后端支持的文章。这是一个涉及两种语言和广泛使用的应用程序的真实场景,这无疑增加了它们的发展势头。
Dylan Schiemann, SitePen的首席执行官和Dojo的联合创始人:
Rust还处于早期的采用者阶段,根据我的经验,它的采用者正在增加,这在很大程度上是由于WebAssembly和Servo。
虽然Go已经有一段时间很有趣,但我仍然会将其认作是早期采用者。例如,语言的生命周期比框架要慢得多,我真的不认为Go已经成为主流。类似地,Elixir和Elm将被视为早期采用者。
在我看来,Pony 是一个语言,我很少听到提及,并在这个时候仍然是一个革新者。
由于Swift是iOS应用程序的默认入口点,因此它很可能已经成为主流。
对于基于云的ide, CodeSandbox和StackBlitz在过去一年中获得了极大的流行,因为它们具有令人印象深刻的基于浏览器的编辑特性集,以及与本地开发工具的集成。
在停滞了几年之后,Dart似乎在很大程度上由于Flutter而复苏。
Charles Humble, InfoQ主编:
我想把Swift变成早期的主流——在我看来,这种趋势还在继续,而且我认为,从WWDC上的一些公告来看——明显是Swift的UIKit——我们正在进入苹果平台的“Swift时代”。
我认为我们也可以将服务器端Swift移植到早期采用者。这是传闻,但与一些接近的人,他们告诉我这是看到稳定增长,有很多好东西,推动了swift-nio的开源,这反过来又增加了一些服务器端框架的性能了。
去年,Rust 肯定有所增长,我想把它从创新者变成早期采用者。他们很擅长将其定位为Wasm的合作伙伴,我认为这很有帮助。
我不确定Go;它仍在增长,但我感觉它还没有达到大众接受的程度;可能会有争议,但我还是想让它尽早被采用。
我听说了一些Elixir,但我认为它仍然是创新者;它仍然是非常小众的。
我们也应该把Python放在这里,可能在早期的大多数。它的受欢迎程度还在持续增长,这主要是由它在数据科学家中的受欢迎程度推动的,我认为我们需要更多地讨论它。
我不认为Pony可能会超越创新者;这是一个耻辱。我喜欢它的语言,虽然我发现它的类型系统相当复杂,而且我确实认为它是一件令人印象深刻的作品,但是它的社区仍然非常小。我会把它从追踪器上拿下来。
最后,我听到了更多关于Dark的消息,尽管它还处于内测阶段。我发现在更广泛的基础设施语言环境中这很有趣。
Werner Schuster, Wolfram的软件管道工:
关于Swift:目前还处于早期阶段,但是Swift对于TensorFlow (S4TF)的支持可能会成为Swift的一大卖点,并成为Python的潜在竞争对手(至少在该领域)。
这里有一个非常全面和有趣的文件,关于为什么是Swift而不是其他语言。Chris Lattner现在在TensorFlow工作;和克里斯是他的老把戏,创造国税局在各地(MLIR)
S4TF的名字有点无聊,而且隐藏了所有有趣的部分(广告,等等)。
关于Python:我对Python的走向很感兴趣;很明显,作为大量数据科学/ML原生图书馆选择的黏合剂语言,它已经获得了巨大的收益——这是Ruby在10年前没有发现的,这是它的损失。
另一方面,Python对其运行时的任何形式的现代化都表现出了明显的抵制(有人记得Unladen Swallow吗?)
我想Jython也死了。我上次访问这个网站时,它已经有好几年没有更新了,而且离Python 3.x还差得很远。
基础架构语言:似乎出现了一种将语言(一些新的语言)耦合到部署的新趋势。
- Pulumi & co - Typescript
- Ballerina
- Unison Language—由ex-Scala/Haskell开发的一种新的函数式语言,但是很好地摆脱了单子;现在还为时过早
- Dark Language ——还没有公开
我很好奇所有这些会去哪里;可能是昙花一现,也可能是15年后不可或缺的语言特性的第一步(比如子例程成为语言特性时)。
我们可能看一个新的,没有阻碍的Wasm未来(浏览器和服务器端WASI等等)以及新发现的升值的本地(vm,容器,serverless)减少JVM /字节码的吸引力,允许每个人都只使用本地版本的语言(规范化近几十年一直在开发版本)。需要说明的是,我上面所说的都与JVM原生语言无关,比如Clojure、Scala或Kotlin等。
Ben Evans, New Relic公司的首席工程师和JVM技术架构师:
Elixir里有少量的东西。我不是一个特别的爱好者——它是一个足够好的语言,但是除非你需要BEAM VM的实际能力(容错,大规模分布的简单事物),否则它似乎不会增加很多。
大多数语言的爱好者似乎喜欢它,因为它是“新的闪亮”,并且/或者他们对Java过敏(通常基于对已经过时10年的>平台的看法),但是……我还没有看到任何在JVM技术中不容易实现的引人注目的功能(尽管可能会有更多的繁文缛节)——而且JVM与库的集成要更好、更广泛。
Dustin Schultz:首席软件工程师、Pluralsight作者和技术布道者
在过去的几年里,我看到Python有了很大的发展。正如其他人所指出的,我认为这主要是由于数据科学、教授it学校/大学以及弗拉斯克(vs Django)这样的轻量级框架。
我并不反对Python(实际上我喜欢编写它),但是我认为它的流行并不代表企业用例的使用。我很少看到用Python编写的大型分布式企业应用程序仍然使用Python。它们可能一开始使用Python,但最终会因为性能的原因切换到其他语言。
查尔斯·汉博:
就核心框架而言,自2012年以来,它似乎有了一些渐进式的改进——我认为很多工作都集中在。net核心上。我认为。net Core已经从创新者变成了早期采用者。我在想,我们是否应该在。net Core 3发布后将其拆分,或许。net Core 3将在innovator中回归,而。net Core 2将在较早的采用者中回归。
同样地,我认为c#应该转向早期的主流——老实说,我不确定为什么不是。
我认为f#正在沿着类似于JVM上的Clojure的道路前进——在我看来,这是一门可爱的语言,但我没有看到它扩展到当前大小之外的迹象。同样,我也没有看到使用量大幅下降。
Jonathan Allen,毕马威的软件架构师,InfoQ的首席.net编辑:
与社区交流,F#有两个问题:
- 它没有来自微软的强大支持
- 领导层致力于以易用性为代价追求c#的兼容性
- 它在不断地变得越来越复杂,这正是计算机科学家所喜欢的。但是,实际上教授f#的培训师主要关注那些需要脚本语言的非程序员。因此,额外的复杂性使他们的工作更加困难。
我也认为c# 8很快就会被早期采用者所接受。自从……以来,人们一直要求可为空的引用类型。嗯。net 1。
讨论的其他公开的研究和调查包括: "The RedMonk Programming Language Rankings: June 2019" 和I"The Top Programming Languages 2019."
请告诉我们您在过去12个月中使用了哪些编程语言,或者您打算使用哪些编程语言。填写调查表。
原文:https://www.infoq.com/articles/programming-language-trends-2019
本文:https://pub.intelligentx.net/programming-languages-infoq-trends-report-october-2019
讨论:请加入知识星球【首席架构师圈】或者飞聊小组【首席架构师智库】
- 37 次浏览
前端技术和框架
- 99 次浏览
【Angular 开发】Angular 路线图:过去、现在和未来
自 2010 年成立以来,Angular 在 Web 和应用程序开发领域取得了长足的进步。开发人员不断地利用他们的全部潜力在市场竞争中保持领先地位。
你知道吗? Angular 一直是 JavaScript 框架世界的主要内容。 在 24 个 JS 框架中,Angular 在全球享有盛誉。
多年来,我们也看到了相当多的 Angular 更新和改进。 它从十几个网站开始,到今天它为 363,336 个网站提供动力,未来的期望更高。
但是,知道它是如何开始的、进展如何以及未来会怎样吗? 不? 让我们在这篇博客中揭示这些观点。 我们还将探索 Angular 提供的一些特性和好处。
所以,让我们开始 Angular 的技术驱动,揭开它的过去、现在和未来。
什么是Angular ?
Angular 是一个用于创建单页应用程序的开源 JavaScript 框架。 Google 于 2010 年推出,此后发布了许多版本。
这个流行的 JS 框架允许您使用 HTML 作为模板语言,向 DOM 元素添加属性,并使用标准 JavaScript 语法编写代码。 您还可以使用指令来扩展 HTML 标记的功能并创建可重用的组件。
Angular 的主要功能
Angular 的一些主要功能包括:
- Angular 使用 HTML 作为其模板语言,使其易于学习和使用。
- Angular 是一个 MVC(模型视图控制器)框架,它可以帮助您更合理地组织代码。
- Angular 具有内置的路由、数据绑定和模板功能,使开发变得更加容易。
- Angular 是一个引人注目的多功能框架,用于小型和大型项目。
多年来,Angular 发生了怎样的变化?
自 2010 年推出以来,Angular 已经走过了漫长的旅程。Angular 团队一直在努力改进和添加新功能。
角度时间线
Angular的发展可以分为三个阶段:
- 第一阶段(2010-2013):以 Angular 的发布为主,包括开发核心框架功能。
- 第二阶段(2014-2016):专注于开发 Angular Material、Angular Flex-Layout 和其他相关库。
- 第三阶段(2017 年至今):专注于 Angular(下一代 Angular)的开发。
- 第四阶段(2020-2021):发布 Angular 并结束对 Angular JS 的支持。
最新的 Angular 版本——认识 Angular 12 和 13
Angular 12
Angular 12 于 2021 年 5 月 12 日推出,是 Angular 框架的改进版本。 它比以往任何时候都更快、更高效、更易于使用。
一些新功能包括:
- 重新关注性能和可扩展性
- 改进了对 TypeScript 的支持
- 更轻松地创建渐进式 Web 应用程序
- 处理动画时更大的灵活性
- 加强对国际化的支持
Angular 13
Angular 13 是最近于 2021 年 12 月 15 日推出的最新版本。它将让开发人员减少编码工作并取得更好的结果。
一些主要功能包括:
- 查看引擎已删除
- 默认启用持久构建缓存
- 支持 TypeScript 4.4
- 支持 Adobe 字体
- Angular 测试和材料的改进
Angular 目前在市场上的表现如何?
Angular 是目前市场上最流行的 JS 框架之一。 它被许多大公司使用,并拥有一个非常活跃的社区。 此外,Angular 的开发是由谷歌赞助的,这给了它很大的信誉和支持。
企业正在利用其全部潜力来创建高性能应用程序。 该框架具有许多使开发更容易和更快的功能。 如果您想开发网站或应用程序,您可以聘请 Angular 开发人员。
了解 Angular 的当前使用情况统计
- 自 2010 年成立以来,Angular 的使用量显着增长。
- 根据 Statista 2021 的结果,Angular 是第四大最受欢迎的 Web 框架,市场份额为 22.96%。
- 0.4% 的网站使用 Angular,这是 0.4% 的 JavaScript 库市场份额。
- Angular 为搜索引擎的高流量网站提供支持。
- 媒体、IT 等顶级垂直行业都在使用 Angular。
Angular 的商业利益
- 有效的跨平台开发——Angular 使您能够编写可以在 Web 和移动平台上运行的代码,只需很少或无需修改。
- 提高速度和性能——Angular 以其高速和高性能而闻名。它可以毫无问题地处理大数据量和复杂的操作。
- 更快的开发过程 - 它显着减少了开发应用程序的时间。您可以非常快速地创建原型和 MVP。
- 可扩展性——一个可扩展的框架,可以开发任何规模的应用程序。它将帮助您处理突然的流量高峰和意外的用户增长。
- 优质应用——开发满足业务需求的优质应用。您可以提供出色的用户体验并获得更好的结果。
- 更轻量级的 Web 应用程序——Angular 是 React 和 Vue 等框架的更轻量级替代方案。对于想要创建快速响应的 Web 应用程序的企业来说,它是一个更好的选择。
- 高效的问题解决模式——这是企业主非常看重的东西。 Angular 有一些最好的问题解决模式,可以帮助快速有效地解决业务问题。
- 提高开发人员的工作效率——使用 Angular 最显着的好处之一是提高了开发人员的工作效率。使用 Angular 的企业可以在更短的时间内完成更多的工作。
Angular 的流行用例
- Adobe 使用 Angular 为其客户创造更加用户友好的体验。
- Upwork 使用 Angular 为其在线招聘平台提供支持。
- Ngrok 使用 Angular 为远程访问 Web 应用程序提供安全隧道。
- Weather.com 使用 Angular 在其网站上提供实时天气更新。
- Google 使用 Angular 创建用户友好且响应迅速的应用程序。
- BBC 使用 Angular 为其用户创造更具互动性和吸引力的体验。
- 沃尔玛使用 Angular 为其客户创造更加无缝的购物体验。
- Netflix 使用 Angular 为其用户创造更具吸引力和个性化的体验。
- Airbnb 使用 Angular 为其客户提供更好的用户体验。
- Lyft 使用 Angular 来改善骑手体验。
哪些类型的项目可以从 Angular 中受益?
对于任何需要快速高效开发的项目来说,Angular 都是一个绝佳的选择。它非常适合创建高性能和可扩展的应用程序。该框架具有许多特性,使其成为业务应用程序的理想选择。
看看你可以用 Angular 开发什么类型的应用程序:
1. 企业应用程序
——Angular 非常适合创建企业应用程序。它具有处理大量数据和复杂操作的特性和性能。它具有 TypeScript 支持,非常适合开发大型企业应用程序。您的项目将快速且高质量地完成。
例如,耐克、福特和麦当劳都以使用 Angular 开发企业应用程序而闻名。
2. 具有动态内容的应用程序
——Angular 非常适合显示动态内容的应用程序。它可以快速轻松地处理大量数据。这使其非常适合创建需要实时更新的新闻应用程序、社交媒体应用程序和其他类型的应用程序。
例如,卫报、福布斯和路透社已经使用 Angular 创建具有动态内容的应用程序。
3. 电子商务应用程序
——Angular 非常适合创建电子商务应用程序。它具有处理大量数据和复杂操作的特性和性能。您的项目将快速且高质量地完成。
例如,亚马逊、阿里巴巴和 eBay 应用程序都是 Angular 驱动的。
4. Progressive Web Apps
——Angular 非常适合创建 Progressive Web Apps。 它具有创建快速响应应用程序的功能和性能。 新的 CLI(命令行界面)工具使使用 Angular 构建渐进式 Web 应用程序变得前所未有的容易。
例如,Flipkart、Twitter Lite 和 Cricbuzz 都是使用 Angular 创建的渐进式 Web 应用程序的最佳示例。
5.实时应用程序
--RTA(实时应用程序)是需要实时更新的应用程序。 他们需要在可用时立即显示最新数据。 Angular 因其性能和可扩展性而成为创建 RTA 的绝佳选择。
例如,Google Maps、Facebook 和 Uber 是使用 Angular 创建的 RTA 应用程序的示例。
Angular 的未来是什么?
Angular 的未来更加光明。它的团队一直在努力使框架变得更好。他们计划发布新版本的 Angular,其中将包含一些很棒的新功能。
根据专家的说法,我们可以期待 Angular 在未来取得以下进展:
1. 更好的开发人员人机工程学和严格的打字
Angular 团队的主要目标之一是使开发过程更易于管理。他们计划通过严格的打字来改善开发人员的人体工程学。这将有助于确保所有代码都以一致的风格编写。
Angular 已经具备类型检查和错误报告等出色功能,使开发人员可以轻松编写高质量代码。该团队计划在 Angular 的未来版本中改进这些功能。
2. 改进文本时间和调试
Angular 团队计划改进文本时间和调试过程。他们正在开发一项称为堆栈跟踪的新功能,以便更轻松地调试代码中的错误。
堆栈跟踪将向您显示导致错误的确切代码行。它将帮助您快速找到并修复应用程序中的任何错误。
3. 减少框架开销
该团队还在努力减少框架开销。这将有助于提高您的应用程序的性能。
他们计划通过将一些代码移动到库中来做到这一点。它将有助于提高性能并保持您的应用程序较小。
4. 可选的 NgModulars
队列中的下一个是 NgModulars。这是一个令人兴奋的功能,旨在模块化 Angular 框架。它将允许您为您的应用程序创建更小、更具体的模块。
这将帮助您保持代码井井有条且易于管理。它还将通过减少需要加载到浏览器中的代码量来提高性能。
5. Angular 编译器作为插件
最后,Angular 编译器将成为 TSC(TypeScript Compiler)的插件。它将允许您在 Angular 应用程序中使用 TypeScript 功能。
这将有助于提高代码的质量,并使编写大型应用程序变得更加容易。它还有助于确保所有代码都以一致的风格编写。
这些只是我们可以期待 Angular 在未来取得的一些进步。该团队正在努力使 Angular 变得更好。因此,请继续关注 Angular 世界中的更多精彩内容。
最后的话
Angular 是创建快速响应式应用程序的绝佳选择。 自成立以来,它已经走过了漫长的道路,而且随着时间的推移,它只会变得越来越好。 该团队正在努力使 Angular 变得更好。
目前,该框架正在为市场的高质量业务应用程序提供动力。 因此,如果您还想开发高性能应用程序,请立即在印度聘请一家 Angular 开发公司并开始使用。
原文:https://enlear.academy/angular-roadmap-the-past-present-future-212d8b98…
- 103 次浏览
【React 开发】React 中的干净代码与脏代码
“让你的代码比你发现的更好”——Clean Coder
不负责任的开发者的特征
程序员在工作中花在阅读遗留代码上的时间多于编写代码的时间。因此,您的代码不能只有您和上帝才能理解。其他人会接管你的工作。想象一下,如果其他人看到您的代码会有什么反应?如果你还没有信心,那可能是因为你的代码还没有写好。糟糕的代码具有以下标准:
- 不容易理解
- 类是紧密耦合的
- 不容易改变
- 不传达意图
- 显示太多内部结构(封装不良)
代码异味是不良代码的标志。有关更具体的解释,请参阅这篇很棒的文章:https://refactoring.guru/refactoring/smells
“WTFs/minute is a valid measurement of code quality”
应用干净代码的紧迫性
要么是由于所有者的压力要求快速推出产品,要么你根本不知道,混乱的代码将无法维持。 修复一件事可能会导致破坏更多的事情,阅读代码将需要很长时间,并阻碍产品本身的改进。 迟早,如果现在不修复,产品将陷入死亡螺旋。 让我们看看在开发产品时,优秀公司与糟糕公司的比较。
让我们修复它
在本文中,我将介绍可以提高代码质量的四个基本部分。 让我们开始吧。
命名
1.命名必须表明您的意图:
姓名必须表明您的意图。 你的函数名应该是动词,例如setName、getUserAge、calculateDiscount等。同时,你的类名和变量名必须是名词。 例如,Car 类和 carColor 变量。 下面是我在 IT 项目课程中使用 React JS 编写的一些代码示例。
第一个不直观。 以后很难推荐他们。 像第二个示例中那样信息丰富且简洁的命名更为可取。
2. 避免虚假信息
上面的函数将一个数字解析为具有 2 个固定点的浮点数。 但是,我将其命名为 toString,这可能会误导其他用户。
3.避免冗长的名称和编码
这些都是不好的例子。 太长的名字将花费大量时间来理解而不是帮助。 对于第二个例子,我敢打赌,除了写这句话的人之外,其他人都会感到困惑,“什么是 statChFrUsrInp ???!”。
4. 类和函数名称:类和对象应该有名词或名词短语名称。 函数名应该是动词。
注释
“一个常见的谬误是假设难以理解的代码的作者能够以某种方式在评论中清晰明了地表达自己”——凯夫林·亨尼
无效用例
1.多余的注释
评论本质上是嘈杂的。 这就是为什么你需要小心地放置它们。 不要发表评论,除非它增加了更多价值,例如解释未明确声明的内容。
2.误导性注释
可能会出现与其功能不匹配的注释,因为开发人员只是忘记更新它们。 重构别人的文章后不要忘记更新评论。
3. 期刊注释
您的版本控制系统可以这样做。 无需以评论的形式跟踪。
有效用例
1.公共 API 注释
这是另一个级别的注释,即 API 文档。 让公共 API 使用者知道要使用哪些端点、有效负载结构如何以及它们将返回什么是非常重要的。
2. 法律注释
你一定经常看到这个,用途是为你的作品设置版权。
3.待办事项注释
4. 意图说明
总而言之,评论应该解释超出书面内容的内容。 如果您觉得有必要解释,它应该能够解释调用块的意图、调用者、传递的内容等。
格式化
1.一致的大写
类名、函数名和变量名的驼峰式大小写。 类(在此上下文中是组件)应以大写字母开头。 同时,function 和 vars 以小写字母开头。
2. 间距
请注意此故障。 你的编译器足够聪明,不需要遵循一定的对齐方式。
3. 缩进可以揭示事物
缩进推断圈复杂度,一种指示代码复杂度的度量。 它测量通过代码的可能路径的数量。 因此,不推荐使用以下冗余示例。
函数
1.一个函数应该很小并且只做一件事。
App 组件中发生了很多事情。 让我们将其分解为代码块,以使每个函数只能执行特定任务。
3. 争论越少越好。
4.偏好异常返回错误码
清洁代码口头禅
- KISS(保持简单和愚蠢):让你的代码简单,避免复杂的难以理解的代码
- YAGNI(你不会需要它):只在你需要它们时创建代码,而不是在你预见到你会需要它们时创建代码
- DRY(不要重复自己):避免使用样板代码,即目标相同但不断被调用的代码。
- DIE(重复是邪恶的):每条知识都必须有一个明确的表示。
看完这篇文章,希望我们从现在开始做一个更负责任的开发者。 您现在已经理解了应用干净代码的冲动,并且您已经了解了一些适用的概念。 我希望您可以在下一次编码实践中应用它们。 我们不能在一周内成为英雄,需要不断的练习和努力。 编码人员快乐!
来源
- Clean code by Robert Cecil Martin
- https://khalilstemmler.com/articles/oop-design-principles/command-query-separation/
- https://www.freecodecamp.org/news/how-to-write-cleaner-react-code/
原文:https://fathinah.medium.com/clean-vs-dirty-code-in-react-24e8fee03858
- 32 次浏览
【React 开发】每个 React 开发人员都应该遵循的 10 个最佳实践
编写干净的 React 代码对于任何新开发人员来说绝对是一项艰巨的任务,但是使用 React 最佳实践将逐渐建立您以最简单和最快的方式编写更好代码的信心。
在本文中,我们将重点介绍每个 React 开发人员应该遵循的 10 个最佳实践,以成为更好的开发人员。
React 是一个易于使用、声明性和基于组件的框架,用于构建高度交互的用户界面。它是 Facebook 推出的一种流行的前端技术,目前在全球拥有 800 万用户。
但是,对于开发人员而言,遵循一些有关该技术的基本实践以充分利用其功能并保持代码整洁和有条理是至关重要的。
例如,在 React 中,您可以重用代码和设计组件,从而节省开发人员的时间。但是在创建组件时,开发人员需要遵循一些基本规则以使其可重用,否则可能会导致一团糟。
1. 将较大的组件分解成较小的组件
要使组件可重用,请将较大的组件分解为较小的组件。这意味着不是将多个功能放在一个组件中,而是创建一个负责单一功能的组件,该原则被称为“单一责任原则”。
从长远来看,分离组件将有助于我们阅读、维护、调试、重用和扩展代码,因为随着时间的推移,由于添加了新功能,项目会变得越来越大。
2. 使用函数式组件而不是类
如果您不熟悉 react,您可能会对使用什么、功能组件或类组件感到困惑。
这是答案!
功能组件是简单地接受数据并以某种形式显示输出的无状态组件,而类组件是实现逻辑和状态的有状态组件。
如果您正在编写不需要访问生命周期方法或拥有自己的组件状态的展示组件,那么您应该使用功能组件。另一方面,如果您需要管理状态,请使用类组件。
以下是使用函数式组件的好处:
- 它们很容易测试、调试和重构,因为它们是用纯 Javascript 函数编写的,没有状态和生命周期钩子。
- 减少代码行数
- 消除“这个”的使用
3. 选择 styled-component 而不是其他 CSS-in-JS 库
Style-Component 是最受欢迎的库之一,它提供了一种在现代 JavaScript 中使用 CSS 的简单方法。它使开发人员能够编写每个组件很好地隔离的 CSS,同时保留级联的全部功能。
使用样式组件的一些优点是:
- 提供使用 CSS 构建自定义组件的自由
- 强制使用道具(props )代替类
- 支持带有样式表再水化的服务器端渲染
- 可以使用 Jest Styled Component 执行单元测试 - 一组使用 Jest 测试样式组件的实用程序。
4. 按照 React 的方式为每个组件相关的所有文件创建单独的文件夹
遵循构建 React 应用程序的 React 方式。正确维护的文件夹和文件结构可帮助您了解项目流程并简化代码维护和提取到任何其他项目。
根据组件组织文件,如果有几个小组件被另一个大组件使用,则将所有相关组件仅保留在另一个组件文件夹中,并在整个项目中保持相同的层次结构。
例如,Form 组件有 CSS 文件、图标、图像、测试等小组件,以及其他子组件,所有这些都应该放在一个文件夹中。
5.避免使用索引作为关键道具
根据 React 文档,Key props 有助于做出反应以识别已更改、添加或删除的项目。因此,应将密钥赋予数组内部的元素,以赋予元素稳定的身份。
那么如果使用索引作为 key props 会发生什么呢?
React 使用 key props 来确定要渲染或重新渲染的内容,因为 React 不会浪费时间重新渲染副本。因此,当两个元素具有相同的键时,React 将省略一个。
另一件需要担心的事情是,尽管实际内容没有改变,但 React 还会重新渲染键已更改为特定元素内容的元素。
6.使用默认道具和道具类型
在 JavaScript 中,您不能将变量和参数设置为特定类型。因此,变量类型有可能被误解。
此外,JavaScrip 不允许为对象或组件设置默认属性,或指定 React 中哪些属性是必需的,哪些是可选的。如果您忘记将属性分配给所需的对象或组件,这将导致问题。
上述两个问题都可以使用 prop type 和 default props 来解决。它还有助于提高代码质量,使测试和调试更加安全和快捷。
7. 避免在初始状态组件处使用道具
使用 props 生成初始状态组件通常会导致“事实来源”的重复。这是因为 getInitialstate 仅在首次创建组件时被调用一次。
下次在组件上对 props 进行更改时,它保持不变,因为之前的值不会被更新。这个问题可以通过避免在初始状态下使用道具来解决。
8. 将有状态方面与渲染隔离开来
React 组件可以是有状态的或无状态的。有状态的组件跟踪变化的数据,而无状态的组件总是呈现相同的数据。
为了最大限度地降低组件复杂性,将有状态数据加载逻辑与呈现无状态逻辑隔离始终是一个好习惯。
9. 始终遵循命名约定
遵循命名约定可确保用户知道如何命名数字资产,以便它们保持一致和正确。它们有助于文件组织和管理,如果没有命名约定,处理代码资产可能会非常困难。
在 react 中,主要有三种命名约定,
- 组件应该是 PascalCase
- 需要key的元素应该是唯一的
- 方法应该用 camelCase 编写,而不是特定于应用程序
10. 为整个代码编写测试
测试确保代码完整性。因此,最好在组件目录中创建一个 Test 目录来执行所有必需的测试,并确保添加新代码不会破坏现有功能。
你可以进行,
- 单元测试来检查 React 应用程序的各个组件。
- 集成测试以检查不同的模型是否可以很好地协同工作。
- 端到端测试以检查整个应用程序流程。
总结:
在这里,我们介绍了 React 开发人员应该遵循的 10 个最佳实践来实现干净的代码、简化代码维护和测试。
希望所有这些最佳实践将帮助您创建一个干净且组织良好的 React 项目,并从长远来看避免任何问题。
查看我其他有用的博客,
- Advanced React Roadmap
- React Component Patterns
- Advanced Javascript Design Patterns
- State management with Redux toolkit
“如果您正在寻找构建高质量 Web 或移动应用程序的最佳方法,那么请开始使用 DhiWise——世界上第一个 ProCode 平台来加速您的应用程序开发,支持最新技术,如 Flutter、React、Node、Kotlin、iOS 和 Laravel。 ”
原文:https://medium.com/dhiwise/10-best-practices-every-react-developer-shou…
- 34 次浏览
【React.js开发】最后一个更好的 react.js 文件夹结构
你可能会想“为什么 react.js 没有标准的文件夹结构?”。
要找到答案,您需要了解框架和库之间的区别。 请参考下图:-
React.js 是一个用于构建用户界面的库
- “框架负责”,因为它决定了项目的架构。
- 使用库时,“您负责”意味着您可以选择在何时何地插入或使用该库。
让我解释一下我在开发新应用程序时遵循的 react 文件夹结构。
.storybook
- Storybook 通过一个名为 .storybook 的文件夹进行配置,其中包含各种配置文件。
public
- 它包含静态文件,例如 index.html、javascript 库文件、图像和其他资产。
src
- 它包含项目的源代码。
src/assets
- 它包含图像、CSS 和字体等资产
src/components
- 它包含可重复使用的原子和分子组件
- 每个组件文件夹将包含组件、测试和文档文件
按钮组件结构解释如下:-
- Button/Button.tsx
- 它包含实际的组件代码
- Button/Button.style.tsx
- 它包含样式
- Button/Button.test.tsx
- 它包含使用 jest 的 Button 单元测试用例
- Button/Button.stories.tsx
- 它包含使用 storybook的组件文档
- Button/index.tsx
- index.tsx 仅导入该组件文件并将其导出。
src/constants
- 它包含常量文件
- 例如:正则表达式和其他应用程序通用常量
src/helpers
- 它包含可重用的辅助函数
src/layouts
- 它包含布局组件
- layout 是常见的顶部包装组件,通常包含 navbar 、 sidebar 和 children 组件
src/pages
- 它包含页面组件。
- 每个组件都可以根据页面结构将组件布局为顶级包装器
- 每个组件都默认导出,因为延迟加载适用于默认导出
src/routes
- 它包含页面路由
- 动态配置最适合使用路由
- 通常它有一个嵌套数组来渲染路由
src/schema
- 它包含使用 yup 的模式文件
- 它与 formik 一起用于字段验证
src/service
- 它包含使用 axios 的动态 http 请求功能
- Axios 是一个基于 Promise 的 HTTP 客户端,用于 node.js 和浏览器
- Axios 可用于 api 请求取消,具有请求和响应拦截器。
src/store
- 它包含 redux 文件,如 action、reducers 和 actionTypes。
store/actions
- 它包含动作文件。它用于触发更新 redux 状态的操作
store/reducers
- 它包含 reducers 文件,每个文件都将具有默认的功能导出,并且将有各种 switch case 来更新 redux 状态
store/actionTypes.tsx
- 它包含将用于配置 reducer 和操作的 actionTypes。
store/selectors
- 它包含选择器功能,有关更多详细信息,请参阅重新选择
store/index.tsx
- 它包含创建存储函数,该函数返回一个存储对象
src/styles
- 它包含样式化组件可重用断点文件、全局样式和主题常量文件
src/App.js
- App Component 是 React 中的主要组件,它充当所有其他组件的容器
src/config
- 它包含使用 env 的配置文件
src/index.js
- 它包含将应用程序渲染为真实 dom 的方法
src/test.utils.tsx
- 它包含渲染笑话组件文件的方法
- 这个函数是必需的,因为我们需要添加 react-router、redux 和 styled-components 的顶级包装组件。如果不添加这个包装器组件,测试用例将不会运行。
Github repo link 😁: https://github.com/vinothwino/react-boilerplate
原文:https://medium.com/@kumarvinoth/finally-a-better-react-js-folder-struct…
- 33 次浏览
【React开发】React 18 有什么新功能?
介绍
借助批处理、并发、转换 API 等,React 18 看起来很有前景。每次发布新版本,框架都会越来越好。作为最常用的 JavaScript 框架,React 最常用于构建具有大量令人难以置信的功能的现代应用程序。
React 团队宣布了第 18 版的发布计划。成立了一个工作组,让社区为逐步适应新功能做好准备。下一个 React 版本中有许多 API 更改和重要特性。
新功能和变化
1.新的 Root API
为了跟踪树渲染,“根”(root)是指向 React 使用的数据结构级别的指针。此外,在 API 遗留系统中,根对用户来说是不透明的,因为他们将其附加到 DOM 的元素上,并使用 DOM 节点访问它,而不会将其暴露给用户。但是,根不需要存储到 DOM 节点。
运行更新存在一些问题,包括需要将容器连续传递到渲染中,即使它保持不变。新增的根 API 解决了这个问题,因此不再需要将容器传递给渲染。此外,根 API 更改允许删除 hydrate 方法并将其替换为根选项。
2.新的开始过渡API (New Start Transition API)
这使应用程序保持响应。这是最重要的更新之一,它使应用程序在大屏幕更新期间保持响应。此外,该 API 使用户能够控制并发方面以促进用户交互。它是通过将大量更新包装为“开始转换”来完成的,并且只有在启动了更紧急的更新时才会中断。
因此,它实际上对缓慢和紧急的更新进行了分类。如果用户操作中断了转换,React 会丢弃未完成的陈旧渲染工作并仅渲染最新的更新。
3.自动批处理增强(Automatic Batching Enhancement)
批处理无非就是将 React 的多个状态更新分组到一个渲染状态中,以实现更好的计算性能。在早期的 React 版本中,批处理仅针对 React 事件处理程序进行。然而,对于任何其他事件,例如设置超时、promise 内的更新、异步状态更新、设置超时和本机事件处理程序,默认情况下更新不会在 React 中批量处理。
这可以通过使用 Root API 在版本 18 中添加自动批处理来解决。所有更新都将自动批处理,无论其来源如何。
4.架构改进,新悬念SSR
通过 React 18 的服务器端渲染,添加了架构增强功能。此外,服务器端渲染从服务器上的 React 组件生成 HTML 并将其返回给客户端。现在,客户端能够在包加载和运行 JavaScript 之前看到页面的内容。
然而,SSR 有一个缺点。它不允许组件等待数据。这意味着在向客户端呈现 HTML 之前,应该为服务器组件准备好数据。在与它们交互之前,您还需要等待所有组件水合。
这个问题可以通过悬念的两个新功能来解决,例如选择性水合和流式 HTML。
包起来
React 18 包括开箱即用的增强功能和具有影响力的新功能。此外,它为新的 React 应用程序开发可能性扫清了道路。
新版本将带来许多强大的功能来提升开发者体验并帮助创造令人惊叹的网络体验。它开启了新的可能性并提高了性能。
原文:https://javascript.plainenglish.io/whats-new-with-react-18-88a06325bf9e
本文:
- 31 次浏览
【前端技术和框架】Angular 的 10 个特性 13 每个开发人员都应该知道
Angular 正迅速走向更美好的未来
2021 年 11 月,Google 团队提出了 Angular 的另一个更新,即 v13。 Angular 13 为开发社区带来了一些令人兴奋的功能。
Google 的核心开发团队总是表示,他们每次发布新版本的目标都是找到切实可行的方法来改进 Angular。 他们在这个版本中通过扩展基于 Ivy 的功能和优化、与优秀的 Angular 社区合作以及继续为开发团队和项目提供流畅、稳定的更新过程来实现这一点。
如果您想知道 Angular 13 中的新功能,这里简要介绍了主要功能。
1. View Engine 不再服务
Angular 的最新版本 Angular 13 不再支持古老的 View Engine。使用 View Engine 会产生维护成本并增加 Angular 13 代码库的复杂性。 为了避免这种麻烦,Angular 现在只支持 Ivy 作为视图引擎。
由于此更改,一些现有库将自动迁移到部分编译模式,并且旧版 View Engine 以前需要的一些元数据将被删除。 此外,为确保顺利过渡,所有内部工具都提前转换为 Ivy。
Ivy 现在可以相互独立地编译各个组件,从而显着提高性能。 Angular 可以通过移除 View Engine 来减少对 ngcc 的依赖。
2. Angular 包格式 (APF) 的修改
Angular 包格式 (APF) 指定了 Angular 框架包的结构和格式以及视图引擎元数据。 这是在 Web 开发环境中打包每个第三方库的好方法。
新版本的 APF 包含一些重大更改。 在 Angular 13 中,不推荐使用旧的输出格式,包括一些特定于视图引擎的元数据。
在 APF 的更新版本中将不再需要使用 ngcc。 由于这些库更改,开发人员可以期待更快的执行。
3. IE 11 支持已被移除。
从版本 13 开始,Angular 将不再支持 Internet Explorer 11。删除 Internet Explorer 11 会导致更小的包大小和更快的应用程序加载。 此外,由于这些增强,Angular 现在可以通过原生 Web API 使用现代浏览器功能,例如 CSS 变量和 Web 动画。
由于改进的 API 和缺少特定于 IE 的 polyfill,应用程序将加载更快。 它还消除了对不同负载的需要。 开发人员将受益于改进的 API 和基础设施,而应用程序用户将受益于更快的加载和更好的用户体验。
在项目迁移期间运行 ng update 将自动删除这些特定于 IE 的 polyfill,从而减小包大小。
4. TypeScript 4.4 兼容性
TypeScript 4.4 支持已添加到 Angular 13 版本中。 因此,核心不再支持 4.4.2 之前的 TypeScript 版本。
以下是 TypeScript 4.4 的主要功能:
类型保护检测已得到改进
默认捕获变量
更快速的增量构建
可以检查条件的控制流
符号和模板字符串模式的索引签名
5、不再支持12.20之前的Node.js版本
Angular 13 不再支持 12.20.0 之前的 Node.js 版本。这是因为 Angular 包现在使用带有子路径模式的 Node.js 包导出功能。
6. RxJS 版本 7.4
RxJS 是 JavaScript 的响应式扩展,包含在 Angular 13 升级中,并且包括所有版本的 RxJS,包括版本 7。
RxJS 7.4 现在是使用 ng new 创建的应用程序的默认值。
必须使用 npm install rxjs@7.4 命令手动更新现有的 RxJS v6.x 应用程序。 你总是可以依赖 RxJS 7 来创建新项目。 现有项目应继续使用 RxJS 6。
7.路由器的变化
路由帮助我们从一个视图移动到另一个视图。 它通过将浏览器 URL 解释为更改视图的请求来促进导航。
当新导航取消当前导航时,路由器不再使用最新更新更改浏览器 URL。
与以前版本的 Angular 的兼容性存在几个问题,主要是查询参数。 例如,默认的 URL 序列化程序倾向于删除查询参数中问号后的所有内容。 相比之下,最近的更新改进了查询参数与问号的兼容性。
以前,routerLink 指令的 null 和 undefined 输入与空字符串相同,并且无法阻止链接被导航。 如果路由器链接指令值为 null 或未定义,导航现在将完全禁用。
8. Angular CLI 的增强
Angular CLI 是 Angular 难题中最重要的部分之一。 通过广泛降低复杂性,Angular CLI 有助于标准化处理现代 Web 开发生态系统错综复杂的过程。
随着 Angular 13 的发布,该框架现在具有持久的构建缓存功能,该功能将内置结果保存到磁盘作为默认功能。 因此,发展进程将加快。 此外,您可以完全控制在当前 Angular 项目中是否启用或禁用此功能。
9. 改进了Angular 测试
TestBed 已由 Angular 团队更新,现在可以在每次测试后正确删除测试环境和模块。
既然 DOM 在测试后被清除,开发人员可能期望更好的流线型、更少的相互依赖、内存密集型和更快的测试。
10. 创建动态组件
动态生成组件的更简化的技术是 Angular 13 中支持 Ivy 的 API 更新之一。要构造组件,ViewContainerRef.createComponent 不再需要实例化工厂(您不再需要使用 ComponentFactoryResolver)。
由于更新了 ViewContainerRef.createComponent API,它现在能够使用更少的样板代码生成动态组件。 下面是使用 Angular 的早期版本构建动态组件的示例。
@Directive({ … }) export class Test { constructor(private viewContainerRef: ViewContainerRef, private componentFactoryResolver: ComponentFactoryResolver) {} createMyComponent() { const componentFactory = this.componentFactoryResolver. resolveComponentFactory(MyComponent); this.viewContainerRef.createComponent(componentFactory); } }
使用 Angular 13 中的新 API,此代码将转换为以下内容:
@Directive({ … }) export class Test { constructor(private viewContainerRef: ViewContainerRef) {} createMyComponent() { this.viewContainerRef.createComponent(MyComponent); } }
结论
您现在了解最新的 Angular 13 更改。 如果您仍在使用 Angular 12,那么是时候升级了,以便您可以在下一个项目中使用新功能。 如果您已经安装了新版本,请在下面的评论区分享您的想法。
这就是本文的内容。 我希望你今天学到了一些新东西。 想阅读更多这样的文章,请继续关注!
原文:https://javascript.plainenglish.io/10-features-of-angular-13-every-deve…
- 45 次浏览
【前端框架】Vue3 开源框架收集
awesome -vue -3
https://github.com/vuesomedev/awesome-vue-3
A curated list of awesome things related to Vue 3
vue3-antd-admin
基于 vue-cli / vite2.x + vue3.x + antd-design-vue2.x + typescript4.x 的后台管理系统模板
vscode 配置
安装项目根目录.vscode 推荐的插件,再安装 Volar,并禁用 Vetur,重启 vscode 即可。
使用了 Vue3.0 全家桶、ant-design-vue2.0 和 typescript4.0,实践 vue3.0 的新特性以及玩法,不得不说 vue3.0 的 Composition API 相比于 vue2.0 的 Options API 灵活很多,让我们可以灵活地组合组件逻辑,我们可以很轻松的使用 hooks 的形式去代替以前 mixins 等的写法。更多 hooks 可以参考vueuse
功能、组件的封装
- 动态表格(扩展了伸缩列功能,以及使用 JSON schema 配置生成表格) // TODO 后续有待加强及完善
- 动态表单(满足基本的需求) // TODO 后续有待加强及完善
- 自定义弹窗(支持 8 个方向拖拽改变大小以及拖拽移动位置)// TODO: 继承 antd 原组件所有 props
- 图片视频预览(目前只是简单显示)
- 分割组件(目前只做了左右)
- 图标组件封装(本地 svg 封装、阿里图标的在线和离线封装)
- 其他...
页面功能
系统看板
- 首页
- 疫情地图
- 系统日志
- 前端性能监控
系统管理
- 账号管理
- 角色管理
- 资源管理
- 字典管理
vue3-admin
https://github.com/newbee-ltd/vue3-admin
🔥 🎉 Vue 3.0 + Vite 2.0 + Vue-Router 4.0 + Element-Plus + Echarts 5.0 + Axios 开发的后台管理系统
newbee-mall 项目是一套电商系统,基于 Spring Boot 2.X 和 Vue 以及相关技术栈开发。 前台商城系统包含首页门户、商品分类、新品上线、首页轮播、商品推荐、商品搜索、商品展示、购物车、订单结算、订单流程、个人订单管理、会员中心、帮助中心等模块。 后台管理系统包含数据面板、轮播图管理、商品管理、订单管理、会员管理、分类管理、设置等模块。
vue3-admin 版本线上预览地址:http://vue3-admin.newbee.ltd,测试账号密码:admin 123456
本仓库中的源码为新蜂商城前后端分离版本的后台管理系统(Vue 版本为 3.x),主要面向前端开发人员,后端 API 源码在另外一个仓库 newbee-mall-api。
前后端分离版本包括四个仓库:
- 新蜂商城后端接口 newbee-mall-api
- 新蜂商城 Vue2 版本 newbee-mall-vue-app
- 新蜂商城 Vue3 版本 newbee-mall-vue3-app
- 新蜂商城后台管理系统 Vue3 版本 vue3-admin
WeBankFinTech/fes.js
Fes.js 是一个好用的前端应用解决方案。 以 Vue 3.0 和路由为基础,同时支持配置式路由和约定式路由,并以此进行功能扩展。配以覆盖编译时和运行时生命周期完善的插件体系,支持各种功能扩展和业务需求。以约定、配置化、组件化的设计思想,让用户仅仅关心用组件搭建页面内容。基于Vue.js,上手简单。经过多个项目中打磨,趋于稳定。
Fes.js 是什么?
Fes.js 是一个优秀的前端应用解决方案。Fes.js 以 Vue 3.0 和路由为基础,同时支持配置式路由和约定式路由,并以此进行功能扩展。配以覆盖编译时和运行时生命周期完善的插件体系,支持各种功能扩展和业务需求。
它主要具备以下功能:
-
🚀 快速 ,内置了路由、开发、构建等,并且提供测试、布局、权限、国际化、状态管理、API请求、数据字典、SvgIcon等插件,可以满足大部分日常开发需求。
-
🧨 简单 ,基于Vue.js 3.0,上手简单。贯彻“约定优于配置”思想,设计插件上尽可能用约定替代配置,同时提供统一的插件配置入口,简单简洁又不失灵活。提供一致性的API入口,一致化的体验,学习起来更轻松。
-
💪 健壮 ,只需要关心页面内容,减少写BUG的机会!提供单元测试、覆盖测试能力保障项目质量。
-
📦 可扩展 ,借鉴Umi实现了完整的生命周期和插件化机制,插件可以管理项目的编译时和运行时,能力均可以通过插件封装进来,在 Fes.js 中协调有序的运行。
-
📡 面向未来 ,在满足需求的同时,我们也不会停止对新技术的探索。已使用Vue3.0来提升应用性能,已使用webpack5提升构建性能和实现微服务,未来会探索vite等新技术。
插件
插件 | 介绍 |
---|---|
@fesjs/plugin-access | 提供对页面资源的权限控制能力 |
@fesjs/plugin-enums | 提供统一的枚举存取及丰富的函数来处理枚举 |
@fesjs/plugin-icon | svg 文件自动注册为组件 |
@fesjs/plugin-jest | 基于 Jest ,提供单元测试、覆盖测试能力 |
@fesjs/plugin-layout | 简单的配置即可拥有布局,包括导航以及侧边栏 |
@fesjs/plugin-locale | 基于 Vue I18n ,提供国际化能力 |
@fesjs/plugin-model | 简易的数据管理方案 |
@fesjs/plugin-request | 基于 Axios 封装的 request,内置防止重复请求、请求节流、错误处理等功能 |
@fesjs/plugin-vuex | 基于 Vuex , 提供状态管理能力 |
@fesjs/plugin-qiankun | 基于 qiankun ,提供微服务能力 |
@fesjs/plugin-sass | 样式支持sass |
@fesjs/plugin-monaco-editor | 提供代码编辑器能力, 基于monaco-editor (VS Code使用的代码编辑器) |
xiaoxian521/vue-pure-admin
Vue3.0+TypeScript+Vite2.0+Element-Plus编写的一套后台管理系统
功能列表
流程图
权限管理
pipipi-pikachu/PPTist
基于 Vue3.x + TypeScript 的在线演示文稿(幻灯片)应用,还原了大部分 Office PowerPoint 常用功能,实现在线PPT的编辑、演示。支持导出PPT文件
📚 功能列表
通用功能
- 历史记录(撤销、重做)
- 快捷键
- 右键菜单
幻灯片页面编辑
- 页面添加、删除
- 页面顺序调整
- 页面复制粘贴
- 背景设置(纯色、渐变、图片)
- 网格线
- 画布缩放
- 主题设置
- 幻灯片备注
- 幻灯片模板
幻灯片元素编辑
- 元素添加、删除
- 元素复制粘贴
- 元素拖拽移动
- 元素旋转
- 元素缩放
- 元素多选(框选、点选)
- 多元素组合
- 元素锁定
- 元素吸附对齐(移动和缩放)
- 元素层级调整
- 元素对齐到画布
- 元素对齐到其他元素
- 多元素均匀分布
- 拖拽添加图文
- 粘贴外部图片
- 元素坐标、尺寸和旋转角度设置
- 元素设置超链接
文字
- 富文本编辑(颜色、高亮、字体、字号、加粗、斜体、下划线、删除线、角标、行内代码、引用、对齐方式、项目符号、清除格式)
- 行高
- 字间距
- 填充色
- 边框
- 阴影
- 透明度
图片
- 裁剪(自定义、按形状、按纵横比)
- 滤镜
- 翻转
- 边框
- 阴影
- 替换图片
- 重置图片
- 设置为背景图
形状
- 填充色
- 边框
- 阴影
- 透明度
- 翻转
- 编辑文字
线条
- 颜色
- 宽度
- 样式
- 端点样式
图表(柱状图、折线图、饼图)
- 数据编辑
- 背景填充
- 主题色
- 坐标系与坐标文字颜色
- 其他设置(柱状图转条形图、折线图转面积图、折线图转散点图、饼图转环形图、折线图开关平滑曲线)
- 边框
表格
- 行、列添加删除
- 行列数设置
- 主题设置(主题色、表头、汇总行、第一列、最后一列)
- 合并单元格
- 单元格样式(填充色、文字颜色、加粗、斜体、下划线、删除线、对齐方式)
- 边框
幻灯片放映
- 翻页动画
- 元素入场动画
- 全部幻灯片预览
- 画笔、黑板工具
- 自动放映
newbee-ltd/newbee-mall-vue-app
🔥 🎉Vue2 全家桶 + Vant 搭建大型单页面商城项目。新蜂商城前后端分离版本-前端Vue项目源码
ewbee-mall 项目是一套电商系统,包括 newbee-mall 商城系统及 newbee-mall-admin 商城后台管理系统,基于 Spring Boot 2.X 和 Vue 以及相关技术栈开发。 前台商城系统包含首页门户、商品分类、新品上线、首页轮播、商品推荐、商品搜索、商品展示、购物车、订单结算、订单流程、个人订单管理、会员中心、帮助中心等模块。 后台管理系统包含数据面板、轮播图管理、商品管理、订单管理、会员管理、分类管理、设置等模块。
本仓库中的源码为新蜂商城前后端分离版本的 Vue 项目(Vue 版本为 2.x),主要面向前端开发人员,后端 API 源码在另外一个仓库 newbee-mall-api。
新蜂商城 Vue 版本线上预览地址:http://vue-app.newbee.ltd,账号可自行注册,建议使用手机模式打开。
前后端分离版本包括四个仓库:
- 新蜂商城后端接口 newbee-mall-api
- 新蜂商城 Vue2 版本 newbee-mall-vue-app
- 新蜂商城 Vue3 版本 newbee-mall-vue3-app
- 新蜂商城后台管理系统 Vue3 版本 vue3-admin
Vue2 版本与 Vue3 版本分成两个仓库,大家需要哪个版本就去对应的仓库即可。
ykfe/ssr
A most advanced ssr framework support React/Vue2/Vue3 on Earth that implemented serverless-side render specification.
ssr
框架是为前端框架在服务端渲染的场景下所打造的开箱即用的服务端渲染框架。了解什么是服务端渲染请查看文档
此框架脱胎于 egg-react-ssr 项目和ssr
v4.3版本(midway-faas + react ssr),在之前的基础上做了诸多演进,通过插件化的代码组织形式,支持任意服务端框架与任意前端框架的组合使用。开发者可以选择通过 Serverless 方式部署或是以传统 Node.js 的应用形式部署,并且我们专注于提升 Serverless 场景下服务端渲染应用的开发体验,打造了一站式的开发,发布应用服务的功能。最大程度提升开发者的开发体验,将应用的开发,部署成本降到最低。
在最新的 v5.0 版本中,同时支持 React
和 Vue2/Vue3
作为服务端渲染框架且构建工具我们同样支持了最流行的 Vite
来提升应用的启动速度和 HMR 速度,且提供一键以 Serverless 的形式发布上云的功能。我们可以非常有自信说它是地球上最先进的 ssr
框架。如果你希望获得开箱即用的体验且能够一键部署上云,请选择 ssr
框架。
biaochenxuying/blog-vue-typescript
Vue3 + TypeScript + Vite2 + Vuex4 + Vue-Router4 + element-plus 支持 markdown 渲染的博客前台展示
已经完成功能
- 登录
- 注册
- 文章列表
- 文章归档
- 标签
- 关于
- 点赞与评论
- 留言
- 历程
- 文章详情(支持代码语法高亮)
- 文章详情目录
- 移动端适配
- github 授权登录
前端主要技术
所有技术都是当前最新的。
- vue: ^3.0.5
- typescript : ^4.1.3
- element-plus: ^1.0.2-beta.41
- vue-router : ^4.0.6
- vite: ^2.2.3
- vuex: ^4.0.0
- axios: ^0.21.1
- highlight.js: ^10.7.2
- marked:^2.0.3
TaleLin/lin-cms-vue
🔆 Vue+ElementPlus构建的CMS开发框架
Lin CMS 简介
-
Lin-CMS 是林间有风团队经过大量项目实践所提炼出的一套内容管理系统框架。
-
Lin-CMS 可以有效的帮助开发者提高 CMS 的开发效率。
-
Lin-CMS 是一套前后端完整的解决方案,后端部署请移步:
hug-sun/element3
A Vue.js 3.0 UI Toolkit for Web. Build with Javascript
alibaba/formily
背景
在 React 中,在受控模式下,表单的整树渲染问题非常明显。特别是对于数据联动的场景,很容易导致页面卡顿,为了解决这个问题,我们将每个表单字段的状态做了分布式管理,从而大大提升了表单操作性能。同时,我们深度整合了 JSON Schema 协议,可以帮助您快速解决后端驱动表单渲染的问题。
特性
- 🖼 可设计,借助 Form Builder 可以快速搭建表单
- 🚀 高性能,字段分布式渲染,大大减轻 React 渲染压力
- 💡 支持 Ant Design/Fusion Next 组件体系
- 🎨 JSX 标签化写法/JSON Schema 数据驱动方案无缝迁移过渡
- 🏅 副作用逻辑独立管理,涵盖各种复杂联动校验逻辑
- 🌯 支持各种表单复杂布局方案
vuestorefront/vue-storefront
The open-source frontend for any eCommerce. Built with a PWA and headless approach, using a modern JS stack. We have custom integrations with Magento, commercetools, Shopware and Shopify and total coverage is just a matter of time. The API approach also allows you to merge VSF with any third-party tool like CMS, payment gateways or analytics. Ne…
chuzhixin/vue-admin-beautiful-pro
vue3,vue3.0,vue,vue3.x,vue.js,vue后台管理,admin,vue-admin,vue-element-admin,ant-design,vue-admin-beautiful-pro,vab admin pro,vab admin plus主线版本基于element-plus、element-ui、ant-design-vue三者并行开发维护,同时支持电脑,手机,平板,切换分支查看不同的vue版本,element-plus版本已发布(vue3,vue3.0,vue,vue3.x,vue.js)
https://github.com/chuzhixin/vue-admin-beautiful-pro
anncwb/vue-vben-admin
A modern vue admin. It is based on Vue3, vite and TypeScript. It's fast!
https://github.com/anncwb/vue-vben-admin/blob/main/README.zh-CN.md
简介
Vue Vben Admin 是一个免费开源的中后台模版。使用了最新的vue3
,vite2
,TypeScript
等主流技术开发,开箱即用的中后台前端解决方案,也可用于学习参考。
特性
- 最新技术栈:使用 Vue3/vite2 等前端前沿技术开发
- TypeScript: 应用程序级 JavaScript 的语言
- 主题:可配置的主题
- 国际化:内置完善的国际化方案
- Mock 数据 内置 Mock 数据方案
- 权限 内置完善的动态路由权限生成方案
- 组件 二次封装了多个常用的组件
buqiyuan/vite-vue3-lowcode
Vue3.x + vite2.x + vant + element-plus H5移动端低代码平台 lowcode 可视化拖拽 可视化编辑器 visual editor 类似易企秀的H5制作、建站工具、可视化搭建工具
https://github.com/buqiyuan/vite-vue3-lowcode
技术栈
- 编程语言:TypeScript 4.x + JavaScript
- 构建工具:Vite 2.x
- 前端框架:Vue 3.x
- 路由工具:Vue Router 4.x
- 状态管理:Vuex 4.x
- PC 端 UI 框架:Element Plus
- H5 端 UI 框架:vant
- CSS 预编译:Stylus / Sass / Less
- HTTP 工具:Axios
- Git Hook 工具:husky + lint-staged
- 代码规范:EditorConfig + Prettier + ESLint + Airbnb JavaScript Style Guide
- 提交规范:Commitizen + Commitlint
- 单元测试:vue-test-utils + jest + vue-jest + ts-jest
- 自动部署:GitHub Actions
功能清单
- 动态添加页面
- 拖拽式生成组件
- service worker + indexeddb 实现无服务端的前端交互
- 数据源管理(支持导入 swagger JSON 生成数据模型及接口)
- 提供预置函数
- 更多组件的封装
- 其他...
buqiyuan/vue3-antd-admin
基于vue-cli/vite + vue3.0 + ant-design-vue2.0 + typescript hooks 的基础后台管理系统模板 RBAC的权限系统, JSON Schema动态表单,动态表格,漂亮锁屏界面
功能、组件的封装
- 动态表格(扩展了伸缩列功能,以及使用 JSON schema 配置生成表格) // TODO 后续有待加强及完善
- 动态表单(满足基本的需求) // TODO 后续有待加强及完善
- 自定义弹窗(支持 8 个方向拖拽改变大小以及拖拽移动位置)// TODO: 继承 antd 原组件所有 props
- 图片视频预览(目前只是简单显示)
- 分割组件(目前只做了左右)
- 图标组件封装(本地 svg 封装、阿里图标的在线和离线封装)
- 其他...
页面功能
系统看板
- 首页
- 疫情地图
- 系统日志
- 前端性能监控
系统管理
- 账号管理
- 角色管理
- 资源管理
- 字典管理
lin-xin/vue-manage-system
基于Vue3 + Element Plus 的后台管理系统解决方案
前言
该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统(Web Management System)开发。基于 Vue3,使用 vue-cli3 脚手架,引用 Element Plus 组件库,方便开发快速简洁好看的组件。分离颜色样式,支持手动切换主题色,而且很方便使用自定义主题色。
功能
- Element Plus
- 登录/注销
- Dashboard
- 表格
- Tab 选项卡
- 表单
- 图表 📊
- 富文本编辑器
- 图片拖拽/裁剪上传
- 权限测试
- 404 / 403
- 三级菜单
- 自定义图标
- 国际化
flipped-aurora/gin-vue-admin
基于gin+vue搭建的(中)后台系统框架,集成jwt鉴权,权限管理,动态路由,分页封装,多点登录拦截,资源权限,上传下载,代码生成器,表单生成器,通用工作流等基础功能,五分钟一套CURD前后端代码,VUE3版本正在重构
https://github.com/flipped-aurora/gin-vue-admin
- 633 次浏览
算法和数据结构
- 35 次浏览