ARGENTINA NOTICIAS PORTADA

#Programación – Dominar el arte del código limpio y ademas excelente propuesta

Hoy les compartimos un post destinado a los lectores que desarrollan código de programación, y principalmente a quienes residan en Argentina. Ya que el 1 de noviembre del 2023, la gente de Binary Studio Academy, desembarco en nuestro país con una propuesta muy interesante.

La de postular a un grupo de desarrolladores locales, para luego capacitarlos de forma gratuita por el termino de 2 meses, seguido a eso, que los mejores puedan sumarse a la Academia y trabajar en los desarrollos que la misma tiene a lo largo de todo el mundo.

Con lo cual les comparto el link desde donde pueden aplicarse a esta iniciativa, que va permanecer abierta hasta el 1 de diciembre inclusive.

Dicho esto, vayamos al excelente artículo donde pueden Dominar el arte del código limpio: desbloquear el poder de los principios de programación.

Cada lenguaje de programación tiene su propio conjunto de mejores prácticas. Estas prácticas ayudan a los desarrolladores a escribir código escalable, legible y organizado. Algunas de estas prácticas son globales y se pueden utilizar con cualquiera de los lenguajes de programación. Estas mejores prácticas globales se denominan Principios de programación. Los principios de programación son reglas y mejores prácticas que se pueden utilizar en cualquier dominio de programación y con cualquier lenguaje de programación. Estos principios son el conocimiento fundamental para el desarrollo de software. Ya sea que recién haya comenzado a programar o que ya sea un desarrollador experimentado, comprender y aplicar estos principios marcará una gran diferencia en su trabajo.

En este artículo, analizaremos 3 principios de programación que pueden y deben usarse en la implementación de programación diaria y que pueden mejorar significativamente la calidad de su código. Estos principios, conocidos como KISS (Keep It Simple, Stupid), DRY (Don’t Repite Yourself) y SRP (Principio de Responsabilidad Única), brindan una excelente guía sobre cómo escribir código mantenible, adaptable y robusto y pueden usarse en todos los dominios del desarrollo.

En este artículo, intentaremos refactorizar el siguiente fragmento de código, que puede usarse para realizar solicitudes HTTP:

TypeScript
Copy
// src/packages/users/libs/types/user-dto.type.ts
type UserDto = {
  id: number;
  name: string;
};

// src/packages/posts/libs/types/post-dto.type.ts
type PostDto = {
  title: string;
  content: string;
};

// src/libs/packages/http/http.package.ts
class Http {
  baseUrl: string;

  headers: Headers;

  public constructor() {
    this.baseUrl = '';
    this.headers = new Headers();
  }

  public setBaseUrl(url: string): void {
    this.baseUrl = url;
  }

  public setHeaders(headers: Headers): void {
    this.headers = headers;
  }

  public async get<T = unknown>(url: string): Promise<T> {
    const response = await fetch(this.baseUrl + url, {
      method: 'GET',
      headers: this.headers,
    });
    const data = await response.json();

    console.log(`GET ${this.baseUrl + url} - Status: ${response.status}`);
    console.log('Response Data:', data);

    return data as T;
  }

  public async post<T = unknown>(url: string, data: T): Promise<T> {
    const response = await fetch(this.baseUrl + url, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify(data),
    });
    const responseData = await response.json();

    console.log(`POST ${this.baseUrl + url} - Status: ${response.status}`);
    console.log('Response Data:', responseData);

    return responseData as T;
  }
}

// src/libs/packages/http/http.ts
const http = new Http();
http.setBaseUrl('https://api.example.com');
const headers = new Headers();
headers.append('Content-Type', 'application/json');
http.setHeaders(headers);

// src/slices/users/actions.ts
const getUserById = (id: number): Promise<UserDto> => {
  return http.get<UserDto>(`/user/${id}`);
};

