GraphQL vs REST en C#: ¿Batalla de titanes o elección de herramienta según la tarea?
\n\n¡Hola, colegas! Si programas en C# y creas APIs, seguro que la pregunta "¿REST o GraphQL?" ha surgido más de una vez. Es como discutir qué es mejor: ¿un martillo o un destornillador eléctrico? Ambos son herramientas, pero para diferentes tareas. En este artículo no defenderemos fanáticamente una tecnología, sino que analizaremos de forma objetiva, con ejemplos de código en C#, cuándo gana GraphQL y cuándo el clásico REST sigue siendo el rey.
\n\nSomos el equipo de PythonLib, y aunque el nombre incluye "Python", amamos el ecosistema .NET y C#. Hoy exploraremos el mundo de las APIs en C# y descubriremos cómo no equivocarse en la elección. ¡Allá vamos!
\n\nBreve introducción: REST y GraphQL para desarrolladores de C#
\n\nREST (Representational State Transfer) es un estilo arquitectónico que todos conocemos y amamos. En C#, probablemente uses ASP.NET Core Web API. Creas controladores, endpoints, y cada endpoint devuelve una estructura de datos fija. ¿Quieres obtener un usuario? Vas a /api/users/1. ¿Quieres sus pedidos? Vas a /api/users/1/orders. Simple, predecible, pero a menudo provoca over-fetching (recibes datos innecesarios) o under-fetching (necesitas hacer varias solicitudes).
GraphQL es un lenguaje de consultas desarrollado por Facebook. En el mundo de C#, se implementa mediante bibliotecas como Hot Chocolate (la más popular) o GraphQL.NET. Tienes un solo endpoint (generalmente /graphql), y el cliente decide qué campos necesita. ¿Quieres el nombre del usuario y solo el primer pedido? ¡Por supuesto! Sin over-fetching.
Comparación práctica: Código en C#
\n\nPasemos de la teoría al código. Imaginemos que tenemos un modelo simple: User y Order.
// Modelos de datos\npublic class User\n{\n public int Id { get; set; }\n public string Name { get; set; }\n public string Email { get; set; }\n public string Phone { get; set; }\n public List<Order> Orders { get; set; }\n}\n\npublic class Order\n{\n public int Id { get; set; }\n public string ProductName { get; set; }\n public decimal Price { get; set; }\n public DateTime CreatedAt { get; set; }\n}\n\n\nEjemplo de API REST en ASP.NET Core
\n\n[ApiController]\n[Route("api/[controller]")]\npublic class UsersController : ControllerBase\n{\n [HttpGet("{id}")]\n public async Task<ActionResult<User>> GetUser(int id)\n {\n // Supongamos que los datos vienen de la BD\n var user = await _dbContext.Users.FindAsync(id);\n if (user == null) return NotFound();\n return Ok(user); // Devuelve TODOS los campos: Id, Name, Email, Phone, Orders\n }\n}\n\n\n¿El problema? Si el cliente solo necesita el nombre y el email, igualmente recibirá Phone y Orders. Y si necesita los pedidos, tendrá que hacer una solicitud aparte a /api/users/1/orders.
Ejemplo de API GraphQL con Hot Chocolate
\n\npublic class Query\n{\n public async Task<User> GetUser(int id, [Service] AppDbContext dbContext)\n {\n return await dbContext.Users.FindAsync(id);\n }\n}\n\n// Registro en Program.cs\nbuilder.Services\n .AddGraphQLServer()\n .AddQueryType<Query>();\n\n\nAhora el cliente puede solicitar exactamente lo que necesita:
\n\n// Consulta GraphQL\n{\n user(id: 1) {\n name\n email\n orders {\n productName\n price\n }\n }\n}\n\n\nLa respuesta contendrá solo name, email y un array de orders con los campos productName y price. Sin basura. ¡Hermoso!
Cuándo gana REST en C# (y está bien)
\n\n1. Simplicidad y almacenamiento en caché. Las API REST son fáciles de cachear a nivel HTTP (CDN, proxies). Una solicitud GET a /api/products se puede cachear, y todo b