Link: http://programmers.stackexchange.com/questions/147977/is-it-wrong-to-use-a-boolean-parameter-to-determine-behavior

I have seen a practice from time to time that “feels” wrong, but I can’t quite articulate what is wrong about it. Or maybe it’s just my prejudice. Here goes:
A developer defines a method with a boolean as one of its parameters, and that method calls another, and so on, and eventually that boolean is used, solely to determine whether or not to take a certain action. This might be used, for example, to allow the action only if the user has certain rights, or perhaps if we are (or aren’t) in test mode or batch mode or live mode, or perhaps only when the system is in a certain state.
Well there is always another way to do it, whether by querying when it is time to take the action (rather than passing the parameter), or by having multiple versions of the method, or multiple implementations of the class, etc. My question isn’t so much how to improve this, but rather whether or not it really is wrong (as I suspect), and if it is, what is wrong about it.

Yes, this is likely a code smell, which would lead to unmaintainable code that is difficult to understand and that has a lower risk of being easily re-used.
As other posters have noted context is everything (don’t go in heavy-handed if it’s a one off or if the practise has been acknowledged as deliberately incurred technical debt to be re-factored later) but broadly speaking if there is a parameter passed into a function that selects specific behaviour to be executed then further stepwise refinement is required; Breaking up this function in to smaller functions will produce more highly cohesive ones.

So what is a highly cohesive function?
It’s a function that does one thing and one thing only.
The problem with a parameter passed in as you describe is that the function is doing more than two things; it may or may not check the users access rights depending on the state of the boolean parameter, then depending on that decision tree it will carry out a piece of functionality.
It would be better to separate the concerns of Access Control from the concerns of Task, Action or Command.
As you have already noted the intertwining of theses concerns seems off.
So the notion of Cohesiveness helps us identify that the function in question is not highly cohesive and that we could refactor the code to produce a set of more cohesive functions.
So the question could be restated; Given that we all agree passing behavioural selection parameters is best avoided how do we improve matters?

I stopped using this pattern a long time ago, for a very simple reason; maintenance cost. Several times I found that I had some function say frobnicate(something, forwards_flag) which was called many times in my code, and needed to locate all the places in the code where the value false was passed as the value of forwards_flag. You can’t easily search for those, so this becomes a maintenance headache. And if you need to make a bugfix at each of those sites, you may have an unfortunate problem if you miss one.
But this specific problem is easily fixed without fundamentally changing the approach:
enum FrobnicationDirection {
FrobnicateForwards,
FrobnicateBackwards;
};

void frobnicate(Object what, FrobnicationDirection direction);

With this code, one would only need to search for instances of FrobnicateBackwards. While it’s possible there is some code which assigns this to a variable so you have to follow a few threads of control, I find in practice that this is rare enough that this alternative works OK.

However, there is another problem with passing the flag in this way, at least in principle. This is that some (only some) systems having this design may be exposing too much knowledge about the implementation details of the deeply-nested parts of the code (which uses the flag) to the outer layers (which need to know which value to pass in this flag).

To use Larry Constantine’s terminology, this design may have over-strong coupling between the setter and the user of the boolean flag. Franky though it’s hard to say with any degree of certainty on this question without knowing more about the codebase.

To address the specific examples you give, I would have some degree of concern in each but mainly for reasons of risk/correctness. That is, if your system needs to pass around flags which indicate what state the system is in, you may find that you’ve got code which should have taken account of this but doesn’t check the parameter (because it was not passed to this function). So you have a bug because someone omitted to pass the parameter.
It’s also worth admitting that a system-state indicator that needs to be passed to almost every function is in fact essentially a global variable. Many of the downsides of a global variable will apply. I think in many cases it is better practice to encapsulate the knowledge of the system state (or the user’s credentials, or the system’s identity) within an object which is responsible for acting correctly on the basis of that data. Then you pass around a reference to that object as opposed to the raw data. The key concept here is encapsulation.

public void foo(boolean flag) {
doThis();
if (flag)
doThat();
}

This is really a problem because it’s a case of bad cohesion. You’re creating a dependency between methods that is not really necessary.

