http://pan.baidu.com/s/1pKFtjw3
youtube-dl -f 'bestvideo[height<=?1081] + bestaudio/best'
u2b 1080p 搬运完了,播放没有声音的话,需要安装支持 webm opus 音频的播放器。
这是我的 u2b 搬砖,用的是 youtube-dl 下载的 720p 格式 https://pan.baidu.com/s/1boFHECR
有 ppt 不同步的可以配合原版 ppt 看 https://ruby-china.org/topics/31164
我的这页 http://chloerei.com/rubyconfchina2016/#/4/4 如果不看动图是没有效果的。
下届务必用录屏方式。
薄荷网的微服务演讲里有一点我不是很明白 为什么要避免使用类方法的形式,而使用传入对象的方式呢?
类方法也可以继承,也可以复写
不知道有没有盆友能够提供下这么做的好处 thx
#21 楼 @jicheng1014 我是薄荷的 vincent,欢迎探讨这个问题,
对于 ServiceObject,我认为使用类方法还是使用对象方法是两种看待(抽象)问题的方式。
# 类方法形式
class SuperService
def self.call(params)
# bla bla...
# process it with params
end
end
# call service
result = SuperService.call params
# 对象方法形式
class SuperService
def initialize(params)
@params = params
end
def call
# bla bla...
# process it with @params
end
end
# call service
service = SuperService.new params
result = service.call
从代码上看起来,对象方法要比类方法要啰嗦一些,而且可能有的同学还担心使用对象方法性能要差一些,因为多生成了一个 service 对象,另外 params 还需要在对象中使用实例变量传递。
我们最初也使用类方法,后来才慢慢转变为使用对象方法。如果 service 很简单,使用类方法更简单直接的,但是当 service 变得复杂之后,我们发现使用对象方法的处理方式要好很多。
首先遇到的方法重构问题。当 service 逻辑变得复杂之后,在一个 call 方法里容纳所有的代码并不合适,这个时候要从中抽离方法,如果使用对象方法的话重构比较简单,剥离一些代码形成私有方法,然后在 call 方法中进行总调度就可以了。如果使用类方法的话,麻烦的是让类方法成为私有不那么直观,另外需要每个调用过程中传递所有参数。
其次是处理复用问题,对象方法形式的 ServiceObject 更容易处理。本质上对象方法形式的 ServiceObject 的方式更 OOP,所以可以很方便的使用一些面向对象的手法,包括继承和多态等等。类方法本质上是一种带了命名空间的全局方法,虽然类方法也能继承使用,但是相比对象方法的处理方式,没有那么优雅。
最后,对于有同学担心的性能问题,相比它带来的易扩展和优雅性,我觉得可以不值一提,一次 Rails request 生成的对象成千上万,一个极其轻量的 ServiceObject 对象生成可以忽略不计。
另外,每次都 new 一个 service 对象在 call 的方式确实有点累赘,本着 DRY 的原则,我们写一个 Servable module,只要 mix 这个 module,就可以使用简洁的直接 call 方式。
代码如下所示:
module Servable
def call(*args)
new(*args).call
end
end
class SuperService
extend Servable
def initialize(params)
@params = params
end
def call
# bla bla ...
end
end
# call service
result = SuperService.call params
The end.
#29 楼 @vincent 感谢如此详实的解释,下面是我自己的一些见解,希望对其他 RubyChina 朋友有用
关于类方法中进行抽象一部分函数私有化,我一般会这样处理
class Template
class < self
def seal
puts "seal"
invoke_private_method
end
private
def invoke_private_method
puts "invoke_private_method"
end
end
end
我觉得实例化服务对象的最大好处就在于传参数只需要传一次参数,在有些时候会在一个动作里调用 service 里的几个方法的时候,这种方式比较轻松。比如下面的例子
def index
service = UserService.new(current_user, params)
service.notice_all_members
service.start_user_docker
end
#30 楼 @jicheng1014 这些动作也可以做成 service 的实例方法,作为一个 service 的对象,可以按照顺序调用实例方法。我是这么理解的。
#30 楼 @jicheng1014 确实,包在 class 的 private 可以把类方法私有,但是这种方法和对象的私有方法相比,没法很简便的共享对象的状态,每个方法都要传递所有参数。
#33 楼 @betterthornbird 感谢聆听!跨服务数据访问是实施微服务化后面临的一个麻烦问题,解决的方式多种多样,共享存储是一种变通方法。
微服务化的一个显著标志就是每个微服务都有自己独立的存储(包括数据库和缓存),独立开发和独立部署。每个微服务应该是独立的,通常情况一个服务需要使用另外一个服务的数据应该通过服务的 API(也就是服务间通信)来完成,但是有些特殊情景走 API 的话,会变得特别麻烦和低效,所以可以通过共享数据存储变通一下。
比如验证用户安全。用户会话建立和安全认证是由账号系统 Passport 统一负责的,但每个微服务也都有验证用户安全的需求,如果每次请求都要访问 Passport 一次十分麻烦和低效,我们的做法是所有微服务之间共享用户会话数据(放在 Redis 中),只有 Passport 有写入权限,其它微服务只有读权限。另外一种做法是使用 API 网关,所有验证都在网关完成,每个微服务都不用管用户验证,我们没有使用这种方法。
另外一个例子是某些使用频繁的公共数据库也使用共享存储。比如我们系统中食物数据使用特别频繁,我们直接把这部分的数据和模型以只读方式共享给其它微服务,这样使用食物数据就简单多了。
#30 楼 @jicheng1014 另外一点,我认为虽然 ServiceObject 中可以有多个实例方法,但是基于单一责任原则,服务主要动作建议只有一个,这是我们只使用一个 call 方法的原因。如果有多个主要动作还不如剥离成多个 ServiceObject,如果它们之间有关联逻辑要复用,可以通过类继承或模块 mix 达成,这也是用实例方法的好处之一。