¿Cómo se usa la encapsulación para la seguridad?

8

Estoy aprendiendo OOP. He estudiado mucho sobre la encapsulación, pero cuanto más leía, más me confundía.

Entiendo que ocultamos (al hacer privados) datos y los exponemos al usuario de la clase (otros desarrolladores) como propiedades o métodos. También entiendo por encapsulación que ocultamos detalles.

En un artículo (http://www.csharp-station.com/Tutorial/CSharp/lesson19) leí:

Resumen del articulo

Al diseñar un objeto, debe pensar en cómo otros podrían usarlo. En el mejor de los casos, cualquier programa que use el objeto estaría bien diseñado y el código nunca cambiaría. Sin embargo, la realidad es que los programas cambian a menudo y en un entorno de equipo, muchas personas tocan el mismo código en un momento u otro. Por lo tanto, es beneficioso considerar qué podría salir mal, así como la imagen prístina de cómo se debe usar el objeto .

En el caso del objeto BankAccount, examine la situación en la que el código fuera de su objeto podría acceder a un campo de Cantidad decimal o un campo de cadena CustomerName. En el momento en que se escribe el código, todo funcionaría bien. Sin embargo, más adelante en el ciclo de desarrollo, se da cuenta de que el objeto BankAccount debe realizar un seguimiento de un CustomerID int en lugar de una cadena CustomerName porque no desea duplicar las relaciones entre la información (o alguna otra razón válida para alterar la definición del estado interno) . Dichos cambios causan un efecto ondulante en su código porque se creó para usar la clase BankAccount, como se diseñó originalmente (con CustomerName como una cadena), y ahora debe cambiar el código que accede a ese estado en toda su aplicación.

El principio de Encapsulación orientado a objetos ayuda a evitar tales problemas, permitiéndole ocultar el estado interno y el acceso abstracto a él a través de miembros de tipo como métodos, propiedades e indexadores. La encapsulación lo ayuda a reducir el acoplamiento entre objetos y aumenta la capacidad de mantenimiento de su código.

Pregunta ¿Cómo ayudará la encapsulación al hacer cambios en el código y sus efectos ondulantes? Para un miembro de datos, si cambio su tipo de int a float, (incluso si estoy exponiendo esto usando la propiedad) tendré que cambiar el tipo de variable donde estoy usando este código.

Por favor, guíenme cómo la encapsulación ayudará con tales cambios.

Gracias por esta ayuda y orientación.

haansi
fuente

Respuestas:

8

Cómo ayudará la encapsulación al hacer cambios en el código y sus efectos ondulantes. Para un miembro de datos, si cambio su tipo de int a float, (incluso si estoy exponiendo esto usando la propiedad) necesitaré cambiar el tipo de variable donde estoy usando este código.

El beneficio de la encapsulación es que le permite cambiar la implementación interna sin romper el código del cliente. No lo protege si decide que necesita cambiar la interfaz a su código, pero eso es algo diferente.

Ejemplo: supongamos que tiene un valor que representa el precio por unidad de alguna mercancía. El precio se expresa en centavos, y debido a que no negocia en centavos fraccionales, decidió convertir la propiedad en un número entero (usaré C aquí porque no estoy muy familiarizado con C #):

int _price

int pricePerUnit(void) {
    return _price;
}

int priceForUnits(int units) {
    return units * _price;
}

Todo eso funciona bien hasta que un día alguien se da cuenta de que su empresa está perdiendo mucho dinero debido a errores de redondeo. Muchos de los productos que rastrea se compran y venden en muchos miles de unidades, por lo que debe comenzar a rastrear el precio con una precisión de al menos 0.001 centavo. Debido a que fue lo suficientemente inteligente como para encapsular el precio en lugar de permitir que los clientes accedan a él directamente, puede hacer que el cambio sea bastante rápido:

double _dprice

int pricePerUnit(void) {
    return (int)_dprice;
}

int priceForUnits(int units) {
    return (int)(units * _dprice);
}

La interfaz que utilizan los clientes para obtener precios sigue siendo la misma, pero los datos que obtienen ahora son más precisos. Si el precio por unidad es $ 1.001, priceForUnits(1000000)ahora devolverá un precio que es $ 1000 mayor que antes. Eso sucede a pesar de que no ha cambiado la interfaz de su sistema y, por lo tanto, no ha roto ningún código de cliente.

Ahora, eso no siempre es todo lo que necesita hacer. A veces necesitará cambiar o aumentar su interfaz para poder informar el precio con mayor precisión a los clientes también:

double pricePerUnit() {
    return _dprice;
}

Un cambio como que va a romper el código del cliente, por lo que en su lugar puede mantener la interfaz de edad y proporcionar una mejor rutina de nuevo:

int pricePerUnit() {
    return (int)_dprice;
}

double accuratePricePerUnit() {
    return _dprice;
}

Usted y el resto de su equipo pueden embarcarse en el proceso de convertir a todos los clientes de su sistema para usar el más nuevo y mejor accuratePricePerUnit(). El código del cliente se volverá más preciso a medida que avance en esa tarea, pero incluso las cosas antiguas deberían seguir funcionando tan bien como en el pasado.

De todos modos, el punto es que la encapsulación le permite cambiar la forma en que funcionan las partes internas mientras presenta una interfaz consistente, y eso lo ayuda a realizar cambios útiles sin romper otro código. No siempre lo protege de tener que actualizar otro código, pero al menos puede ayudarlo a hacerlo de manera controlada.

Caleb
fuente
3

En mi experiencia, la encapsulación hace que hacer lo "incorrecto" sea mucho más difícil. Puede agrupar la funcionalidad que se une semánticamente y aislarla de la funcionalidad que puede conducir a un comportamiento malo o impredecible. También puede ayudar a ocultar los detalles del usuario final, lo que puede ayudar a aumentar la seguridad y la fiabilidad.

Considere esta publicación de John D Cook . Considera que tienes un Breadobjeto. Una cosa natural para cortar este pan. Entonces escribes una slice()función, para que puedas hacer

slice(loaf)

con un nuevo loafobjeto que has creado. Esto tiene sentido. Pero si no tienes cuidado, puedes llamar accidentalmente

slice(finger)

con un fingerobjeto en algún lugar de tu proyecto. Esto podría conducir a cosas muy malas. En cambio, encapsule esta función / método en una Breadclase para que pueda hacer esto

loaf.slice()

Esto definitivamente ayuda a evitar llamadas finger.slice()accidentales, ya que fingerprobablemente no tenga un slice()método asociado.

Este es un ejemplo un poco artificial, pero lo he encontrado útil. La encapsulación a veces puede ser un aspecto subestimado de OOP, pero es bueno.

joshin4colours
fuente
2

La encapsulación ayuda a grandes grupos de desarrolladores a coordinar su trabajo de manera más eficiente. Cada grupo de desarrolladores trabaja en diferentes módulos, y esos módulos están encapsulados: separe el código en una pequeña cantidad de operadores ampliamente disponibles cuyo uso no pueden controlar estrictamente, y una gran cantidad de operadores internos que pueden controlar estrictamente. Lo que esto significa es que cada grupo de desarrolladores puede definir invariantes que son importantes para el mantenimiento de su módulo y asegurarse de que esos invariantes se mantengan independientemente de lo que hagan los desarrolladores de otros módulos.

Dado que la encapsulación permite la preservación de invariantes, a menudo se usa para mantener invariantes de seguridad, p. Ej.

  • que nunca se accede a un almacén de datos sin las credenciales adecuadas
  • que una cuenta bancaria nunca tiene más dinero agregado que el que fue eliminado de otra
  • que ciertas operaciones siempre se registran

El modelo de capacidad Object es una metodología para escribir código sensible a la seguridad que es la encapsulación en esteroides.

El modelo de seguridad se basa en no poder falsificar referencias; ver Sintetizar direcciones de actores.

Los objetos solo pueden interactuar enviando mensajes sobre referencias. Se puede obtener una referencia por:

  1. condiciones iniciales: en el estado inicial del mundo computacional que se describe, el objeto A ya puede tener una referencia al objeto B. parentalidad: si A crea B, en ese momento A obtiene la única referencia al recién creado B.
  2. dotación: si A crea B, B nace con ese subconjunto de referencias de A con el que A eligió dotarlo.
  3. Introducción: si A tiene referencias a B y C, A puede enviar a B un mensaje que contenga una referencia a C. B puede retener esa referencia para su uso posterior.

En el modelo de capacidad de objeto, todos los cálculos se realizan siguiendo las reglas anteriores.

Las ventajas que motivan la programación orientada a objetos, como la encapsulación o el ocultamiento de la información, la modularidad y la separación de preocupaciones, corresponden a objetivos de seguridad, como la separación de privilegios y privilegios mínimos en la programación basada en capacidades.

Mike Samuel
fuente
2

Cómo ayudará la encapsulación al hacer cambios en el código y sus efectos ondulantes.

Déjame darte un ejemplo típico y simplista. Primero, suponga que no está usando la encapsulación: tiene un conjunto de datos y usa una matriz para almacenar esos datos, y hay otra parte de su programa que usa esa matriz. Ahora, si en algún momento decide que una lista vinculada es una mejor opción para almacenar sus datos. Si reemplaza la matriz con una lista vinculada, ¿qué va a pasar? Su programa se interrumpirá, a menos que realice cambios por todas partes para reemplazar la lógica de procesamiento de matriz con la lógica de procesamiento de lista enlazada.

Pero, si usa OO / Encapsulación, entonces probablemente particione su programa en clases, una que almacena los datos y otra que usa los datos. En la primera clase, oculta su implementación (encapsulación) y expone sus servicios a través de métodos como

size()
remove(int index)
add(int index, Object o)
get(int index)

...

En este segundo caso, si cambia la implementación de la clase de almacenamiento de la matriz a la lista vinculada, o cualquier otra cosa, no afectará a sus clientes. Sin efecto dominó.

Nazar Merza
fuente
1

La forma principal en que la encapsulación ayuda a reducir los efectos ondulantes del cambio es manteniendo la privacidad de la mayoría de los detalles de implementación. Al limitar la interfaz solo a aquellos miembros necesarios para usar la clase, se pueden hacer muchos cambios en la implementación sin afectar ningún código que use la clase.

Ese parece ser el punto que señala el texto que citó, aunque también lo encontré un poco confuso en mi primera lectura.

Jonathan Wood
fuente
1

Creo que le permite cambiar la funcionalidad de su clase sin, aunque no siempre, introducir interrupciones BC (compatibilidad binaria o conductual). Es decir, puede cambiar cómo su clase hace 'algo' sin tener que cambiar cómo el usuario final le dice que haga ese 'algo'.

El ejemplo que usted dio de cambiar el tipo de retorno es una interrupción de BC, porque cualquiera que haya usado previamente su clase no podrá usar la nueva versión sin volver a compilar. Esto es algo que debe hacerse solo como último recurso, y en un entorno profesional solo puede hacerse con la autorización de los arquitectos y después de que se haya archivado el papeleo, se notifique a los clientes, etc.

También le da control total sobre el estado de su objeto.

James
fuente