Professional refactoring in Visual Basic
副标题:无
作 者:(美)Danijel Arsenovski著;冯飞译
分类号:
ISBN:9787302200840
微信扫一扫,移动浏览光盘
简介
在这本独一无二的书中,本书作者向您介绍如何利用重构改进现有代
码的设计,使之变得更有效和更具生产力。它提供了实用方法,所以您可
以快速学会如何使用重构工具和功能来管理和修改代码。本书还介绍了如
何进行单元测试、重构模式和重构升级原有的Visual Basic代码。
在学习本书的过程中,将从头开始构建原型应用程序。然后,利用重
构技术将代码转换为正确设计的、企业级的应用程序。本书作者将手把手
地教您每个过程,同时提供了专家级的编码技巧。然后,可以将这些信息
应用到由于公司扩张、策略改变或类似业务决策所引起的实际情形中。
目录
目录
第Ⅰ部分 重构的介绍
第1章 重构的全面介绍
1.1 重构的快速浏览
1.1.1 重构过程
1.1.2 软件行业现状概述
1.2 重构过程的详细介绍
1.2.1 代码味道的使用
1.2.2 代码的转换
1.2.3 重构的优点
1.2.4 澄清一些常见的误解
1.3 Visual Basic和重构
1.3.1 Visual Basic的发展史和遗留问题
1.3.2 Visual Basic的演变
1.3.3 通过重构处理遗留的问题
1.4 小结
第2章 重构的初体验
2.1 Calories Calculator样本应用程序
2.1.1 Calories Calculator应用程序
2.1.2 需求的增长:计算理想的体重
2.1.3 需求的增长:保存病人的数据
2.2 运用中的重构
2.2.1 将BtnCalculate_Click方法分解
2.2.2 发现新的类
2.2.3 限制Patient类的接口
2.2.4 将条件逻辑放到Patient类中
2.2.5 创建Patient类的层次结构
2.3 保存功能的实现
2.3.1 保存数据
2.3.2 实现显示病人历史信息的功能
2.4 Calories Calculator重构过的版本
2.5 小结
第3章 组建重构的工具箱
3.1 使用自动化的重构工具
3.1.1 JetBrains提供的ReSharper
3.1.2 Whole Tomato提供的Visual Assist X
3.1.3 Developer Express提供的Refactor! Pro
3.1.4 从Refactor!开始入手
3.1.5 进一步探讨VB用户界面的Refactor!
3.1.6 快速浏览:可供使用的重构
3.2 单元测试的基本内容:测试的护具
3.2.1 单元测试架构的出现
3.2.2 NUnit的初体验
3.2.3 NUnit的安装
3.2.4 第一个测试的实现
3.2.5 测试驱动的方法
3.2.6 需要考虑的其他测试工具
3.3 关于版本控制的一些问题
3.4 小结
第4章 Rent-a-Wheels应用程序的原型
4.1 会见客户
4.1.1 会见经理
4.1.2 会见前台接待员
4.1.3 会见停车场的服务人员
4.1.4 会见维护人员
4.2 采取Rent-a-Wheels项目中最初的步骤
4.2.1 参与者和用例
4.2.2 汽车的状态
4.2.3 首次拟定主要的应用程序窗口
4.2.4 Rent-a-Wheels开发团队的会议
4.3 让原型运转
4.3.1 检查数据库模型
4.3.2 检查Visual Basic的代码
4.4 快速而高效的VB编程方法
4.4.1 数据库驱动的设计
4.4.2 基于GUI的应用程序
4.4.3 事件驱动的编程
4.4.4 快速应用程序开发(RAD)
4.4.5 复制/粘贴作为代码重用的机制
4.5 通过重构过程从原型进入到交付
4.6 小结
第Ⅱ部分 VB重构的初步知识
第5章 Chameleon语言:从静态弱类型化到动态强类型化
5.1 Option Explicit和Option Strict的.NET影响
5.2 在不严格的代码中设置Option Explicit On
5.2.1 理解Set Option Explicit On重构
5.2.2 将Rent-a-Wheels代码重构成显式的形式
5.3 在不严格的代码中设置Option Strict On
5.3.1 一个有点人为的随意的VB代码示例
5.3.2 通过新变量的定义来解决变量的复杂用法
5.3.3 推断变量的类型
5.3.4 通过类型转换函数将所有内容整合在一起
5.3.5 方法、字段、属性和其他成员的处理
5.3.6 将Set Option Strict On重构运用到Rent-a-Wheels应用程序中
5.4 静态类型化对动态类型化及其与Visual Basic的关系
5.4.1 Visual Basic 6及其之前版本中的后期绑定
5.4.2 鸭子类型化
5.4.3 在文件层次上重设动态行为或静态行为
5.4.4 为动态代码提供一个静态类型化的封装器
5.5 激活显式而严格的编译器选项
5.5.1 在Project Properties窗口中设置选项
5.5.2 更改Visual Basic编译器的默认行为
5.5.3 在源文件中设置选项
5.5.4 使用项模板来设置选项
5.6 小结
第6章 错误处理:以一些简单的步骤从传统风格步入到结构化风格
6.1 传统的错误处理和结构化的错误处理
6.1.1 传统的(非结构化的)错误处理
6.1.2 结构化的错误处理
6.2 结构化错误处理的好处
6.2.1 结构化的代码和非结构化的代码
6.2.2 作为类型而不是数字出现的异常
6.2.3 错误过滤
6.2.4 Finally代码块
6.2.5 .NET的互操作性
6.3 用Try-Catch-Finally取代On Error构造
6.3.1 理解关键字When
6.3.2 用Try-Catch-Finally替换On Error的重构步骤
6.3.3 用Try-Catch-Finally构造替换On Error Goto标签
6.3.4 用Try-Catch-Finally构造替换On Error Resume Next
6.4 用异常类型替换错误代码
6.4.1 用异常类型替换系统错误代码
6.4.2 用异常类型来替换自定义的错误代码
6.5 Rent-a-Wheels应用程序中的错误处理
6.6 小结
第7章 基本的代码卫生:消除无用代码、降低作用域、使用显式导入以及删除不用的引用
7.1 删除无用代码
7.1.1 无用代码的类型
7.1.2 无用代码常见的来源
7.2 降低过度曝光的元素的作用域和访问级别
7.2.1 作用域和访问级别
7.2.2 过度曝光常见的来源
7.2.3 处理过度曝光的问题
7.3 使用显式导入
7.4 删除未使用的程序集引用
7.5 Rent-a-Wheels应用程序中的基本卫生
7.6 小结
第Ⅲ部分 标准重构转换的初步介绍
第8章 从问题域到代码:消除差距
8.1 理解问题域
8.1.1 第1步:收集信息
8.1.2 第2步:就词汇表达成一致意见
8.1.3 第3步:描述交互作用
8.1.4 第4步:建立原型
8.2 命名的指导原则
8.2.1 大写风格
8.2.2 简单的命名指导原则
8.2.3 顺畅地传递信息:选择正确的单词
8.2.4 Rename重构
8.3 发布接口和公有接口
8.3.1 自包含的应用程序与可重用的模块
8.3.2 修改公有接口
8.3.3 Refactor!中的Safe Rename重构
8.4 Rent-a-Wheels应用程序中的 Rename和Safe Rename重构
8.5 小结
第9章 对重复代码进行方法提取
9.1 保持封装代码和隐藏细节的原因
9.2 信息和实现的隐藏
9.3 分解方法
9.3.1 周长计算——长方法的一个示例
9.3.2 提取周长计算的代码
9.3.3 提取计算半径的代码
9.3.4 提取Wait for User to Close代码
9.3.5 提取读取坐标的代码
9.3.6 Refactor!中的Extract Method重构
9.4 重复代码的味道
9.4.1 重复代码的来源
9.4.2 复制/粘贴编程
9.5 幻数
9.6 Rent-a-Wheels应用程序中的Extract Method和Replace Magic Literal重构
9.7 小结
第10章 方法合并与方法提取的技术
10.1 临时变量的处理
10.1.1 Move Declaration Near Reference重构
10.1.2 Move Initialization to Declaration重构
10.1.3 Split Temporary Variable重构
10.1.4 Inline Temp重构
10.1.5 Replace Temp with Query重构
10.2 方法重组的试探
10.3 方法重组与Rent-a-Wheels
10.3.1 删除Rent-a-Wheels中的重复
10.3.2 Rent-a-Wheels中的幻数、注释以及事件处理盲区
10.4 小结
第Ⅳ部分 高级重构
第11章 发现对象
11.1 面向对象编程的快速回顾
11.1.1 到底什么是对象
11.1.2 封装与对象
11.1.3 Refactor!中的Encapsulate Field重构
11.1.4 对象状态的保持
11.1.5 类
11.1.6 对象标识
11.1.7 作为基本构建块的对象
11.1.8 根对象
11.1.9 对象的生存期和垃圾回收
11.1.10 消息
11.2 类的设计
11.2.1 类是名词,操作是动词
11.2.2 类、责任和协作者
11.2.3 实体和关系
11.3 发现隐藏的类
11.3.1 处理数据库驱动的设计
11.3.2 从过程化设计到面向对象设计的转移
11.3.3 保持域、表示和持久化分离
11.3.4 发现对象和Rent-a-Wheels应用程序
11.4 小结
第12章 面向对象的高级概念和相关的重构
12.1 继承、多态性和泛型
12.1.1 继承
12.1.2 多态性
12.1.3 泛型
12.2 继承的误用以及重构解决方案
12.2.1 误用继承的组合和其他误用情形
12.2.2 继承的重构——打印系统的举例
12.3 泛型的使用
12.4 Rent-a-Wheels应用程序中的继承和泛型
12.4.1 提取超类
12.4.2 运用泛型
12.4.3 提取数据对象提供者的类
12.5 小结
第13章 大规模的代码组织
13.1 命名空间
13.1.1 命名指导原则与命名空间的组织
13.1.2 嵌套的命名空间
13.1.3 修改根命名空间的名称
13.1.4 使用导入语句
13.2 程序集
13.2.1 二进制重用
13.2.2 命名空间组织的指导原则
13.2.3 依赖性方面的考虑
13.3 Visual Basic项目文件的结构组织
13.3.1 Refactor!中的Move Type to File重构
13.3.2 部分类
13.3.3 继承窗体
13.3.4 抽象窗体的继承
13.3.5 将抽象窗体的工作委托给窗体辅助类
13.4 Rent-a-Wheels中命名空间的组织与Windows窗体继承
13.4.1 通过抽象窗体辅助模式的应用程序来提取父管理窗体
13.4.2 命名空间和程序集的重组
13.5 小结
第V部分 重构的运用
第14章 重构成模式
14.1 到底什么是设计模式
14.1.1 设计模式的定义
14.1.2 模式的分类
14.1.3 模式的元素
14.1.4 权衡设计模式的利弊
14.1.5 模式的使用
14.2 设计模式的示例:Abstract Factory
14.2.1 名称
14.2.2 问题
14.2.3 解决方案
14.2.4 后果
14.3 Dependency Injection模式
14.3.1 问题
14.3.2 解决方案
14.3.3 基于构造函数注入与基于属性注入
14.3.4 应该注入什么服务实现
14.3.5 后果
14.3.6 重构成DI
14.4 重构成模式以及Rent-a-Wheels应用程序
14.4.1 消除.NET架构中所提供的重复功能的代码
14.4.2 通过依赖注入向GUI类中注入Data类
14.4.3 CRUD持久化模式
14.5 小结
第15章 LINQ和VB 2008的其他增强功能
15.1 局部变量的类型推断
15.2 XML生产能力的增强
15.2.1 XML字面量
15.2.2 通过XML轴属性导航XML
15.2.3 将XML字面量提取到Refactor!中的资源中
15.3 通过LINQ查询对象
15.3.1 旧示例换“新颜”
15.3.2 LINQ to SQL的对象/关系映射
15.3.3 LINQ和Rent-a-Wheels应用程序
15.4 小结
第16章 VB遗留代码的未来
16.1 是否需要迁移
16.1.1 迁移不可能是百分之百自动进行的
16.1.2 VB 6和VB.NET代码可以互操作
16.1.3 迁移工具和库
16.2 初步的VB 6重构
16.2.1 打破整体化
16.2.2 条件编译的处理
16.3 将被迁移的代码放到测试护具中
16.3.1 引入功能测试护具
16.3.2 实现功能测试护具
16.4 遗留代码的升级
16.4.1 静态严格类型化
16.4.2 将设计从过程式设计移到面向对象设计的范例中
16.4.3 引入继承
16.4.4 利用参数化的构造函数
16.4.5 将泛型容器用于额外的类型安全
16.4.6 异常处理的升级
16.4.7 XML注释的实现
16.4.8 释放.NET中的资源
16.5 小结
附录A Refactor!揭密
附录B Rent-a-Wheels原型的内部机理和相互联系
第Ⅰ部分 重构的介绍
第1章 重构的全面介绍
1.1 重构的快速浏览
1.1.1 重构过程
1.1.2 软件行业现状概述
1.2 重构过程的详细介绍
1.2.1 代码味道的使用
1.2.2 代码的转换
1.2.3 重构的优点
1.2.4 澄清一些常见的误解
1.3 Visual Basic和重构
1.3.1 Visual Basic的发展史和遗留问题
1.3.2 Visual Basic的演变
1.3.3 通过重构处理遗留的问题
1.4 小结
第2章 重构的初体验
2.1 Calories Calculator样本应用程序
2.1.1 Calories Calculator应用程序
2.1.2 需求的增长:计算理想的体重
2.1.3 需求的增长:保存病人的数据
2.2 运用中的重构
2.2.1 将BtnCalculate_Click方法分解
2.2.2 发现新的类
2.2.3 限制Patient类的接口
2.2.4 将条件逻辑放到Patient类中
2.2.5 创建Patient类的层次结构
2.3 保存功能的实现
2.3.1 保存数据
2.3.2 实现显示病人历史信息的功能
2.4 Calories Calculator重构过的版本
2.5 小结
第3章 组建重构的工具箱
3.1 使用自动化的重构工具
3.1.1 JetBrains提供的ReSharper
3.1.2 Whole Tomato提供的Visual Assist X
3.1.3 Developer Express提供的Refactor! Pro
3.1.4 从Refactor!开始入手
3.1.5 进一步探讨VB用户界面的Refactor!
3.1.6 快速浏览:可供使用的重构
3.2 单元测试的基本内容:测试的护具
3.2.1 单元测试架构的出现
3.2.2 NUnit的初体验
3.2.3 NUnit的安装
3.2.4 第一个测试的实现
3.2.5 测试驱动的方法
3.2.6 需要考虑的其他测试工具
3.3 关于版本控制的一些问题
3.4 小结
第4章 Rent-a-Wheels应用程序的原型
4.1 会见客户
4.1.1 会见经理
4.1.2 会见前台接待员
4.1.3 会见停车场的服务人员
4.1.4 会见维护人员
4.2 采取Rent-a-Wheels项目中最初的步骤
4.2.1 参与者和用例
4.2.2 汽车的状态
4.2.3 首次拟定主要的应用程序窗口
4.2.4 Rent-a-Wheels开发团队的会议
4.3 让原型运转
4.3.1 检查数据库模型
4.3.2 检查Visual Basic的代码
4.4 快速而高效的VB编程方法
4.4.1 数据库驱动的设计
4.4.2 基于GUI的应用程序
4.4.3 事件驱动的编程
4.4.4 快速应用程序开发(RAD)
4.4.5 复制/粘贴作为代码重用的机制
4.5 通过重构过程从原型进入到交付
4.6 小结
第Ⅱ部分 VB重构的初步知识
第5章 Chameleon语言:从静态弱类型化到动态强类型化
5.1 Option Explicit和Option Strict的.NET影响
5.2 在不严格的代码中设置Option Explicit On
5.2.1 理解Set Option Explicit On重构
5.2.2 将Rent-a-Wheels代码重构成显式的形式
5.3 在不严格的代码中设置Option Strict On
5.3.1 一个有点人为的随意的VB代码示例
5.3.2 通过新变量的定义来解决变量的复杂用法
5.3.3 推断变量的类型
5.3.4 通过类型转换函数将所有内容整合在一起
5.3.5 方法、字段、属性和其他成员的处理
5.3.6 将Set Option Strict On重构运用到Rent-a-Wheels应用程序中
5.4 静态类型化对动态类型化及其与Visual Basic的关系
5.4.1 Visual Basic 6及其之前版本中的后期绑定
5.4.2 鸭子类型化
5.4.3 在文件层次上重设动态行为或静态行为
5.4.4 为动态代码提供一个静态类型化的封装器
5.5 激活显式而严格的编译器选项
5.5.1 在Project Properties窗口中设置选项
5.5.2 更改Visual Basic编译器的默认行为
5.5.3 在源文件中设置选项
5.5.4 使用项模板来设置选项
5.6 小结
第6章 错误处理:以一些简单的步骤从传统风格步入到结构化风格
6.1 传统的错误处理和结构化的错误处理
6.1.1 传统的(非结构化的)错误处理
6.1.2 结构化的错误处理
6.2 结构化错误处理的好处
6.2.1 结构化的代码和非结构化的代码
6.2.2 作为类型而不是数字出现的异常
6.2.3 错误过滤
6.2.4 Finally代码块
6.2.5 .NET的互操作性
6.3 用Try-Catch-Finally取代On Error构造
6.3.1 理解关键字When
6.3.2 用Try-Catch-Finally替换On Error的重构步骤
6.3.3 用Try-Catch-Finally构造替换On Error Goto标签
6.3.4 用Try-Catch-Finally构造替换On Error Resume Next
6.4 用异常类型替换错误代码
6.4.1 用异常类型替换系统错误代码
6.4.2 用异常类型来替换自定义的错误代码
6.5 Rent-a-Wheels应用程序中的错误处理
6.6 小结
第7章 基本的代码卫生:消除无用代码、降低作用域、使用显式导入以及删除不用的引用
7.1 删除无用代码
7.1.1 无用代码的类型
7.1.2 无用代码常见的来源
7.2 降低过度曝光的元素的作用域和访问级别
7.2.1 作用域和访问级别
7.2.2 过度曝光常见的来源
7.2.3 处理过度曝光的问题
7.3 使用显式导入
7.4 删除未使用的程序集引用
7.5 Rent-a-Wheels应用程序中的基本卫生
7.6 小结
第Ⅲ部分 标准重构转换的初步介绍
第8章 从问题域到代码:消除差距
8.1 理解问题域
8.1.1 第1步:收集信息
8.1.2 第2步:就词汇表达成一致意见
8.1.3 第3步:描述交互作用
8.1.4 第4步:建立原型
8.2 命名的指导原则
8.2.1 大写风格
8.2.2 简单的命名指导原则
8.2.3 顺畅地传递信息:选择正确的单词
8.2.4 Rename重构
8.3 发布接口和公有接口
8.3.1 自包含的应用程序与可重用的模块
8.3.2 修改公有接口
8.3.3 Refactor!中的Safe Rename重构
8.4 Rent-a-Wheels应用程序中的 Rename和Safe Rename重构
8.5 小结
第9章 对重复代码进行方法提取
9.1 保持封装代码和隐藏细节的原因
9.2 信息和实现的隐藏
9.3 分解方法
9.3.1 周长计算——长方法的一个示例
9.3.2 提取周长计算的代码
9.3.3 提取计算半径的代码
9.3.4 提取Wait for User to Close代码
9.3.5 提取读取坐标的代码
9.3.6 Refactor!中的Extract Method重构
9.4 重复代码的味道
9.4.1 重复代码的来源
9.4.2 复制/粘贴编程
9.5 幻数
9.6 Rent-a-Wheels应用程序中的Extract Method和Replace Magic Literal重构
9.7 小结
第10章 方法合并与方法提取的技术
10.1 临时变量的处理
10.1.1 Move Declaration Near Reference重构
10.1.2 Move Initialization to Declaration重构
10.1.3 Split Temporary Variable重构
10.1.4 Inline Temp重构
10.1.5 Replace Temp with Query重构
10.2 方法重组的试探
10.3 方法重组与Rent-a-Wheels
10.3.1 删除Rent-a-Wheels中的重复
10.3.2 Rent-a-Wheels中的幻数、注释以及事件处理盲区
10.4 小结
第Ⅳ部分 高级重构
第11章 发现对象
11.1 面向对象编程的快速回顾
11.1.1 到底什么是对象
11.1.2 封装与对象
11.1.3 Refactor!中的Encapsulate Field重构
11.1.4 对象状态的保持
11.1.5 类
11.1.6 对象标识
11.1.7 作为基本构建块的对象
11.1.8 根对象
11.1.9 对象的生存期和垃圾回收
11.1.10 消息
11.2 类的设计
11.2.1 类是名词,操作是动词
11.2.2 类、责任和协作者
11.2.3 实体和关系
11.3 发现隐藏的类
11.3.1 处理数据库驱动的设计
11.3.2 从过程化设计到面向对象设计的转移
11.3.3 保持域、表示和持久化分离
11.3.4 发现对象和Rent-a-Wheels应用程序
11.4 小结
第12章 面向对象的高级概念和相关的重构
12.1 继承、多态性和泛型
12.1.1 继承
12.1.2 多态性
12.1.3 泛型
12.2 继承的误用以及重构解决方案
12.2.1 误用继承的组合和其他误用情形
12.2.2 继承的重构——打印系统的举例
12.3 泛型的使用
12.4 Rent-a-Wheels应用程序中的继承和泛型
12.4.1 提取超类
12.4.2 运用泛型
12.4.3 提取数据对象提供者的类
12.5 小结
第13章 大规模的代码组织
13.1 命名空间
13.1.1 命名指导原则与命名空间的组织
13.1.2 嵌套的命名空间
13.1.3 修改根命名空间的名称
13.1.4 使用导入语句
13.2 程序集
13.2.1 二进制重用
13.2.2 命名空间组织的指导原则
13.2.3 依赖性方面的考虑
13.3 Visual Basic项目文件的结构组织
13.3.1 Refactor!中的Move Type to File重构
13.3.2 部分类
13.3.3 继承窗体
13.3.4 抽象窗体的继承
13.3.5 将抽象窗体的工作委托给窗体辅助类
13.4 Rent-a-Wheels中命名空间的组织与Windows窗体继承
13.4.1 通过抽象窗体辅助模式的应用程序来提取父管理窗体
13.4.2 命名空间和程序集的重组
13.5 小结
第V部分 重构的运用
第14章 重构成模式
14.1 到底什么是设计模式
14.1.1 设计模式的定义
14.1.2 模式的分类
14.1.3 模式的元素
14.1.4 权衡设计模式的利弊
14.1.5 模式的使用
14.2 设计模式的示例:Abstract Factory
14.2.1 名称
14.2.2 问题
14.2.3 解决方案
14.2.4 后果
14.3 Dependency Injection模式
14.3.1 问题
14.3.2 解决方案
14.3.3 基于构造函数注入与基于属性注入
14.3.4 应该注入什么服务实现
14.3.5 后果
14.3.6 重构成DI
14.4 重构成模式以及Rent-a-Wheels应用程序
14.4.1 消除.NET架构中所提供的重复功能的代码
14.4.2 通过依赖注入向GUI类中注入Data类
14.4.3 CRUD持久化模式
14.5 小结
第15章 LINQ和VB 2008的其他增强功能
15.1 局部变量的类型推断
15.2 XML生产能力的增强
15.2.1 XML字面量
15.2.2 通过XML轴属性导航XML
15.2.3 将XML字面量提取到Refactor!中的资源中
15.3 通过LINQ查询对象
15.3.1 旧示例换“新颜”
15.3.2 LINQ to SQL的对象/关系映射
15.3.3 LINQ和Rent-a-Wheels应用程序
15.4 小结
第16章 VB遗留代码的未来
16.1 是否需要迁移
16.1.1 迁移不可能是百分之百自动进行的
16.1.2 VB 6和VB.NET代码可以互操作
16.1.3 迁移工具和库
16.2 初步的VB 6重构
16.2.1 打破整体化
16.2.2 条件编译的处理
16.3 将被迁移的代码放到测试护具中
16.3.1 引入功能测试护具
16.3.2 实现功能测试护具
16.4 遗留代码的升级
16.4.1 静态严格类型化
16.4.2 将设计从过程式设计移到面向对象设计的范例中
16.4.3 引入继承
16.4.4 利用参数化的构造函数
16.4.5 将泛型容器用于额外的类型安全
16.4.6 异常处理的升级
16.4.7 XML注释的实现
16.4.8 释放.NET中的资源
16.5 小结
附录A Refactor!揭密
附录B Rent-a-Wheels原型的内部机理和相互联系
Professional refactoring in Visual Basic
- 名称
- 类型
- 大小
光盘服务联系方式: 020-38250260 客服QQ:4006604884
云图客服:
用户发送的提问,这种方式就需要有位在线客服来回答用户的问题,这种 就属于对话式的,问题是这种提问是否需要用户登录才能提问
Video Player
×
Audio Player
×
pdf Player
×