ЛЕКЦ 06: КОДЫН ЧАНАР БА ЦЭВЭР КОД (Code Quality & Clean Code)
Хичээлийн зорилго: Кодын чанарын ойлголт, цэвэр код бичих зарчмууд, нэрлэлтийн конвенци, функц/метод дизайн, алдаа зохицуулалт, кодын стандарт, статик анализ, Code Review зэргийг Java жишээнүүдтэйгээр эзэмшүүлэх.
Хамрах хүрээ: Clean Code зарчмууд (Robert C. Martin), нэрлэлт, функц дизайн, тайлбар, формат, алдаа зохицуулалт, кодын стандарт, статик анализын хэрэгслүүд, Code Review.
ХЭСЭГ 1: ОНОЛЫН СУУРЬ (Theory & Foundations)
1.1 Кодын чанар (Code Quality) гэж юу вэ?
Кодын чанар гэдэг нь код нь зорилгодоо хэр нийцэж, засвар хийхэд хэр хялбар, ойлгоход хэр тодорхой, алдаагүй, найдвартай ажиллаж байгааг илэрхийлдэг нэгдмэл ойлголт.
🔑 Robert C. Martin: "Цэвэр код гэдэг нь БУСАД хөгжүүлэгч хялбараар УНШИЖ, ОЙЛГОЖ, ӨӨРЧИЛЖ чаддаг код."
Зүйрлэл:
💡 Сайн бичмэл шиг — үг найруулга ойлгомжтой, бүтэц тодорхой, цэвэрхэн бичигдсэн. Муу кодыг уншихад "гүнзгий муу гар бичмэл" уншиж байгаа мэт.
Кодын чанарын хэмжигдэхүүнүүд:
| # | Чанарын шинж | Англи | Тайлбар |
|---|---|---|---|
| 1 | Уншигдах чанар | Readability | Код уншихад ойлгомжтой эсэх |
| 2 | Засварлах чанар | Maintainability | Код өөрчлөхөд хялбар эсэх |
| 3 | Найдвартай байдал | Reliability | Код зөв ажилладаг эсэх |
| 4 | Гүйцэтгэл | Performance | Код хурдан, оновчтой ажиллаж байгаа эсэх |
| 5 | Аюулгүй байдал | Security | Код аюулгүй эсэх |
| 6 | Тестлэх боломж | Testability | Код тестлэхэд хялбар эсэх |
| 7 | Дахин ашиглах | Reusability | Код өөр газар ашиглаж болох эсэх |
Яагаад кодын чанар чухал вэ?
Хөгжүүлэгчийн цагийн хуваарилалт:
┌────────────────────────────────────────┐
│ КОД УНШИХАД: ~70% ████████████████ │
│ КОД БИЧИХЭД: ~30% ███████ │
└────────────────────────────────────────┘
⚠️ Бодит байдал: Хөгжүүлэгч цагийнхаа ~70%-ийг КОД УНШИХАД, зөвхөн ~30%-ийг бичихэд зарцуулдаг. Тиймээс уншигдах чанар нь бүтээмжид шууд нөлөөлнө.
1.2 Clean Code — Цэвэр кодын зарчмууд
Robert C. Martin-ий "Clean Code" номны гол зарчмууд:
| # | Зарчим | Тайлбар |
|---|---|---|
| 1 | Утга учиртай нэрлэлт | Хувьсагч, функц, классын нэр нь зорилгоо илэрхийлэх |
| 2 | Функц жижиг байх | Нэг функц нэг зүйл хийх |
| 3 | Тайлбар бага байх | Код өөрөө тайлбарлагдах |
| 4 | Формат зөв байх | Тогтсон стиль, зохион байгуулалт |
| 5 | Алдаа зохицуулалт | Exception зөв ашиглах |
| 6 | DRY | Давхардал байхгүй |
| 7 | KISS | Энгийн байлга |
| 8 | YAGNI | Шаардлагагүй зүйл нэмэхгүй |
1.3 Нэрлэлт (Naming)
1.3.1 Утга учиртай нэр (Meaningful Names)
Нэр нь "юу хийдэг", "юу агуулдаг", "юунд зориулагдсан" гэдгийг тодорхой илэрхийлэх ёстой.
// ❌ БУРУУ — Юу гэсэн утга вэ?
int d;
String s;
List<int[]> list1;
public void doStuff() { ... }
// ✅ ЗӨӨВ — Нэр нь зорилгоо илэрхийлж байна
int daysSinceLastLogin;
String customerName;
List<int[]> flaggedCells;
public void calculateMonthlyReport() { ... }
1.3.2 Нэрлэлтийн дүрмүүд
| Дүрэм | Тайлбар | Жишээ |
|---|---|---|
| Зорилгыг илэрхийлэх | Нэрийг уншихад зорилго нь мэдэгдэх | maxRetryCount (✅) vs mrc (❌) |
| Төөрөгдөл үүсгэхгүй | Хуурмаг мэдээлэл агуулахгүй | accountList зөвхөн List бол → accounts |
| Ялгаатай нэр | Ижил төстэй нэр ашиглахгүй | getActiveAccount() vs getActiveAccountInfo() — юугаараа ялгаатай? |
| Дуудаж болохуйц | Амаар хэлж болохуйц нэр | genymdhms (❌) → generationTimestamp (✅) |
| Хайж болохуйц | Нэг үсэгтэй нэр хайхад хэцүү | e (❌) → event (✅) |
1.3.3 Java нэрлэлтийн конвенци
| Төрөл | Конвенци | Жишээ |
|---|---|---|
| Класс | PascalCase (Нэр үг) | StudentService, OrderProcessor |
| Метод | camelCase (Үйл үг) | calculateTotal(), findByName() |
| Хувьсагч | camelCase | studentName, totalAmount |
| Тогтмол | UPPER_SNAKE_CASE | MAX_RETRY_COUNT, DEFAULT_TIMEOUT |
| Package | бүгд жижиг | com.company.project.service |
| Interface | PascalCase | Serializable, PaymentService |
| Enum | PascalCase (нэр), UPPER (утга) | enum Color { RED, GREEN, BLUE } |
| Boolean | is/has/can + Тэмдэг нэр | isActive, hasPermission, canDelete |
// ❌ БУРУУ нэрлэлт
class data { ... } // Жижиг үсэг, тодорхойгүй
public void proc() { ... } // Товчилсон
boolean flag; // Юуны flag?
static final int num = 30; // Тогтмол нэрлэлт буруу
// ✅ ЗӨӨВ нэрлэлт
class StudentRegistration { ... } // PascalCase, тодорхой
public void processRegistration() { } // camelCase, үйл үг
boolean isEnrollmentOpen; // Boolean конвенци
static final int MAX_CLASS_SIZE = 30; // UPPER_SNAKE_CASE
1.3.4 Тохиромжтой нэрийн урт
// Хэт богино — ойлгомжгүй
int d;
String n;
void p() { }
// Хэт урт — уншихад хэцүү
int numberOfDaysSinceTheUserLastLoggedInToTheSystem;
void processAndValidateAndSaveStudentRegistrationFormData() { }
// Тохиромжтой — ойлгомжтой, товч
int daysSinceLastLogin;
String studentName;
void processRegistration() { }
💡 Зүйрлэл: Хүний нэр шиг — "Б" гэхэд хэн бэ мэдэхгүй, "Баатарын хүү Болдбаатарын ач Эрдэнэбаатар" гэхэд хэт урт. "Баатар" гэхэд яг тохиромжтой.
1.4 Функц / Метод дизайн
1.4.1 Функц жижиг байх ёстой
🔑 Robert C. Martin: "Функцийн эхний дүрэм — ЖИЖИГ байх. Хоёр дахь дүрэм — БҮҮР ЖИЖИГ байх."
// ❌ БУРУУ — 50+ мөр, олон зүйл хийж байна
public void processOrder(Order order) {
// Хэрэглэгч шалгах (15 мөр)
if (order.getCustomer() == null) { ... }
if (!order.getCustomer().isActive()) { ... }
// Нөөц шалгах (10 мөр)
for (Item item : order.getItems()) { ... }
// Үнэ тооцоолох (15 мөр)
double total = 0;
for (Item item : order.getItems()) { ... }
// Хөнгөлөлт (10 мөр)
if (order.getCustomer().isVIP()) { ... }
// Төлбөр (5 мөр)
paymentService.charge(total);
}
// ✅ ЗӨӨВ — Жижиг функцүүдэд хуваасан
public void processOrder(Order order) {
validateCustomer(order.getCustomer());
checkInventory(order.getItems());
double total = calculateTotal(order);
total = applyDiscount(order.getCustomer(), total);
processPayment(order.getCustomer(), total);
}
1.4.2 Нэг функц — Нэг зүйл (Do One Thing)
// ❌ БУРУУ — Олон зүйл хийж байна
public void emailClients(List<Client> clients) {
for (Client client : clients) {
if (client.isActive()) { // Шүүх
String email = client.getEmail(); // Өгөгдөл авах
if (email != null && !email.isEmpty()) { // Шалгах
sendEmail(email, "Hello!"); // Илгээх
}
}
}
}
// ✅ ЗӨӨВ — Тус тусдаа функцүүд
public void emailActiveClients(List<Client> clients) {
List<Client> activeClients = filterActiveClients(clients);
List<String> emails = extractValidEmails(activeClients);
sendBulkEmail(emails, "Hello!");
}
private List<Client> filterActiveClients(List<Client> clients) {
return clients.stream()
.filter(Client::isActive)
.collect(Collectors.toList());
}
private List<String> extractValidEmails(List<Client> clients) {
return clients.stream()
.map(Client::getEmail)
.filter(email -> email != null && !email.isEmpty())
.collect(Collectors.toList());
}
1.4.3 Функцийн параметрийн тоо
| Тоо | Нэр | Зөвлөмж |
|---|---|---|
| 0 | Niladic | ✅ Хамгийн сайн |
| 1 | Monadic | ✅ Сайн |
| 2 | Dyadic | ⚠️ Болгоомжтой |
| 3 | Triadic | ❌ Зайлсхий |
| 3+ | Polyadic | ❌ Объект ашигла |
// ❌ БУРУУ — 6 параметр
public void createStudent(String firstName, String lastName,
int age, String email,
String phone, double gpa) { ... }
// ✅ ЗӨӨВ — Объект ашиглах
public void createStudent(StudentDTO student) { ... }
class StudentDTO {
private String firstName;
private String lastName;
private int age;
private String email;
private String phone;
private double gpa;
}
1.4.4 Функцийн нэрлэлт
// ❌ БУРУУ — Юу хийдэг нь мэдэгдэхгүй
public void handle() { ... }
public Object get() { ... }
public void process() { ... }
public boolean check(Student s) { ... }
// ✅ ЗӨӨВ — Нэр нь зорилгоо тодорхой хэлж байна
public void handlePaymentTimeout() { ... }
public Student findStudentById(long id) { ... }
public void processMonthlyBilling() { ... }
public boolean isEligibleForScholarship(Student student) { ... }
1.4.5 Side Effect байхгүй байх
Side Effect = Функц нь нэрнээс мэдэгдэхгүй "нуугдмал" зүйл хийж байна.
// ❌ БУРУУ — checkPassword нь нууц "session initialize" хийж байна
public boolean checkPassword(String username, String password) {
User user = userRepository.findByName(username);
if (user != null && user.getPassword().equals(encrypt(password))) {
Session.initialize(); // ⚠️ Side Effect! Нэрнээс мэдэгдэхгүй
return true;
}
return false;
}
// ✅ ЗӨӨВ — Тусдаа функцүүд
public boolean checkPassword(String username, String password) {
User user = userRepository.findByName(username);
return user != null && user.getPassword().equals(encrypt(password));
}
public void loginUser(String username, String password) {
if (checkPassword(username, password)) {
Session.initialize(); // Тодорхой — login хийхэд session эхлэнэ
}
}
1.5 Тайлбар (Comments)
1.5.1 Сайн тайлбар vs Муу тайлбар
🔑 Robert C. Martin: "Тайлбар бичих шаардлагатай болсон бол — кодоо илүү сайн бичиж чадаагүй гэсэн дохио."
Сайн тайлбар:
// ✅ Хуулийн шаардлага тайлбарлах
// Хувийн мэдээлэл хамгаалах тухай хуулийн 15.3 заалтын дагуу
// 18 нас хүрээгүй хэрэглэгчийн мэдээллийг 90 хоногийн дараа устгана
public void deleteMinorUserData() { ... }
// ✅ Яагаад ийм шийдвэр гаргасныг тайлбарлах
// SimpleDateFormat нь thread-safe биш тул ThreadLocal ашиглаж байна
private static final ThreadLocal<SimpleDateFormat> formatter =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
// ✅ TODO тайлбар
// TODO: Кэш нэвтрүүлэх — одоогоор DB-с шууд уншиж байна
public Student findById(long id) { ... }
// ✅ Анхааруулга
// WARNING: Энэ тест 10 минут ажиллана
@Test
public void performanceTest() { ... }
Муу тайлбар:
// ❌ Код юу хийж байгааг давтах
// i-г нэгээр нэмэгдүүлэх
i++;
// ❌ Хуучирсан тайлбар (код өөрчлөгдсөн, тайлбар хэвээрээ)
// Хэрэглэгчийн нэрийг буцаана
public String getEmail() { return email; } // Нэр биш, имэйл!
// ❌ Шаардлагагүй тайлбар — код өөрөө ойлгомжтой
// Default constructor
public Student() { }
// ❌ Comment-оор "хаасан" хуучин код
// public void oldMethod() {
// // Хуучин логик...
// }
1.5.2 Код өөрөө тайлбарлагдах ёстой
// ❌ БУРУУ — Тайлбараар нөхсөн
// Хэрэглэгч нэвтрэх эрхтэй эсэхийг шалгах
// Нас 18-аас дээш, бүртгэл идэвхтэй, блоклогдоогүй байх
public boolean chk(User u) {
return u.getAge() >= 18 && u.isActive() && !u.isBlocked();
}
// ✅ ЗӨӨВ — Код өөрөө тайлбарлагдаж байна
public boolean isEligibleForAccess(User user) {
return user.isAdult() && user.isActive() && !user.isBlocked();
}
1.6 Формат (Formatting)
1.6.1 Босоо формат (Vertical Formatting)
// ✅ Холбоотой кодыг ойрхон, хоосон мөрөөр бүлэглэх
public class StudentService {
private final StudentRepository repository;
private final EmailService emailService;
public StudentService(StudentRepository repository, EmailService emailService) {
this.repository = repository;
this.emailService = emailService;
}
public Student findById(long id) {
return repository.findById(id)
.orElseThrow(() -> new StudentNotFoundException(id));
}
public Student createStudent(StudentDTO dto) {
Student student = mapToEntity(dto);
Student saved = repository.save(student);
emailService.sendWelcomeEmail(saved.getEmail());
return saved;
}
private Student mapToEntity(StudentDTO dto) {
// ...
}
}
Зарчим:
- Холбоотой код ойрхон байх (хувьсагч → ашигласан газар)
- Хоосон мөрөөр логик бүлгүүдийг тусгаарлах
- Нэг файлд 200-500 мөр (дээд тал нь)
- Import → Талбар → Constructor → Public метод → Private метод
1.6.2 Хэвтээ формат (Horizontal Formatting)
// ❌ БУРУУ — Нэг мөр хэт урт
public List<StudentDTO> findActiveStudentsWithGPAAboveThresholdAndEnrolledInCurrentSemester(double threshold) { ... }
// ✅ ЗӨӨВ — Мөр хуваах (80-120 тэмдэгт)
public List<StudentDTO> findActiveHighPerformers(double minGPA) {
return repository.findAll().stream()
.filter(Student::isActive)
.filter(s -> s.getGpa() >= minGPA)
.filter(s -> s.isEnrolledInCurrentSemester())
.map(this::toDTO)
.collect(Collectors.toList());
}
1.7 Алдаа зохицуулалт (Error Handling)
1.7.1 Exception ашиглах (Return Code биш)
// ❌ БУРУУ — Return code ашиглах
public int withdraw(double amount) {
if (amount <= 0) return -1; // Буруу дүн
if (amount > balance) return -2; // Хүрэлцэхгүй
balance -= amount;
return 0; // Амжилттай
}
// Дуудаж буй код:
int result = account.withdraw(100);
if (result == -1) { ... } // -1, -2 юу гэсэн утга вэ?
// ✅ ЗӨӨВ — Exception ашиглах
public void withdraw(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("Дүн эерэг байх ёстой: " + amount);
}
if (amount > balance) {
throw new InsufficientFundsException(
"Үлдэгдэл хүрэлцэхгүй. Үлдэгдэл: " + balance + ", Хүсэлт: " + amount
);
}
balance -= amount;
}
1.7.2 Checked vs Unchecked Exception
| Төрөл | Тайлбар | Хэзээ ашиглах | Жишээ |
|---|---|---|---|
| Checked | Компайлер шалгадаг, заавал барих | Сэргээж болох алдаа | IOException, SQLException |
| Unchecked | Runtime-д гардаг, барих заавал биш | Програмын алдаа | NullPointerException, IllegalArgumentException |
1.7.3 Тодорхой Exception ашиглах
// ❌ БУРУУ — Ерөнхий Exception
try {
student = repository.findById(id);
} catch (Exception e) { // Бүх алдааг нэг дор барьж байна
log.error("Алдаа", e);
}
// ✅ ЗӨӨВ — Тодорхой Exception
try {
student = repository.findById(id);
} catch (StudentNotFoundException e) {
log.warn("Оюутан олдсонгүй: {}", id);
throw new ResponseStatusException(HttpStatus.NOT_FOUND, e.getMessage());
} catch (DatabaseException e) {
log.error("Мэдээллийн сангийн алдаа: {}", e.getMessage());
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR);
}
1.7.4 Null буцаахгүй байх
// ❌ БУРУУ — null буцааж, NullPointerException-ийн эрсдэл
public Student findById(long id) {
return repository.findById(id); // null байж болно!
}
// Дуудсан газар:
Student s = service.findById(1);
s.getName(); // NullPointerException!
// ✅ ЗӨӨВ — Optional ашиглах
public Optional<Student> findById(long id) {
return repository.findById(id);
}
// Дуудсан газар:
Student s = service.findById(1)
.orElseThrow(() -> new StudentNotFoundException(id));
// Эсвэл:
service.findById(1).ifPresent(student -> {
System.out.println(student.getName());
});
1.7.5 Утга учиртай алдааны мессеж
// ❌ БУРУУ
throw new RuntimeException("Error");
throw new IllegalArgumentException("Invalid");
// ✅ ЗӨӨВ
throw new StudentNotFoundException("ID=" + id + " оюутан олдсонгүй");
throw new IllegalArgumentException(
"Нас 1-150 хооронд байх ёстой. Оруулсан: " + age
);
throw new InsufficientFundsException(
String.format("Үлдэгдэл хүрэлцэхгүй. Үлдэгдэл: %.2f₮, Хүсэлт: %.2f₮",
balance, amount)
);
1.8 Кодын стандарт (Coding Standards)
1.8.1 Кодын стандарт гэж юу вэ?
Баг/байгууллагын хэмжээнд хэрэглэх нэгдсэн дүрэм, конвенци — нэрлэлт, формат, бүтэц, алдаа зохицуулалт зэргийг тогтоосон.
💡 Зүйрлэл: Замын хөдөлгөөний дүрэм шиг — хүн бүр ижил дүрмээр жолоодвол осол бага. Код ч мөн адил — нэгдсэн стандартаар бичвэл алдаа бага, ойлголцох хялбар.
1.8.2 Java-ийн алдартай стандартууд
| Стандарт | Байгууллага | Онцлог |
|---|---|---|
| Google Java Style Guide | Маш дэлгэрэнгүй, өргөн хэрэглэгддэг | |
| Oracle Code Conventions | Oracle (Sun) | Java-ийн албан ёсны стандарт |
| Alibaba Java Coding Guidelines | Alibaba | Алдааны эрсдэлд анхаарсан |
1.8.3 Стандартын жишээ дүрмүүд
// ✅ Нэг мөрд нэг зарлалт
int width;
int height;
// ❌ БУРУУ
int width, height;
// ✅ Braces ашиглах (нэг мөр ч бай)
if (isActive) {
doSomething();
}
// ❌ БУРУУ — Braces-гүй бол ирээдүйд алдаа гарч болно
if (isActive)
doSomething();
// ✅ Magic number ашиглахгүй
private static final int MAX_LOGIN_ATTEMPTS = 5;
if (loginAttempts >= MAX_LOGIN_ATTEMPTS) { ... }
// ❌ БУРУУ
if (loginAttempts >= 5) { ... } // 5 юу вэ?
1.9 Статик анализ (Static Analysis)
Статик анализ гэж юу вэ?
Кодыг АЖИЛЛУУЛАХГҮЙГЭЭР автоматаар шалгаж, алдаа, code smell, аюулгүй байдлын сул тал зэргийг олох.
💡 Зүйрлэл: Эмчид үзүүлэхийн өмнө "эрүүл мэндийн оношилгоо" хийх шиг — кодыг ажиллуулахын өмнө статик анализ нь "оношилгоо" хийнэ.
Алдартай хэрэгслүүд:
| Хэрэгсэл | Зорилго | Тайлбар |
|---|---|---|
| SonarQube | Бүх талын анализ | Code smell, bug, аюулгүй байдал, давхардал, test coverage |
| PMD | Код чанар | Код загварын алдаа, шаардлагагүй код олох |
| CheckStyle | Формат/стиль | Google/Sun style guide-д нийцэж байгаа эсэх |
| SpotBugs | Bug олох | Нийтлэг алдааны загвар олох |
| IntelliJ Inspections | IDE шалгалт | IDE дотор real-time шалгалт |
| Lombok | Boilerplate бууруулах | Getter/Setter автомат үүсгэх |
SonarQube-ийн үндсэн хэмжигдэхүүнүүд:
| Хэмжигдэхүүн | Тайлбар | Сайн утга |
|---|---|---|
| Bugs | Алдааны тоо | 0 |
| Vulnerabilities | Аюулгүй байдлын сул тал | 0 |
| Code Smells | Кодын чанарын асуудал | Бага байх |
| Coverage | Тестийн хамралт | >80% |
| Duplications | Давхардсан кодын хувь | <3% |
| Technical Debt | Техникийн өрийг засах хугацаа | Бага байх |
1.10 Code Review
Code Review гэж юу вэ?
Code Review нь нэг хөгжүүлэгчийн бичсэн кодыг бусад хөгжүүлэгч шалгаж, санал болгож, сайжруулах процесс.
💡 Зүйрлэл: Эссэ бичсний дараа найзаараа уншуулж, алдаа олуулах шиг — Code Review нь кодын "эссэ шалгалт".
Code Review-ийн давуу тал:
| # | Давуу тал | Тайлбар |
|---|---|---|
| 1 | Алдаа олох | Тестэд баригдаагүй алдааг олно |
| 2 | Мэдлэг хуваалцах | Баг бүгд кодыг мэддэг болно |
| 3 | Стандарт баримтлах | Нэгдсэн стиль, чанар |
| 4 | Суралцах | Бие биенээсээ суралцана |
| 5 | Кодын эзэмшил | "Энэ зөвхөн миний код" биш, "МАНАЙ КОД" |
Code Review хийхдээ юуг шалгах вэ?
| Шалгах зүйл | Асуулт |
|---|---|
| Зөв ажиллагаа | Логик зөв үү? Edge case зохицуулсан уу? |
| Нэрлэлт | Нэрс утга учиртай юу? Конвенци баримталсан уу? |
| Бүтэц | Функц жижиг үү? SRP баримталсан уу? |
| Алдаа зохицуулалт | Exception зөв ашигласан уу? Null шалгасан уу? |
| Тест | Шинэ код тестлэгдсэн үү? Edge case тестэлсэн үү? |
| Аюулгүй байдал | SQL injection, XSS зэрэг эрсдэл байна уу? |
| Гүйцэтгэл | N+1 query, шаардлагагүй loop байна уу? |
| DRY | Давхардсан код байна уу? |
Сайн Code Review тайлбар:
// ❌ БУРУУ тайлбар:
"Энэ муу байна"
"Засаарай"
"Яагаад ингэж бичсэн бэ?"
// ✅ ЗӨӨВ тайлбар:
"Энд Optional ашиглавал NullPointerException-ийн эрсдэл буурна.
Жишээ: return Optional.ofNullable(result);"
"Энэ метод 2 зүйл хийж байна (шалгах + хадгалах).
validateStudent() ба saveStudent() гэж хуваах санал."
"nit: studentName → enrolledStudentName гэвэл илүү тодорхой болно."
"nit" = Nitpick (жижиг зүйл) — заавал засах шаардлагагүй, зөвхөн санал.
1.11 Кодын чанарын пирамид
╱╲
╱ ╲
╱ UI ╲ ← Хэрэглэгчийн туршлага
╱──────╲
╱ Тест ╲ ← Автомат тест
╱──────────╲
╱ Code Review╲ ← Багийн шалгалт
╱──────────────╲
╱ Статик анализ ╲ ← Автомат шалгалт
╱──────────────────╲
╱ Кодын стандарт ╲ ← Дүрэм, конвенци
╱──────────────────────╲
╱ Цэвэр код зарчмууд ╲ ← Clean Code
╱────────────────────────────╲
Доороос дээш: Цэвэр код → Стандарт → Статик анализ → Code Review → Тест → UI чанар
1.12 Нийтлэг алдаанууд ба засвар
1.12.1 God Class / God Method
// ❌ БУРУУ — "God Class" — бүхнийг мэддэг, бүхнийг хийдэг
class ApplicationManager {
void createUser() { ... }
void deleteUser() { ... }
void processPayment() { ... }
void generateReport() { ... }
void sendEmail() { ... }
void backupDatabase() { ... }
void handleError() { ... }
// ... 50+ метод
}
// ✅ ЗӨӨВ — Үүргээр хуваах (SRP)
class UserService { ... }
class PaymentService { ... }
class ReportService { ... }
class EmailService { ... }
class BackupService { ... }
1.12.2 Boolean параметр
// ❌ БУРУУ — Boolean параметр нь функцыг 2 зүйл хийхэд хүргэнэ
public void processOrder(Order order, boolean isExpress) {
if (isExpress) {
// Шуурхай боловсруулалт
} else {
// Энгийн боловсруулалт
}
}
// ✅ ЗӨӨВ — Тусдаа функцүүд
public void processStandardOrder(Order order) { ... }
public void processExpressOrder(Order order) { ... }
1.12.3 Гинжин if-else
// ❌ БУРУУ — Гинжин if-else
public double calculateShipping(String type) {
if (type.equals("standard")) {
return 5.0;
} else if (type.equals("express")) {
return 15.0;
} else if (type.equals("overnight")) {
return 25.0;
} else if (type.equals("international")) {
return 50.0;
}
return 0;
}
// ✅ ЗӨӨВ — Enum + Map ашиглах
enum ShippingType {
STANDARD(5.0), EXPRESS(15.0), OVERNIGHT(25.0), INTERNATIONAL(50.0);
private final double cost;
ShippingType(double cost) { this.cost = cost; }
public double getCost() { return cost; }
}
public double calculateShipping(ShippingType type) {
return type.getCost();
}
1.12.4 Hardcoded утга
// ❌ БУРУУ — Hardcoded
if (user.getRole().equals("admin")) { ... }
Thread.sleep(5000);
String url = "http://localhost:8080/api";
// ✅ ЗӨӨВ — Тогтмол / тохиргоо ашиглах
private static final String ADMIN_ROLE = "admin";
private static final long RETRY_DELAY_MS = 5000;
@Value("${api.base-url}")
private String apiBaseUrl;
if (user.getRole().equals(ADMIN_ROLE)) { ... }
Thread.sleep(RETRY_DELAY_MS);
ХЭСЭГ 2: ТҮЛХҮҮР ҮГ БА МЭРГЭЖЛИЙН НЭР ТОМЬЁО (Keywords & Glossary)
| # | Англи нэр томьёо | Монгол утга | Дэлгэрэнгүй тайлбар |
|---|---|---|---|
| 1 | Clean Code | Цэвэр код | Уншихад хялбар, засвар хийхэд тохиромжтой, бүтэц зохион байгуулалттай код. |
| 2 | Code Quality | Кодын чанар | Код зөв, найдвартай, уншигдахуйц, засварлаж болохуйц байх нэгдмэл ойлголт. |
| 3 | Readability | Уншигдах чанар | Бусад хөгжүүлэгч кодыг хялбар уншиж, ойлгож чадах эсэх. |
| 4 | Maintainability | Засварлах чанар | Кодонд өөрчлөлт хийхэд хэр хялбар байх. |
| 5 | Naming Convention | Нэрлэлтийн конвенци | Хувьсагч, метод, классын нэрлэлтийн нэгдсэн дүрэм. |
| 6 | camelCase | Тэмээний хэв | firstWordLower, дараагийнх UPPER: studentName. |
| 7 | PascalCase | Паскаль хэв | EveryWordCapitalized: StudentService. |
| 8 | UPPER_SNAKE_CASE | Дээд могойн хэв | Тогтмол (constant): MAX_RETRY_COUNT. |
| 9 | Side Effect | Гаж нөлөө | Функц нь нэрнээсээ гадуур нуугдмал зүйл хийх. |
| 10 | DRY | Өөрийгөө бүү давт | Don't Repeat Yourself — Ижил логик нэг газар л байх. |
| 11 | KISS | Энгийн байлга | Keep It Simple, Stupid — Хамгийн энгийн шийдлийг сонгох. |
| 12 | YAGNI | Танд хэрэг болохгүй | You Aren't Gonna Need It — Шаардлагагүй зүйл нэмэхгүй. |
| 13 | Magic Number | Шидэт тоо | Нэргүй тоон утга, тогтмолоор солих ёстой. |
| 14 | Boilerplate Code | Давтамжийн код | Олон газар давтагддаг загварчилсан код (getter/setter зэрэг). |
| 15 | Static Analysis | Статик анализ | Кодыг ажиллуулахгүйгээр автоматаар шалгах. |
| 16 | Code Review | Кодын шалгалт | Бусад хөгжүүлэгч кодыг шалгаж, санал болгох процесс. |
| 17 | SonarQube | СонарКьюб | Кодын чанарын платформ — bug, smell, coverage шалгана. |
| 18 | PMD | ПМД | Java кодын статик анализын хэрэгсэл. |
| 19 | CheckStyle | ЧекСтайл | Кодын формат, стилийн дүрэм шалгах хэрэгсэл. |
| 20 | SpotBugs | СпотБагс | Java кодын нийтлэг алдааг олох хэрэгсэл. |
| 21 | Technical Debt | Техникийн өр | Богино хугацааны шийдэл → Ирээдүйд нэмэлт ажил шаардах. |
| 22 | God Class | Бурхан класс | Бүх зүйлийг мэддэг, бүх зүйлийг хийдэг нэг том класс. |
| 23 | Code Smell | Кодын үнэр | Кодын чанарын асуудлыг илтгэх шинж тэмдэг. |
| 24 | Exception Handling | Алдаа зохицуулалт | Алдааг зохицуулах, мэдэгдэх, сэргээх механизм. |
| 25 | Checked Exception | Шалгагддаг алдаа | Компайлер шалгадаг, заавал барих ёстой алдаа. |
| 26 | Unchecked Exception | Шалгагддаггүй алдаа | Runtime-д гарах, барих заавал биш алдаа. |
| 27 | NullPointerException | Null заагчийн алдаа | null утга дээр метод дуудах үед гарах алдаа. |
| 28 | Optional | Заавал биш утга | null-ийн оронд ашигладаг, утга байж ч, байхгүй ч болно. |
| 29 | Coding Standard | Кодын стандарт | Баг/байгууллагын нэгдсэн кодын бичлэгийн дүрэм. |
| 30 | Linter | Линтер | Кодын стиль, формат автоматаар шалгах хэрэгсэл. |
| 31 | Code Coverage | Кодын хамралт | Тестүүд кодын хэдэн хувийг хамарч байгаа. |
| 32 | Cyclomatic Complexity | Цикломатик нарийн байдал | Кодын нөхцөл салаалтын нарийн байдлын хэмжигдэхүүн. |
| 33 | Self-Documenting Code | Өөрийгөө тайлбарладаг код | Нэрлэлт, бүтцээрээ тайлбаргүй ойлгогддог код. |
| 34 | Defensive Programming | Хамгаалалтын программчлал | Алдаа гарч болзошгүй бүх тохиолдлыг урьдчилж шалгах. |
| 35 | Fail Fast | Хурдан бүдрэх | Алдааг аль болох ЭРТ илрүүлж, тодорхой мэдэгдэх. |
| 36 | Guard Clause | Хамгаалалтын нөхцөл | Метод эхэнд буруу оролтыг шалгаж, эрт буцаах. |
| 37 | Single Responsibility | Нэг үүрэг | Нэг класс/метод зөвхөн нэг зүйлийг хариуцах. |
| 38 | Pair Programming | Хосоор программчлах | Хоёр хөгжүүлэгч нэг компьютер дээр хамтран код бичих. |
| 39 | Rubber Duck Debugging | Нугасан дебаг | Асуудлыг бусдад (эсвэл нугасанд) тайлбарлаж, шийдлийг олох арга. |
| 40 | Boy Scout Rule | Скаутын дүрэм | Кодыг олсноосоо илүү цэвэр орхи — жижиг сайжруулалт хий. |
ХЭСЭГ 3: ЛАБОРАТОРИ БА ПРАКТИК ЗААВАР (Labs & Step-by-Step Guide)
3.1 Лабораторийн зорилго
Энэ лабораторид та цэвэр код бичих ур чадварыг бодит жишээнүүд дээр дадлагаар эзэмшинэ:
- Муу кодыг цэвэр код болгон сайжруулах
- Нэрлэлт, функц дизайн, алдаа зохицуулалтыг дадлагажуулах
- Кодын чанарын хэрэгсэл (CheckStyle) ашиглах
- Code Review хийх
Хэл: Java 17+ | IDE: Eclipse IDE
3.2 Лаб 1: Муу нэрлэлтийг засварлах
Даалгавар: Дараах кодын нэрлэлтийг цэвэр код зарчмаар сайжруулах
ӨМНӨ (Муу нэрлэлт):
public class Mgr {
private List<int[]> lst = new ArrayList<>();
public List<int[]> getThm() {
List<int[]> r = new ArrayList<>();
for (int[] x : lst) {
if (x[0] == 4) {
r.add(x);
}
}
return r;
}
public double calc(List<Map<String, Object>> d) {
double t = 0;
int c = 0;
for (Map<String, Object> m : d) {
double v = (Double) m.get("v");
t += v;
c++;
}
return c > 0 ? t / c : 0;
}
public boolean chk(String s) {
if (s == null) return false;
if (s.length() < 8) return false;
boolean h1 = false, h2 = false, h3 = false;
for (char c : s.toCharArray()) {
if (Character.isUpperCase(c)) h1 = true;
if (Character.isLowerCase(c)) h2 = true;
if (Character.isDigit(c)) h3 = true;
}
return h1 && h2 && h3;
}
}
ДАРАА (Цэвэр нэрлэлт):
public class GameBoardManager {
private List<int[]> cells = new ArrayList<>();
public List<int[]> getFlaggedCells() {
List<int[]> flaggedCells = new ArrayList<>();
for (int[] cell : cells) {
if (cell[STATUS_INDEX] == FLAGGED) {
flaggedCells.add(cell);
}
}
return flaggedCells;
}
public double calculateAverage(List<Map<String, Object>> dataPoints) {
double totalValue = 0;
int count = 0;
for (Map<String, Object> dataPoint : dataPoints) {
double value = (Double) dataPoint.get("value");
totalValue += value;
count++;
}
return count > 0 ? totalValue / count : 0;
}
public boolean isPasswordStrong(String password) {
if (password == null) return false;
if (password.length() < MIN_PASSWORD_LENGTH) return false;
boolean hasUpperCase = false;
boolean hasLowerCase = false;
boolean hasDigit = false;
for (char character : password.toCharArray()) {
if (Character.isUpperCase(character)) hasUpperCase = true;
if (Character.isLowerCase(character)) hasLowerCase = true;
if (Character.isDigit(character)) hasDigit = true;
}
return hasUpperCase && hasLowerCase && hasDigit;
}
private static final int STATUS_INDEX = 0;
private static final int FLAGGED = 4;
private static final int MIN_PASSWORD_LENGTH = 8;
}
Сайжруулсан зүйлс:
| # | Өмнө | Дараа | Ашигласан зарчим |
|---|---|---|---|
| 1 | Mgr | GameBoardManager | Утга учиртай класс нэр |
| 2 | lst, r, x | cells, flaggedCells, cell | Утга учиртай хувьсагч нэр |
| 3 | getThm() | getFlaggedCells() | Метод зорилгоо илэрхийлэх |
| 4 | calc() | calculateAverage() | Тодорхой метод нэр |
| 5 | chk() | isPasswordStrong() | Boolean конвенци (is + тэмдэг нэр) |
| 6 | 4, 8 | FLAGGED, MIN_PASSWORD_LENGTH | Magic number → Тогтмол |
| 7 | h1, h2, h3 | hasUpperCase, hasLowerCase, hasDigit | Boolean хувьсагчийн нэрлэлт |
3.3 Лаб 2: Функц дизайн — Нэг функц, нэг зүйл
Даалгавар: Дараах том функцыг жижиг, нэг зорилготой функцүүдэд хуваах
ӨМНӨ (Нэг том функц):
public class OrderProcessor {
public String processOrder(String customerName, String email,
List<String> items, List<Double> prices,
String cardNumber, boolean isVIP) {
// 1. Шалгах
if (customerName == null || customerName.isEmpty()) {
return "ERROR: Хэрэглэгчийн нэр хоосон";
}
if (email == null || !email.contains("@")) {
return "ERROR: Имэйл буруу";
}
if (items.size() != prices.size()) {
return "ERROR: Бүтээгдэхүүн ба үнэ тохирохгүй";
}
if (items.isEmpty()) {
return "ERROR: Сагс хоосон";
}
// 2. Үнэ тооцоолох
double total = 0;
for (int i = 0; i < items.size(); i++) {
total += prices.get(i);
}
// 3. Хөнгөлөлт
double discount = 0;
if (isVIP) {
discount = total * 0.15;
} else if (total > 100000) {
discount = total * 0.05;
}
total = total - discount;
// 4. Татвар
double tax = total * 0.1;
total = total + tax;
// 5. Төлбөр
if (cardNumber == null || cardNumber.length() != 16) {
return "ERROR: Картын дугаар буруу";
}
System.out.println("Төлбөр боловсруулж байна: " + cardNumber);
// 6. Баримт
StringBuilder receipt = new StringBuilder();
receipt.append("=== БАРИМТ ===\n");
receipt.append("Хэрэглэгч: ").append(customerName).append("\n");
for (int i = 0; i < items.size(); i++) {
receipt.append(items.get(i)).append(": ")
.append(prices.get(i)).append("₮\n");
}
receipt.append("Хөнгөлөлт: -").append(discount).append("₮\n");
receipt.append("Татвар: +").append(tax).append("₮\n");
receipt.append("Нийт: ").append(total).append("₮\n");
// 7. Имэйл илгээх
System.out.println(email + " руу баримт илгээсэн");
return receipt.toString();
}
}
ДАРАА (Цэвэр функц дизайн):
public class OrderProcessor {
private static final double VIP_DISCOUNT_RATE = 0.15;
private static final double BULK_DISCOUNT_RATE = 0.05;
private static final double BULK_THRESHOLD = 100_000;
private static final double TAX_RATE = 0.10;
private static final int CARD_NUMBER_LENGTH = 16;
private final PaymentService paymentService;
private final EmailService emailService;
public OrderProcessor(PaymentService paymentService, EmailService emailService) {
this.paymentService = paymentService;
this.emailService = emailService;
}
public OrderResult processOrder(OrderRequest request) {
validateOrder(request);
OrderSummary summary = calculateOrderSummary(request);
paymentService.charge(request.getCardNumber(), summary.getTotal());
String receipt = generateReceipt(request, summary);
emailService.sendReceipt(request.getEmail(), receipt);
return new OrderResult(true, receipt);
}
private void validateOrder(OrderRequest request) {
if (request.getCustomerName() == null || request.getCustomerName().isEmpty()) {
throw new ValidationException("Хэрэглэгчийн нэр хоосон");
}
if (request.getEmail() == null || !request.getEmail().contains("@")) {
throw new ValidationException("Имэйл буруу");
}
if (request.getItems().isEmpty()) {
throw new ValidationException("Сагс хоосон");
}
if (request.getCardNumber() == null ||
request.getCardNumber().length() != CARD_NUMBER_LENGTH) {
throw new ValidationException("Картын дугаар буруу");
}
}
private OrderSummary calculateOrderSummary(OrderRequest request) {
double subtotal = calculateSubtotal(request.getItems());
double discount = calculateDiscount(subtotal, request.isVIP());
double taxableAmount = subtotal - discount;
double tax = taxableAmount * TAX_RATE;
double total = taxableAmount + tax;
return new OrderSummary(subtotal, discount, tax, total);
}
private double calculateSubtotal(List<OrderItem> items) {
return items.stream()
.mapToDouble(OrderItem::getPrice)
.sum();
}
private double calculateDiscount(double subtotal, boolean isVIP) {
if (isVIP) return subtotal * VIP_DISCOUNT_RATE;
if (subtotal > BULK_THRESHOLD) return subtotal * BULK_DISCOUNT_RATE;
return 0;
}
private String generateReceipt(OrderRequest request, OrderSummary summary) {
StringBuilder receipt = new StringBuilder();
receipt.append("=== БАРИМТ ===\n");
receipt.append("Хэрэглэгч: ").append(request.getCustomerName()).append("\n");
for (OrderItem item : request.getItems()) {
receipt.append(item.getName()).append(": ")
.append(String.format("%.0f₮", item.getPrice())).append("\n");
}
receipt.append(String.format("Хөнгөлөлт: -%.0f₮\n", summary.getDiscount()));
receipt.append(String.format("Татвар: +%.0f₮\n", summary.getTax()));
receipt.append(String.format("Нийт: %.0f₮\n", summary.getTotal()));
return receipt.toString();
}
}
Сайжруулсан зүйлс:
| # | Зарчим | Тайлбар |
|---|---|---|
| 1 | Нэг функц — Нэг зүйл | processOrder → validate, calculate, pay, receipt, email |
| 2 | Parameter Object | 6 параметр → OrderRequest объект |
| 3 | Magic Number арилгасан | 0.15, 0.05, 100000 → Тогтмол |
| 4 | Return code → Exception | "ERROR:" string → ValidationException |
| 5 | Dependency Injection | PaymentService, EmailService тусгаарлагдсан |
3.4 Лаб 3: Алдаа зохицуулалт сайжруулах
Даалгавар: Null шалгалт, Exception зохицуулалтыг Clean Code зарчмаар сайжруулах
ӨМНӨ (Муу алдаа зохицуулалт):
public class StudentService {
public String getStudentInfo(long id) {
try {
Student student = repository.findById(id);
if (student == null) {
return null;
}
String name = student.getName();
if (name == null) {
name = "Unknown";
}
Address addr = student.getAddress();
String city = "";
if (addr != null) {
city = addr.getCity();
if (city == null) {
city = "Unknown";
}
}
return name + " - " + city;
} catch (Exception e) {
System.out.println("error");
return null;
}
}
public int divide(int a, int b) {
return a / b; // ArithmeticException if b == 0
}
}
ДАРАА (Цэвэр алдаа зохицуулалт):
public class StudentService {
private static final Logger log = LoggerFactory.getLogger(StudentService.class);
public StudentInfo getStudentInfo(long id) {
Student student = findStudentOrThrow(id);
String name = student.getNameOrDefault("Нэргүй");
String city = extractCity(student).orElse("Хотгүй");
return new StudentInfo(name, city);
}
private Student findStudentOrThrow(long id) {
return repository.findById(id)
.orElseThrow(() -> {
log.warn("Оюутан олдсонгүй: id={}", id);
return new StudentNotFoundException("ID=" + id + " оюутан олдсонгүй");
});
}
private Optional<String> extractCity(Student student) {
return Optional.ofNullable(student.getAddress())
.map(Address::getCity);
}
public int divideSafe(int dividend, int divisor) {
if (divisor == 0) {
throw new IllegalArgumentException(
"Хуваагч 0 байж болохгүй. Хуваагдагч: " + dividend
);
}
return dividend / divisor;
}
}
Сайжруулсан зүйлс:
| # | Зарчим | Тайлбар |
|---|---|---|
| 1 | Optional ашиглах | null шалгалтыг Optional-оор солих |
| 2 | Тодорхой Exception | Exception → StudentNotFoundException |
| 3 | Logger ашиглах | System.out.println → Logger |
| 4 | Guard Clause | divideSafe() — оролтыг эрт шалгах |
| 5 | Утга учиртай мессеж | "error" → "ID=1 оюутан олдсонгүй" |
3.5 Лаб 4: Code Review дадлага
Даалгавар: Дараах кодыг Code Review хийж, асуудлуудыг олж, засварын санал бичих
Шалгах код:
public class u {
String n;
String e;
int a;
String p;
public boolean l(String un, String pw) {
if (un.equals(n) && pw.equals(p)) {
System.out.println("ok");
return true;
} else {
System.out.println("fail");
return false;
}
}
public void r(String n, String e, int a, String p) {
this.n = n;
this.e = e;
this.a = a;
this.p = p;
}
public String info() {
return n + "," + e + "," + a;
}
}
Code Review тайлбарууд:
| # | Мөр | Асуудал | Санал |
|---|---|---|---|
| 1 | class u | Муу нэрлэлт | class User — PascalCase, тодорхой нэр |
| 2 | String n, e, p | Нэргүй талбар | name, email, password |
| 3 | int a | Тодорхойгүй | int age |
| 4 | public талбарууд | Encapsulation зөрчил | private + getter/setter |
| 5 | l() метод | Муу нэр | login() |
| 6 | r() метод | Муу нэр | register() |
| 7 | pw.equals(p) | Нууц үг шифрлэлтгүй | Хэзээ ч plain text нууц үг хадгалахгүй |
| 8 | un.equals(n) | NullPointerException | Objects.equals() эсвэл null шалгах |
| 9 | System.out.println | Logger ашиглахгүй | log.info() ашиглах |
| 10 | Validation байхгүй | Оролт шалгаагүй | Email формат, нас зэрэг шалгах |
| 11 | info() муу нэр | Тодорхойгүй | getFormattedInfo() |
| 12 | "," hardcoded | Magic string | Тогтмол ашиглах |
Засварласан код:
public class User {
private String name;
private String email;
private int age;
private String passwordHash;
private static final Logger log = LoggerFactory.getLogger(User.class);
public boolean login(String inputName, String inputPassword) {
Objects.requireNonNull(inputName, "Нэр null байж болохгүй");
Objects.requireNonNull(inputPassword, "Нууц үг null байж болохгүй");
boolean isValid = inputName.equals(this.name)
&& PasswordEncoder.matches(inputPassword, this.passwordHash);
if (isValid) {
log.info("Амжилттай нэвтэрлэв: {}", inputName);
} else {
log.warn("Нэвтрэлт амжилтгүй: {}", inputName);
}
return isValid;
}
public void register(String name, String email, int age, String password) {
validateRegistration(name, email, age, password);
this.name = name;
this.email = email;
this.age = age;
this.passwordHash = PasswordEncoder.encode(password);
log.info("Шинэ хэрэглэгч бүртгэгдлээ: {}", name);
}
private void validateRegistration(String name, String email, int age, String password) {
if (name == null || name.isBlank()) {
throw new ValidationException("Нэр хоосон байж болохгүй");
}
if (email == null || !email.contains("@")) {
throw new ValidationException("Имэйл буруу формат");
}
if (age < 1 || age > 150) {
throw new ValidationException("Нас 1-150 хооронд байх ёстой");
}
if (password == null || password.length() < 8) {
throw new ValidationException("Нууц үг 8+ тэмдэгттэй байх ёстой");
}
}
public String getFormattedInfo() {
return String.format("%s (%s, %d нас)", name, email, age);
}
// Getter методууд
public String getName() { return name; }
public String getEmail() { return email; }
public int getAge() { return age; }
}
ХЭСЭГ 4: ШАЛГАЛТЫН АСУУЛТ (Knowledge Check — 100 тест)
Тест 1
"Цэвэр код" (Clean Code) гэж юу вэ?
- A) Хурдан ажилладаг код
- B) Бусад хөгжүүлэгч хялбараар уншиж, ойлгож, өөрчилж чаддаг код
- C) Тайлбар маш их бүхий код
- D) Нэг мөрөнд бичсэн код
Зөв хариулт: B
Тайлбар: Robert C. Martin-ий тодорхойлолтоор цэвэр код нь уншигдахуйц, ойлгомжтой, засварлахад хялбар байх ёстой. Зөвхөн хурдан биш — УНШИХАД хялбар.
Тест 2
Хөгжүүлэгч цагийнхаа хэдэн хувийг КОД УНШИХАД зарцуулдаг вэ?
- A) ~10%
- B) ~30%
- C) ~50%
- D) ~70%
Зөв хариулт: D
Тайлбар: Судалгаагаар хөгжүүлэгч цагийнхаа ~70%-ийг код уншихад, зөвхөн ~30%-ийг бичихэд зарцуулдаг. Тиймээс уншигдах чанар маш чухал.
Тест 3
DRY зарчим юу гэсэн утгатай вэ?
- A) Do Repeat Yourself
- B) Don't Repeat Yourself — Өөрийгөө бүү давт
- C) Delete Repeated YAML
- D) Debug Run Yesterday
Зөв хариулт: B
Тайлбар: DRY = Ижил логик нэг газар л байх. Давхардсан код → Нэг газар засвал, бусад газрыг мартана → Алдаа.
Тест 4
KISS зарчим юу гэсэн утгатай вэ?
- A) Keep It Safe and Secure
- B) Keep It Simple, Stupid — Энгийн байлга
- C) Know It, Solve it, Ship it
- D) Keep Iterating Software Solutions
Зөв хариулт: B
Тайлбар: KISS = Хамгийн энгийн шийдлийг сонгох. Нарийн төвөгтэй шийдэл ≠ Сайн шийдэл. Энгийн код = Ойлгомжтой + Алдаа бага.
Тест 5
YAGNI зарчим юу гэсэн утгатай вэ?
- A) You Are Getting New Ideas
- B) You Aren't Gonna Need It — Танд хэрэг болохгүй
- C) Your Application Gets New Interfaces
- D) Yet Another Great New Invention
Зөв хариулт: B
Тайлбар: YAGNI = Одоо хэрэггүй зүйлийг НЭМЭХГҮЙ. "Ирээдүйд хэрэг болно" гэж бодож шаардлагагүй функц нэмэх нь code bloat үүсгэнэ.
Тест 6
Дараах аль нь ЗӨӨВ нэрлэлт вэ?
- A)
int d; - B)
int daysSinceLastLogin; - C)
int x; - D)
int temp;
Зөв хариулт: B
Тайлбар:
daysSinceLastLoginнь юу хадгалж байгааг тодорхой хэлж байна.d,x,tempнь утга учирыг илэрхийлэхгүй.
Тест 7
Java-д класс нэрлэхэд ямар конвенци ашигладаг вэ?
- A) camelCase
- B) PascalCase
- C) UPPER_SNAKE_CASE
- D) kebab-case
Зөв хариулт: B
Тайлбар: Java класс = PascalCase (UpperCamelCase). Жишээ:
StudentService,OrderProcessor. Нэр үг ашиглана.
Тест 8
Java-д тогтмол (constant) нэрлэхэд ямар конвенци ашигладаг вэ?
- A) camelCase
- B) PascalCase
- C) UPPER_SNAKE_CASE
- D) lowercase
Зөв хариулт: C
Тайлбар: Java constant =
UPPER_SNAKE_CASE. Жишээ:MAX_RETRY_COUNT,DEFAULT_TIMEOUT.static finalхувьсагчид ашиглана.
Тест 9
Boolean хувьсагчийн зөв нэрлэлт аль нь вэ?
- A)
boolean flag; - B)
boolean isActive; - C)
boolean status; - D)
boolean value;
Зөв хариулт: B
Тайлбар: Boolean хувьсагч нь is/has/can + тэмдэг нэр:
isActive,hasPermission,canDelete.flag,statusнь тодорхойгүй.
Тест 10
"Magic Number" гэж юу вэ?
- A) Тоон хувьсагч
- B) Кодонд нэргүй шууд бичигдсэн тоон утга — юу гэсэн утга нь мэдэгдэхгүй
- C) Тогтмол хувьсагч
- D) Enum утга
Зөв хариулт: B
Тайлбар:
if (age >= 18)— 18 юу вэ? Magic number!if (age >= LEGAL_AGE)— тодорхой. Тогтмолоор солих ёстой.
Тест 11
Функцийн эхний дүрэм юу вэ (Robert C. Martin-ий зарчмаар)?
- A) Хурдан ажиллах
- B) ЖИЖИГ байх
- C) Олон параметртэй байх
- D) Тайлбар ихтэй байх
Зөв хариулт: B
Тайлбар: "Функцийн эхний дүрэм — ЖИЖИГ байх. Хоёр дахь дүрэм — БҮҮР ЖИЖИГ байх." Нэг функц нэг зүйл хийх.
Тест 12
Функцийн параметрийн хамгийн сайн тоо хэд вэ?
- A) 5
- B) 0 (niladic)
- C) 3
- D) 10
Зөв хариулт: B
Тайлбар: 0 параметр хамгийн сайн, 1-2 зүгээр, 3+ нь олон → Объект (Parameter Object) ашиглах.
Тест 13
"Side Effect" гэж юу вэ?
- A) Функцийн буцаах утга
- B) Функц нь нэрнээсээ гадуур нуугдмал зүйл хийх
- C) Функцийн параметр
- D) Exception шидэх
Зөв хариулт: B
Тайлбар:
checkPassword()функц доторSession.initialize()хийх = Side Effect. Нэрнээс мэдэгдэхгүй, нуугдмал зүйл. Тусдаа функц болгох ёстой.
Тест 14
Дараах аль тайлбар нь ЗӨӨВ вэ?
- A)
// i-г нэгээр нэмэх(i++ мөрний дээр) - B)
// Хувийн мэдээлэл хамгаалах хуулийн 15.3 заалтын дагуу - C)
// Default constructor - D)
// Хэрэглэгчийн нэрийг буцаана(getEmail() дээр)
Зөв хариулт: B
Тайлбар: Хуулийн шаардлага тайлбарлах = Сайн тайлбар. Код юу хийж байгааг давтах, хуучирсан тайлбар, шаардлагагүй тайлбар = Муу тайлбар.
Тест 15
"Код өөрөө тайлбарлагдах ёстой" (Self-Documenting Code) гэж юу гэсэн утгатай вэ?
- A) Тайлбар хэзээ ч бичэхгүй
- B) Нэрлэлт, бүтцээрээ тайлбаргүйгээр ойлгогддог код бичих
- C) Бүх мөрд тайлбар бичих
- D) README файл бичих
Зөв хариулт: B
Тайлбар: Сайн нэрлэлт + цэвэр бүтэц = тайлбар шаардлагагүй.
isEligibleForAccess(user)ньchk(u)-аас ХАВЬГҮЙ ойлгомжтой.
Тест 16
Нэг мөрийн урт хэдэн тэмдэгтээс хэтрэхгүй байх ёстой вэ?
- A) 50
- B) 80-120
- C) 200
- D) Хязгааргүй
Зөв хариулт: B
Тайлбар: Ихэнх стандарт 80-120 тэмдэгт зөвлөдөг. Хэт урт мөр = Хажуу тийш scroll хийх → Уншихад хэцүү.
Тест 17
Exception ашиглах нь return code (эрроор код)-аас яагаад дээр вэ?
- A) Хурдан
- B) Алдааны утга тодорхой, заавал зохицуулах, тусдаа flow
- C) Бичихэд богино
- D) Санах ой бага зарцуулна
Зөв хариулт: B
Тайлбар: Return code (
-1,-2) — юу гэсэн утга вэ? Exception = Тодорхой нэр (InsufficientFundsException), заавал зохицуулах, callstack мэдээлэл.
Тест 18
Checked Exception ба Unchecked Exception-ийн ялгаа юу вэ?
- A) Ялгаагүй
- B) Checked-ийг компайлер шалгаж, заавал барих шаарддаг. Unchecked нь Runtime-д гардаг
- C) Unchecked-ийг заавал барих
- D) Checked нь хурдан
Зөв хариулт: B
Тайлбар: Checked = IOException, заавал try-catch. Unchecked = NullPointerException, RuntimeException удамшил, барих заавал биш.
Тест 19
Optional юу хийдэг вэ?
- A) Код хурдасгадаг
- B) null-ийн оронд ашиглаж, NullPointerException-ийн эрсдэлийг бууруулдаг
- C) Exception шиддэг
- D) Тайлбар нэмдэг
Зөв хариулт: B
Тайлбар:
Optional<Student>= Утга байж ч, байхгүй ч болно..orElseThrow(),.ifPresent()зэргээр аюулгүй null шалгалт хийнэ.
Тест 20
God Class гэж юу вэ?
- A) Хамгийн сайн класс
- B) Бүхнийг мэддэг, бүхнийг хийдэг нэг том класс — SRP зөрчилдсөн
- C) Abstract класс
- D) Interface
Зөв хариулт: B
Тайлбар: God Class =
ApplicationManagerдотор user, payment, email, report, backup бүгдийг хийдэг. SRP зөрчил → Үүргээр хуваах ёстой.
Тест 21
SonarQube юу хийдэг вэ?
- A) Код бичих
- B) Кодын чанарын бүх талын статик анализ — bug, smell, coverage, давхардал шалгах
- C) Тест ажиллуулах
- D) Deploy хийх
Зөв хариулт: B
Тайлбар: SonarQube = Кодын чанарын платформ. Bug, Code Smell, Vulnerability, Coverage, Duplication зэргийг автоматаар шалгана. Dashboard-аар харуулна.
Тест 22
Code Review-ийн гол зорилго юу вэ?
- A) Зөвхөн алдаа олох
- B) Алдаа олох, мэдлэг хуваалцах, кодын чанар сайжруулах, нэгдмэл стиль
- C) Код устгах
- D) Зөвхөн формат шалгах
Зөв хариулт: B
Тайлбар: Code Review = Олон зорилготой: Алдаа + Мэдлэг хуваалцах + Чанар + Стиль. Баг бүхэлдээ суралцана.
Тест 23
"nit" гэж Code Review-д юу гэсэн утгатай вэ?
- A) Заавал засах ёстой алдаа
- B) Жижиг зүйл (nitpick) — заавал засах шаардлагагүй, зөвхөн санал
- C) Том алдаа
- D) Аюулгүй байдлын асуудал
Зөв хариулт: B
Тайлбар: "nit: studentName → enrolledStudentName гэвэл илүү тодорхой" — Жижиг санал, заавал биш. Reviewer нь ялгааг ойлгуулахад ашиглана.
Тест 24
"Boy Scout Rule" гэж юу вэ?
- A) Код бүгдийг устгах
- B) Кодыг олсноосоо илүү цэвэр орхих — жижиг сайжруулалт хий
- C) Код хэзээ ч өөрчлөхгүй
- D) Зөвхөн шинэ код бичих
Зөв хариулт: B
Тайлбар: Boy Scout Rule = "Хотыг олсноосоо цэвэрхэн орхи." Муу нэр олвол засах, magic number олвол тогтмол болгох. Жижиг, тогтмол сайжруулалт.
Тест 25
Дараах кодын асуудал юу вэ?
public void processOrder(Order order, boolean isExpress) {
if (isExpress) { /* шуурхай */ }
else { /* энгийн */ }
}
- A) Асуудалгүй
- B) Boolean параметр — функцыг 2 зүйл хийхэд хүргэж байна
- C) Нэрлэлт буруу
- D) Return утга байхгүй
Зөв хариулт: B
Тайлбар: Boolean параметр = Функц 2 зүйл хийж байна →
processStandardOrder(),processExpressOrder()гэж хуваах.
Тест 26
Дараах аль нь "Fail Fast" зарчим вэ?
- A) Алдааг нуух
- B) Оролтыг метод эхэнд шалгаж, буруу бол шууд Exception шидэх
- C) Алдааг дуусгалд л шалгах
- D) Алдааг үл тоомсорлох
Зөв хариулт: B
Тайлбар: Fail Fast = Guard Clause. Метод эхэнд
if (input == null) throw new ...→ Алдаа ЭРТ илэрнэ, дебаг хялбар.
Тест 27
Guard Clause гэж юу вэ?
- A) Try-catch блок
- B) Метод эхэнд буруу оролтыг шалгаж, эрт буцаах/Exception шидэх
- C) Finally блок
- D) Бүх мөрд null шалгах
Зөв хариулт: B
Тайлбар: Guard Clause = Метод эхэнд оролтыг шалгаж, буруу бол цааш явахгүй. Nested if бууруулна, код уншигдах чанар сайжирна.
Тест 28
Дараах кодын аль нь зөв вэ?
// A:
if (loginAttempts >= 5) { lockAccount(); }
// B:
if (loginAttempts >= MAX_LOGIN_ATTEMPTS) { lockAccount(); }
- A) A зөв
- B) B зөв — тогтмол ашигласан, magic number арилгасан
- C) Хоёулаа зөв
- D) Хоёулаа буруу
Зөв хариулт: B
Тайлбар:
5= Magic number (юу гэсэн утга вэ?).MAX_LOGIN_ATTEMPTS= Утга тодорхой, нэг газар солиход хангалттай.
Тест 29
Cyclomatic Complexity гэж юу вэ?
- A) Кодын мөрийн тоо
- B) Кодын нөхцөл салаалтын (if, switch, loop) нарийн байдлын хэмжигдэхүүн
- C) Кодын хурд
- D) Кодын хэмжээ
Зөв хариулт: B
Тайлбар: Cyclomatic Complexity = if, switch, for, while зэрэг нөхцөл бүр +1. Өндөр CC = Тестлэхэд хэцүү, алдаа ихтэй. 10-аас бага байх зөвлөмжтэй.
Тест 30
Статик анализ гэж юу вэ?
- A) Кодыг ажиллуулж тестлэх
- B) Кодыг АЖИЛЛУУЛАХГҮЙГЭЭР автоматаар шалгах
- C) Гараар код уншиж шалгах
- D) Deploy хийх
Зөв хариулт: B
Тайлбар: Статик анализ = Код ажиллуулахгүйгээр алдаа, code smell, аюулгүй байдлын сул талыг олно. SonarQube, PMD, CheckStyle зэрэг хэрэгсэл.
Тест 31
Дараах аль нь .gitignore-д БИЧИХГҮЙ?
- A)
.classфайлууд - B)
.idea/хавтас - C)
Student.java— Эх код - D)
.envфайл
Зөв хариулт: C
Тайлбар: Эх код (
.java) нь Git-д ЗААВАЛ байх ёстой..class(compiled),.idea/(IDE),.env(нууц) →.gitignore-д.
Тест 32
"Technical Debt" гэж юу вэ?
- A) Мөнгөний өр
- B) Богино хугацааны хялбар шийдэл → Ирээдүйд нэмэлт засвар, ажил шаардах
- C) Кодын хэмжээ
- D) Тестийн тоо
Зөв хариулт: B
Тайлбар: Technical Debt = "Одоо хурдан хийе, дараа засна" → "Дараа" хэзээ ч ирэхгүй → Код улам муудна. Тогтмол засах нь чухал.
Тест 33
CheckStyle хэрэгсэл юу шалгадаг вэ?
- A) Кодын хурд
- B) Кодын формат, стиль — нэрлэлтийн конвенци, мөрийн урт, braces зэрэг
- C) Кодын логик алдаа
- D) Кодын аюулгүй байдал
Зөв хариулт: B
Тайлбар: CheckStyle = Google/Sun Java Style Guide-д нийцэж байгаа эсэхийг шалгана: нэрлэлт, indentation, мөрийн урт, braces, import дараалал.
Тест 34
Дараах аль нь ЗӨӨВ алдааны мессеж вэ?
- A)
throw new RuntimeException("Error"); - B)
throw new RuntimeException("Invalid"); - C)
throw new StudentNotFoundException("ID=5 оюутан олдсонгүй"); - D)
throw new RuntimeException("");
Зөв хариулт: C
Тайлбар: Утга учиртай, тодорхой мессеж → Дебаг хялбар. "Error", "Invalid" → Юуны алдаа, хаана, яагаад мэдэхгүй.
Тест 35
"Defensive Programming" гэж юу вэ?
- A) Зөвхөн тест бичих
- B) Алдаа гарч болзошгүй бүх тохиолдлыг урьдчилж шалгах, хамгаалах
- C) Код нуух
- D) Зөвхөн try-catch ашиглах
Зөв хариулт: B
Тайлбар: Defensive Programming = Оролтыг шалгах, null шалгах, хязгаар шалгах — "Юу ч буруу байж болно" гэж бодож код бичих. Бат бөх код.
Тест 36
Дараах кодын хамгийн том асуудал юу вэ?
public void handle() { ... }
public Object get() { ... }
public boolean check(Student s) { ... }
- A) Асуудалгүй
- B) Метод нэрс тодорхойгүй — юу хийдэг нь мэдэгдэхгүй
- C) Return утга буруу
- D) Параметр олон
Зөв хариулт: B
Тайлбар:
handle()юу handle хийх вэ?get()юу авах вэ?check()юу шалгах вэ? →handlePaymentTimeout(),findStudentById(),isEligibleForScholarship().
Тест 37
Нэг файлд хэдэн мөр код байх нь тохиромжтой вэ?
- A) 10-50
- B) 200-500
- C) 1000-5000
- D) Хязгааргүй
Зөв хариулт: B
Тайлбар: Нэг файлд 200-500 мөр тохиромжтой. Хэт богино = Хэт олон файл. Хэт урт = God Class шинж. Clean Code = Тохиромжтой хэмжээ.
Тест 38
Дараах кодын асуудал юу вэ?
if (isActive)
doSomething();
- A) Асуудалгүй
- B) Braces ({}) байхгүй — ирээдүйд мөр нэмэхэд алдаа гарч болно
- C) Нэрлэлт буруу
- D) Return утга байхгүй
Зөв хариулт: B
Тайлбар: Braces-гүй бол дараа нь мөр нэмэхэд if-ийн гадна бичигдэж, logical алдаа гарна. ЯМАГТ
{ }ашиглах.
Тест 39
Кодын чанарын пирамидын хамгийн доод (суурь) давхарга юу вэ?
- A) Тест
- B) UI чанар
- C) Цэвэр код зарчмууд
- D) Статик анализ
Зөв хариулт: C
Тайлбар: Суурь → Дээш: Цэвэр код → Стандарт → Статик анализ → Code Review → Тест → UI. Суурь бат бол дээрх давхаргууд сайн.
Тест 40
PMD хэрэгсэл юу хийдэг вэ?
- A) Код форматлах
- B) Кодын загварын алдаа, шаардлагагүй код, нарийн байдлын асуудал олох
- C) Тест ажиллуулах
- D) Deploy хийх
Зөв хариулт: B
Тайлбар: PMD = Java кодын статик анализ. Unused variable, empty catch, unnecessary code зэргийг олно. Кодын чанарын "эрт анхааруулга".
Тест 41
SpotBugs хэрэгсэл юу хийдэг вэ?
- A) Формат шалгах
- B) Java байткод анализаар нийтлэг bug загвар олох
- C) Тест бичих
- D) Код компайлдах
Зөв хариулт: B
Тайлбар: SpotBugs (FindBugs-ийн залгамжлагч) = Compiled байткодыг шалгаж, null dereference, infinite loop, resource leak зэрэг нийтлэг bug олно.
Тест 42
Code Coverage 80% гэдэг юу гэсэн утгатай вэ?
- A) 80% функц бичигдсэн
- B) Тестүүд кодын 80%-ийг ажиллуулж шалгасан
- C) 80% алдаа олдсон
- D) 80% хөгжүүлэгч тест бичсэн
Зөв хариулт: B
Тайлбар: Code Coverage = Тестүүд кодын ямар хувийг "ажиллуулж" шалгасан. 80%+ нь ерөнхий зөвлөмж. 100% нь бодит бус зорилт.
Тест 43
"Pair Programming" гэж юу вэ?
- A) Хоёр хөгжүүлэгч тус тусдаа ажиллах
- B) Хоёр хөгжүүлэгч нэг компьютер дээр хамтран код бичих — нэг нь бичих, нөгөө нь шалгах
- C) Хоёр тест бичих
- D) Хоёр branch ашиглах
Зөв хариулт: B
Тайлбар: Pair Programming = Driver (бичих) + Navigator (шалгах, чиглүүлэх). Алдаа бага, мэдлэг хуваалцах, кодын чанар сайн.
Тест 44
"Rubber Duck Debugging" гэж юу вэ?
- A) Нугас хэлбэрийн хэрэгсэл ашиглах
- B) Асуудлыг бусдад (эсвэл нугасанд) тайлбарлахад шийдэл олдох
- C) Кодыг устгах
- D) Тест ажиллуулах
Зөв хариулт: B
Тайлбар: Асуудлыг тайлбарлах явцад тархи зөв бодол дагуулж, шийдлийг ӨӨРӨӨ олдог. Бусад хүнд (эсвэл нугасанд) тайлбарлах = Маш үр дүнтэй дебаг арга.
Тест 45
Дараах аль нь encapsulation зөрчил вэ?
- A)
private String name; - B)
public String name;(getter/setter-гүй шууд хандалт) - C)
protected String name; - D) Бүгд зөрчил
Зөв хариулт: B
Тайлбар:
publicталбар = Гаднаас шууд хандаж, өөрчилж болно → Хяналтгүй.private+ getter/setter = Encapsulation. Validation нэмэх боломжтой.
Тест 46
Дараах кодын асуудал юу вэ?
catch (Exception e) {
// do nothing
}
- A) Асуудалгүй
- B) Алдааг "залгидаг" — асуудал нуугдаж, дебаг хэцүүдэнэ
- C) Хурдан ажилладаг
- D) Зөв арга
Зөв хариулт: B
Тайлбар: Хоосон catch = Алдааг "залгих" → Асуудал нуугдана, хожим арай том асуудал болж гарна. НААД зах нь log бичих, эсвэл дахин шидэх.
Тест 47
Дараах аль нь Parameter Object загвар вэ?
- A)
void create(String a, String b, int c, String d, double e) - B)
void create(StudentDTO dto)— олон параметрийг нэг объектод нэгтгэх - C)
void create() - D)
void create(int id)
Зөв хариулт: B
Тайлбар: 3+ параметр → Parameter Object (DTO) ашиглах.
StudentDTOдотор бүх талбар → Код уншигдах чанар сайжирна, хялбар өргөтгөнө.
Тест 48
Дараах аль нь SonarQube-ийн "Code Smell" шинж вэ?
- A) Compile error
- B) Хэт урт метод, давхардсан код, хэт нарийн нөхцөл
- C) Runtime error
- D) Syntax error
Зөв хариулт: B
Тайлбар: Code Smell = Compile/Runtime error биш, гэхдээ чанарын асуудал. Хэт урт метод, давхардал, magic number, God class зэрэг. "Үнэртэй" код.
Тест 49
Objects.requireNonNull(param, "message") юу хийдэг вэ?
- A) Объект үүсгэх
- B) param null бол NullPointerException шидэх — тодорхой мессежтэй
- C) Файл нээх
- D) Тест ажиллуулах
Зөв хариулт: B
Тайлбар:
Objects.requireNonNull()= null шалгалтын стандарт арга.nullбол мессежтэй NullPointerException шидэнэ. Guard clause-ийн нэг хэлбэр.
Тест 50
Дараах аль нь Dependency Injection (DI) зарчим вэ?
- A)
new PaymentService()метод дотор үүсгэх - B)
PaymentService-ийг constructor-оор дамжуулах - C) Static метод ашиглах
- D) Global хувьсагч ашиглах
Зөв хариулт: B
Тайлбар: DI = Хамааралтай объектыг ГАДНААС дамжуулах (constructor injection).
newхийхгүй → Тестлэхэд хялбар, mock ашиглаж болно.
Тест 51
Дараах кодын гол асуудал юу вэ?
String url = "http://localhost:8080/api";
Thread.sleep(5000);
- A) Асуудалгүй
- B) Hardcoded утгууд — тогтмол/тохиргоо ашиглах ёстой
- C) Нэрлэлт буруу
- D) Exception байхгүй
Зөв хариулт: B
Тайлбар: URL, timeout зэрэг = Тохиргоо (configuration). Hardcode хийвэл орчин бүрт солих хэрэгтэй. Тогтмол, property файл,
@Valueашиглах.
Тест 52
"Readability" ба "Performance" хоорондоо зөрчилдвөл ямар шийдвэр гаргах вэ?
- A) Үргэлж Performance
- B) ИХЭНХ тохиолдолд Readability-г сонгож, performance асуудал БАТАЛГААЖСАН үед оновчлох
- C) Үргэлж Readability
- D) Хоёуланг нь үл тоомсорлох
Зөв хариулт: B
Тайлбар: "Premature optimization is the root of all evil" (Knuth). Эхлээд уншигдахуйц, зөв код бич → Profiler-аар bottleneck олж, ЗӨвхөн тэндээ optimize хий.
Тест 53
Дараах if-else бүтцийг юугаар солих вэ?
if (type.equals("A")) return 10;
else if (type.equals("B")) return 20;
else if (type.equals("C")) return 30;
- A) Солихгүй
- B) Enum, Map, эсвэл Strategy Pattern ашиглах
- C) Switch ашиглах
- D) Бүгдийг устгах
Зөв хариулт: B
Тайлбар: Гинжин if-else = Open/Closed зөрчил. Enum + Map эсвэл Strategy Pattern → Шинэ төрөл нэмэхэд if-else нэмэхгүй.
Тест 54
Import дарааллын зөв дүрэм аль нь вэ?
- A) Дарааллаар биш
- B) java.* → javax.* → third-party → project — бүлэглэж, хоосон мөрөөр тусгаарлах
- C) Бүгдийг
*wildcard ашиглах - D) Нэг мөрд бүгдийг бичих
Зөв хариулт: B
Тайлбар: Import бүлэглэх + хоосон мөрөөр тусгаарлах = Уншигдах чанар. Wildcard
*зайлсхий → Тодорхой класс import хийх.
Тест 55
"Single Responsibility Principle" (SRP) гэж юу вэ?
- A) Нэг файлд нэг класс
- B) Нэг класс/метод зөвхөн нэг үүрэг хариуцах, нэг шалтгаанаар л өөрчлөгдөх
- C) Нэг хувьсагч нэг утга
- D) Нэг тест нэг assert
Зөв хариулт: B
Тайлбар: SRP = "Нэг класс зөвхөн НЭГ шалтгаанаар өөрчлөгдөх ёстой."
UserServiceнь зөвхөн user-тай холбоотой логик → Email, Payment тусдаа.
Тест 56
Лог (logging) бичихэд System.out.println ашиглах нь яагаад БУРУУ вэ?
- A) Зөв, ашиглаж болно
- B) Лог түвшин (level) байхгүй, файлд бичихгүй, формат байхгүй
- C) Хурдан
- D) Автомат
Зөв хариулт: B
Тайлбар:
System.out.println= Лог түвшин (DEBUG, INFO, WARN, ERROR) байхгүй, файлд бичихгүй, production-д удирдах боломжгүй. → SLF4J/Logback ашиглах.
Тест 57
Дараах кодын аль нь илүү сайн вэ?
// A:
List<Student> result = new ArrayList<>();
for (Student s : students) {
if (s.getGpa() >= 3.5) result.add(s);
}
// B:
List<Student> result = students.stream()
.filter(s -> s.getGpa() >= 3.5)
.collect(Collectors.toList());
- A) A илүү сайн
- B) B илүү сайн — Stream API нь зорилгоо илүү тодорхой илэрхийлж байна
- C) Хоёулаа ижил
- D) Хоёулаа буруу
Зөв хариулт: B
Тайлбар: Stream API = Declarative (юу хийхийг хэлэх), for loop = Imperative (яаж хийхийг хэлэх). Stream нь зорилгыг илүү тодорхой, товч илэрхийлнэ.
Тест 58
String.format() ашиглах нь string concatenation (+)-аас яагаад дээр вэ?
- A) Хурдан
- B) Уншигдах чанар сайн, формат тодорхой, олон хэлний дэмжлэг
- C) Ялгаагүй
- D) Compile error гарахгүй
Зөв хариулт: B
Тайлбар:
String.format("Нэр: %s, Нас: %d", name, age)vs"Нэр: " + name + ", Нас: " + age. Format = Илүү уншигдахуйц, ялангуяа олон хувьсагчтай.
Тест 59
Enum ашиглах нь String тогтмолоос яагаад дээр вэ?
- A) Ялгаагүй
- B) Type-safe, IDE autocomplete, бүх боломжит утгыг нэг дор, typo алдаа compile-д баригдана
- C) Бичихэд богино
- D) Хурдан
Зөв хариулт: B
Тайлбар:
String role = "admim"→ Typo, runtime-д алдаа.Role.ADMIN→ Compile-д шалгагдана, autocomplete, бүх утгыг switch-ээр handle хийж болно.
Тест 60
Дараах аль нь "code smell" БИШ вэ?
- A) God Class
- B) Magic Number
- C) Утга учиртай нэрлэлт бүхий жижиг метод
- D) Гинжин if-else
Зөв хариулт: C
Тайлбар: Утга учиртай нэрлэлт + жижиг метод = Clean Code зарчим. God Class, Magic Number, гинжин if-else = Code smell (кодын чанарын асуудал).
Тест 61
SonarQube-д "Vulnerability" гэж юу вэ?
- A) Кодын стиль асуудал
- B) Аюулгүй байдлын сул тал — SQL injection, XSS зэрэг эрсдэл
- C) Кодын формат
- D) Тестийн хамралт
Зөв хариулт: B
Тайлбар: Vulnerability = Аюулгүй байдлын асуудал. SQL injection, XSS, hardcoded password, insecure random зэрэг. Хакер ашиглаж болох сул тал.
Тест 62
Дараах кодын гол асуудал юу вэ?
// public void oldMethod() {
// // хуучин логик
// // маш олон мөр
// }
- A) Асуудалгүй
- B) Comment-оор хаасан хуучин код — Git түүхэнд хадгалагдана, устгах ёстой
- C) Сайн арга
- D) Нөөц код
Зөв хариулт: B
Тайлбар: Comment-оор хаасан код = "Код оршуулга". Git-ийн түүхэнд хуучин код хадгалагдана → Шаардлагагүй, устгах. Boy Scout Rule.
Тест 63
Тогтмолд (constant) ямар утга хадгалах ЗӨӨВ вэ?
- A) Бүх зүйл
- B) Олон газар давтагддаг, бизнес утга бүхий тоо/string
- C) Хувьсагч бүрийг тогтмол болгох
- D) Зөвхөн тоо
Зөв хариулт: B
Тайлбар:
MAX_LOGIN_ATTEMPTS = 5,TAX_RATE = 0.1,ADMIN_ROLE = "admin"— Олон газар давтагддаг + утга учиртай.0,1,""зэрэг ерөнхий утгыг заавал тогтмол болгохгүй.
Тест 64
"Premature Optimization" гэж юу вэ?
- A) Зөв оновчлол
- B) Performance асуудал БАТАЛГААЖААГҮЙ байхад хэт эрт, шаардлагагүй оновчлол хийх
- C) Тест хийх
- D) Code review
Зөв хариулт: B
Тайлбар: "Premature optimization is the root of all evil" — Donald Knuth. Эхлээд зөв, цэвэр код бич → Profiler-аар bottleneck ол → ЗӨВХӨН тэндээ optimize хий.
Тест 65
Дараах аль нь нэрлэлтийн "Хуурмаг мэдээлэл" (Disinformation) вэ?
- A)
List<Account> accountList;— БодитоорListбайвал зөв - B)
List<Account> accountList;— БодитоорSetбайвал ХУУРМАГ - C)
int age; - D)
String name;
Зөв хариулт: B
Тайлбар:
accountListгэж нэрлээдSetтөрөл бол = Хуурмаг мэдээлэл. УншигчListгэж бодно → Алдаа.accountsгэж нэрлэх нь зөв.
Тест 66
Файл нэрлэхэд аль зарчим зөв вэ?
- A)
file1.java,file2.java - B) Нэг файлд нэг public class, файлын нэр = классын нэр
- C) Бүгд
Main.java - D) Дугаарлах
Зөв хариулт: B
Тайлбар: Java стандарт: Нэг файл = Нэг public class.
StudentService.javaфайлдpublic class StudentService. Олж хайхад хялбар.
Тест 67
Кодын "Complexity vs Readability" харьцааг хэрхэн шийдвэрлэх вэ?
- A) Үргэлж readability
- B) Эхлээд уншигдахуйц бич, зөвхөн БАТАЛГААЖСАН шаардлагаар complexity нэм
- C) Үргэлж complexity
- D) Хоёуланг нь үл тоомсорлох
Зөв хариулт: B
Тайлбар: Уншигдах чанар = Анхдагч зорилт. Performance/complexity зөвхөн profiler-аар баталгаажсан bottleneck-д → Тайлбартай optimize хийх.
Тест 68
try-with-resources юу хийдэг вэ?
- A) Тест ажиллуулах
- B) AutoCloseable нөөцийг (file, connection) автоматаар хаах — resource leak-ээс хамгаалах
- C) Exception шидэх
- D) Loop ажиллуулах
Зөв хариулт: B
Тайлбар:
try (var reader = new FileReader(file)) { ... }— try блок дуусахад автоматаарclose()дуудна. Finally-д гараар хаах шаардлагагүй.
Тест 69
Дараах аль нь null буцаахын оронд ашиглах ЗӨӨВ арга вэ?
- A) null буцаах
- B) Optional, хоосон collection, эсвэл Exception шидэх
- C) -1 буцаах
- D) "" (хоосон string) буцаах
Зөв хариулт: B
Тайлбар: null буцаавал дуудсан газар NullPointerException гарч болно. Optional = Утга байж ч болно, байхгүй ч болно. Хоосон List = null-аас аюулгүй. Exception = Тодорхой алдаа.
Тест 70
Дараах кодын аль нь илүү сайн вэ?
// A: return a > b ? a : b;
// B: return Math.max(a, b);
- A) A
- B) B — Стандарт сангийн метод ашиглах нь илүү ойлгомжтой
- C) Хоёулаа ижил
- D) Хоёулаа буруу
Зөв хариулт: B
Тайлбар:
Math.max()= Зорилго тодорхой, бэлэн тестлэгдсэн, бусад хөгжүүлэгч шууд ойлгоно. "Дугуйг дахин зохиохгүй" зарчим.
Тест 71
Accessor метод (getter/setter) хэзээ шаардлагагүй вэ?
- A) Хэзээ ч шаардлагатай
- B) Дотоод (private) хэрэглээнд зориулсан immutable объектод setter шаардлагагүй
- C) Бүх тохиолдолд шаардлагагүй
- D) Public класст
Зөв хариулт: B
Тайлбар: Immutable объект = Үүсгэсний дараа өөрчлөгдөхгүй → setter шаардлагагүй. DTO, Value Object зэрэгт getter-ийг л хадгалж болно.
Тест 72
Builder Pattern хэзээ ашиглах вэ?
- A) Нэг параметртэй үед
- B) Олон параметр бүхий объект үүсгэхэд — constructor параметр олон болохоос сэргийлж
- C) Хэзээ ч ашиглахгүй
- D) Зөвхөн тест бичихэд
Зөв хариулт: B
Тайлбар:
Student.builder().name("Бат").age(20).gpa(3.5).build()— Уншигдахуйц, параметр олон ч тодорхой. Telescope constructor-ийн оронд.
Тест 73
"Law of Demeter" (LoD) гэж юу вэ?
- A) Хурд тооцоолох дүрэм
- B) Объект зөвхөн шууд хамааралтай объекттой харилцах — гинжин дуудалт хийхгүй
- C) Нэрлэлтийн дүрэм
- D) Тестийн дүрэм
Зөв хариулт: B
Тайлбар: LoD = "Зөвхөн найзтайгаа ярь, найзын найзтай ярихгүй."
a.getB().getC().doSomething()= Зөрчил.a.doSomethingViaB()= Зөв.
Тест 74
Дараах аль нь "Early Return" загвар вэ?
// A:
if (input != null) {
if (input.isValid()) {
// logic (олон мөр)
}
}
// B:
if (input == null) return;
if (!input.isValid()) return;
// logic (олон мөр)
- A) A
- B) B — Буруу нөхцлийг эрт шалгаж буцаах → nested if бууруулна
- C) Хоёулаа ижил
- D) Хоёулаа буруу
Зөв хариулт: B
Тайлбар: Early Return = Guard Clause. Буруу нөхцлийг эрт шалгаж буцаах → Nested if (arrow code) бууруулж, гол логикийг тодорхой харуулна.
Тест 75
Immutable объект (өөрчлөгдөшгүй) ямар давуу талтай вэ?
- A) Давуу талгүй
- B) Thread-safe, side effect-гүй, debug хялбар, cache-д тохиромжтой
- C) Зөвхөн хурдан
- D) Зөвхөн жижиг
Зөв хариулт: B
Тайлбар: Immutable = Үүсгэсний дараа утга өөрчлөгдөхгүй → Thread-safe (lock шаардлагагүй), side effect-гүй, debug хялбар.
String,LocalDate= Immutable.
Тест 76
Дараах аль нь equals() override хийхэд ЗААВАЛ хийх зүйл вэ?
- A)
toString()override - B)
hashCode()ЗААВАЛ override — equals/hashCode гэрээ - C)
clone()override - D)
compareTo()override
Зөв хариулт: B
Тайлбар: Java гэрээ:
equals()override хийвэлhashCode()ЗААВАЛ override. Хийхгүй бол HashMap, HashSet зэрэгт буруу ажиллана.
Тест 77
Дараах аль нь "Liskov Substitution Principle" (LSP) зөрчил вэ?
- A) ArrayList-ийг List-ийн оронд ашиглах
- B) Square класс Rectangle-аас удамшиж, setWidth хийхэд height ч өөрчлөгдөх
- C) Interface implement хийх
- D) Abstract class extend хийх
Зөв хариулт: B
Тайлбар: LSP = Удамшсан класс нь эцэг классын оронд ямар ч тохиолдолд ажиллах ёстой. Square.setWidth() нь Rectangle-ийн "width-ийг л өөрчлөх" гэрээг зөрчиж байна.
Тест 78
Code Review-д хэдэн мөр өөрчлөлт шалгахад ХАМГИЙН ҮР ДҮНТЭЙ вэ?
- A) 1000+ мөр
- B) 200-400 мөр
- C) 1-10 мөр
- D) 5000+ мөр
Зөв хариулт: B
Тайлбар: 200-400 мөр = Reviewer анхаарлаа хадгалж чадна. 1000+ мөр = "Бүгд зүгээр харагдаж байна" → Алдаа алдагдана. Жижиг PR = Чанартай review.
Тест 79
"Composition over Inheritance" зарчим юу гэсэн утгатай вэ?
- A) Удамшил ашиглахгүй
- B) Удамшлын оронд объектуудын нийлмэл бүтэц (composition) ашиглахыг зөвлөх
- C) Зөвхөн interface ашиглах
- D) Зөвхөн abstract class ашиглах
Зөв хариулт: B
Тайлбар: Удамшил = Хатуу холбоос, нэг эцгийн өөрчлөлт бүх хүүхдэд нөлөөлнө. Composition =
has-aхарилцаа, уян хатан, солих хялбар.is-aбат итгэлтэй бол л удамшил.
Тест 80
var keyword (Java 10+) хэзээ ашиглах нь зөв вэ?
- A) Хэзээ ч ашиглахгүй
- B) Баруун талд төрөл тодорхой байх үед —
var list = new ArrayList<String>(); - C) Бүх газар ашиглах
- D) Зөвхөн тест бичихэд
Зөв хариулт: B
Тайлбар:
var= Баруун талд төрөл тодорхой бол уншигдах чанарт сайн.var result = service.findById(id)— result юу вэ мэдэгдэхгүй болStudent result = ...илүү тодорхой.
Тест 81
"Cognitive Complexity" гэж юу вэ?
- A) Кодын мөрийн тоо
- B) Хүний тархинд кодыг ойлгоход хэр хүнд байдгийн хэмжигдэхүүн
- C) Кодын хурд
- D) Тестийн тоо
Зөв хариулт: B
Тайлбар: Cognitive Complexity = SonarQube-ийн хэмжигдэхүүн. Cyclomatic-аас ялгаатай нь: nested if, break/continue зэрэг "ойлгоход хэцүү" бүтцэд илүү өндөр оноо.
Тест 82
Дараах аль нь "Interface Segregation Principle" (ISP) зөрчил вэ?
- A) Жижиг, тодорхой interface
- B) Нэг том interface-д олон холбоогүй метод — зарим класс хэрэггүй метод implement хийх шаардлагатай
- C) Олон жижиг interface
- D) Abstract class
Зөв хариулт: B
Тайлбар: ISP = "Хэрэглэгч өөрт хэрэггүй interface-д хамаарах ёсгүй." Том interface-ийг жижиг, тодорхой interface болгон хуваах.
Тест 83
"Semantic Versioning" (v1.2.3) дахь MINOR дугаар хэзээ нэмэгдэх вэ?
- A) Алдаа засахад
- B) Шинэ функц нэмэхэд (хуучинтай нийцтэй)
- C) Breaking change хийхэд
- D) Код refactor хийхэд
Зөв хариулт: B
Тайлбар: MAJOR = Breaking change. MINOR = Шинэ функц (backward compatible). PATCH = Алдаа засвар. v1.2.3 → v1.3.0 = Шинэ функц нэмэгдсэн.
Тест 84
Lombok сангийн @Data annotation юу хийдэг вэ?
- A) Мэдээллийн сан үүсгэх
- B) Getter, Setter, toString, equals, hashCode автоматаар үүсгэх — boilerplate бууруулах
- C) Тест ажиллуулах
- D) Файл нээх
Зөв хариулт: B
Тайлбар:
@Data= Getter + Setter + toString + equals + hashCode. Boilerplate код бууруулна. Compile-д автоматаар үүсгэнэ. Код товч, цэвэр.
Тест 85
Дараах аль нь "Open/Closed Principle" (OCP) зарчим вэ?
- A) Код хаалттай байх
- B) Өргөтгөхөд НЭЭЛТТЭЙ, засварлахад ХААЛТТАЙ — шинэ функц нэмэхдээ байгаа кодыг өөрчлөхгүй
- C) Файл нээх, хаах
- D) Зөвхөн public метод
Зөв хариулт: B
Тайлбар: OCP = Шинэ функц нэмэхдээ interface/abstract class + шинэ implementation. Байгаа if-else-д шинэ нөхцөл нэмэхгүй → Strategy, Factory pattern.
Тест 86
Дараах аль нь "Тест хялбар бичиж болох" кодын шинж вэ?
- A) Static метод олонтой
- B) Constructor Injection, жижиг метод, нэг үүрэг
- C) Global хувьсагч олонтой
- D) God Class
Зөв хариулт: B
Тайлбар: Тестлэхэд хялбар код = DI (mock ашиглаж болно) + жижиг метод (тусдаа тестлэж болно) + SRP. Static, global, God Class = Тестлэхэд хэцүү.
Тест 87
"Dead Code" гэж юу вэ?
- A) Runtime error
- B) Хэзээ ч ажиллахгүй, хүрч чадахгүй код — устгах ёстой
- C) Production код
- D) Тест код
Зөв хариулт: B
Тайлбар: Dead Code = Хэзээ ч дуудагдахгүй метод, хүрч чадахгүй if branch, unused import/variable. IDE анхааруулдаг → Устгах. Код цэвэрхэн.
Тест 88
final keyword хувьсагч дээр ашиглахын давуу тал юу вэ?
- A) Давуу талгүй
- B) Утга дахин оноогдохгүй гэдгийг баталгаажуулж, кодын зорилгыг тодорхой болгох
- C) Хурдасгах
- D) Санах ой хэмнэх
Зөв хариулт: B
Тайлбар:
final String name = "Бат"— Энэ утга ХЭЗЭЭ Ч өөрчлөгдөхгүй. Код уншигчид тодорхой мэдээлэл → Итгэлтэй бодох. Immutability-ийн нэг хэсэг.
Тест 89
Дараах аль нь "Cohesion" (нягтралт) өндөр классын шинж вэ?
- A) Олон холбоогүй метод
- B) Классын бүх метод ижил зорилгод чиглэсэн, талбаруудыг хамтдаа ашигладаг
- C) Static метод олонтой
- D) 1000+ мөр
Зөв хариулт: B
Тайлбар: Өндөр Cohesion = Классын бүх гишүүд нэг зорилгод чиглэсэн.
StudentService-ийн бүх метод оюутантай холбоотой. Бага Cohesion = God Class.
Тест 90
"Coupling" (холбоос) бага байх нь яагаад сайн вэ?
- A) Ялгаагүй
- B) Нэг класс өөрчлөхөд бусад класст нөлөөлөхгүй, тестлэхэд хялбар, дахин ашиглахуйц
- C) Зөвхөн хурдан
- D) Зөвхөн жижиг
Зөв хариулт: B
Тайлбар: Бага Coupling = Классууд бие биенээсээ бага хамааралтай → Нэгийг өөрчлөхөд нөгөө нь эвдэрэхгүй. Interface + DI = Coupling бууруулах.
Тест 91
Дараах аль нь switch expression (Java 14+) ашиглалт вэ?
// A: switch (day) { case MONDAY: return "Даваа"; ... }
// B: String name = switch (day) { case MONDAY -> "Даваа"; ... };
- A) A
- B) B — Arrow syntax, утга буцааж хувьсагчид оноох
- C) Хоёулаа ижил
- D) Хоёулаа буруу
Зөв хариулт: B
Тайлбар: Java 14+ switch expression =
->arrow syntax, break шаардлагагүй, утга буцааж хувьсагчид оноох боломжтой. Товч, аюулгүй (exhaustive шалгалт).
Тест 92
"Principle of Least Astonishment" гэж юу вэ?
- A) Код аль болох нарийн байх
- B) Код уншигчийг ГАЙХШРУУЛАХГҮЙ — нэрнээсээ ойлгогддог, хүлээгдсэн зүйлийг хийх
- C) Код хурдан байх
- D) Код жижиг байх
Зөв хариулт: B
Тайлбар:
checkPassword()дотор session эхлүүлбэл = Гайхшруулна (Side Effect). Функц нэрнээс хүлээгдсэн зүйлийг л хийх. Гайхшруулалгүй = Аюулгүй.
Тест 93
Record (Java 16+) юу хийдэг вэ?
- A) Файл бичих
- B) Immutable data класс автоматаар үүсгэх — constructor, getter, equals, hashCode, toString
- C) Тест бичих
- D) Exception шидэх
Зөв хариулт: B
Тайлбар:
record Student(String name, int age) {}— Автоматаар constructor, getter, equals, hashCode, toString үүсгэнэ. DTO, Value Object-д тохиромжтой.
Тест 94
Дараах аль нь sealed class (Java 17+) ашиглалт вэ?
- A) Бүх классыг хязгаарлах
- B) Зөвхөн зөвшөөрөгдсөн классууд л удамших боломжтой — domain model-д хяналт
- C) Файл хааах
- D) Thread хааах
Зөв хариулт: B
Тайлбар:
sealed class Shape permits Circle, Rectangle, Triangle {}— Зөвхөн эдгээр 3 класс л удамших боломжтой. Pattern matching-д маш тохиромжтой.
Тест 95
Дараах аль нь logging-ийн ЗӨӨВ түвшин вэ?
- A) Бүгд ERROR
- B) DEBUG → хөгжүүлэлтийн дэлгэрэнгүй, INFO → ерөнхий, WARN → анхааруулга, ERROR → алдаа
- C) Бүгд INFO
- D) Бүгд DEBUG
Зөв хариулт: B
Тайлбар: DEBUG = Хөгжүүлэлтийн дэлгэрэнгүй (production-д унтраах). INFO = Ерөнхий мэдээлэл. WARN = Анхааруулга. ERROR = Алдаа. Зөв түвшин = Зөв мэдээлэл.
Тест 96
"Extract Method" refactoring юу хийдэг вэ?
- A) Метод устгах
- B) Кодын хэсгийг тусдаа метод болгон салгах — уншигдах чанар, дахин ашиглалт сайжруулах
- C) Файл нэмэх
- D) Тест бичих
Зөв хариулт: B
Тайлбар: Том метод дотроос логик бүлгийг тусдаа метод болгон салгах → Утга учиртай нэр → Код уншигдахуйц, дахин ашиглахуйц.
Тест 97
Дараах аль нь "Temporal Coupling" (цаг хугацааны холбоос) вэ?
- A) Хурд хэмжих
- B) Методуудыг тодорхой дарааллаар дуудах ШААРДЛАГА — init() дуудахгүйгээр process() ажиллахгүй
- C) Threading
- D) Timeout
Зөв хариулт: B
Тайлбар:
init()→process()→cleanup()дарааллаар дуудах шаардлагатай = Temporal Coupling. Нэг метод болгох эсвэл Template Method Pattern ашиглах.
Тест 98
"Separation of Concerns" (SoC) зарчим юу вэ?
- A) Бүгдийг нэг газар бичих
- B) Өөр өөр үүрэг/зорилгыг тусдаа модуль/давхаргад хуваах
- C) Зөвхөн тест бичих
- D) Зөвхөн нэг хэл ашиглах
Зөв хариулт: B
Тайлбар: SoC = Controller (хүсэлт удирдах) ≠ Service (бизнес логик) ≠ Repository (мэдээллийн сан). Тус тусын үүрэг → Засвар хялбар, тест хялбар.
Тест 99
Дараах аль нь "Testability" сайн кодын шинж БИШ вэ?
- A) Constructor Injection
- B) Жижиг метод
- C) Нэг метод дотор
newkeyword олонтой ашиглах - D) Interface ашиглах
Зөв хариулт: C
Тайлбар:
newkeyword олонтой = Тестлэхэд mock-оор солиж чадахгүй. DI (Constructor Injection) + Interface = Mock хялбар → Тестлэхэд хялбар.
Тест 100
Кодын чанар яагаад програм хангамжийн бүтээлтэд хамгийн чухал зүйлсийн нэг вэ?
- A) Зөвхөн мэргэжлийн шаардлага
- B) Уншигдахуйц, засварлахуйц, найдвартай код = Бүтээмж өндөр, алдаа бага, баг хамтран ажиллаж чадна, техникийн өр бага
- C) Зөвхөн code review-д хэрэгтэй
- D) Зөвхөн том компаниудад
Зөв хариулт: B
Тайлбар: Кодын чанар = Бүтээлтийн суурь. Цэвэр код → Уншихад хялбар (70% цагийг хэмнэнэ) → Засварлахад хурдан → Алдаа бага → Баг хамтран ажиллана → Техникийн өр бага → Бүтээмж ӨНДӨР.
📚 Ашигласан эх сурвалжууд:
- Robert C. Martin — Clean Code: A Handbook of Agile Software Craftsmanship (2008)
- Robert C. Martin — The Clean Coder (2011)
- Martin Fowler — Refactoring: Improving the Design of Existing Code (2nd Edition, 2018)
- Joshua Bloch — Effective Java (3rd Edition, 2018)
- Google Java Style Guide — google.github.io/styleguide/javaguide.html
- SonarQube Documentation — docs.sonarqube.org
- Oracle Java Code Conventions
- IEEE SWEBOK — Software Quality