Роберт Мартин как-то сказал, что «частота ругательств при чтении кода — единственная мера качества кода». в то же время,Код должен быть написан таким образом, чтобы минимизировать время, необходимое для его понимания другими., что означает, что мы пишем код для людей, а не для машин. Итак, как написать элегантный код? Код может быть оптимизирован с идеологического уровня и определенного уровня навыков.Идеологический уровень относится к следованию принципам объектно-ориентированного проектирования.Этот вопрос знакомит с конкретными методами.
## 1. Всегда ли код максимально краток?
assert((!(bucket = findBucket(key))) || !bucket.isOccupied());
Приведенная выше строка кода, хотя и относительно короткая, трудно читаема. Для лучшего чтения делаем следующие модификации:
bucket = findBucket(key);
if(bucket != null){
assert(!bucket.isOccupied());
}
Сокращение количества строк кода — хорошая цель, но сведение к минимуму чтения кода — лучшая цель..
2. Добавляйте комментарии к важным заявлениям
// Fast version of "hash = (65599*hash) + c"
hash = (hash << 6) + (hash << 16) - hash + c
Если приведенная выше строка кода не прокомментирована, мы вообще не знаем, что это значит, но с этой строкой комментария мы знаем, что производительность можно улучшить за счет операций сдвига.
## 3. Использование tmp tmp — это то, что мы часто используем.Например, две замены переменных стали соглашениями.
tmp = right;
right = left;
left = tmp;
String tmp = user.getName();
tmp += " " + user.getPhoneNumber();
tmp += " " + user.getEmail();
template.set("user_info",tmp);
4.i,j,k,iter,it
: используется только для индексации или итерации цикла
i,j,k,iter,it
В отрасли стало нормой использовать индекс или итерацию цикла (i — это сокращение от индекса), например:
for(int i=0;i<100;i++){
for(int j=0;j<100;j++){
......
}
}
Iterator<String> iter = list.iterator();
while(iter.hasNext()){
......
}
Если мы будем использовать i,j,k в другом месте, это увеличит время чтения.
5. Поставляется с важными атрибутами
Мы относимся к неймингу как к способу комментирования, делая его более информативным!
6. Какой длины должно быть имя?
- Используйте короткие имена в небольших областях
- Длинные имена можно использовать в больших областях.
if(debug){
Map<String,Integer> m = new HashMap<>();
lookUpNamesNumbers(m);
print(m);
}
7. Не используйте вводящие в заблуждение имена
results = Database.all_objects.filter("year<=2011")
Какую информацию теперь содержит результат приведенной выше строки кода? фильтр для фильтрации данных, чей год меньше или равен 2011 году? Или сохранить?
8. Рекомендуется использовать минимальное и максимальное значение для представления предела.
MAX_ITEMS_IN_CART = 10;
if (shoppingCart.numOfItems()> MAX_ITEMS_IN_CART){
error("Too many items in cart");
}
9. Рекомендуется использовать begin и end для указания области включения/исключения.
begin означает включение, end означает исключение, типичным примером в Java является String.substring()
String s = "Hello world";
s.substring(2,5);-> "llo"
10. Соответствуйте ожиданиям пользователей
В общем, геттер-метод предназначен для получения значения поля.Пользователи ожидают легковесного метода.Если вы выполняете слишком много вычислений в нем, вам следует подумать об изменении имени.
public double getMeanPrice(){
//遍历所有条目计算总价,然后计算平均价格
}
public double computeMeanPrice(){
//遍历所有条目计算总价,然后计算平均价格
}
11. Не пишите комментарии к фактам, которые можно быстро вывести из самого кода.
public class Account {
// Constructor
public Account(){
}
// Set the profit member to a new value
void setProfit(double profit){
…….
}
// Return the profit from this Account
double getProfit(){
….
}
};
12. Не комментируйте плохие имена — меняйте их
// Releases the handle for this key.This doesn't modify the actual registry.
void deleteRegistry(RegistryKey key)
На первый взгляд мы можем принять это за функцию, удаляющую реестр, но в комментариях поясняется, что она не изменяет реальный реестр. Поэтому мы можем использовать более понятное имя, например:
void releaseRegistryHandle(registryKey key);
13. Пишите комментарии к недостаткам вашего кода
// TODO: использовать более быстрый алгоритм или когда код не закончен // TODO(dustin): обработка изображений в форматах, отличных от JPEG
14. Пишите комментарии для констант
// users thought 0.72 gave the best size/quality tradeoff
image_quality = 0.72;
// as long as it's >= 2*num_processors,that's good enough
NUM_THREADS = 8;
// impose a reasonable limit - no human can read that much anywhere
const int MAX_RSS_SUBSCRIPTIONS = 1000;
15. Пишите заметки с точки зрения читателя
struct Recoder {
vector<float> data;
......
void clear(){
// 每个人读到这里都会问,为啥不直接调用data.clear()
vector<float>().swap(data);
}
}
Если есть хороший комментарий, чтобы ответить на вопрос читателя, измените вышеприведенное следующим образом: Заставить вектор фактически вернуть память в распределитель памяти, подробности см. в трюке подкачки STL.
16. Объявите о возможных подводных камнях
void sendMail(String to,String subject,String body);
Эта функция может занимать много времени, поскольку для отправки сообщений электронной почты требуется вызов внешнего сервера, что может привести к зависанию потока пользователя. Это описание нужно поместить в комментарий.
17. Порядок параметров в условных операторах
Общее правило: располагайте переменные слева, а константы справа. В более широком смысле,Поместите более стабильные переменные справа, большее изменение помещается слева. Например, if (length >= 10) вместо if (10 Приведенный выше принцип, похоже, не работает в случае сравнения без «размера»., например, чтобы убедиться, что параметр запроса имеет определенное значение:if ( request.getParameterValue("name")).equals("Brandon"))
, На данный момент константа "Брэндон" может избежать ситуации с нулевым указателем (верхний параметр не имеет имени или значение пусто).
18. Порядок блоков if/else
Спецификация написания if/else: во-первых, работайте с положительной логикой вместо отрицательной, например, if(ok) вместо if(!ok); во-вторых, работайте с простыми случаями, в которых выгодно, чтобы if и else обрабатывали код в одном и том же коде. экран виден.
19. Уменьшите вложенность, возвращаясь раньше
Используя механизм раннего возврата, уровень вложенности функций может быть меньше. Например, без использования раннего кода возврата:
static bool checkUserAuthority()
{
bool a, b, c, d, e;
if (a)
{
if (b)
{
if (c)
{
if (d)
{
if (e)
{
return true;
}
}
}
}
}
return false;
}
Используется код, возвращающий раньше:
static bool checkUserAuthority()
{
bool a, b, c, d, e;
if (!a)
return false;
if (!b)
return false;
if (!c)
return false;
if (!d)
return false;
if (!e)
return false;
return true;
}
##20. Повысьте читабельность с помощью «суммарных переменных»
if(request.user.id == document.owner_id){
// user can edit this document ...
}
if(request.user.id != document.owner_id){
// document is read-only...
}
Наблюдая, мы извлекаем переменнуюfinal boolean user_owns_document=(request.user.id == document.owner_id)
, то код можно изменить на:
if(user_owns_document){
// user can edit this document ...
}
if(!user_owns_document){
// document is read-only...
}
21. Уменьшите переменные потока управления
В операторах цикла, таких как while и for, мы обычно используем настраиваемые логические переменные для управления потоком.
boolean done = false;
while(/* condition */ && !done){
...
if(...){
done = true;
continue;
}
}
По нашему опыту, «переменные потока управления» можно устранить путем оптимизации структуры программы, логики.
while(/* condition */){
...
if(...){
break;
}
}
22. Уменьшите область действия переменных
void foo(){
int i = 7;
if(someCondition){
// i is used only within this block
}
}
void foo(){
if(someCondition){
int i = 7;
// i is used only within this block
}
}
23. Не устанавливайте переменные в качестве полей класса для совместного использования
public class LargeClass{
String s;
void method1(){
s = ...
method2();
}
void method2(){
//使用s
}
}
Обмен данными через передачу параметров
public class LargeClass{
void method1(){
String s = ...
method2(s);
}
void method2(String s){
//使用s
}
}
24. Не определяйте все переменные в начале
Определение всех переменных в начале — это стиль C, а объектно-ориентированные языки имеют привычку определять переменные далеко от того места, где они используются.
public void foo(){
boolean debug = false;
String[] pvs;
String pn;
String pv;
...
}
В дополнение к приведенным выше предложениям мы также можем обратиться к спецификации Ali Java,Обратите внимание на WeChat: «Му Ке Да», отправьте «Спецификацию Ali Java», чтобы получить соответствующую информацию.
Добро пожаловать в общедоступную учетную запись WeChat: Mu Keda, все статьи будут синхронизированы в общедоступной учетной записи.