предисловие
Недавно я смотрел на красоту шаблона проектирования Ван Чжэна.В нем говорилось о спецификациях кода, которые оказались некоторыми моментами, на которые я обычно обращаю внимание.Вот краткое изложение.
Далее будут обсуждаться четыре аспекта именования, комментариев, стиля кода и навыков программирования.
название
Подобрать подходящее имя иногда сложно, вот несколько советов, которые могут помочь мне с нашим именованием
1. Выбор именованной длины
Что касается длины наименования, то в случае возможности выразить значение наименование, конечно, должно быть как можно короче. В большинстве случаев короткие имена не так выразительны, как длинные, и многие книги не рекомендуют использовать сокращения.
Хотя длинные имена могут содержать больше информации и более точно и интуитивно выражать намерения, если имена функций и переменных очень длинные, то и операторы, составленные из них, будут очень длинными. Когда длина столбца кода ограничена, оператор часто разбивается на две строки, что на самом деле влияет на читабельность кода.
Поэтому иногда мы можем умеренно использовать сокращенные короткие имена.
В каких случаях уместно использовать короткие имена?
1. Хорошо известно, что для некоторых значений по умолчанию можно использовать сокращенные имена, например, sec означает секунду, str означает строку, num означает число, doc означает документ и т. д.
2. Для переменных с относительно небольшой областью видимости можно использовать относительно короткие имена, например временные переменные в некоторых функциях, соответственно, для относительно больших переменных рекомендуется использовать длинные имена.
2. Используйте контекст для упрощения именования
Приходите посмотреть на каштан
type User struct {
UserName string
UserAge string
UserAvatarUrl string
}
Например, эта структура, мы уже знаем, что это структура информации о пользователе. Внутри имени пользователя, возраста нет необходимости добавлять префикс пользователя
после доработки
type User struct {
Name string
Age string
AvatarUrl string
}
Конечно, это также полезно при проектировании базы данных.
3. Название должно быть читабельным и доступным для поиска
«Читаемый» означает не использовать для названия какие-то необычные и труднопроизносимые английские слова.
Когда мы пишем код в IDE, мы часто используем метод «ассоциации ключевых слов» для автоматического завершения и поиска. Например, если вы вводите объект ".get", вы хотите, чтобы среда IDE возвращала все методы, начинающиеся с get для этого объекта. Другой пример: найдите функции и методы, связанные с массивами, в JDK, введя слово «массив» в поле поиска IDE. Поэтому, когда мы назовем его, лучше всего следовать соглашению об именовании всего проекта. Все используют «selectXXX» для выражения запроса, вы не используете «queryXXX»; все используют «insertXXX» для выражения фрагмента данных, вам не нужно использовать «addXXX», унифицированный протокол очень важен, он может уменьшить много ненужных проблем.
4. Как назвать интерфейс
Для именования интерфейсов обычно используются два распространенных способа. Один из них — добавить префикс «I», что означает интерфейс. Например, IUserService, соответствующая реализация называется UserService. Другой вариант — не добавлять префикс, например UserService, а соответствующая реализация добавляет суффикс «Impl», например UserServiceImpl.
Примечания
Когда мы принимаем проект, мы часто жалуемся, что старый проект плохо аннотирован и документация неполная.Так что, если мы должны написать все комментарии, какие комментарии являются хорошими комментариями?
Иногда мы увидим в книгах или каких-то блогах, что если хороший нейминг не требует комментариев, то есть код является комментарием, если нужны комментарии, значит, нейминг кода нехороший, и нужно работать сложно в названии.
Это немного экстремально, каким бы хорошим ни было нейминг, все-таки есть ограничение по длине, и невозможно быть достаточно подробным.В это время хорошим дополнением являются комментарии.
1. Что мне писать в примечаниях?
Цель написания комментариев — сделать код более понятным.Комментарии обычно включают три аспекта: что, почему и как.
Это аннотация в sync.map в golang, а также аннотация от чего, почему и как это сделать.
// Map is like a Go map[interface{}]interface{} but is safe for concurrent use
// by multiple goroutines without additional locking or coordination.
// Loads, stores, and deletes run in amortized constant time.
//
// The Map type is specialized. Most code should use a plain Go map instead,
// with separate locking or coordination, for better type safety and to make it
// easier to maintain other invariants along with the map content.
//
// The Map type is optimized for two common use cases: (1) when the entry for a given
// key is only ever written once but read many times, as in caches that only grow,
// or (2) when multiple goroutines read, write, and overwrite entries for disjoint
// sets of keys. In these two cases, use of a Map may significantly reduce lock
// contention compared to a Go map paired with a separate Mutex or RWMutex.
//
// The zero Map is empty and ready for use. A Map must not be copied after first use.
type Map struct {
mu Mutex
read atomic.Value // readOnly
dirty map[interface{}]*entry
misses int
}
Некоторые люди думают, что комментарии должны давать дополнительную информацию, которой нет в коде, поэтому не пишите "что делать, как делать", оба аспекта могут быть отражены в коде, просто пишите четко "почему", указывающий на намерение проекта кода Вот и все.
Однако написание комментариев может иметь следующие преимущества:
1. Комментарии несут больше информации, чем код
Хорошо названные функции и переменные действительно не нуждаются в пояснении в комментариях, что они делают. Однако для структуры оно содержит больше информации, а простое имя недостаточно исчерпывающее. В этот момент имеет смысл написать «что делать» в комментариях.
2. Комментарии играют роль в подведении итогов и документировании
В комментариях мы можем написать несколько кратких описаний и описаний особых случаев конкретных идей реализации кода. Таким образом, люди, которые читают код, могут получить общее представление об идеях реализации кода через комментарии, и его будет легче читать.
3. Некоторые итоговые комментарии могут сделать структуру кода более понятной.
Для кода со сложной логикой или длинной функцией, если его сложно извлечь и разделить на небольшие вызовы функций, мы можем использовать сводные комментарии, чтобы сделать структуру кода более четкой и организованной.
2. Чем больше комментариев, тем лучше?
Аннотации сами по себе имеют определенную стоимость обслуживания, поэтому больше не всегда лучше. Структуры и функции должны быть прокомментированы, и они должны быть написаны как можно более полными и подробными, в то время как комментарии внутри функций относительно немногочисленны, обычно они основаны на правильном именовании, уточняющих функциях, пояснительных переменных и итоговых комментариях для улучшения читабельности кода.
стиль кода
1. Насколько велика функция?
Слишком много кода и слишком мало кода функций — это нехорошо.
Перебор:
Тысячи строк для метода и сотни строк для функции.Логика слишком сложна.При чтении кода легко прочитать конец и забыть начало.
слишком мало:
Когда общий объем кода одинаков, количество разделенных функций соответственно увеличивается, а отношения вызова усложняются.При чтении определенной логики кода необходимо часто переходить между n методами или n функциями. , впечатление от чтения тоже не очень.
Сколько самое подходящее?
Однако указать конкретное значение сложно, в некоторых местах указано, что оно не должно превышать высоту экрана дисплея по вертикали. Например, на моем компьютере, если код функции должен полностью отображаться в среде IDE, максимальное количество строк кода не может превышать 50.
2. Какой длины самая подходящая строка кода
Это не полная квази-сторона, ведь у разных языков разные требования
Конечно, есть общий принцип: строка кода не может превышать ширину, отображаемую IDE.
Слишком длинный и неудобный для чтения код
3. Используйте пустые строки для разделения блоков блоков.
То есть оставлять вертикальный пробел.Записывать наш код не рекомендуется.В функции или методе не остается места.Обычно по разной семантике содержимое небольшого модуля закончено, и он делится на пустые места.
// Store sets the value for a key.
func (m *Map) Store(key, value interface{}) {
read, _ := m.read.Load().(readOnly)
if e, ok := read.m[key]; ok && e.tryStore(&value) {
return
}
m.mu.Lock()
// ...
m.mu.Unlock()
}
Заблокированный код здесь отделен от приведенного выше
Конечно, кое-где скажут, что в первой строке нет пробелов, что тоже верно, пустая строка в заголовке функции бесполезна.
навыки программирования
1. Разделите код на более мелкие блоки
Хорошо абстрагирует модули в коде, что может облегчить наше чтение.
Следовательно, мы должны иметь модульное и абстрактное мышление, уметь разбивать большие блоки сложной логики на маленькие методы или функции и скрывать детали, чтобы люди, читающие код, не терялись в деталях, что может значительно улучшить надежность кода, читабельность. Однако мы рекомендуем извлекать соответствующую логику только тогда, когда логика кода более сложная.
2. Избегайте слишком большого количества параметров функций или методов
Когда функция содержит 3 или 4 параметра, это еще допустимо, когда больше или равно 5, мы чувствуем, что параметров слишком много, что повлияет на читабельность кода, и неудобно использовать.
Есть два способа справиться с этой ситуацией
1. Подумайте, несет ли функция единую ответственность и можно ли уменьшить параметры, разделив ее на несколько функций.
2. Инкапсулировать параметры функции в объекты.
каштан
func updateBookshelf(userId, deviceId string, platform, channel, step int) {
// ...
}
// 修改后
type UpdateBookshelfInput struct {
UserId string
DeviceId string
Step int
Platform int
Channel int
}
func updateBookshelf(input *UpdateBookshelfInput) {
// ...
}
3. Не используйте функциональные параметры для управления логикой
Не используйте логические параметры-идентификаторы в функциях для управления внутренней логикой, при true переходим к этой логике, при false переходим к другой логике. Это явно нарушает принцип единой ответственности и принцип изоляции интерфейса.
Можно разделить на две функции для отдельного вызова
каштан
func sendVip(userId string, isNewUser bool) {
// 是新用户
if isNewUser {
// ...
} else {
// ...
}
}
// 修改后
func sendVip(userId string) {
// ...
}
func sendNewUserVip(userId string) {
// ...
}
Однако, если функция является частной функцией с ограниченной областью влияния или две функции после разделения часто вызываются одновременно, мы можем рассмотреть возможность отказа от разделения.
4. Функциональный дизайн должен нести единую ответственность
При разработке функций мы также должны стараться нести единую ответственность, избегать разработки большой и всеобъемлющей функции и разделять функции по разным функциональным точкам.
Например: Давайте проверим некоторые из наших пользовательских атрибутов.Конечно, эта проверка опущена, чтобы судить, является ли он пустым или нет.
func validate(name, phone, email string) error {
if name == "" {
return errors.New("name is empty")
}
if phone == "" {
return errors.New("phone is empty")
}
if email == "" {
return errors.New("name is empty")
}
return nil
}
Модифицировано
func validateName(name string) error {
if name == "" {
return errors.New("name is empty")
}
return nil
}
func validatePhone( phone string) error {
if phone == "" {
return errors.New("phone is empty")
}
return nil
}
func validateEmail(name, phone, email string) error {
if email == "" {
return errors.New("name is empty")
}
return nil
}
5. Удалите слишком глубокие уровни вложенности
Слишком глубоко вложенный код часто возникает из-за чрезмерной вложенности циклов if-else, switch-case и for. Если код слишком глубоко вложен, его нелегко понять.Если код слишком глубоко вложен, его легко разбить на две строки, потому что код имеет многократный отступ, в результате чего оператор внутри вложения превышает длина одной строки, что влияет на чистоту кода.
Для модификации вложенного кода необходимо рассмотреть четыре направления.
Возьмите каштан:
В этом коде некоторые места не подходят, разбираем со следующих четырех направлений
func sum(sil []*User, age int) int {
count := 0
if len(sil) == 0 || age == 0 {
return count
} else {
for _, item := range sil {
if item.Age > age {
count++
}
}
}
return count
}
1. Удалите лишние операторы if или else
превратиться в
func sum(sil []*User, age int) int {
count := 0
if len(sil) != 0 && age == 0 {
for _, item := range sil {
if item.Age > age {
count++
}
}
}
return count
}
2. Используйте ключевые слова continue, break и return, предоставленные языком программирования, чтобы выйти из вложенности заранее.
func sum(sil []*User, age int) int {
count := 0
if len(sil) != 0 && age == 0 {
for _, item := range sil {
if item.Age <= age {
continue
}
count++
}
}
return count
}
3. Отрегулируйте порядок выполнения, чтобы уменьшить вложенность
func sum(sil []*User, age int) int {
count := 0
if len(sil) == 0 || age == 0 {
return count
}
for _, item := range sil {
if item.Age <= age {
continue
}
count++
}
return count
}
4. Инкапсулируйте некоторую вложенную логику в вызовы функций, чтобы уменьшить вложенность.
6. Научитесь использовать объясняющие переменные
Обычно используемые объясняющие переменные для улучшения читабельности кода — это следующие две
1. Константы заменяют магические числа
func CalculateCircularArea(radius float64) float64 {
return 3.1415 * radius * radius
}
// 修改后
const PI = 3.1415
func CalculateCircularArea(radius float64) float64 {
return PI * radius * radius
}
2. Используйте объясняющие переменные для объяснения сложных выражений
if appOnlineTime.Before(userId.Timestamp()) {
appOnlineTime = userId.Timestamp()
}
// 修改后
isBeforeRegisterTime := appOnlineTime.Before(userId.Timestamp())
if isBeforeRegisterTime {
appOnlineTime = userId.Timestamp()
}
Ссылаться на
【Красота шаблонов проектирования】time.geekhelp.org/column/int R…