// src/slices/posts/actions.ts
const createPost = (title: string, content: string): Promise<PostDto> => {
  return http.post<PostDto>('/posts', { title, content });
};

KISS – ¡Mantenlo simple, estúpido!

A menudo, los desarrolladores complican innecesariamente el código que escriben. Escribir código complejo dificulta su depuración en el futuro y prolonga el tiempo de desarrollo. El principio KISS anima a los desarrolladores a escribir el código de la forma más sencilla posible. En la mayoría de los casos, puede ser difícil o incluso imposible hacerlo, pero siempre debes intentar mantener tu código simple. La simplicidad del código garantiza un desarrollo más rápido, una depuración más sencilla y también aumenta exponencialmente la legibilidad del código.

¿Qué es un código simple?

El código simple no se trata solo de la lógica del código, sino también de nombrar y seguir claramente las variables. criterios de calidad. Estos pasos garantizarán la creación de código legible y mantenible. El código simple no siempre significa código corto. Esto debe tenerse especialmente en cuenta al escribir frases ingeniosas. Las frases ingeniosas pueden parecer interesantes al realizar una tarea solo en una línea de código. Pero cuando se trata de legibilidad, es importante mantenerlo simple.

Las ventajas de seguir el principio KISS:

Simplicidad y legibilidad: el código sencillo y fácil de entender reduce el riesgo de introducir errores y ayuda en la depuración.

Mantenimiento más sencillo: el principio KISS reduce la complejidad de un código base. Cuando el código es simple, mantener, actualizar y refactorizar se vuelve mucho más fácil.

Desarrollo más rápido: el código simple es más rápido de desarrollar, probar y actualizar porque minimiza la complejidad innecesaria.

En nuestro fragmento de código, no necesitamos tener métodosestablecerURLBase yestablecer encabezados. Con estos métodos, es posible que necesitemos establecer diferentesURL base yencabezados para cada solicitud. En cambio, podemos enviarURL base cuando creamos el servicio y calculamosencabezados dentro del servicio.

Así es como se ve el código del principio de este artículo si aplicamos el principio KISS:

TypeScript
Copy
// src/libs/types/content-type.type.ts
type ContentType = 'application/json' | 'multipart/form-data';

// src/libs/packages/http/http.package.ts
type Constructor = {
  baseUrl: string;
};

class Http {
	private baseUrl: string;

	public constructor({ baseUrl }: Constructor) {
		this.baseUrl = baseUrl;
	}
	// Other methods

	private getHeaders(contentType?: ContentType): Headers {
    const headers = new Headers();

    if (contentType) {
      headers.append('Content-Type', contentType);
    }

    return headers;
  }

	// Other methods
}

// src/libs/packages/http/http.ts
const http = new Http({ baseUrl: 'https://api.example.com' });

La versión fija es mucho más fácil de mantener. Podemos usar fácilmente esta clase para diferentes puntos finales, creando una instancia conURL base y podemos agregar fácilmente nuevos encabezados, por ejemplo, si nuestro Backend requiere autenticación. Los nuevos encabezados se agregarán en un solo lugar y no tendremos que agregar encabezados por separado en cada lugar donde usemos esta clase.

¿Cómo aplicar el principio KISS?

Divida los programas grandes en varios más pequeños

Utilice nombres de variables legibles y significativos

Evite complicaciones innecesarias

SECO – No te repitas

Como indica el nombre de este principio, anima a los desarrolladores a no repetir nunca el mismo código dos veces. Según este principio, la lógica particular debe escribirse solo una vez dentro de un código base. La forma más sencilla de violar el principio DRY es copiar y pegar su propio código.

Beneficios de escribir código DRY

Reutilización del código: evitar la duplicación de código ahorra tiempo de desarrollo, garantiza la coherencia en el comportamiento y reduce las posibilidades de introducir nuevos errores.

Depuración y mantenimiento más sencillos: la depuración del código DRY se realiza en unos pocos archivos. Encontrar el error o agregar una nueva característica al código que no es DRY generalmente significa hacer los mismos cambios en muchos archivos.

