编程原则
不要写只能起作用的代码。旨在编写可以维护的代码-不仅可以由您自己维护,还可以由可能在将来某个时候使用该软件的其他任何人维护。
开发人员80%的时间正在阅读代码,而20%的时间在编写和测试代码。因此,请专注于编写可读代码!
您的代码无需注释即可了解其功能!
为了帮助我们开发良好的代码,有许多编程原则可以用作指导原则。在下面,我将列出最重要的那些。
KISS—它代表“保持简单,愚蠢”。您可能会注意到,开发人员在开始旅程时便尝试实现复杂的,模棱两可的设计。 DRY-“不要重复自己”。尝试避免任何重复,而是将它们放入系统或方法的单个部分中。 YAGNI -“您将不需要它”。如果遇到自问“添加额外的功能(功能,代码等)?”的情况,您可能需要重新考虑一下。 Clean code over clever code -说到干净的代码,把我的自我遗忘在门外,而不必再编写聪明的代码了。 Avoid premature optimization—过早的优化 的问题在于,直到事后,您才真正知道程序的瓶颈在哪里。 Single responsibility-程序中的每个类或模块都应只关注提供一点特定功能。 Composition over Inheritance-具有复杂行为的对象应该通过包含具有单独行为的对象实例来做到这一点,而不是继承类并添加新行为。
KISS
DRY
YAGNI
Clean code over clever code
Avoid premature optimization
Single responsibility
Composition over Inheritance
Object calisthenics — Object calisthenics 是编程练习,被正式定义为一组9条规则
Object calisthenics
Fail fast, fail hard - 快速失败原则表示停止当前操作,一旦发生任何意外的错误。坚持这一原则通常会带来更稳定的解决方案
Fail fast, fail hard
Packages
Static
Inheritance
如果不需要构造函数,请不要创建没有实现逻辑的默认构造函数。如果未指定默认构造函数,则Java将自动提供默认构造函数。
Interfaces
不要使用常量接口模式(常量的接口),因为它允许类实现和破坏API。请改用静态类。这具有允许您在静态块中执行更复杂的对象初始化(例如填充Collection)的附加好处。
始终保持界面小巧和特定,以便客户端只需要了解他们感兴趣的方法。从SOLID中检出ISP。
Finalizers
应该明智地使用Object#finalize(),并且只能将其用作故障清除,以进行资源清理(例如,关闭文件)。始终提供明确的清除方法(例如close())。
Assertions
通常以先决条件检查的形式进行的断言以快速失败,难以失败的方式强制执行类型的约定。应该自由地使用它们,以捕获尽可能靠近源代码的编程错误。
对象状态:
Generics
Java Generics FAQ中提供了完整,非常详细的解释。以下是开发人员应注意的常见方案。
如果可能,最好使用类型推断,而不是返回基类/接口:
// MySpecialObject o = MyObjectFactory.getMyObject(); public <T extends MyObject> T getMyObject(int type) { return (T) factory.create(type); }
2.当无法自动推断类型时,请内联它。
public class MySpecialObject extends MyObject<SpecialType> { public MySpecialObject() { super(Collections.emptyList()); // This is ugly, as we loose type super(Collections.EMPTY_LIST(); // This is just dumb // But this is beauty super(new ArrayList<SpecialType>()); super(Collections.<SpecialType>emptyList()); } }
3.Wildcards:
当您仅从结构中获取值时,请使用扩展通配符;仅将值放入结构中时,请使用超级通配符;当您同时执行这两个操作时,请不要使用通配符。
Use Foo<? super T> for a T consumer.。
Singletons 绝对不能以经典的“设计模式”样式来编写单例,这在C ++中是完全有效的(因为它是用它编写的),但是在Java中是不合适的。
尽管正确是线程安全的,但切勿执行以下操作。(这一直是性能瓶颈!)
public final class MySingleton { private static MySingleton instance; private MySingleton() { // singleton } public static synchronized MySingleton getInstance() { if (instance == null) { instance = new MySingleton(); } return instance; } }
2.如果确实需要延迟初始化,则可以将两种方法结合使用!
public final class MySingleton { private MySingleton() { // singleton } private static final class MySingletonHolder { static final MySingleton instance = new MySingleton(); } public static MySingleton getInstance() { return MySingletonHolder.instance; } }
例外情况
1.将检查的异常用于可恢复的条件,将运行时异常用于编程错误。示例:从字符串获取整数。
// String str = input string Integer value = null; try { value = Integer.valueOf(str); } catch (NumberFormatException e) { // non-numeric string } if (value == null) { // handle bad string } else { // business logic }
// String str = input string // Numeric string with at least one digit and optional leading negative sign if ( (str != null) && str.matches("-?\\d++") ) { Integer value = Integer.valueOf(str); // business logic } else { // handle bad string }
2.您应该在正确的地方处理异常,正确的地方在域级别。
class UserDAO{ public List<User> getUsers(){ try{ ps = conn.prepareStatement("SELECT * from users"); rs = ps.executeQuery(); //return result }catch(Exception e){ log.error("exception") return null }finally{ //release resources } }}
=== RECOMMENDED WAY === Data layer should just retrow the exception and transfer the responsability to handle the exception or not to the right layer. class UserDAO{ public List<User> getUsers(){ try{ ps = conn.prepareStatement("SELECT * from users"); rs = ps.executeQuery(); //return result }catch(Exception e){ throw new DataLayerException(e); }finally{ //release resources } } }
3.通常,异常不应在引发异常时记录,而应在实际处理时记录。抛出或重新抛出异常时,记录日志往往会使日志文件杂乱无章。另外,请注意,异常堆栈跟踪会捕获生成异常的位置。
4.赞成使用标准例外
5.使用例外而不是返回码。
等于和HashCode
在编写适当的对象等效项和哈希码方法时,需要注意许多问题。为了简化用法,请使用java.util.Objects的equals和hash。
public final class User { private final String firstName; private final String lastName; private final int age; ... public boolean equals(Object o) { if (this == o) { return true; } else if (!(o instanceof User)) { return false; } User user = (User) o; return Objects.equals(getFirstName(), user.getFirstName()) && Objects.equals(getLastName(),user.getLastName()) && Objects.equals(getAge(), user.getAge()); } public int hashCode() { return Objects.hash(getFirstName(),getLastName(),getAge()); } }
资源管理
private doSomething() { try (BufferedReader br = new BufferedReader(new FileReader(path))) { try { // business logic } }
提供关机钩
如果JVM正常终止,则提供要调用的关闭挂钩。(这将无法处理突然的终止,例如由于断电而导致的终止)
这是推荐的替代方法,而不是声明finalize()方法,该方法仅在System.runFinalizersOnExit()为true(默认情况下为false)时运行。
public final class SomeObject { var distributedLock = new ExpiringGeneralLock ("SomeObject", "shared"); public SomeObject() { Runtime .getRuntime() .addShutdownHook(new Thread(new LockShutdown(distributedLock))); } /** Code may have acquired lock across servers */ ... /** Safely releases the distributed lock. */ private static final class LockShutdown implements Runnable { private final ExpiringGeneralLock distributedLock; public LockShutdown(ExpiringGeneralLock distributedLock) { if (distributedLock == null) { throw new IllegalArgumentException("ExpiringGeneralLock is null"); } this.distributedLock = distributedLock; } public void run() { if (isLockAlive()) { distributedLock.release(); } } /** @return True if the lock is acquired and has not expired yet. */ private boolean isLockAlive() { return distributedLock.getExpirationTimeMillis() > System.currentTimeMillis(); } } }
服务器之间共享允许资源过期(也可以再生)的资源。(这允许从突然终止(例如断电)中恢复)。
请参阅上面的代码示例,该示例使用ExpiringGeneralLock(在系统之间共享的锁)。
Date-Time
Java 8在包java.time下引入了新的日期时间API。在Java 8中,引入了新的日期时间API,以弥补旧日期时间API的以下缺点:线程安全,设计不良,时区处理困难等。
General
<Void>
Threads
this.executor = Executors.newCachedThreadPool((Runnable runnable) -> { Thread thread = Executors.defaultThreadFactory().newThread(runnable); thread.setDaemon(true); return thread; });
Collections
Miscellaneous
Optional
延迟初始化
延迟初始化是一种性能优化。当出于某种原因数据被认为是“昂贵的”时使用。对于Java 8,我们应该为此使用Supplier功能接口。
== Thread safe Lazy initialization === public final class Lazy<T> { private volatile T value; public T getOrCompute(Supplier<T> supplier) { final T result = value; // Just one volatile read return result == null ? maybeCompute(supplier) : result; } private synchronized T maybeCompute(Supplier<T> supplier) { if (value == null) { value = supplier.get(); } return value; } } Lazy<String> lazyToString= new Lazy<>() return lazyToString.getOrCompute( () -> "(" + x + ", " + y + ")");
到此为止,希望它有用!
原文链接:http://codingdict.com/