What you should be doing in this case is leaving doThis and doThat as separate and public methods then doing:
doThis();
doThat();
or
doThis();
That way you leave the correct decision to the caller (exactly as if you were passing a boolean parameter) without create coupling.
Of course not all boolean parameters are used in such bad way but it’s definitely a code smell and you’re right to get suspicious if you see that a lot in the source code.
This is just one example of how to solve this problem based on the examples I wrote. There are other cases where a different approach will be necessary.

There are lots of situations where if (flag) doThat() inside foo() is legitimate. Pushing the decision about invoking doThat() to every caller forces repetition that will have to be removed if you later find out for some methods, the flag behavior also needs to call doTheOther(). I’d much rather put dependencies between methods in the same class than have to go scour all of the callers later.

First off: programming is not a science so much as it is an art. So there is very rarely a “wrong” and a “right” way to program. Most coding-standards are merely “preferences” that some programmers consider useful; but ultimately they are rather arbitrary. So I would never label a choice of parameter to be “wrong” in and of itself – and certainly not something as generic and useful as a boolean parameter. The use of a boolean (or an int, for that matter) to encapsulate state is perfectly justifiable in many cases.
Coding decisions, by & large, should be based primarily on performance and maintainability. If performance isn’t at stake (and I can’t imagine how it ever could be in your examples), then your next consideration should be: how easy will this be for me (or a future redactor) to maintain? Is it intuitive and understandable? Is it isolated? Your example of chained function calls does in fact seem potentially brittle in this respect: if you decide to change your bIsUp to bIsDown, how many other places in the code will need to be changed too? Also, is your paramater list ballooning? If your function has 17 parameters, then readability is an issue, and you need to reconsider whether you are appreciating the benefits of object-oriented architecture.

Context is important. Such methods are pretty common in iOS. As just one often-used example, UINavigationController provides the method -pushViewController:animated:, and the animatedparameter is a BOOL. The method performs essentially the same function either way, but it animates the transition from one view controller to another if you pass in YES, and doesn’t if you pass NO. This seems entirely reasonable; it’d be silly to have to provide two methods in place of this one just so you could determine whether or not to use animation.
It may be easier to justify this sort of thing in Objective-C, where the method-naming syntax provides more context for each parameter than you get in languages like C and Java. Nevertheless, I’d think that a method that takes a single parameter could easily take a boolean and still make sense:
file.saveWithEncryption(false); // is there any doubt about the meaning of ‘false’ here?

n Actually I have no clue what false means in the file.saveWithEncryption example. Does it mean that it will save without encryption? If so, why in the world would the method have “with encryption” right in the name? I could understand have a method like save(boolean withEncryption), but when I seefile.save(false), it is not at all obvious at a glance that the parameter indicates that it would be with or without encryption. I think, in fact, this makes James Youngman’s first point, about using an enum. – RayMay 9 '12 at 23:20
n An alternative hypothesis is that false means, don’t overwirte any existing file of the same name. Contrived example I know, but to be sure you’d need to check the documentation (or code) for the function.– James Youngman May 9 '12 at 23:34

No problem in ABAP and Scala…

要获取更多Jerry的原创文章,请关注公众号"汪子熙":