Consistencia del código: el código DRY garantiza que la lógica sea coherente en todos los archivos y en las diferentes partes de una aplicación. Esto reduce el riesgo de errores causados ​​por las inconsistencias entre el código duplicado.

En nuestro fragmento de código, repetimos la lógica paraCONSEGUIR yCORREO peticiones. Podemos combinar métodos paraCONSEGUIR yCORREO solicitudes y crear un método llamadocarga, que manejará todos los métodos de solicitud.

Así es como se ve el código del principio de este artículo si aplicamos el principio DRY:

TypeScript
Copy
// src/libs/packages/http/libs/types/http-request-parameters.ts
type HttpRequestParameters = {
  method: HttpMethod;
  url: string;
  payload?: BodyInit | null;
  contentType?: ContentType;
};

// src/libs/packages/http/http.package.ts
class Http {
	// Other methods

	public async load<T = unknown>({
    method,
    url,
    payload,
    contentType,
  }: HttpRequestParameters): Promise<T> {
    const headers = this.getHeaders(contentType);
    const response = await fetch(`${this.baseUrl}${url}`, {
      method,
      headers,
      body: payload ? JSON.stringify(payload) : null,
    });

    console.log(`${method} ${url} - Status: ${response.status}`);
    console.log('Response:', response);

    return response.json();
  }

	// Other methods
}

// src/libs/packages/http/http.ts
const http = new Http({ baseUrl: 'https://api.example.com' });

¿Cómo escribir código DRY?

Siempre escriba código reutilizable, cuando sea posible.

Nunca copie y pegue el mismo código

Divide tu código en funciones modulares

SRP – Principio de Responsabilidad Única

El Principio de Responsabilidad Única (SRP) establece que una clase o módulo debe tener solo una razón para cambiar. En otras palabras, cada clase o módulo debe tener una única responsabilidad o tarea a realizar. Este principio ayuda a mantener el código base organizado, mantenible y escalable.

Al implementar el principio SRP, puede lograr las siguientes ventajas:

Organización del Código: Cada clase o módulo tiene un propósito claro y definido, facilitando la localización y comprensión de su funcionalidad.

Facilidad de mantenimiento: con una única responsabilidad, se pueden realizar cambios y actualizaciones de una funcionalidad específica sin afectar otras partes del código base.

Hacer cumplir los principios de KISS y DRY: al tener una responsabilidad clara y enfocada, resulta más fácil mantener el código simple y evitar la duplicación de código.

En nuestro fragmento, el servicio Http es responsable de realizar solicitudes y registrar el mensaje. El registro debe manejarse dentro de su propia clase y el servicio Http no debe ser responsable de ello. Como establece este principio, cada servicio debe ser responsable de realizar una tarea.

Así es como se ve el código del principio de este artículo si aplicamos el principio SRP:

TypeScript
Copy
// src/libs/packages/http/http.package.ts
type Constructor = {
  baseUrl: string;
  logger: Logger;
};

class Http {
	private baseUrl: string;

  private logger: Logger;

	public constructor(baseUrl, logger) {
		this.baseUrl = baseUrl;
		this.logger = logger;
	}
	// Other methods

	public async load<T = unknown>({
    method,
    url,
    payload,
    contentType,
  }: LoadArguments): Promise<T> {
    const headers = this.getHeaders(contentType);
    const response = await fetch(`${this.baseUrl}${url}`, {
      method,
      headers,
      body: payload ? JSON.stringify(payload) : null,
    });

    this.logger.log(`${method} ${url} - Status: ${response.status}`);
    this.logger.log(`Response: ${JSON.stringify(response)}`);

    return response.json();
  }

	// Other methods
}

// src/libs/packages/logger/logger.package.ts
class Logger {
	public log(message: string) {
		console.log('LOGGER: ', message);
	}
}

