-经过几个小时的睡眠和崭新的思路后,我准备开始使用Scala来开始新的一天。 在内部,我想知道我将能够花多少时间继续理解谈话内容-
Dick Wall和Bill Venners编写的 Scala高级概念
隐式是第一个解决的主题。 首先,要知道隐式是Scala编译器难以完成工作的原因之一。 为了说明隐式,显示了一个Swing匿名类代码段代码:
valbutton=newJButton
button.addActionListener(newActionListener{
defactionPerformed(event:ActionEvent){
println("pressed")
}
})
button.addActionListener(_:ActionEvent)=>println("pressed")// Compile time error with type mismatch
implicit
关键字是Scala编译器尝试从一种类型到另一种类型的转换直到编译的一种方法。 唯一重要的是类型签名,名称无关。 由于隐式函数是如此强大(因此很危险),因此在Scala 2.10中,您必须显式导入language.implicitConversions
。 此外,必须导入其他此类功能( 例如宏)才能使用。 如果未导入,则编译器会发出警告,但在将来的版本中,它将作为错误处理。
使用隐式的规则如下:
- 标记规则:仅标记为隐式的defs可用
- 范围规则:隐式转换必须在范围内作为单个标识符(或与转换的源类型或目标类型相关联)。 这类似于邀请隐式转换。 如果隐式对象在伴随对象中,它将被自动使用。 另一个更合理的选择是将其置于可能在范围内或不在范围内的特征。
- 一次一个的规则:只有一个隐式转换必须满足编译器的要求。
- 显式优先规则:如果代码编译时没有隐式,则不会使用隐式。
- 最后,如果Scala有一个以上的隐式转换可用,则编译器将尽可能选择更具体的转换。 如果不能,它将不选择任何内容,并抛出一个错误。
即使编译器不在乎隐式def的名称,但阅读您的代码的人都这样做,因此应该为转换的显式用法和显式导入转换范围选择名称。 请注意,Predef对象中已包含一些已经可用的隐式对象。
在Scala 2.10中,隐式可以在类上设置,因此隐式甚至更安全。 因此,您不必导入功能。 这些类必须仅使用一个参数,并且必须在可以定义方法的位置进行定义(因此它们不能是顶级的)。 请注意,生成的方法将与该类具有相同的名称。
隐式参数可用于咖喱defs中并替换最后一个参数。
defcurried(a:Int)(implicitb:Int)=a+b
implicitvalevilOne:Int=1
curried(1)(2)// Returns 3 as expected
curried(1)// Returns 2 because evilOne is implicit and used in the def
隐式参数最好用作您自己控制的类型之一:请勿将Int
或String
用作隐式参数。 它还允许您在类型上设置有意义的名称(例如Scala API中的Ordered
)。
顺便说一句,为了简化API的使用,您可以指定@ImplicitNotFound
批注,以向编译器提供特定的错误消息。 同样,当不应用隐式时,编译器也不会提供很多调试信息。 在这种情况下,一个好技巧是显式开始使用该参数并查看会发生什么。 总之,请谨慎使用隐式:问问自己是否还有其他方法(例如继承或特质)。
Scala 2.10还提供了一些通过applyDynamics(s:String)
鸭子输入的方法(这也是必须导入才能使用)。 它看起来很像反射,但是让编译器检查直通并在运行时而不是在编译时失败(如果所需的方法不存在)。
现在该是一些良好的Scala编码实践的时候了。
- 首先,主张不变性:特别是,如果您绝对需要使用
var
,请使用最小范围。 另外,可变的收藏尤其邪恶。 如果您需要在这种情况下使用可变性,那么最重要的是不要将其暴露在方法之外(在签名中)。 - 对于集合,请在
foreach
考虑map
和flatMap
:这倾向于使您想到函数式编程。 - 然后,不要链接多个map / filter / ...调用,以使您的代码更具可读性。 而是使用有意义的名称声明中间变量。
- 偏好使用部分函数来消除元组:
wl.zipWithIndex.map{case(w,i)=>w.toList(i)}// better than wl.zipWithIndex.map{t=>t._1.toList(t._2)}// not a good thing
- 考虑将“任一”作为异常的替代方法,因为异常会干扰代码流。
- 您可以从代码中消除更多的
if
和for,则最少需要考虑所有情况。 因此,最好在循环和可变项上增加尾部递归和不可变项。 - 看看
Vector
overList
。 前者是恒定时间的表现... - *知道您的收藏!* - 已经开始! -
- 开发`public`方法时,请务必提供返回类型。 它不仅可以避免运行时错误(由于类型推断而进行编译),还可以很好地记录代码并提高可读性。
- 仔细考虑案例类:您可以免费获得已经定义的方法(
toString()
,apply()
,unapply()
等)。
-我的电池没电了-
更快的网站: Iliya Grigorik关于前端性能的速成课程
-尽管后端性能很重要,但我确实倾向于像演讲者一样认为,在大多数“传统” Web应用程序中,大部分时间都花在了前端上。 我希望增加我可用的工具组合,以防万一-
发言人是Google内部的Web Fast团队的成员。 议程分为三个主要部分:问题,浏览器体系结构和最佳实践以及上下文。
问题所在
建立快速网站有什么意义? Google和Bing试图通过在响应过程中的各个点注入人为延迟来衡量延迟的影响。 所有指标(包括“每个用户的收入”)均下降,并且延迟越长,线性下降的幅度越大。 附带一提,延迟消除后,指标需要时间才能恢复到原始值。 另一家公司确实将页面加载速度和跳出率相关联。 移动网络给网站的负载带来了更大的压力...
如果您想通过网络性能获得成功,请不要将其视为技术指标。 相反,要衡量其影响并将其与业务指标相关联
延迟 | 用户React |
---|---|
0-100ms | Instant |
100-300ms | Feels sluggush |
300-1000ms | Machine is working |
+1s | Mental context switch |
+10s | I’ll come back later |
Google Page Analytics显示,在桌面网络上,平均网页加载时间约为3毫秒,而在移动网络上,平均网页加载时间为5毫秒(仅考虑到这些新的Google手机)。 问题在于,一个平均页面由84个is和1MB左右的请求组成!
让我们看一下HTTP请求的生命:DNS查找,套接字连接,请求管理本身以及最后的内容下载。 生命周期中的每个阶段都可以优化。
- 例如,大多数DNS服务器都非常糟糕。 这就是Google提供免费的公共DNS服务器8.8.4.4和8.8.8.8的原因。 一个名为namebench的项目可以部分根据您的浏览器历史记录来帮助您找到最佳的DNS服务器。
- 可以通过将服务器移近一些来减少套接字连接。 或者,我们可以使用CDN。
对于devoxx.com ,只有67个请求,但比4Mb少一些。 这些请求不仅是HTML,而且是CSS,JavaScript和图像。 请求所有这些资源可以图形化地表示为瀑布。 有两种优化瀑布的方法:使其更短更细。 不要低估前端的时间:平均而言,前端会花费86%的时间。
有人可能会说,网络速度的提高可以拯救我们。 大多数“先进”国家的平均速度为5Mb / s,并且还在不断提高。 不幸的是,带宽并不重要,延迟更重要! 超过5Mb / s,增加带宽将无助于改善页面加载时间(PLT),即使它可以下载电影也是如此。🙂问题是,增加带宽很容易(只需布置更多电缆),而改善延迟则很昂贵(无法读取),因为它受光速的约束:这将需要铺设更短的电缆。
HTTP 1.1是对HTTP 1.0的改进,可以使连接保持活动状态:在以前的版本中,一个请求需要一个连接,而在以后的版本中则不是。 现在,这意味着浏览器最多可以打开6个TCP连接来请求资源。 由于TCP启动缓慢,因此该数目基本上是一个限制:它是TCP的一项功能,旨在探测网络性能而不会使网络过载。 在现实生活中,大多数HTTP流量由小的,突发性的TCP流组成,因为存在许多请求,每个请求的大小都是有限的(请考虑JS文件)。 一种改进是增加TCP初始拥塞窗口,但它需要调整底层系统资源。
正在进行的工作是HTTP 2.0! 好消息是SPDY已经存在,并且v2旨在作为HTTP 2.0的基础。 HTTP 2.0的目标(当然)是使事情变得更好,它建立在HTTP 1.1之上并且具有可扩展性。 增加PLT的实际解决方法包括级联文件(CSS,JS),图像拼接和域分片(因为存在“伪”域,从而误导浏览器建立6个以上的连接)。 SPDY旨在消除这些变通办法,以使开发人员不必再为肮脏的骇客而nail之以鼻。 您无需修改站点即可使用SPDY,但可以对其进行优化(停止拼版和分片)
本质上,使用SDPY,您可以打开一个TCP连接,并在此连接内发送多个“流”,这些流将被多路复用。 SPDY还提供服务器推送,以便服务器可以将资源推送到客户端...只要客户端不取消流即可。 请注意,可以将HTML主页面中的内联资源视为服务器推送的一种形式。 如今,SPDY在许多浏览器中都受支持,包括Chrome(当然),Firefox 13+和Opera 12.10+。 此外,还有许多兼容的服务器(Apache通过mod_spdy,nginx,Jetty等)。
移动网络正在爆炸式增长:移动互联网用户将在2年内达到台式机互联网用户。 在像印度这样的国家,情况已经如此! 当然,有很大一部分互联网用户会严格通过移动设备进行访问,确切的数字取决于国家/地区(美国为25%,埃及为79%)。 问题的核心是,尽管我们不想区分桌面访问和移动访问,但要犯错误:物理层完全不同。 实际上,对于移动设备而言,延迟要严重得多,因为在3G或4G中退出空闲状态都非常耗时(尽管在后一种情况下数量会减少)。
有一些解决这些问题的解决方案:
- 再想想SPDY
- 重用连接,管道
- 批量下载资源以避免唤醒收音机
- 压缩资源
- 拥有它们后就缓存!
浏览器架构
好消息是浏览器正在尝试为您提供帮助。 例如,Chrome具有以下策略:DNS预取(针对同一页面上的链接),TCP预连接(与此处相同),池化和重用TCP连接并最终进行缓存(针对已下载的资源)。 更准确地说,将鼠标悬停在链接上可能会触发DNS完美和TCP预连接。 Chrome提供了许多优化参数,只要您了解它们,就可以使用它们。
当您的网站使用关联的脚本时,Google Analytics(分析)可为您提供上述指标。 一个重要的功能是细分,以分析用户之间的差异。 例如,听众可以分为日本,新加坡和美国:它让我们看到,仅针对新加坡用户的PLT高峰是由于社交微件的暂时不可用所致,而仅针对新加坡人群。
现在,浏览器如何呈现服务器提供的字节? HTML解析器执行许多不同的操作:创建DOM树,以及创建CSS树CSS树。 顺便说一下,HTML5指定了如何解析HTML,而HTML 4中则不是这样:字节被标记化,令牌被内置到树中。 但是,JavaScript可以通过doc.write
更改DOM,因此浏览器必须先管理脚本再执行任何操作。 结果,同步脚本确实阻止了浏览器。 推论,代码异步脚本,像这样
(function()){
// do something here
})();
在HTML5中,具有script
标记属性的异步脚本有更简单的方法:
-
regular
,这只是标准脚本 -
defer
告诉浏览器在后台下载并按顺序执行脚本 -
async
告诉它也要在后台下载,但准备好后执行
-3小时的谈话实在太多了,最好停顿一下,然后重新意识到,而不要睡着-
为了优化页面,您可以在Chrome中安装PageSpeed扩展程序,该扩展程序将基本上审核页面( -请注意,它也可以作为Firebug插件-来使用 )。 检查包括:
- 图像压缩优化:更好的是,优化后的内容是由PageSpeed计算的,因此您可以直接使用它并替换您自己的内容。
- 调整大小为0x0像素(是的,这似乎发生了,并且有足够的规则进行检查)
- 寻找未压缩的资源。 可以轻松放置Web服务器以使用gzip压缩,而无需更新站点本身
或者,您可以使用在线PageSpeed Insights
绩效最佳实践
- 减少DNC查找
- 避免重定向
- 减少HTTP请求
- 及早刷新文档,以帮助文档解析器及早发现外部资源
- 使用CDN来减少延迟:必须将内容放在离您的用户最近的位置
- 缩小页面大小
- GZIP您的文字资产
- 优化图像,选择最佳格式
- 添加`Expires`标题
- 添加电子
ETags
- 针对快速的首次渲染进行优化, 不阻止解析器
- 将样式表放在顶部
- 异步加载脚本
- 将脚本放在底部
- 缩小并连接
- 消除内存泄漏
- 构建黄油状光滑的页面(包括卷轴)
- 尽可能利用硬件加速
- 消除JS和DOM内存泄漏
- 在移动设备上测试
- 使用正确的工具进行工作(免费!)
- 了解开发人员工具
- PageSpeed见解
- WebPageTest.org
- 再次在移动设备上测试
参考: 那里有完整的幻灯片(警告,超过3张)
Geoffrey de Smet的 Maven依赖难题
-似乎是步调,娱乐和所有方面的好变化...--
第一张幻灯片重新结合了我的经验:如果将不良的POM部署到Maven存储库,您的用户会感到痛苦( -请参阅最新版本的log4j以获得不执行的操作- )
-他,你可以赢啤酒! -
-
当您添加具有不同groupId的工件时会发生什么?
-
Maven不知道它是同一工件,因此将两者都添加了。 对于用户而言,这意味着您必须禁止过时的工件,并排除传递依赖项。 对于提供者,请使用重定位。 在任何情况下,您都不应该在自己的情况下重新分发其他项目的工件!
当您定义的依赖项版本与依赖项管理的版本父级不同时,会发生什么?
-
Maven覆盖版本。 为了使用父版本,请不要在项目中使用任何版本。
当您定义版本并获得具有不同版本的传递依赖项时会发生什么?
-
Maven可以正确检测到冲突,并使用POM中版本与项目中关系最少的版本。 要快速失败,请使用
maven-enforcer-plugin
和enforce
目标。
关系数相同时会发生什么?
-
Maven从POM中首先声明的依赖项中选择版本! 本质上,这意味着依赖关系是有序的; 版本本身不起作用,而好的策略是保留最高版本。
-满足了希望,真的很有趣! -
Jens Schauder的 Junit规则
-尽管我更像是TestNG的忠实拥,,但似乎规则的概念可能会使两者之间的平衡转向有利于后者。 至少值得一看-
规则解决了测试时遇到的许多问题:
- 由于缺少拆卸而导致测试失败
- 从多个基础测试类继承
- 在测试中复制粘贴代码
- 与不同的跑步者一起跑步
当JUnit尝试运行测试类时,它将找到所有用@Test
注释的方法,并将它们包装在“ statement”中。 规则是将语句作为参数并返回语句的事物。 创建规则就像创建一个继承自Rule
的类并使用@Rule
对其进行注释一样简单。 因此,绑定设置和拆卸代码就像创建一个在评估该语句之前和之后执行某些操作的规则一样简单。 规则还可以用于强制超时,在Event-Dispatch线程中运行测试,甚至更改环境。 此外,可以使用规则创建仅在特定条件下运行的测试,例如,在某些环境中测试特定于Oracle的代码,而在其他环境中测试特定于H2的代码。 最后,可以使用规则为测试类提供服务。
一旦开始使用规则,在测试执行过程中您可能最终将拥有多个规则。 作为一个标准,规则不应该相互依赖,所以顺序应该不是问题。 但是,现实生活中的情况证明需要使用规则链:JUnit提供了RuleChain
来实现这一点。
最后,如果需要在单次运行之前执行规则(类似于@BeforeClass
),则可以使用@RuleClass
。
-恕我直言,似乎规则就像TestNG侦听器一样,自古以来就可以使用。 至少,我尝试过-