关于面向对象设计中类的方法是否应该使用boolean类型的参数相关推荐

  1. activexobject对象不能创建_面向对象设计方法(Object oriented)

    1.面向对象 (1)OOA(Object-oriented Analysis) 面向对象分析--事物的分类.命名.描述. (2)OOD(Object-oriented Design) 面向对象设计-- ...

  2. 系统设计知识:面向对象设计方法介绍

    面向对象设计(Object Oriented Design,OOD)是面向对象分析(OOA)方法的延续,是在OOA模型的基础上,采用面向对象的方法,主要解决与实现相关的问题,最终目标是产生一个符号具体 ...

  3. python核心编程:Python面向对象程序设计中类的定义、实例化、封装及私有变量/方法详解

    这篇文章主要介绍了Python面向对象程序设计中类的定义.实例化.封装及私有变量/方法,结合具体实例形式较为详细的分析了Python面向对象程序设计中类的定义.实例化.封装.私有变量.私有方法等相关使 ...

  4. php 面向对象 教程,PHP学习笔记之面向对象设计_PHP教程

    面向对象设计是php程序开发中一个很重要的内容块,如果你想成为高级php程序员我们必须知道面向对象设计具体用法与写法. 维护简单 模块化是面向对象编程中的一个特征.实体被表示为类和同一名字空间中具有相 ...

  5. Java—面向对象设计—类和对象

    理解面向对象程序设计 面向对象程序(Object-oriented programming,OOP)设计是继面向过程又一具有里程碑意义的编程思想,是现实世界模型的自然延伸.下面从结构化程序设计说起,逐 ...

  6. iOS开发 - 面向对象设计的设计模式(一):创建型模式(附 Demo UML类图)

    继上一篇的面向对象设计的设计原则,本篇是面向对象设计系列的第二个部分:面向对象设计的设计模式的第一篇文章. 另外,本篇博客的代码和类图都保存在我的GitHub库中:中的Chapter2. 最开始说一下 ...

  7. 【Python知识点梳理】8.飞机大战(面向对象设计思维)

    8.飞机大战(面向对象设计思维) 文章目录 1.飞机大战效果展示 2.我方飞机类 3.敌方飞机类 4.子弹类 5.补给类 6.主函数 总结 1.飞机大战效果展示   飞机大战(面向对象设计思维),主要 ...

  8. 01.面向对象设计原则实验

    面向对象设计原则实验 题目1:某绘图软件提供了多种大小不同的笔(Pen),并且可以给画笔指定不同颜色,某设计人员针对画笔的结构设计了如图1-1所示的初始类图.通过仔细分析,设计人员发现该类图存在非严重 ...

  9. 设计模式之实验一:面向对象设计原则实验

    实验项目一:面向对象设计原则实验 (1)实验目的与原理 ①深入理解和掌握面向对象设计原则. ②能运用面向对象设计原则对系统进行重构. ③能绘制系统结构图(类图) (2)实验内容与步骤 ①某绘图软件提供 ...

最新文章

  1. 系统延时任务和定时任务
  2. websocket采用tomcat方式,IOC类对象无法注入的解决方案
  3. 【C++深度剖析教程33】C++中的构造函数与析构函数是否可以为虚函数
  4. 04号团队-团队任务3:每日立会(2018-12-04)
  5. 64. 雇员管理系统
  6. Mac彻底卸载搜狗输入法,看这一篇就够了
  7. Visio2016安装
  8. 【SENCHA TOUCH】datepickerfield将日期改为中文日期或自定义的日期
  9. 2018年阿里巴巴重要开源项目汇总(持续更新中)
  10. 湖南省中职学业水平考试复习试题(语文)
  11. 关于手机打开开发者方式的方法
  12. 浅学 web安全知识(好奇)
  13. 百鸡问题扩展-N鸡问题
  14. windows下的./ 和 ../
  15. python爬去新浪微博_Python爬虫爬取新浪微博内容示例【基于代理IP】
  16. 钣金行业mes解决方案,缩短产品在制周期
  17. python太极代码_Python turtle绘制阴阳太极图代码解析
  18. 2022年初级审计师考试综合试题及答案
  19. Cadence Other格式网表导出与导入ortelesis.dll
  20. AI产品--苹果的Face ID

热门文章

  1. Android Studio 多渠道打包、自动版本号及 gradlew 命令的基本使用
  2. 文献记录(part24)--Nonlinear dictionary learning with application to image classification
  3. JavaWeb(part2)--request
  4. WebAPI(part3)--事件基础
  5. JavaScript入门(part12)--内置对象
  6. 投资学习网课笔记(part1)--基金第一课
  7. 利用python爬虫(案例2)--X凰的一天
  8. python与正则表达式(part5)--re模块使用
  9. linux 杀掉php,Linux_在Linux系统中使用xkill命令杀掉未响应的进程,我们如何在Linux中杀掉一个资 - phpStudy...
  10. 使用在线编辑器创建 SAP UI5 项目并运行