Przejdź do głównej zawartości

Niestandardowe reguły i szablony: standaryzacja doskonałości zespołu

Niestandardowe reguły i szablony: standaryzacja doskonałości zespołu

Dział zatytułowany „Niestandardowe reguły i szablony: standaryzacja doskonałości zespołu”

Niestandardowe reguły i szablony w Cursor przekształcają pomoc AI z ogólnej pomocy w precyzyjne narzędzie dostosowane do konkretnych potrzeb twojego zespołu. Zapewniają spójność, egzekwują standardy i przechwytują wiedzę instytucjonalną.

Reguły to instrukcje, które kształtują zachowanie AI Cursor w twoim projekcie. Mogą:

  • Egzekwować standardy kodowania specyficzne dla twojego zespołu
  • Przechwytywać wiedzę domenową o twojej logice biznesowej
  • Zapobiegać częstym błędom poprzez kodowanie wyciągniętych wniosków
  • Przyspieszać rozwój dzięki wzorcom specyficznym dla projektu

Cursor stosuje reguły w określonej kolejności:

graph TD A[Reguły globalne
~/.cursor/rules] --> B[Reguły workspace
.cursor/rules/] B --> C[Reguły projektu
projectname.rules] C --> D[Reguły inline
@rules w czacie] style A fill:#f9f,stroke:#333,stroke-width:2px style B fill:#bbf,stroke:#333,stroke-width:2px style C fill:#bfb,stroke:#333,stroke-width:2px style D fill:#fbf,stroke:#333,stroke-width:2px
  • Folder.cursor/ - rules/ - README.md - architecture.md - coding-standards.md - security.md - performance.md - testing.md - domain/ - authentication.md - payments.md - user-management.md - technology/ - react-patterns.md - nodejs-backend.md - database-queries.md
# [Kategoria reguły]: [Konkretny temat]
## Kontekst
Krótki opis kiedy i dlaczego ta reguła ma zastosowanie.
## Wymagania
- Konkretne wymaganie 1
- Konkretne wymaganie 2
- Konkretne wymaganie 3
## Przykłady
### Dobry przykład
```language
// Kod zgodny z regułą
```
// Kod naruszający regułę

Wyjaśnienie dlaczego ta reguła istnieje i jej korzyści.

Przypadki, w których ta reguła może nie mieć zastosowania.

