
การตั้งชื่อที่ถูกต้อง
ชื่อที่ถูกต้องช่วยให้อ่านโค้ดได้ง่ายขึ้น ซึ่งช่วยประหยัดเวลาในการทำความคุ้นเคย เนื่องจากจะง่ายกว่ามากในการใช้วิธีการเมื่อชื่ออธิบายฟังก์ชันการทำงานคร่าวๆ เนื่องจากทุกสิ่งในโค้ดประกอบด้วยชื่อ (ตัวแปร วิธีการ คลาส อ็อบเจ็กต์ไฟล์ ฯลฯ) ประเด็นนี้จึงมีความสำคัญมากเมื่อสร้างโค้ดที่ถูกต้องและสะอาดตา จากที่กล่าวมาข้างต้น ชื่อควรสื่อความหมายว่าทำไม เช่น ตัวแปรจึงมีอยู่ ทำอะไร และใช้อย่างไร ฉันจะสังเกตครั้งแล้วครั้งเล่าว่าความคิดเห็นที่ดีที่สุดในการอธิบายตัวแปรคือชื่อที่ถูกต้อง
อินเตอร์เฟซการตั้งชื่อ
โดยทั่วไปอินเทอร์เฟซจะใช้ชื่อที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่และเขียนด้วยตัวพิมพ์เล็ก (CamelCase) เคยเป็นแนวทางปฏิบัติที่ดีเมื่อเขียนอินเทอร์เฟซโดยขึ้นต้นด้วย I เพื่อกำหนดให้เป็นอินเทอร์เฟซ (เช่น IUserService) แต่นี่ค่อนข้างน่าเกลียดและเสียสมาธิ ในกรณีเช่นนี้ จะเป็นการดีกว่าถ้าเขียนโดยไม่มีมัน (UserService) และเพิ่ม -Impl (UserServiceImpl) ในการนำไปใช้งาน หรือเป็นทางเลือกสุดท้ายให้เพิ่มคำนำหน้า C (CUserService) ในการใช้งานชื่อชั้นเรียน
เช่นเดียวกับอินเทอร์เฟซ ชื่อจะใช้ตัวพิมพ์ใหญ่และใช้สไตล์อูฐ (CamelCase) ไม่ว่าวันสิ้นโลกจะเกิดขึ้นแบบไหน ไม่ว่ากำหนดเวลาจะเร็วแค่ไหน แต่อย่าลืม ชื่อของชั้นเรียนไม่ควรเป็นคำกริยา! ชื่อคลาสและออบเจ็กต์ต้องเป็นคำนามและการผสมผสานกัน (UserController, UserDetails, UserAccount และอื่นๆ) คุณไม่ควรระบุชื่อของแต่ละคลาสด้วยคำย่อของแอปพลิเคชันนี้ เนื่องจากจะเพิ่มความซับซ้อนที่ไม่จำเป็นเท่านั้น (เช่น เรามีแอปพลิเคชันการย้ายข้อมูลผู้ใช้ และเราจะเพิ่ม UDM ให้กับแต่ละคลาส - UDMUserDeatils, UDMUserAccount, UDMUserController ).ชื่อวิธีการ
โดยปกติแล้วชื่อของเมธอดจะขึ้นต้นด้วยตัวอักษรตัวเล็ก แต่ก็ใช้รูปแบบอูฐด้วย (CamelCase) ข้างต้นเราได้พูดถึงความจริงที่ว่าชื่อคลาสไม่ควรเป็นคำกริยา ในกรณีนี้สถานการณ์จะตรงกันข้าม: ชื่อของเมธอดต้องเป็นคำกริยาหรือใช้ร่วมกับคำกริยา: findUserById, findAllUsers, createUser และอื่นๆ เมื่อสร้างวิธีการ (เช่นเดียวกับตัวแปรและคลาส) เพื่อหลีกเลี่ยงความสับสน ให้ใช้วิธีการตั้งชื่อวิธีเดียว ตัวอย่างเช่น หากต้องการค้นหาผู้ใช้ สามารถเขียนเมธอดเป็น getUserById หรือ findUserById และอีกอย่างหนึ่ง: อย่าใช้อารมณ์ขันในชื่อวิธีการเพราะพวกเขาอาจไม่เข้าใจเรื่องตลกและสิ่งที่วิธีนี้ทำชื่อตัวแปร
ในกรณีส่วนใหญ่ ชื่อตัวแปรจะขึ้นต้นด้วยอักษรตัวพิมพ์เล็กและใช้ Camelcase ด้วย ยกเว้นในกรณีที่ตัวแปรเป็นค่าคงที่ส่วนกลาง ในกรณีเช่นนี้ ตัวอักษรทั้งหมดของชื่อจะเขียนด้วยตัวพิมพ์ใหญ่ และคำต่างๆ จะถูกคั่นด้วยเครื่องหมายขีดล่าง - “_” เมื่อตั้งชื่อตัวแปร คุณสามารถใช้บริบทที่มีความหมายเพื่อความสะดวกได้ กล่าวอีกนัยหนึ่ง เมื่อมีตัวแปรเป็นส่วนหนึ่งของสิ่งที่ใหญ่กว่า เช่น ชื่อ นามสกุล สถานะ ในกรณีเช่นนี้ คุณสามารถเพิ่มคำนำหน้าเพื่อระบุออบเจ็กต์ที่มีตัวแปรนี้อยู่เป็นส่วนหนึ่งได้ ตัวอย่างเช่น: userFirstName, userLastName, userStatus คุณต้องหลีกเลี่ยงชื่อตัวแปรที่คล้ายกันเมื่อมีความหมายต่างกันโดยสิ้นเชิง คำตรงข้ามที่พบบ่อยสำหรับตัวแปร:- เริ่มต้น/สิ้นสุด
- ที่ผ่านมาเป็นครั้งแรก
- ล็อค/ปลดล็อค
- ต่ำสุด/สูงสุด
- ถัดไป/ก่อนหน้า
- เก่า/ใหม่
- เปิด/ปิด
- มองเห็น/มองไม่เห็น
- แหล่งที่มา/เป้าหมาย
- แหล่งที่มา/ปลายทาง
- ขึ้นลง
ชื่อตัวแปรแบบสั้น
เมื่อเรามีตัวแปรเช่น x หรือ n หรืออะไรทำนองนั้น เราจะไม่เห็นเจตนาของผู้เขียนโค้ดในทันที ไม่ชัดเจนว่าวิธีการ n ทำอะไร: ต้องใช้การคิดอย่างรอบคอบมากขึ้น (และนั่นคือ เวลา เวลา เวลา) ตัวอย่างเช่น เรามีฟิลด์ - id ของผู้ใช้ที่รับผิดชอบ และแทนที่จะเป็นชื่อบางอย่างเช่น x หรือเพียง id เราจะเรียกตัวแปรนี้ว่ารับผิดชอบ UserId ซึ่งจะเพิ่มความสามารถในการอ่านและความหมายได้ทันที อย่างไรก็ตาม ชื่อย่ออย่าง n มีตำแหน่งเป็นการเปลี่ยนแปลงเฉพาะที่สำหรับวิธีการเล็กๆ โดยที่บล็อกของโค้ดที่มีการเปลี่ยนแปลงนั้นเป็นเพียงโค้ดสองสามบรรทัด และชื่อวิธีการอธิบายสิ่งที่เกิดขึ้นที่นั่นได้อย่างสมบูรณ์แบบ นักพัฒนามองเห็นตัวแปรดังกล่าวจึงเข้าใจถึงความสำคัญรองและขอบเขตที่จำกัดมาก เป็นผลให้มีการขึ้นอยู่กับความยาวของชื่อตัวแปร: ยิ่งนานเท่าไร ตัวแปรก็จะยิ่งมีความเป็นสากลมากขึ้น และในทางกลับกัน ตัวอย่างเช่น วิธีการค้นหาผู้ใช้ที่บันทึกไว้ล่าสุดตามวันที่:public User findLastUser() {
return findAllUsers().stream()
.sorted((x, y) -> -x.getCreatedDate().compareTo(y.getCreatedDate()))
.findFirst()
.orElseThrow(() -> new ResourceNotFoundException("Any user doesn't exist "));
}
ที่นี่เราใช้ชื่อย่อ x และ y เพื่อตั้งค่าการเรียงลำดับสตรีม และลืมมันไปเลย
ความยาวที่เหมาะสมที่สุด
เรามาต่อหัวข้อความยาวของชื่อกันดีกว่า ความยาวของชื่อที่เหมาะสมที่สุดอยู่ระหว่างความยาวของชื่อ maximumNumberOfUsersInTheCurrentGroup และ n นั่นคือ รายการที่สั้นเกินไปต้องทนทุกข์ทรมานจากการขาดความหมาย และรายการที่ยาวเกินไปจะทำให้โปรแกรมขยายโดยไม่เพิ่มความสามารถในการอ่าน และพวกเขาก็ขี้เกียจเกินกว่าจะเขียนทุกครั้ง โดยไม่คำนึงถึงกรณีข้างต้น สำหรับตัวแปรที่มีชื่อสั้นเช่น n คุณต้องคงความยาวไว้ประมาณ 8-16 อักขระ นี่ไม่ใช่กฎที่เข้มงวด แต่เป็นแนวทางมากกว่าความแตกต่างเล็กๆ น้อยๆ
ฉันไม่สามารถเพิกเฉยต่อความแตกต่างเล็กๆ น้อยๆ ในชื่อได้ เพราะนี่เป็นแนวทางปฏิบัติที่ไม่ดีเช่นกัน เนื่องจากคุณอาจสับสนหรือใช้เวลาพิเศษมากในการสังเกตความแตกต่างเล็กๆ น้อยๆ ในชื่อได้ ตัวอย่างเช่น ความแตกต่างระหว่าง InvalidDataAccessApiUsageException และ InvalidDataAccessResourceUsageException นั้นยากที่จะมองเห็นได้อย่างรวดเร็ว นอกจากนี้ ข้อมูลที่ผิดมักเกิดขึ้นได้เมื่อใช้ L และ O ขนาดเล็ก เนื่องจากอาจสับสนได้ง่ายด้วย 1 และ 0: ในแบบอักษรบางแบบความแตกต่างจะชัดเจนมากขึ้น ในแบบอักษรอื่น ๆ จะน้อยกว่านั้นส่วนความหมาย
เราจำเป็นต้องใส่ส่วนความหมายลงในชื่อ แต่อย่าใช้คำพ้องความหมายมากเกินไป เนื่องจากจริง ๆ แล้ว UserData และ UserInfo มีความหมายเหมือนกัน และเราจะต้องเจาะลึกลงไปในโค้ดอีกเล็กน้อยเพื่อทำความเข้าใจว่าวัตถุใดที่เราต้องการ . หลีกเลี่ยงคำที่ไม่ให้ข้อมูล เช่น firstNameString: ทำไมเราจึงต้องมีคำว่า string? ชื่อสามารถเป็นวัตถุประเภทวันที่ได้หรือไม่? ไม่แน่นอน: ดังนั้นเพียงแค่ - firstName ตามตัวอย่าง ฉันอยากจะพูดถึงตัวแปรบูลีน เช่น flagDelete คำว่า flag ไม่มีความหมายเชิงความหมายใดๆ มันจะสมเหตุสมผลกว่าถ้าจะเรียกมันว่า - isDeleteข้อมูลบิดเบือน
ฉันอยากจะพูดสองสามคำเกี่ยวกับการตั้งชื่อที่ไม่ถูกต้อง สมมติว่าเรามีชื่อ userActivityList และออบเจ็กต์ที่ตั้งชื่อนั้นไม่ใช่ประเภทรายการ แต่เป็นคอนเทนเนอร์หรือออบเจ็กต์แบบกำหนดเองอื่น ๆ สำหรับการจัดเก็บ สิ่งนี้อาจทำให้โปรแกรมเมอร์ทั่วไปสับสน: ควรจะเรียกมันว่า userActivityGroup หรือ userActivities จะดีกว่าค้นหา
ข้อเสียอย่างหนึ่งของชื่อที่สั้นและเรียบง่ายก็คือค้นหาได้ยากในโค้ดจำนวนมาก เพราะอะไรจะค้นหาได้ง่ายกว่า: ตัวแปรที่เรียกว่า name หรือ NAME_FOR_DEFAULT_USER แน่นอนว่าตัวเลือกที่สอง จำเป็นต้องหลีกเลี่ยงคำ (ตัวอักษร) ที่เกิดขึ้นบ่อยครั้งในชื่อ เนื่องจากจะทำให้จำนวนไฟล์ที่พบระหว่างการค้นหาเพิ่มขึ้นเท่านั้น ซึ่งไม่ดี เราขอเตือนคุณว่าโปรแกรมเมอร์ใช้เวลาในการอ่านโค้ดมากกว่าการเขียน ดังนั้นโปรดคำนึงถึงการตั้งชื่อองค์ประกอบของแอปพลิเคชันของคุณ แต่ถ้าคุณไม่สามารถตั้งชื่อได้สำเร็จล่ะ? จะเกิดอะไรขึ้นถ้าชื่อของวิธีการอธิบายฟังก์ชันการทำงานได้ไม่ดีนัก? นี่คือที่มาของการเล่น รายการถัดไปของเราคือความคิดเห็นความคิดเห็น

