四时宝库

程序员的知识宝库

还在面向对象?快来看看这个(面向对象是什么意思?)

今天这一章说的是,要改变我们日常编码的思维习惯,回归到它的本质——数据。

所有的程序,就是在处理一个输入信息,然后产生输出,当然,有的程序虽然没有返回值,但是依旧对数据进行了转换。

所以,程序就是对数据的转换。

但是,我们现在很多时候都会被其他东西占据了注意力,比如、技术选型、表设计、类、算法……

面向数据编程

假如我们想要得到某个目录底下行数最多的五个文件的名字,我们会得到这样一条命令:

find . -type f | xargs wc -l | sort -n | tail -6 | head -5

find . -type f 表示从当前目录获取所有类型的文章

xargs wc -l 计算行数输出

sort -n 正序排序

tail -6 输出结果的最后6行(因为最后一行会显示左右文件的总行数,所以也稍微做一些调整)

head -5 输入结果的前5行

上面这个例子里的数据流向是很清晰的:

目录名称

→ 文件列表

→ 带有行数的列表

→ 排序后的列表

→ 最后的五个文件+总数

→ 最后的五个

可以说完全是自解释的,而且,其中的每一步的功能都可以很方便地复用。

然后,作者用Elixir语言写了另一个例子,例子本身我也不放上来了。但是例子中提到了一个操作符|> ,想特别说明一下。

管道操作符

|>是一个管道操作符:

它的作用是把它左边的值作为右边函数的第一个参数传入,所以下面两种写法等价。

"vinyl" |> String.codepoints |> Comb.subsets()

Comb.subsets(String.codepoints("vinyl"))

不是所有的语言都支持这种操作符,但是作者说,不用把它当做一种语言的特性,而应该把它当做一种不同的思考方式,一种设计哲学。就像面向对象之于过程式变成一样。

面向数据的好处

说到面向对象,今天这个主题也是要革面向对象的命的。

使用面向对象的编程思路,我们会习惯于讲数据隐藏起来,封装起来。然后对象之间互相改变状态,这也是很多耦合发生的原因。

上面的那个例子,如果用面向对象的方式来写,下面的例子,可以当一个伪代码来看,就是简单做个示例。

List<File> getMax5LineCountFiles(String path)
List<File> files
=getFiles(path);
for(File file :files){
int lineCount=FileUtil.countLine(file);
file.setLineCount(lineCount);
}
files.sort(Comparator.comparing(File::getLineCount));
return files.subList(files.getSize()-5-1,files.getSize()-1);
}

很显然的是,这个方法没有太多的复用空间,顶多是获取文件行数这个方法可以复用一下。

而且,为了让这个示例简单一点点,我直接把行数写进了File类里,实际上这个类里可能并没有这个字段属性,我需要用一些其他方式,来保存文件与行数的对应,比如一个Map,Map<Integer,File>,如果这样用的话,排序也会麻烦一些,要自己写比较器。

总之,不论实现麻不麻烦,最重要的是,它们是耦合的。

改用数据流的方式,可让数据从封装中解放出来。

让程序遵循 数据->代码->数据->

今天先说这些,明天把补充后半部分,大家晚安~


发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接