// src/libs/packages/logger/logger.ts
const logger = new Logger();

// src/libs/packages/http/http.ts
const http = new Http({
	baseUrl: 'https://api.example.com',
	logger,
});

Hemos creado un separadoregistrador clase, que es responsable de registrar mensajes. Ahora las solicitudes HTTP y el registro de mensajes están separados y manejados por clases diferentes.

Siguiendo el principio SRP, puede crear código más modular y fácil de mantener, lo que conduce a una mejor calidad general del software.

¿Cómo aplicar el principio SRP?

Definir claramente las responsabilidades

Seguir SRP en funciones y métodos

Primero identifique las responsabilidades, luego sepárelas

Conclusión

En conclusión, estos principios de programación (KISS, DRY y SRP) son esenciales para escribir código legible, mantenible y de alta calidad. Siguiendo estos principios, los desarrolladores pueden mejorar la eficiencia de su proceso de desarrollo, reducir la duplicación de código y hacer que su código sea más organizado y adaptable. Es importante señalar que estos principios no son específicos de ningún lenguaje de programación y pueden aplicarse universalmente en cualquier dominio de desarrollo. Adoptar estos principios beneficiará enormemente a los desarrolladores en su viaje de programación.

Hay muchos otros principios, como SOLID, YAGNI y otros. Puede buscar y aprender más sobre estos principios, pero pueden resultar muy difíciles de entender.

Después de refactorizar nuestro fragmento parte por parte, un principio a la vez, aquí está la versión final:

TypeScript
Copy
// src/libs/types/content-type.type.ts
type ContentType = 'application/json' | 'multipart/form-data';

// src/libs/packages/http/libs/types/http-method.type.ts
type HttpMethod = 'GET' | 'POST';

// src/packages/users/libs/types/user-dto.type.ts
type UserDto = {
  id: number;
  name: string;
};

// src/packages/posts/libs/types/post-dto.type.ts
type PostDto = {
  title: string;
  content: string;
};

// src/libs/packages/http/http.package.ts
type LoadArguments = {
  method: HttpMethod;
  url: string;
  payload?: BodyInit | null;
  contentType?: ContentType;
};

type Constructor = {
  baseUrl: string;
  logger: Logger;
};

class Http {
  private baseUrl: string;

  private logger: Logger;

  public constructor({ baseUrl, logger }: Constructor) {
    this.baseUrl = baseUrl;
    this.logger = logger;
  }

  private getHeaders(contentType?: ContentType): Headers {
    const headers = new Headers();

    if (contentType) {
      headers.append('Content-Type', contentType);
    }

    return headers;
  }

  public async load<T = unknown>({
    method,
    url,
    payload,
    contentType,
  }: LoadArguments): Promise<T> {
    const headers = this.getHeaders(contentType);
    const response = await fetch(`${this.baseUrl}${url}`, {
      method,
      headers,
      body: payload ? JSON.stringify(payload) : null,
    });

    this.logger.log(`${method} ${url} - Status: ${response.status}`);
    this.logger.log(`Response: ${JSON.stringify(response)}`);

    return response.json();
  }
}

// src/libs/packages/logger/logger.package.ts
class Logger {
  public log(message: string) {
    console.log('LOGGER: ', message);
  }
}

// src/libs/packages/logger/logger.ts
const logger = new Logger();

// src/libs/packages/http/http.ts
const http = new Http({ baseUrl: 'https://api.example.com', logger });

// src/slices/users/actions.ts
const getUserById = (id: number): Promise<UserDto> => {
  return http.load<UserDto>({
    url: `/user/${id}`,
    method: 'GET',
  });
};

// src/slices/posts/actions.ts
const createPost = (title: string, content: string): Promise<PostDto> => {
  return http.load<PostDto>({
    url: '/posts',
    method: 'POST',
    contentType: 'application/json',
    payload: JSON.stringify({ title, content }),
  });
};