ประเภทของความคิดเห็น
-
ความคิดเห็นทางกฎหมายคือความคิดเห็นที่ทิ้งไว้ที่จุดเริ่มต้นของไฟล์ซอร์สโค้ดแต่ละไฟล์ด้วยเหตุผลทางกฎหมาย เช่น:
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-
ความคิดเห็นที่ให้ข้อมูลคือความคิดเห็นที่ให้คำอธิบายของโค้ด (ให้ข้อมูลเพิ่มเติมหรือจุดประสงค์ของโค้ดที่กำหนด
ตัวอย่างเช่น:
/* * Объединяет пользователя из бд и пришедшего для обновления * Когда в requestUser поле пустое, оно заполняется старыми данными из foundUser */ private User mergeUser(User requestUser, User foundUser) { return new User( foundUser.getId(), requestUser.getFirstName() == null ? requestUser.getFirstName() : foundUser.getFirstName(), requestUser.getMiddleName() == null ? requestUser.getMiddleName() : foundUser.getMiddleName(), requestUser.getLastName() == null ? requestUser.getLastName() : foundUser.getLastName(), requestUser.getAge() == null ? requestUser.getAge() : foundUser.getAge() ); }
ในกรณีนี้ คุณสามารถทำได้โดยไม่ต้องแสดงความคิดเห็น เนื่องจากชื่อของวิธีการและข้อโต้แย้งประกอบกับฟังก์ชันการทำงานที่โปร่งใสมาก อธิบายตัวเองได้ค่อนข้างดี
-
ความคิดเห็นคำเตือน - ความคิดเห็นที่มีจุดประสงค์เพื่อเตือนนักพัฒนารายอื่นเกี่ยวกับผลที่ไม่พึงประสงค์จากการกระทำบางอย่าง (ตัวอย่างเช่น เหตุใดการทดสอบจึงถูกทำเครื่องหมายเป็น @Ignore):
// Слишком долго отрабатывает // Не запускайте, если не располагаете избытком времени @Ignore @Test public void someIntegrationTest() { …… }
-
สิ่ง ที่ต้องทำ - ความคิดเห็นที่เป็นบันทึกสำหรับอนาคตที่จะต้องทำให้เสร็จ แต่ด้วยเหตุผลบางอย่างไม่สามารถทำได้ในตอนนี้ นี่เป็นแนวทางปฏิบัติที่ดี แต่ยังต้องมีการตรวจสอบเป็นประจำเพื่อลบสิ่งที่ไม่เกี่ยวข้องออกเพื่อหลีกเลี่ยงความยุ่งเหยิง
Примером послужит:
//TODO: Add a check for the current user ID (when will be created security context) @Override public Resource downloadFile(File file) { return fileManager.download(file); }
Тут мы помечаем, что нужно добавить проверку юзера, который скачивает (id которого мы вытащим из security контекста) с тем, кто сохранил.
-
усorвающий комментарий — комментарий, подчеркивающий важность Howого-то обстоятельства, что на первый взгляд может показаться несущественным.
Как пример, кусочек метода, заполняющий тестовую БД, некими скриптами:
Stream.of(IOUtils.resourceToString("/fill-scripts/" + x, StandardCharsets.UTF_8) .trim() .split(";")) .forEach(jdbcTemplate::update); // Вызов trim() очень важен, убирает возможные пробелы в конце скрипта // чтобы при считке и разбивке на отдельные requestы не было пустых
-
javaDoc — комментарии, которые описывают API определенного функционала для общего пользования. Наверное, самые полезные комментарии, так How с documentированным API в разы легче работать, но они также могут устаревать, How и любые другие. Поэтому не забываем, что главный вклад в documentацию вносится не комментариями, а хорошим codeом.
Пример вполне обычного метода обновления пользователя:
/** * Обновляет передаваемые поля для пользователя по id. * * @param id id обновляемого пользователя * @param user пользователь с заполненными полями для обновления * @return обновленный пользователь */ User update(Long id, User user);
Плохие сценарии комментариев

-
бормочущий комментарий — комментарии, которые обычно пишут на скорую руку, смысл которых понятен только разработчику, писавшего их, так How только он видит ту ситуацию с теми нюансами, на которые он и ссылается.
Рассмотрим данный пример:
public void configureSomeSystem() { try{ String configPath = filesLocation.concat("/").concat(CONFIGURATION_FILE); FileInputStream stream = new FileInputStream(configPath); } catch (FileNotFoundException e) { //В случае отсутствия конфигурационного file, загружается конфигурация по умолчанию } }
Кто загружает эти настройки? Были ли они загружены ранее? Метод предназначен для перехвата исключений и вызова дефолтных настроек? Слишком много вопросов возникает, ответы на которые можно получить лишь углубившись в изучение других частей системы.
-
избыточный комментарий — комментарий, который не несёт смысловой нагрузки, так How и так понятно что происходит в заданном участке codeа (он читается не проще, чем code).
Смотрим пример:
public class JdbcConnection{ public class JdbcConnection{ /** * Журнальный компонент, связанный с текущим классом */ private Logger log = Logger.getLogger(JdbcConnection.class.getName()); /** * Создаёт и возвращает connection с помощью входящих параметров */ public static Connection buildConnection(String url, String login, String password, String driver) throws Exception { Class.forName(driver); connection = DriverManager.getConnection(url, login, password); log.info("Created connection with db"); return connection; }
Какой смысл таких комментариев, если мы и так всё прекрасно видим
-
недостоверные комментарии — комментарии, не соответствующие истине и лишь вгоняющие в заблуждение (дезинформирующие). Как например:
/** * Вспомогательный метод, закрывает соединение со сканером, если isNotUsing истинно */ private void scanClose(Scanner scan, boolean isNotUsing) throws Exception { if (!isNotUsing) { throw new Exception("The scanner is still in use"); } scan.close(); }
What в этом комменте не так? А то, что он немножко врёт нам, ведь соединение закрывается, если isNotUsing = false, но ниHow не наоборот, How нам вещает пометка.
-
обязательные комментарии — комментарии, которые считают обязательными (Javadoc), но кои по факту иногда бывают излишне нагромождающими, недостоверными и ненужными (нужно задуматься, а нужны ли здесь такие комментарии).
Пример:
/** * Creation пользователя по переданным параметрам * @param firstName Name созданного пользователя * @param middleName среднее Name созданного пользователя * @param lastName фамorя созданного пользователя * @param age возраст созданного пользователя * @param address addressс созданного пользователя * @return пользователь который был создан */ User createNewUser(String firstName, String middleName, String lastName, String age, String address);
Смогли бы вы понять, что делает метод без этих комментариев? Скорее всего да, поэтому комментарии в этом случае стают бессмысленными.
-
журнальные комментарии — комментарии, которые иногда добавляют в начало модуля, при каждом его редактировании (что-то вроде журнала вносимых изменений).
/** * Записи ведутся с 09 января 2020; ********************************************************************** * 09.01.2020 : Обеспечение соединения с БД с помощью Jdbc Connection; * 15.01.2020 : Добавление интерфейсов уровня дао для работы с БД; * 23.01.2020 : Добавление интеграционных тестов для БД; * 28.01.2020 : Имплементация интерфейсов уровня дао; * 01.02.2020 : Разработка интерфейсов для сервисов, * согласно требованиям прописанным в user stories; * 16.02.2020 : Имплементация интерфейсов сервисов * (реализация бизнес логики связанной с работой БД); * 25.02.2020 : Добавление тестов для сервисов; * 08.03.2020 : Празднование восьмого марта(Миша опять в хлам); * 21.03.2020 : Рефакторинг сервис слоя; */
Когда-то этот проход был оправдан, но с появлением систем управления исходным codeом (например — Git), это стало лишним нагромождением и усложнением codeа.
-
комментарии ссылки на авторов — комментарии, преднаmeaningм которых является, указание человека, писавшего code, чтобы можно было связаться и обсудить, How что и зачем:
* @author Bender Benderovich
Опять же, системы контроля версий прекрасно запоминают, кто и когда добавил данный code, и подобный подход излишен.
-
รหัสความคิดเห็นคือรหัสที่ถูกใส่ความคิดเห็นด้วยเหตุผลใดก็ตาม หนึ่งในนิสัยที่แย่ที่สุดเพราะคุณแสดงความคิดเห็นและลืม และนักพัฒนารายอื่นก็ไม่กล้าที่จะลบมัน (จะเป็นอย่างไรถ้ามันเป็นสิ่งที่มีค่า)
// public void someMethod(SomeObject obj) { // ..... // }
ส่งผลให้มันสะสมเหมือนขยะ ไม่ควรทิ้งรหัสดังกล่าวไว้ไม่ว่าในกรณีใด หากคุณต้องการมันจริงๆ อย่าลืมเกี่ยวกับระบบควบคุมเวอร์ชัน
-
ความคิดเห็นที่ไม่ชัดเจนคือความคิดเห็นที่อธิบายบางสิ่งในลักษณะที่ซับซ้อนโดยไม่จำเป็น
/* * Начать с массива, размер которого достаточен для хранения * всех byteов данных (плюс byteы фильтра) с запасом, плюс 300 byte * для данных заголовка */ this.dataBytes = new byte[(this.size * (this.deep + 1) * 2)+300];
ความคิดเห็นควรอธิบายโค้ด ไม่จำเป็นต้องอธิบายเอง นี่อะไรน่ะ? “ไบต์ตัวกรอง” คืออะไร +1 เกี่ยวอะไรกับมัน? ทำไมต้อง 300 จริงๆ?
- ใช้สไตล์ที่ดูแลรักษาง่าย: การรักษาสไตล์ที่ดูหรูหราและแปลกใหม่เกินไปอาจสร้างความรำคาญและใช้เวลานาน
- อย่าใช้ความคิดเห็นที่ท้ายบรรทัดที่อ้างถึงบรรทัดเดียว เพราะจะทำให้มีความคิดเห็นจำนวนมาก และเป็นการยากที่จะแสดงความคิดเห็นที่แสดงออกในแต่ละบรรทัด
- เมื่อสร้างความคิดเห็น พยายามตอบคำถามว่า "ทำไม" มากกว่า "อย่างไร"
- หลีกเลี่ยงคำย่อ ดังที่ฉันได้กล่าวไว้ข้างต้น เราไม่ต้องการคำอธิบายสำหรับความคิดเห็น: ความคิดเห็นคือคำอธิบาย
- คุณสามารถใช้ความคิดเห็นเพื่อทำเครื่องหมายหน่วยการวัดและช่วงของค่าที่ยอมรับได้
- วางความคิดเห็นใกล้กับโค้ดที่พวกเขาอธิบาย

GO TO FULL VERSION