您的经历中发现了最糟糕的Java实践?
与此问题类似……
您在Java代码中实际发现的最差实践是什么?
我的是:
- 在servlet中使用实例变量(这不仅仅是不好的做法,而是bug,实际上)
- 使用像HashMap这样的Collection实现,而不是使用适当的接口
- 使用看似神秘的类名,如SmsMaker(SmsFactory)或CommEnvironment(CommunicationContext)
我必须维护java代码,其中大多数exception处理如下:
catch( Exception e ) {}
一旦遇到’singleton’exception:
class Singletons { public static final MyException myException = new MyException(); } class Test { public void doSomething() throws MyException { throw Singletons.myException; } }
每次都抛出相同的exception实例 …与完全相同的堆栈跟踪,与实际代码流无关:-(
六个非常糟糕的例子;
- 而不是错误报告,只是
System.exit
没有警告。 例如
if(properties.size()>10000) System.exit(0);
埋藏在图书馆深处。 - 使用字符串常量作为锁。 例如,
synchronized("one") { }
。 - 锁定可变字段。 例如
synchronized(object) { object = ...; }
synchronized(object) { object = ...; }
。 - 在构造函数中初始化静态字段。
- 触发exception只是为了获得堆栈跟踪。 例如,
try { Integer i = null; i.intValue(); } catch(NullPointerException e) { e.printStackTrace(); }
try { Integer i = null; i.intValue(); } catch(NullPointerException e) { e.printStackTrace(); }
try { Integer i = null; i.intValue(); } catch(NullPointerException e) { e.printStackTrace(); }
。 - 无意义的对象创建,例如
new Integer(text).intValue() or worse new Integer(0).getClass()
if{ if{ if{ if{ if{ if{ if{ if{ ....
当人们创建接口只是为了挂起一组常量时,我讨厌它:
public interface InterfaceAntiPattern { boolean BAD_IDEA = true; int THIS_SUCKS = 1; }
– 接口用于指定行为合同,而不是用于包含常量的便利机制。
严格地说与Java没有关系,但是当你知道它不会改变时,反复调用昂贵的函数而不是存储结果。 例:
if (expensiveFunction() > aVar) aVar = expensiveFunction(); for (int i=0; i < expensiveFunction(); ++i) System.out.println(expensiveFunction());
最糟糕的Java实践几乎涵盖了所有其他实践: 全局可变状态。
荒谬的OO狂热与阶级层次10+级深。
这就是DefaultConcreteMutableAbstractWhizzBangImpl
这样的名字来自的地方。 试着调试那种代码 – 你会在课堂上上下几个小时。
当您不应该进行子类化时,例如,而不是使用组合,聚合等。
编辑:这是锤子的一个特例。
看到这样的事情:
public static boolean isNull(int value) { Integer integer = new Integer(value); if(integer == null) { return true; } else { return false; } }
他们对多头有类似的方法。
我认为他们最初做过类似的事情
if(value == null) {
并得到一个编译错误,仍然没有意识到原始值不能为空。
我们的实习生使用static
修改器将当前登录的用户存储在Seam应用程序中。
class Identity{ ... public static User user; ... } class foo{ void bar(){ someEntity.setCreator(Identity.user); } }
当然,当他测试它时它有效:)
不关闭finally {}中的数据库连接,文件句柄等
我曾经不得不调查一个Web应用程序,其中所有状态都保存在发送给客户端的网页中,而Web服务器中没有状态。
尽管比例很好:)
需要调用者执行的API:
Foobar f = new Foobar(foobar_id); f = f.retrieve();
以下任何一项都会更好:
Foobar f = Foobar.retrieve(foobar_id);
要么
Foobar f = new Foobar(foobar_id); // implicit retrieve
要么
Foobar f = new Foobar(); f.retrieve(foobar_id); // but not f = ...
将function抽象到库类中,永远不会被重复使用,因为它对于要解决的原始问题是如此具体 。 因此最终得到了大量的库类,没有人会使用它们,这完全掩盖了你实际拥有的两个有用的实用程序(即CollectionUtils
和IOUtils
)。
……停下来呼吸……
为所有私有变量创建acessors和mutator,而不是停下来思考,有时是自动的。
封装是出于某种原因而发明的。
不像程序员那样思考。
长时间曝光后,Java会对某些人这样做。
为什么? 我的观点是,这是因为有太多的智能感知而且毫无意义 。 它可以让你快速做出愚蠢的事情,人们不会停下来思考。
例1:
boolean negate( boolean shouldNegate, boolean value ) { return (shouldNegate?(!value):value; }
当然,它与值^ shouldNegate相同,是一个简单的XOR。
例2 🙁我发誓我不是这样做的)
boolean isNotNull( Object o ) { return o != null; }
两者都有额外的4-6行Javadoc, 解释了这些方法的作用。
例3:
/** * * */
一个空的Javadoc,让那些讨厌的 Eclipse“缺少Javadoc”的警告消失了。
例3b:
/** * A constructor. Takes no parameters and creates a new instance of MyClass. */ public MyClass() { }
面向对象设计的过度抽象(仅删除10k)。
类似线程上的相同答案(适用于允许面向对象设计的所有语言)。
我最喜欢的排序算法,礼貌的灰胡子旅:
List needsToBeSorted = new List (); ...blah blah blah... Set sorted = new TreeSet (); for (int i = 0; i < needsToBeSorted; i++) sorted.add (needsToBeSorted.get (i)); needsToBeSorted.clear (); for (Iterator i = sorted.iterator (); i.hasNext ();) needsToBeSorted.add (i.next ());
不可否认,它确实奏效了,但最终我对他说,也许Collections.sort会更容易。
几分钟前我看到了这条线:
Short result = new Short(new Integer(new Double(d).intValue()).shortValue());
在文件I / O中:错误使用try-catch块。
try { /* open file */ } catch(Exception e) { e.printStackTrace(); } try { /* read file content */ } catch (Exception e) { e.printStackTrace(); } try { /* close the file */ } catch (Exception e) { e.printStackTrace(); }
@madlep完全正确! Java社区的某些部分真的过于极端抽象和疯狂深层次的层次结构。 几年前史蒂夫·耶格(Steve Yegge)有一篇关于它的好文章: 在名词王国中执行 。
使用for循环或任何forms的循环就足够的exception来定义逻辑。
例:
while(i < MAX_VALUE) { try { while(true) { array[j] = //some operation on the array; j++; } } catch(Exception e) { j = 0; } }
严肃的,我知道写这段代码的人。 我查看了它并更正了代码:)
与您的相似,但更进了一步:
在Struts操作中,当请求范围变量是正确的事情时,使用类(静态)变量。 :o
这实际上已经在生产中部署了几个月,在我有一天审查代码之前没有人注意到任何事情。
过度关注重复使用导致各处静止物体的物体。 (在某些情况下,重复使用可能非常有用)。
Java具有GC内置function,如果需要对象,请创建一个新对象。
这是一个来自实际applet的裁剪样本我维护它让我永远意识到正在做的事情。
int sval, eval, stepv, i; double d; if (/*someCondition*/) { sval = 360;//(all values multiplied by 20) eval = -271; stepv = -10; } else if (/*someCondition*/) { sval = 320; eval = -601; stepv = -10; } else if (/*someCondition*/) { sval = 0; eval = -311; stepv = -10; } else { sval = 360; eval = -601; stepv = -10; } for (i = sval; i > eval; i = i + stepv) { d = i; d = d / 20.0; //do some more stuff in loop }
结果他想在循环上迭代.5而不是粘贴错误,即缩进方案
巨大的class级名称。 我记得: AbstractTableComponentListeningBehaviourPanel.java
和其他类似的怪物。
最糟糕的是,尽管命名约定是疯狂详细的,但我仍然需要分开文件以确定其目的。
初级程序员犯的错误:不必要地使用成员变量而不是局部变量。
一个Java EE示例:
在servlet或EJB中启动线程(例如,启动异步处理任务)。
这打破了Java EE应用程序的可伸缩性。 您不应该在Java EE组件中混淆线程,因为应用服务器应该为您管理。
我们通过让servlet在JMS队列上放置消息并编写消息驱动的bean来处理异步处理任务来重构这一点。
我认为这个对我来说必须是一个记录。 类用于为前端构建涉及过滤的复杂数据模型。 所以返回对象列表的方法是这样的:
public DataObjectList (GenerateList (massive signature involving 14 parameters, three of which are collections and one is a collection of collections) try { 250 lines of code to retrieve the data which calls a stored proc that parses some of it and basically contains GUI logic } catch (Exception e) { return new DataObjectList(e, filterFields); }
所以我到这里是因为我想知道以下调用方法是如何失败的,我无法看到Exception字段的设置位置。
DataObjectList dataObjectList= EntireSystemObject.getDataObjectList Generator().generateDataObjectList (viewAsUserCode, processedDataRowHandler, folderQuery, pageNumber, listCount, sortColumns, sortDirections, groupField, filters, firstRun, false, false, resetView); dataObjectList.setData(processedDataRowHandler.getData()); if (dataObjectList.getErrorException() == null) { do stuff for GUI, I think, put lots of things into maps ... 250 lines or so } return dataObjectList; } else { put a blank version into the GUI and then throw new DWRErrorException("List failed due to list generation error", "list failed due to list generation error for folder: " + folderID + ", column: " + columnID, List.getErrorException(), ListInfo); }
到目前为止一直伴随着我?
好吧,至少他们确实在前端告诉我们确实出了问题!
AbstractSpringBeanFactoryFactoryFacadeMutatorBeanFactory。 我无法忍受这个过度设计,难以理解的BS。 Benji Smith把它放得更优雅。