Files
YandexMusic/CONTRIBUTING.md
2026-04-21 12:51:23 +03:00

12 KiB
Raw Blame History

🤝 Руководство для участников

Спасибо за интерес к проекту YandexMusic! Этот документ содержит рекомендации для тех, кто хочет внести свой вклад в развитие проекта.

📋 Содержание

🤐 Кодекс поведения

  • Будьте уважительны к другим участникам
  • Не допускайте дискриминацию, оскорбления и враждебного поведения
  • Критикуйте идеи, а не людей
  • Решайте конфликты конструктивно

🚀 Как начать

1. Подготовка окружения

# Клонируем репозиторий
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. Запуск тестов

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 документацию на русском

Пример документированного кода

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);
    }
}

Правила именования

// Классы: 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 для автоматического форматирования:

# Отступы - 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>. Правила:

// ✅ Хорошо - явно указано может быть 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;

Асинхронное программирование

// ✅ Хорошо - 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);
}

Обработка ошибок

// ✅ Хорошо
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;
}

Структура файла

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: - обновление зависимостей, версии и т.д.

Примеры

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

## Описание
Краткое описание внесённых изменений.

## Тип изменения
- [ ] Новая функция (non-breaking change)
- [ ] Исправление ошибки (non-breaking change)
- [ ] Breaking change (поясните почему)
- [ ] Обновление документации

## Как это было протестировано?
Опишите шаги для тестирования.

## Связанные Issues
Closes #issue_number

## Чеклист
- [ ] Код следует стилю проекта
- [ ] Добавлена документация
- [ ] Нет новых warnings
- [ ] Тесты проходят
- [ ] Изменения совместимы с существующим кодом

🐛 Отчёты об ошибках

Шаблон Issue

## Описание ошибки
Четкое и краткое описание проблемы.

## Шаги воспроизведения
1. Сделайте...
2. Затем...
3. Ошибка воспроизведится

## Ожидаемое поведение
Что должно было происходить.

## Фактическое поведение
Что происходит на самом деле.

## Окружение
- OS: Windows 11
- .NET Version: 10.0
- Visual Studio: 2026 Enterprise
- YandexMusic Version: 0.0.1

## Дополнительный контекст
Скриптстек, логи, код примера.

💡 Предложения по улучшениям

Шаблон Feature Request

## Описание
Четкое описание желаемой функции.

## Использование
Как бы выглядел код с использованием этой функции?

## Альтернативы
Есть ли другие способы решить эту проблему?

## Дополнительный контекст
Почему это нужно добавить?

🎯 Области для внесения вклада

High Priority

  • Документация API методов
  • Unit тесты для API классов
  • Обработка ошибок
  • Оптимизация производительности

Medium Priority

  • Примеры использования
  • Интеграционные тесты
  • Улучшение логирования
  • Расширение функциональности

Low Priority

  • Рефакторинг кода
  • Улучшение читаемости
  • Документация

📞 Контакты

Вопросы? Свяжитесь с разработчиком:


Спасибо за то, что делаете YandexMusic лучше! 🚀