### Przykłady reguł z prawdziwego świata
<Tabs>
<TabItem label="Reguły architektury">
```markdown
# Architektura: wzorzec warstwy serwisu
## Kontekst
Cała logika biznesowa musi być zaimplementowana w klasach serwisu, nie w kontrolerach lub modelach.
## Wymagania
- Kontrolery obsługują tylko kwestie HTTP (żądanie/odpowiedź)
- Serwisy zawierają całą logikę biznesową
- Serwisy są bezstanowe i testowalne
- Serwisy wstrzykują zależności przez konstruktor
- Jeden serwis na encję domenową
## Przykłady
### Dobry przykład
```typescript
// UserController.ts
export class UserController {
constructor(private userService: UserService) {}
async createUser(req: Request, res: Response) {
const userData = req.body;
const user = await this.userService.create(userData);
res.json(user);
}
}
// UserService.ts
export class UserService {
constructor(
private userRepo: UserRepository,
private emailService: EmailService
) {}
async create(data: CreateUserDto): Promise<User> {
// Logika biznesowa tutaj
const user = await this.userRepo.save(data);
await this.emailService.sendWelcome(user);
return user;
}
}
```
### Zły przykład
```typescript
// UserController.ts - ŹLE: logika biznesowa w kontrolerze
export class UserController {
async createUser(req: Request, res: Response) {
const user = new User(req.body);
// Logika biznesowa nie powinna być tutaj!
if (await this.checkDuplicateEmail(user.email)) {
throw new Error('Email istnieje');
}
await db.users.insert(user);
await sendEmail(user.email, 'Witamy!');
res.json(user);
}
}
```
## Uzasadnienie
- Separacja zagadnień
- Łatwiejsze testowanie (mockowanie serwisów)
- Wielokrotnego użytku logika biznesowa
- Jasne granice między warstwami
```
</TabItem>
<TabItem label="Reguły bezpieczeństwa">
```markdown
# Bezpieczeństwo: walidacja wejścia
## Kontekst
Wszystkie dane wejściowe użytkownika muszą być zwalidowane przed przetworzeniem.
## Wymagania
- Używaj biblioteki walidacji (Joi, Yup, Zod)
- Waliduj na poziomie kontrolera
- Sanityzuj ciągi znaków, aby zapobiec XSS
- Używaj sparametryzowanych zapytań dla SQL
- Nigdy nie ufaj tylko walidacji po stronie klienta
## Przykłady
### Dobry przykład
```typescript
import { z } from 'zod';
const CreateUserSchema = z.object({
email: z.string().email(),
password: z.string().min(8).regex(/[A-Z]/).regex(/[0-9]/),
name: z.string().min(2).max(100).transform(sanitizeHtml),
age: z.number().int().min(18).max(120)
});
async createUser(req: Request, res: Response) {
try {
const validated = CreateUserSchema.parse(req.body);
const user = await this.userService.create(validated);
res.json(user);
} catch (error) {
if (error instanceof z.ZodError) {
res.status(400).json({ errors: error.errors });
}
}
}
```
### Zły przykład
```typescript
// ŹLE: brak walidacji
async createUser(req: Request, res: Response) {
const user = await this.userService.create(req.body);
res.json(user);
}
// ŹLE: luka SQL injection
const query = `SELECT * FROM users WHERE email = '${email}'`;
```
## Wyjątki
- Wewnętrzne wywołania serwis-do-serwisu mogą pomijać walidację
- Ale zawsze waliduj na granicach systemu
```
</TabItem>
<TabItem label="Reguły wydajności">
```markdown
# Wydajność: optymalizacja zapytań bazy danych
## Kontekst
Optymalizuj wszystkie zapytania do bazy danych pod kątem wydajności.
## Wymagania
- Zawsze używaj indeksów dla klauzul WHERE
- Paginuj wyniki ponad 100 rekordów
- Używaj SELECT z konkretnymi kolumnami, nie SELECT *
- Grupuj operacje, gdy to możliwe
- Monitoruj wolne zapytania
## Przykłady
### Dobry przykład
```typescript
// Zoptymalizowane zapytanie z użyciem indeksu
async findActiveUsers(page: number, limit: number = 50) {
return this.db.users
.select(['id', 'name', 'email', 'lastActive'])
.where('status', 'active')
.where('lastActive', '>', thirtyDaysAgo)
.orderBy('lastActive', 'desc')
.limit(limit)
.offset(page * limit);
}
// Operacja wsadowa
async updateMultipleUsers(updates: UserUpdate[]) {
const chunks = chunk(updates, 1000);
for (const batch of chunks) {
await this.db.transaction(async (trx) => {
await Promise.all(
batch.map(update =>
trx.users.update(update.id, update.data)
)
);
});
}
}
```
### Zły przykład
```typescript
// ŹLE: brak paginacji, SELECT *
async getAllUsers() {
return this.db.query('SELECT * FROM users');
}
// ŹLE: problem zapytania N+1
const users = await getUsers();
for (const user of users) {
user.posts = await getPosts(user.id);
}
```
```
</TabItem>
</Tabs>
## Zaawansowane wzorce reguł
### Dynamiczne reguły z kontekstem
```markdown
# Reguła dynamiczna: format odpowiedzi API
## Kontekst
Odpowiedzi API muszą följować nasz standardowy format, który różni się w zależności od środowiska.
## Implementacja
```typescript
interface ApiResponse<T> {
success: boolean;
data?: T;
error?: {
code: string;
message: string;
details?: any;
};
metadata: {
timestamp: string;
version: string;
environment: 'dev' | 'staging' | 'prod';
};
}
// W środowisku rozwoju, uwzględnij informacje debugowania
if (process.env.NODE_ENV === 'development') {
response.metadata.debug = {
query: req.query,
headers: req.headers,
processingTime: Date.now() - startTime
};
}

Podczas generowania punktów końcowych API:

  1. Zawsze używaj wrappera ApiResponse
  2. Uwzględnij odpowiednie kody błędów
  3. Dodaj informacje debugowania tylko w rozwoju
  4. Loguj wszystkie błędy z ID korelacji
