Принципи чистого коду для XOOPS
Чистий код – це код, який легко читати, розуміти та підтримувати. Цей посібник охоплює принципи чистого коду, які спеціально застосовуються до розробки модулів XOOPS.
Основні принципи
Section titled “Основні принципи”mindmap root((Clean Code)) Readability Meaningful Names Small Functions Comments When Needed Simplicity Single Responsibility DRY Principle KISS Principle Maintainability Consistent Style Error Handling TestingЗначущі імена
Section titled “Значущі імена”Змінні
Section titled “Змінні”// Bad$d = new DateTime();$u = $memberHandler->getUser($id);$arr = [];
// Good$createdDate = new DateTime();$currentUser = $memberHandler->getUser($userId);$publishedArticles = [];Функції
Section titled “Функції”// Badfunction process($data) { ... }function handle($item) { ... }function doStuff($x, $y) { ... }
// Goodfunction publishArticle(Article $article): void { ... }function calculateTotalPrice(array $items): float { ... }function sendNotificationEmail(User $user, string $subject): bool { ... }// Badclass Manager { ... }class Helper { ... }class Utils { ... }
// Goodclass ArticleRepository { ... }class NotificationService { ... }class PermissionChecker { ... }Невеликі функції
Section titled “Невеликі функції”Єдина відповідальність
Section titled “Єдина відповідальність”// Bad - does too many thingsfunction processArticle($data) { // Validate if (empty($data['title'])) { throw new Exception('Title required'); } // Save $article = new Article(); $article->setTitle($data['title']); $this->repository->save($article); // Notify $this->mailer->send($article->getAuthor(), 'Article published'); // Log $this->logger->info('Article created'); return $article;}
// Good - each function does one thingfunction validateArticleData(array $data): void{ if (empty($data['title'])) { throw new ValidationException('Title required'); }}
function createArticle(array $data): Article{ $this->validateArticleData($data); return Article::create($data['title'], $data['content']);}
function publishArticle(Article $article): void{ $this->repository->save($article); $this->notifyAuthor($article); $this->logArticleCreation($article);}Довжина функції
Section titled “Довжина функції”Зберігайте функції короткими - в ідеалі менше 20 рядків:
// Good - focused functionpublic function getPublishedArticles(int $limit = 10): array{ $criteria = new CriteriaCompo(); $criteria->add(new Criteria('status', 'published')); $criteria->setSort('published_at'); $criteria->setOrder('DESC'); $criteria->setLimit($limit);
return $this->repository->getObjects($criteria);}Сухий принцип (не повторюйтеся)
Section titled “Сухий принцип (не повторюйтеся)”Видобути загальний код
Section titled “Видобути загальний код”// Bad - repeated codefunction getActiveUsers() { $criteria = new CriteriaCompo(); $criteria->add(new Criteria('level', 0, '>')); $criteria->setSort('uname'); return $this->userHandler->getObjects($criteria);}
function getActiveAdmins() { $criteria = new CriteriaCompo(); $criteria->add(new Criteria('level', 0, '>')); $criteria->add(new Criteria('is_admin', 1)); $criteria->setSort('uname'); return $this->userHandler->getObjects($criteria);}
// Good - shared logic extractedfunction getUsers(CriteriaCompo $criteria): array{ $criteria->add(new Criteria('level', 0, '>')); $criteria->setSort('uname'); return $this->userHandler->getObjects($criteria);}
function getActiveUsers(): array{ return $this->getUsers(new CriteriaCompo());}
function getActiveAdmins(): array{ $criteria = new CriteriaCompo(); $criteria->add(new Criteria('is_admin', 1)); return $this->getUsers($criteria);}Обробка помилок
Section titled “Обробка помилок”Правильно використовуйте винятки
Section titled “Правильно використовуйте винятки”// Bad - generic exceptionsthrow new Exception('Error');
// Good - specific exceptionsthrow new ArticleNotFoundException($articleId);throw new PermissionDeniedException('Cannot edit article');throw new ValidationException(['title' => 'Title is required']);Витончено виправляйте помилки
Section titled “Витончено виправляйте помилки”public function findArticle(string $id): ?Article{ try { return $this->repository->findById($id); } catch (DatabaseException $e) { $this->logger->error('Database error finding article', [ 'id' => $id, 'error' => $e->getMessage() ]); throw new ServiceException('Unable to retrieve article', 0, $e); }}Коментарі
Section titled “Коментарі”Коли коментувати
Section titled “Коли коментувати”// Bad - obvious comment// Increment counter$counter++;
// Good - explains why, not what// Cache for 1 hour to reduce database load during peak traffic$cache->set($key, $data, 3600);
// Good - documents complex algorithm/** * Calculate article relevance score using TF-IDF algorithm. * Higher scores indicate better match with search terms. */function calculateRelevanceScore(Article $article, array $terms): float{ // ...}Організація коду
Section titled “Організація коду”Структура класу
Section titled “Структура класу”class ArticleService{ // 1. Constants private const MAX_TITLE_LENGTH = 255;
// 2. Properties private ArticleRepository $repository; private EventDispatcher $events;
// 3. Constructor public function __construct( ArticleRepository $repository, EventDispatcher $events ) { $this->repository = $repository; $this->events = $events; }
// 4. Public methods public function publish(Article $article): void { ... } public function archive(Article $article): void { ... }
// 5. Private methods private function validateForPublication(Article $article): void { ... }}Контрольний список чистого коду
Section titled “Контрольний список чистого коду”- Імена значні та вимовні
- Функції виконують лише одну дію
- Функції малі (< 20 рядків)
- Немає дубльованого коду
- Правильна обробка помилок із певними винятками
- Коментарі пояснюють “чому”, а не “що”
- Послідовне форматування та стиль
- Жодних магічних чисел чи рядків
- Залежності впроваджуються, а не створюються
Пов’язана документація
Section titled “Пов’язана документація”- Організація коду
- Обробка помилок
- Тестування найкращих практик
- Стандарти PHP