readme
This commit is contained in:
410
CONTRIBUTING.md
Normal file
410
CONTRIBUTING.md
Normal file
@@ -0,0 +1,410 @@
|
||||
# 🤝 Руководство для участников
|
||||
|
||||
Спасибо за интерес к проекту YandexMusic! Этот документ содержит рекомендации для тех, кто хочет внести свой вклад в развитие проекта.
|
||||
|
||||
## 📋 Содержание
|
||||
|
||||
- [Кодекс поведения](#кодекс-поведения)
|
||||
- [Как начать](#как-начать)
|
||||
- [Процесс разработки](#процесс-разработки)
|
||||
- [Стандарты кода](#стандарты-кода)
|
||||
- [Commit сообщения](#commit-сообщения)
|
||||
- [Pull Requests](#pull-requests)
|
||||
- [Отчёты об ошибках](#отчёты-об-ошибках)
|
||||
- [Предложения по улучшениям](#предложения-по-улучшениям)
|
||||
|
||||
## 🤐 Кодекс поведения
|
||||
|
||||
- Будьте уважительны к другим участникам
|
||||
- Не допускайте дискриминацию, оскорбления и враждебного поведения
|
||||
- Критикуйте идеи, а не людей
|
||||
- Решайте конфликты конструктивно
|
||||
|
||||
## 🚀 Как начать
|
||||
|
||||
### 1. Подготовка окружения
|
||||
|
||||
```bash
|
||||
# Клонируем репозиторий
|
||||
git clone https://git.frigat.duckdns.org/FrigaT/YandexMusic.git
|
||||
cd YandexMusic
|
||||
|
||||
# Создаём ветку для своей работы
|
||||
git checkout -b feature/my-feature
|
||||
|
||||
# Восстанавливаем зависимости
|
||||
dotnet restore
|
||||
|
||||
# Собираем проект
|
||||
dotnet build
|
||||
```
|
||||
|
||||
### 2. Установка инструментов
|
||||
|
||||
- **Visual Studio 2026 Enterprise** (рекомендуется)
|
||||
- **Visual Studio Code** + C# extension (альтернатива)
|
||||
- **.NET 10 SDK**
|
||||
|
||||
### 3. Запуск тестов
|
||||
|
||||
```bash
|
||||
dotnet test
|
||||
```
|
||||
|
||||
## 🔄 Процесс разработки
|
||||
|
||||
### Workflow
|
||||
|
||||
```
|
||||
1. Выберите issue или создайте новый
|
||||
2. Создайте feature-ветку
|
||||
3. Внесите изменения
|
||||
4. Напишите/обновите тесты
|
||||
5. Убедитесь что код собирается и тесты проходят
|
||||
6. Создайте Pull Request
|
||||
7. Ждите review
|
||||
8. Исправьте замечания если нужно
|
||||
9. Merge в master
|
||||
```
|
||||
|
||||
### Версионирование веток
|
||||
|
||||
```
|
||||
master → Production версия
|
||||
├── feature/* → Новые функции
|
||||
├── bugfix/* → Исправления ошибок
|
||||
├── refactor/* → Рефакторинг кода
|
||||
└── docs/* → Обновления документации
|
||||
```
|
||||
|
||||
## 📐 Стандарты кода
|
||||
|
||||
### Общие правила
|
||||
|
||||
- **Язык:** C# 12
|
||||
- **Платформа:** .NET 10
|
||||
- **Стиль:** Microsoft C# Coding Conventions
|
||||
- **Документация:** Все публичные члены должны иметь XML документацию на русском
|
||||
|
||||
### Пример документированного кода
|
||||
|
||||
```csharp
|
||||
namespace YandexMusic.API.API;
|
||||
|
||||
/// <summary>API для работы с альбомами.</summary>
|
||||
public class YAlbumAPI : YCommonAPI
|
||||
{
|
||||
/// <summary>Инициализирует новый экземпляр.</summary>
|
||||
/// <param name="yandex">Экземпляр основного API.</param>
|
||||
public YAlbumAPI(YandexMusicApi yandex) : base(yandex) { }
|
||||
|
||||
/// <summary>Получает информацию об альбоме по идентификатору.</summary>
|
||||
/// <param name="albumId">Идентификатор альбома</param>
|
||||
/// <returns>Модель альбома или null если не найден</returns>
|
||||
/// <exception cref="ArgumentNullException">Если albumId null</exception>
|
||||
public async Task<YAlbum?> GetAlbumAsync(string albumId)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(albumId);
|
||||
|
||||
// Реализация
|
||||
return await Task.FromResult<YAlbum?>(null);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Правила именования
|
||||
|
||||
```csharp
|
||||
// Классы: PascalCase
|
||||
public class YandexMusicApi { }
|
||||
|
||||
// Методы: PascalCase с Async суффиксом для асинхронных
|
||||
public async Task<YTrack?> GetTrackAsync(string trackId) { }
|
||||
|
||||
// Свойства: PascalCase
|
||||
public YandexMusicApi Api { get; }
|
||||
|
||||
// Приватные поля: _camelCase
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
// Параметры: camelCase
|
||||
public void DoSomething(string userName, int userId) { }
|
||||
|
||||
// Локальные переменные: camelCase
|
||||
var trackList = new List<YTrack>();
|
||||
```
|
||||
|
||||
### Code Style
|
||||
|
||||
Используйте `.editorconfig` для автоматического форматирования:
|
||||
|
||||
```ini
|
||||
# Отступы - 4 пробела
|
||||
indent_size = 4
|
||||
|
||||
# Новая строка для фигурных скобок
|
||||
csharp_new_line_before_open_brace = all
|
||||
|
||||
# Используйте var где возможно
|
||||
csharp_style_var_for_built_in_types = true
|
||||
|
||||
# Null-forgiving operator с осторожностью
|
||||
csharp_style_null_forgiving_operator = false
|
||||
```
|
||||
|
||||
### Nullable Reference Types
|
||||
|
||||
Всегда включен `<Nullable>enable</Nullable>`. Правила:
|
||||
|
||||
```csharp
|
||||
// ✅ Хорошо - явно указано может быть null
|
||||
public string? GetUserName() { }
|
||||
|
||||
// ✅ Хорошо - явно не null
|
||||
public string GetTitle() => "Title";
|
||||
|
||||
// ❌ Плохо - неявная nullable ссылка
|
||||
public object GetSomething() { }
|
||||
|
||||
// ✅ Хорошо - используйте null-coalescing
|
||||
var result = value ?? defaultValue;
|
||||
|
||||
// ✅ Хорошо - используйте null-conditional
|
||||
var count = list?.Count ?? 0;
|
||||
```
|
||||
|
||||
### Асинхронное программирование
|
||||
|
||||
```csharp
|
||||
// ✅ Хорошо - async/await
|
||||
public async Task<YTrack?> GetTrackAsync(string id)
|
||||
{
|
||||
return await api.Track.GetTrackAsync(id);
|
||||
}
|
||||
|
||||
// ❌ Плохо - Task.Result блокирует поток
|
||||
public YTrack? GetTrack(string id)
|
||||
{
|
||||
return api.Track.GetTrackAsync(id).Result;
|
||||
}
|
||||
|
||||
// ✅ Хорошо - ConfigureAwait(false) в библиотеках
|
||||
public async Task<YTrack?> GetTrackAsync(string id)
|
||||
{
|
||||
return await api.Track.GetTrackAsync(id).ConfigureAwait(false);
|
||||
}
|
||||
```
|
||||
|
||||
### Обработка ошибок
|
||||
|
||||
```csharp
|
||||
// ✅ Хорошо
|
||||
public async Task<YTrack?> GetTrackAsync(string trackId)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(trackId);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(trackId);
|
||||
|
||||
try
|
||||
{
|
||||
return await _provider.GetTrackAsync(trackId);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
Logger.LogError(ex, "Ошибка при получении трека");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// ❌ Плохо - молча игнорируем ошибки
|
||||
public async Task<YTrack?> GetTrackAsync(string trackId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _provider.GetTrackAsync(trackId);
|
||||
}
|
||||
catch { }
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
### Структура файла
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace YandexMusic.API.API;
|
||||
|
||||
/// <summary>API для работы с треками.</summary>
|
||||
public class YTrackAPI : YCommonAPI
|
||||
{
|
||||
/// <summary>Инициализирует новый экземпляр.</summary>
|
||||
public YTrackAPI(YandexMusicApi yandex) : base(yandex) { }
|
||||
|
||||
/// <summary>Получает трек.</summary>
|
||||
public async Task<YTrack?> GetTrackAsync(string trackId)
|
||||
{
|
||||
// реализация
|
||||
}
|
||||
|
||||
/// <summary>Получает несколько треков.</summary>
|
||||
public async Task<IEnumerable<YTrack>> GetTracksAsync(IEnumerable<string> trackIds)
|
||||
{
|
||||
// реализация
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📝 Commit сообщения
|
||||
|
||||
### Формат
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
<body>
|
||||
|
||||
<footer>
|
||||
```
|
||||
|
||||
### Type
|
||||
|
||||
- `feat:` - новая функция
|
||||
- `fix:` - исправление ошибки
|
||||
- `docs:` - обновление документации
|
||||
- `style:` - форматирование кода (не влияет на функциональность)
|
||||
- `refactor:` - переписывание кода (не меняет функциональность)
|
||||
- `perf:` - улучшение производительности
|
||||
- `test:` - добавление или обновление тестов
|
||||
- `ci:` - изменения в CI/CD
|
||||
- `chore:` - обновление зависимостей, версии и т.д.
|
||||
|
||||
### Примеры
|
||||
|
||||
```bash
|
||||
git commit -m "feat(track-api): add support for track recommendations"
|
||||
|
||||
git commit -m "fix(auth): handle refresh token expiration correctly"
|
||||
|
||||
git commit -m "docs(readme): update installation instructions"
|
||||
|
||||
git commit -m "refactor(models): simplify YTrack class structure"
|
||||
|
||||
git commit -m "test(playlist): add tests for playlist operations"
|
||||
```
|
||||
|
||||
## 🔀 Pull Requests
|
||||
|
||||
### Перед созданием PR
|
||||
|
||||
- [ ] Код собирается без ошибок: `dotnet build`
|
||||
- [ ] Все тесты проходят: `dotnet test`
|
||||
- [ ] Код отформатирован согласно стилю
|
||||
- [ ] Добавлена XML документация для всех публичных членов
|
||||
- [ ] Обновлена документация если нужно
|
||||
|
||||
### Шаблон PR
|
||||
|
||||
```markdown
|
||||
## Описание
|
||||
Краткое описание внесённых изменений.
|
||||
|
||||
## Тип изменения
|
||||
- [ ] Новая функция (non-breaking change)
|
||||
- [ ] Исправление ошибки (non-breaking change)
|
||||
- [ ] Breaking change (поясните почему)
|
||||
- [ ] Обновление документации
|
||||
|
||||
## Как это было протестировано?
|
||||
Опишите шаги для тестирования.
|
||||
|
||||
## Связанные Issues
|
||||
Closes #issue_number
|
||||
|
||||
## Чеклист
|
||||
- [ ] Код следует стилю проекта
|
||||
- [ ] Добавлена документация
|
||||
- [ ] Нет новых warnings
|
||||
- [ ] Тесты проходят
|
||||
- [ ] Изменения совместимы с существующим кодом
|
||||
```
|
||||
|
||||
## 🐛 Отчёты об ошибках
|
||||
|
||||
### Шаблон Issue
|
||||
|
||||
```markdown
|
||||
## Описание ошибки
|
||||
Четкое и краткое описание проблемы.
|
||||
|
||||
## Шаги воспроизведения
|
||||
1. Сделайте...
|
||||
2. Затем...
|
||||
3. Ошибка воспроизведится
|
||||
|
||||
## Ожидаемое поведение
|
||||
Что должно было происходить.
|
||||
|
||||
## Фактическое поведение
|
||||
Что происходит на самом деле.
|
||||
|
||||
## Окружение
|
||||
- OS: Windows 11
|
||||
- .NET Version: 10.0
|
||||
- Visual Studio: 2026 Enterprise
|
||||
- YandexMusic Version: 0.0.1
|
||||
|
||||
## Дополнительный контекст
|
||||
Скриптстек, логи, код примера.
|
||||
```
|
||||
|
||||
## 💡 Предложения по улучшениям
|
||||
|
||||
### Шаблон Feature Request
|
||||
|
||||
```markdown
|
||||
## Описание
|
||||
Четкое описание желаемой функции.
|
||||
|
||||
## Использование
|
||||
Как бы выглядел код с использованием этой функции?
|
||||
|
||||
## Альтернативы
|
||||
Есть ли другие способы решить эту проблему?
|
||||
|
||||
## Дополнительный контекст
|
||||
Почему это нужно добавить?
|
||||
```
|
||||
|
||||
## 🎯 Области для внесения вклада
|
||||
|
||||
### High Priority
|
||||
|
||||
- [ ] Документация API методов
|
||||
- [ ] Unit тесты для API классов
|
||||
- [ ] Обработка ошибок
|
||||
- [ ] Оптимизация производительности
|
||||
|
||||
### Medium Priority
|
||||
|
||||
- [ ] Примеры использования
|
||||
- [ ] Интеграционные тесты
|
||||
- [ ] Улучшение логирования
|
||||
- [ ] Расширение функциональности
|
||||
|
||||
### Low Priority
|
||||
|
||||
- [ ] Рефакторинг кода
|
||||
- [ ] Улучшение читаемости
|
||||
- [ ] Документация
|
||||
|
||||
## 📞 Контакты
|
||||
|
||||
Вопросы? Свяжитесь с разработчиком:
|
||||
|
||||
- **Issues:** [https://git.frigat.duckdns.org/FrigaT/YandexMusic/issues]
|
||||
|
||||
---
|
||||
|
||||
Спасибо за то, что делаете YandexMusic лучше! 🚀
|
||||
Reference in New Issue
Block a user