У 2024 році я приєднався до японського стартапу і вперше почав працювати з Ruby. До цього у мене було майже 10 років досвіду розробки на Python. Багато хто вважає Python та Ruby схожими динамічними мовами, але в реальній розробці їхні філософії дизайну та випадки використання значно відрізняються.
Філософія дизайну: Чіткість перш за все vs Гнучкість перш за все
- Ruby: Пропагує гнучкість, що робить її особливо зручною для стартапів, які потребують швидкої ітерації. Підхід Rails “конвенція замість конфігурації” значно підвищує ефективність розробки, але його динамічний характер та неявна логіка можуть збільшити складність при масштабуванні системи.
- Python: Пріоритет надається чіткості та читабельності коду. Його філософія “явне краще за неявне” дає йому перевагу в великих проектах, знижуючи технічний борг і покращуючи довготривалу підтримуваність.
Давайте порівняємо фреймворки Ruby on Rails, Django, Flask та Go Echo на практичному прикладі реалізації управління дозволами у складних сценаріях.
Практичний приклад: Управління дозволами для вебсайту з публікацією книг
Сценарій: Вебсайт для публікації книг вимагає функціоналу управління дозволами, де середні адміністратори можуть вирішувати, чи можна опублікувати книгу.
1. Rails (Pundit)
Логіка дозволів розподілена між файлом Policy та контролером:
# app/policies/book_policy.rb
class BookPolicy < ApplicationPolicy
def publish?
user.role == 'moderator'
end
end
# app/controllers/books_controller.rb
class BooksController < ApplicationController
include Pundit
def publish
@book = Book.find(params[:id])
authorize @book, :publish?
@book.update!(published: true)
render json: { message: 'Book published successfully' }
end
end
- Переваги: Файли Policy відокремлюють логіку дозволів, що дає велику гнучкість.
- Недоліки: Неявні виклики (наприклад,
authorize
) не інтуїтивно зрозумілі, а розпорошена логіка дозволів підвищує вартість читання і відлагодження коду.
2. Django
Логіка дозволів реалізована через прив’язки до моделей і декоратори:
# views.py
from django.contrib.auth.decorators import permission_required
from django.shortcuts import get_object_or_404
from django.http import JsonResponse
@permission_required('app.change_book')
def publish_book(request, book_id):
book = get_object_or_404(Book, id=book_id)
book.published = True
book.save()
return JsonResponse({'message': 'Book published successfully'})
- Переваги: Логіка дозволів тісно пов’язана з моделями, а декоратори спрощують перевірку дозволів, що дозволяє писати чистий і простий код.
- Недоліки: Менша гнучкість; складніші сценарії дозволів потребують додаткових розширень.
3. Flask
Перевірка дозволів централізована в функції:
def check_permission(user):
if user.get('role') != 'moderator':
abort(403, 'Permission denied')
@app.route('/publish/', methods=['POST'])
def publish_book(book_id):
user = request.json.get('user')
check_permission(user)
return jsonify({'message': f'Book {book_id} published successfully'})
- Переваги: Централізована логіка дозволів забезпечує простоту та підтримуваність.
- Недоліки: Розробникам доводиться вручну проектувати логіку дозволів, що підвищує вартість розробки.
Go Echo
Явні перевірки дозволів:
func checkPermission(user User) bool {
return user.Role == "moderator"
}
func publishBook(c echo.Context) error {
bookID := c.Param("id")
user := User{Role: c.QueryParam("role")}
if !checkPermission(user) {
return c.JSON(http.StatusForbidden, map[string]string{"error": "Permission denied"})
}
return c.JSON(http.StatusOK, map[string]string{"message": "Book " + bookID + " published successfully"})
}
- Переваги: Явна реалізація логіки дозволів робить код зрозумілим та легким для читання.
- Недоліки: Розробникам потрібно самостійно проектувати механізм дозволів, що додає складності.
Підсумок практичного прикладу: Баланс між чіткістю та підтримуваністю
- Django: Інтуїтивно зрозумілий дизайн дозволів, підходить для середніх проектів з чіткими правилами.
- Flask та Go Echo: Простий і зрозумілий код, але потребує більшої участі розробників у проектуванні дозволів.
- Rails: Забезпечує велику гнучкість, але покладається на неявну логіку, що знижує читабельність коду та ефективність співпраці в команді.
У великих проектах гнучкість Rails може призвести до більшого технічного боргу, тому я схильний надавати перевагу Python або Go для розробки.
Через обмеження по місцю, подальші практичні приклади (наприклад, проектування ORM у Rails та обмеження паралелізму в сценаріях високої продуктивності) будуть обговорені в майбутніх статтях.
Перекладено з: Ruby, Python, and Go: A Practical Comparison for Developers