为什么说private方法是有罪的
具体的这句话从什么地方获得,我已经无从考证了,但是想想我们现在使用private的场景,你慢慢的就会发现,private的方法,大多数都是copy代码,当然我只是说大多数,还有就是大多数private方法实际上是设计的不太合理的遗留物。我先说两个我应用的场景,第一种场景与设计没有关系,只是与维护系统有关系。
第一种场景:维护系统,扩展系统
不知道大家有没有这种场景,需要维护或者扩展一个系统,这个时候,你只能通过继承某个类来做事情,不能通过修改source来达到目的,而这个时候,你会发现,你真正需要修改的,或者言之,替换的只是一个小小的方法,你只要override这个小方法就可以,而这个时候,很不幸的是,他是一个private方法,你能怎么办呢?只能找到更大范围的方法来进行override,然后把其它不相关的方法在copy到自己的类里面,只有这样才能达到目的。
第二种场景,设计角度,这个是我真正想说的地方。
大家写代码的时候,很多时候,会遵循Refactor里面的一些原则,会把很多代码抽成很多小的方法,而这些小的方法往往会是private的方法,这些private方法,大体上可以分为两类,一类是Util方法,一类是业务方法。
先说第一种Util方法,很多时候,大多数是判断时间是否合理,String是否为空,字符是否够长等等,诸如此类的方法,就是与业务一点关系都没有的,这种方法,我想不用我说什么了,你自己应该明白,为什么这些是可耻的了吧,或者有罪了吧。因为这些Util方法很多地方都会用到的,不止这一个地方,这些方法如果是private的话,你会在这个项目里面很多地方都看到类似的private方法,大家都是copy来,copy去,DRY原则不用重复了。
再说第二种业务方法的,这类我也分为两种,A是业务逻辑在错误地方,B是模板方法中的流程方法。
A业务逻辑在错误地方
举个小例子:
有个业务逻辑判断是否可以卖烟给这个人,一个判断逻辑就是是否18岁
private boolean isCanSale(Person person) {
if (person.getAge() < 18) {
return false;
}
return true;
}
但是慢慢的你会发现,很多地方都需要这个业务逻辑,比如是否可以卖酒给这个人,同样也是如此。那么这个时候,其实就是这个方法逻辑,放错了地方,应该属于Person的属性。
public boolean isAdult() {
if (this.getAge() < 18) {
return false;
}
return true;
}
在别的地方就会调用person.isAdult(),就可以了。当然在深入的讲,是否为成年人,这个其实还是与地方的法律有关系的,所以后面可能还会把这个方法挪到另外的地方去。
B 模板方法中的流程方法
就是在模板类中,有很多流程的方法,这些方法写成了private,例如我之前的例子
public abstract class FatherTemplate {
public void doProcess() {
a();
b();
c();
}
private void a() {
// doSomething();
};
private void void b();
private void void c();
}
这种方法,在将来就会遇到我说的第一种情况,就是对于扩展和使用会出现很多问题,同时这个地方变成框架中的一部分的时候,也会遇到第一种情况,对于扩展不是很友好。当然如果说,我的方法,永远不会扩展,那么你也会发现,这里面的方法,也会逐步的挪到其它的类里面。----没有继承使用,那么就会变成其它类里面的公开方法,这个是我的判断。
private的第一原则,就是永远不要private
为什么说private方法是有罪的的更多相关文章
- 用PowerMock spy mock private方法
在实际的工作中,经常碰到只需要mock一个类的一部分方法,这时候可以用spy来实现. 被测类: public class EmployeeService { public boolean exist( ...
- 【Thinking in Java】编写构造器时应注意:尽量避免调用其他非private方法
最近重温了<Thinking in Java>,发现了一个让我为之兴奋的知识漏洞,必须得分享一下. 上一篇的<Java类初始化的过程>的随笔中,那个初始化顺序并不完整.初始化的 ...
- PHPUnit单元测试中类protected/private方法测试
这里首先有一个问题要考虑的是,这类方法是否要被测试? 理论上,这类方法都会被其它public类型的方法调用,只要对那些public的方法做充分的测试,就可以保证这些方法的可靠性,就没有必要再测了.好像 ...
- powermockito “mock public 方法内部 Private方法的问题”
我需要测试的方法是 public 方法: public ResponseResult subscribe(SysSubscription sysSubscription) throws JsonGen ...
- 分享调用Java private方法
上周在修复bug时,发现Java类中某方法是private,且类中没有用到,第一感觉是方法多余.其实通过分析,发现原来Native Code会通过JNI调到此方法.这也给自己启发,平时做Code re ...
- 利用反射编写私有 Private 方法的单元测试
利用反射编写私有 Private 方法的单元测试 最近在添加一个新feature时,鉴于要给自己的代码一是增加代码的强壮性,二是增加代码测试的覆盖率.但是遇到了有些方法是 Private 的,但是在调 ...
- java中static,final,private方法的继承多态问题
父类中的final private方法不能被继承,父类中的static方法可以被继承,但是不能重写,这三者都属于前期绑定,java中除了这三种以及构造方法之外剩下的都是后期绑定(运行是绑定). 当父 ...
- 在MS Test中如何测试private方法
前言: 在博客开始之前,我们先讨论一下是否应该对private方法做测试,通常有两种观点: private方法应该被测试: private方法不应该被测试: 我们以下面的代码为例子来进行说明: pub ...
- C++ 外部调用private方法
1.思考,对于C++,能不能在外部调用私有方法? 2.在Java中,子类继承不能缩小父类成员的访问权限.因为在Java中,继承只是表示Is-A关系,因此,父类提供的接口,子类必须承诺仍然提供,不能缩小 ...
随机推荐
- 四级菜单实现(Python)
menu_dict = { '山东' : { '青岛' : { '四方':{'兴隆路','平安路','杭州路'}, '黄岛':{}, '崂山':{} }, '济南' : { '历城':{}, '槐荫' ...
- 【jQuery】deferred对象了解
deferred对象就是jQuery的回调函数解决方案,在英语中,defer的意思是"延迟",所以deferred对象的含义就是"延迟"到未来某个点再执行. 它 ...
- 【金融123】CNY和CNH的差异和关联
https://www.sohu.com/a/117406459_473263 离岸人民币(CNH)与在岸人民币(CNY) 差异: CNY CNH 法律监管限制 在岸人民币受大陆市场的管制,外汇和 ...
- Ubunru 16.04 kinetic 下安装turtlebot2
默认安装Ubuntu16.04以及ROS kinetic 防止忘记. 1. 准备工作: $ sudo apt-get install python-rosdep python-wstool ros-k ...
- php7.0编译安装
1.解压安装 tar zxvf php-7.0.2.tar.gz cd php-7.0.2 2.安装依赖库: yum -y install libjpeg libjpeg-devel libpng ...
- [USACO06NOV]玉米田$Corn \ \ Fields$ (状压$DP$)
#\(\mathcal{\color{red}{Description}}\) \(Link\) 农场主\(John\)新买了一块长方形的新牧场,这块牧场被划分成\(M\)行\(N\)列\((1 ≤ ...
- Xcode 错误收集及解决办法
1.An unknown error occurred. 如果仅仅提示“An unknown error occurred.” 而没有别的提示,很有可能是设备内存已满,没有足够的空间来安装这个应用. ...
- Filters in ASP.NET Core (转自MSDN)
Filters in ASP.NET Core MVC allow you to run code before or after specific stages in the request pro ...
- ACM-SG函数之S-Nim——hdu1536 hdu1944 poj2960
S-Nim Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...
- spring,springMVC,mybatis项目添加maven后报500错
<resources> <resource> <directory>src/main/java</directory> <includes> ...