### Reguły specyficzne dla technologii
<Tabs>
<TabItem label="Reguły React">
```markdown
# React: wzorce komponentów
## Tylko komponenty funkcyjne
Używaj komponentów funkcyjnych z hookami. Żadnych komponentów klasowych.
## Struktura komponentu
```tsx
// 1. Importy
import React, { useState, useEffect } from 'react';
import { useUser } from '@/hooks/useUser';
import { Button } from '@/components/ui/Button';
import type { UserProps } from '@/types';
// 2. Typy
interface ComponentProps {
userId: string;
onUpdate?: (user: User) => void;
}
// 3. Komponent
export function UserProfile({ userId, onUpdate }: ComponentProps) {
// 4. Hooki
const { user, loading, error } = useUser(userId);
const [isEditing, setIsEditing] = useState(false);
// 5. Efekty
useEffect(() => {
// Logika efektu
}, [userId]);
// 6. Handlery
const handleEdit = () => {
setIsEditing(true);
};
// 7. Render
if (loading) return <Spinner />;
if (error) return <ErrorDisplay error={error} />;
return (
<div>
{/* JSX */}
</div>
);
}
```
## Zarządzanie stanem
- Używaj React Query dla stanu serwera
- Używaj Zustand dla stanu klienta
- Unikaj prop drilling - używaj kontekstu oszczędnie
```
</TabItem>
<TabItem label="Reguły Node.js">
```markdown
# Node.js: wzorce backendu
## Obsługa błędów
```typescript
// Niestandardowe klasy błędów
export class AppError extends Error {
constructor(
public statusCode: number,
public message: string,
public code: string
) {
super(message);
}
}
// Globalny handler błędów
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
if (err instanceof AppError) {
return res.status(err.statusCode).json({
success: false,
error: {
code: err.code,
message: err.message
}
});
}
// Loguj nieoczekiwane błędy
logger.error('Nieoczekiwany błąd:', err);
res.status(500).json({
success: false,
error: {
code: 'INTERNAL_ERROR',
message: 'Wystąpił nieoczekiwany błąd'
}
});
});
```
## Wzorzec handler async
```typescript
const asyncHandler = (fn: Function) => (
req: Request,
res: Response,
next: NextFunction
) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
// Użycie
router.post('/users', asyncHandler(async (req, res) => {
const user = await userService.create(req.body);
res.json(user);
}));
```
```
</TabItem>
</Tabs>
## System szablonów
### Tworzenie szablonów wielokrotnego użytku
```markdown
# Szablon: nowy mikroserwis
Podczas tworzenia nowego mikroserwisu, wygeneruj następującą strukturę:
## Struktura katalogów

service-name/ ├── src/ │ ├── api/ │ │ ├── controllers/ │ │ ├── middlewares/ │ │ └── routes/ │ ├── core/ │ │ ├── domain/ │ │ ├── services/ │ │ └── repositories/ │ ├── infrastructure/ │ │ ├── database/ │ │ ├── cache/ │ │ └── messaging/ │ └── index.ts ├── tests/ │ ├── unit/ │ ├── integration/ │ └── e2e/ ├── .env.example ├── Dockerfile ├── docker-compose.yml └── package.json

## Podstawowe pliki do wygenerowania
1. **package.json** z naszymi standardowymi zależnościami
2. **tsconfig.json** z naszymi ustawieniami TypeScript
3. **Dockerfile** z wieloetapowym buildem
4. **.env.example** z wymaganymi zmiennymi
5. **src/index.ts** z kontrolą zdrowia i graceful shutdown
6. Podstawowe przykłady kontrolera, serwisu i repozytorium
7. Standardowe middleware (auth, logowanie, obsługa błędów)
8. Konfiguracja testów z przykładami
// Skrypt generatora szablonów
class TemplateGenerator {
async generateFromTemplate(templateName: string, variables: Record<string, any>) {
const template = await this.loadTemplate(templateName);
// Przetwórz szablon ze zmiennymi
const processed = this.processTemplate(template, variables);
// Wygeneruj pliki
for (const file of processed.files) {
await this.createFile(file.path, file.content);
}
// Uruchom hooki post-generacji
await this.runHooks(processed.hooks);
}
private processTemplate(template: string, vars: Record<string, any>): ProcessedTemplate {
// Zastąp zmienne jak {{serviceName}}
let content = template;
for (const [key, value] of Object.entries(vars)) {
const regex = new RegExp(`{{${key}}}`, 'g');
content = content.replace(regex, value);
}
// Obsłuż warunki
content = this.processConditionals(content, vars);
// Obsłuż pętle
content = this.processLoops(content, vars);
return this.parseToFiles(content);
}
}
  1. Ustanów własność reguł

    • Przypisz opiekunów dla każdej kategorii reguł
    • Stwórz proces przeglądu zmian reguł
    • Wersjonuj wszystkie reguły
  2. Dokumentacja reguł

    # Metadane reguły
    - **Autor**: @teamlead
    - **Utworzone**: 2024-01-15
    - **Zmodyfikowane**: 2024-03-20
    - **Wersja**: 2.1
    - **Recenzenci**: @senior-dev, @architect
    - **Dotknięte zespoły**: Backend, Frontend
  3. Testowanie reguł

    // Testuj, że wygenerowany kod przestrzega reguł
    describe('Zgodność reguł architektury', () => {
    test('Sprawdź, czy serwisy postępują zgodnie ze wzorcem dependency injection', () => {
    // Stwórz plik testowego promptu
    const testPrompt = `
    Stwórz UserService zgodnie z tymi regułami:
    - Użyj dependency injection w konstruktorze
    - Wstrzyknij Repository jako zależność
    - Nie twórz instancji zależności z 'new'
    - Postępuj zgodnie z naszymi wzorcami architektury z @Cursor Rules
    `;
    // Otwórz w Cursor i ręcznie zweryfikuj wygenerowany kod
    // Użyj trybu Agent (Ctrl+I) z powyższym promptem
    // Następnie uruchom ten test na wygenerowanym pliku:
    const generatedCode = fs.readFileSync('src/services/UserService.ts', 'utf8');
    expect(generatedCode).toMatch(/constructor\s*\(/);
    expect(generatedCode).toMatch(/private.*Repository/);
    expect(generatedCode).not.toMatch(/new.*Repository/);
    });
    });
  4. Dystrybucja reguł

    • Synchronizuj reguły między repozytoriami
    • Uwzględnij w dokumentacji wdrożenia
    • Regularne sesje szkoleniowe zespołu
// Śledź zgodność z regułami
class RuleComplianceTracker {
async analyzeCodebase() {
const violations = [];
// Sprawdź każdą regułę
for (const rule of this.rules) {
const ruleViolations = await this.checkRule(rule);
violations.push(...ruleViolations);
}
// Wygeneruj raport
return {
totalFiles: this.fileCount,
violations: violations,
complianceRate: this.calculateCompliance(violations),
byRule: this.groupByRule(violations),
byTeam: this.groupByTeam(violations),
};
}
}

Bądź konkretny

Niejasne reguły prowadzą do niespójnego kodu. Uwzględnij konkretne przykłady.

Wyjaśnij dlaczego

Zawsze uwzględnij uzasadnienie. Deweloperzy przestrzegają reguł, które rozumieją.

Pokaż przykłady

Dobre i złe przykłady czynią reguły krystalicznie jasnymi.

Aktualizuj regularnie

Przeglądaj reguły kwartalnie. Usuwaj przestarzałe, dodawaj nowe wnioski.

  1. Nadmierne ograniczanie

    ❌ Źle: "Nigdy nie używaj pętli forEach"
    ✅ Dobrze: "Preferuj map/filter/reduce do transformacji. Używaj forEach tylko do efektów ubocznych."
  2. Sprzeczne reguły

    ❌ Źle: Posiadanie zarówno "Zawsze używaj async/await" i "Używaj callbacków dla wydajności"
    ✅ Dobrze: Jasne wytyczne kiedy używać każdego podejścia
  3. Uzależnienie od technologii

    ❌ Źle: "Zawsze używaj biblioteki X do wszystkiego"
    ✅ Dobrze: "Używaj biblioteki X do przypadku użycia Y z powodu Z"

Cursor może generować reguły z twoich sesji rozwoju:

/generate-rules
Cursor przeanalizuje tę konwersację i stworzy reguły na podstawie:
- Wzorców, które ustanowiłeś
- Poprawek, które wprowadziłeś
- Preferencji, które wyraziłeś
- Standardów, które egzekwowałeś
# Wygenerowana reguła: obsługa błędów API
Na podstawie konwersacji z 2024-03-20
## Wykryty wzorzec
Konsekwentnie poprawiasz punkty końcowe API, aby:
1. Używać bloków try-catch
2. Zwracać standardowe odpowiedzi błędów
3. Logować błędy z kontekstem
4. Używać odpowiednich kodów statusu HTTP
## Zalecana reguła
Wszystkie punkty końcowe API muszą implementować obsługę błędów, która:
- Przechwytuje wszystkie możliwe błędy
- Zwraca instancje AppError
- Loguje z ID korelacji
- Nigdy nie ujawnia wewnętrznych błędów klientom
## Szablon kodu
[Wygenerowany szablon na podstawie twoich poprawek]
.github/workflows/rule-compliance.yml
name: Kontrola zgodności reguł
on: [push, pull_request]
jobs:
check-rules:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Uruchom kontrolę reguł Cursor
run: |
npx @company/cursor-rule-checker \
--rules .cursor/rules \
--source src \
--report compliance-report.json
- name: Komentarz PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v6
with:
script: |
const report = require('./compliance-report.json');
const comment = generateComplianceComment(report);
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});

Opanuj niestandardowe reguły i szablony:

  1. Audytuj obecne wzorce - Zidentyfikuj powtarzalne wzorce w swojej bazie kodu
  2. Stwórz pierwszy zestaw reguł - Zacznij od 5-10 podstawowych reguł
  3. Przetestuj z zespołem - Uzyskaj opinie i iteruj
  4. Rozwijaj stopniowo - Dodawaj reguły w miarę pojawiania się wzorców

Reguły i szablony to żywe dokumenty. Powinny ewoluować wraz z nauką twojego zespołu i rozwojem projektu. Opanuj to, a będziesz miał asystę AI, która naprawdę rozumie twoje konkretne potrzeby.