Vous êtes sur la page 1sur 17

1

1. Diseño y uso de API

Clement (año)“Diseñar una interfaz significa decidir (y documentar con un documento de

interfaz) qué servicios y propiedades deben ser visibles externamente y cuáles no.”(p.261)

Una interfaz de programación de aplicaciones (API) es el conjunto de firmas que se

exportan y están disponibles para los usuarios de una biblioteca o un marco para escribir sus

aplicaciones. Además de las firmas, una API siempre debe incluir declaraciones sobre los

efectos y / o comportamientos del programa (es decir, su semántica).

El diseño de API debe tratar de hacer que la API sea fácil de aprender y memorizar,

conducir a un código legible, ser difícil de usar mal, ser fácil de extender, estar completo y

mantener la compatibilidad con versiones anteriores. Como las API generalmente superan sus

implementaciones para una biblioteca o marco ampliamente utilizado, se desea que la API sea

sencilla y estable para facilitar el desarrollo y el mantenimiento de las aplicaciones cliente.

El uso de API implica los procesos de selección, aprendizaje, prueba, integración y,

posiblemente, extensión de las API proporcionadas por una biblioteca o marco (ver sección

3.6, Construcción con reutilización).

1.1 Documentación de la interfaz 265 clement

La documentación de la interfaz indica lo que otros desarrolladores necesitan saber sobre

una interfaz para poder utilizarla en combinación con otros elementos. Se debe tener en

cuenta que un desarrollador puede observar las propiedades del elemento que son un artefacto

de cómo se implementa el elemento pero que no están en la documentación de la interfaz.

Debido a que estos no se encuentran en la documentación de la interfaz, están sujetos a

cambios, y los desarrolladores los utilizan bajo su propio riesgo.


2

También se debe reconocer que diferentes personas necesitan conocer diferentes tipos de

información sobre la interfaz. Es posible que tenga que proporcionar secciones separadas en la

documentación de la interfaz para dar cabida a diferentes partes interesadas de la interfaz. Las

interfaces se documentan como parte de una vista. Cuando se produce una interfaz

determinada en más de una vista, elija una para guardar la documentación de la interfaz y

refiérase a ella en la otra. Alternativamente, empaque la documentación de la interfaz por

separado y haga que todas las vistas apunten a ella.

268 clement

Como en toda la documentación de arquitectura, la cantidad de información transmitida en

la documentación de la interfaz puede variar, dependiendo de la importancia de la interfaz y

de la etapa del proceso de diseño cuando se actualiza la documentación.

- Al principio del proceso de diseño, la interfaz podría estar poco especificada; por ejemplo,

un módulo de seguimiento de pedidos proporciona una operación para localizar un pedido.


- Más tarde, cuando las responsabilidades de los elementos se vuelvan estables, la

documentación de la interfaz se elabora con mayor detalle; por ejemplo, el módulo de

seguimiento de pedidos proporciona al método locatedOrder (orderId) una descripción

sobre su semántica.

- Algún tiempo después, incluso puede refinar la documentación de la interfaz con la

sintaxis final del método: OrderBean locatedOrderById (long orderId)


3

2. Temas de la ejecución orientada a objetos

Los lenguajes orientados a objetos admiten una serie de mecanismos de tiempo de

ejecución que incluyen polimorfismo y reflexión. Estos mecanismos de tiempo de ejecución

aumentan la flexibilidad y adaptabilidad de los programas orientados a objetos. El

polimorfismo es la capacidad de un lenguaje para admitir operaciones generales sin saber

hasta el tiempo de ejecución qué tipo de objetos concretos incluirá el software. Debido a que

el programa no conoce de antemano los tipos exactos de los objetos, el comportamiento

exacto se determina en el tiempo de ejecución (llamado enlace dinámico).

La reflexión es la capacidad de un programa para observar y modificar su propia

estructura y comportamiento en tiempo de ejecución. La reflexión permite la inspección de

clases, interfaces, campos y métodos en tiempo de ejecución sin saber sus nombres en tiempo

de compilación. También permite la creación de instancias en tiempo de ejecución de nuevos

objetos e invocación de métodos utilizando nombres de métodos y clases parametrizados.

2.1 Fundamentos de la clase: tipos de datos abstractos página 126 mc

Un tipo de datos abstracto es una colección de datos y operaciones que funcionan con esos

datos. Las operaciones describen los datos al resto del programa y permiten que el resto del

programa cambie los datos. La palabra "datos" en "tipo de datos abstractos" se usa a la ligera.

Una ADT puede ser una ventana gráfica con todas las operaciones que la afectan, una

operación de archivo y archivo, una tabla de tasas de seguro y las operaciones en ella, o algo

más.
4

Comprender los ADT es esencial para entender la programación orientada a objetos. Sin

entender los ADT, los programadores crean clases que son “clases” solo de nombre; en

realidad, son poco más que casos convenientes para colecciones de datos y rutinas poco

relacionadas. Al comprender los ADT, los programadores pueden crear clases que son más

fáciles de implementar inicialmente y más fáciles de modificar con el tiempo.

Tradicionalmente, los libros de programación se vuelven matemáticos cuando llegan al tema

de los tipos de datos abstractos. Tienden a hacer afirmaciones como "Uno puede pensar en un

tipo de datos abstractos como un modelo matemático con una colección de operaciones

definidas en ellos". Tales libros hacen que parezca que en realidad nunca usarían un tipo de

datos abstractos.

2.2 Buenas interfaces de clase 133 mc

Para crear una clase de alta calidad es crear una buena interfaz. Esto consiste en crear una

buena abstracción para que la interfaz represente y garantizar que los detalles permanezcan

ocultos detrás de la abstracción. La abstracción es la capacidad de ver una operación compleja

en forma simplificada. Una interfaz de clase proporciona una abstracción de la

implementación que está oculta detrás de la interfaz. La interfaz de la clase debe ofrecer un

grupo de rutinas que claramente pertenecen juntas. Es posible que tenga una clase que

implementa un empleado. Contendría datos que describan el nombre, la dirección, el número

de teléfono del empleado, etc. Ofrecería servicios para inicializar y utilizar a un empleado. Así

es como podría verse.


5

134mc

C ++ Ejemplo de una interfaz de clase que presenta una buena abstracción

class Employee {

public:

// public constructors and destructors

Employee ();

Employee (

FullName name,

String address,

String workPhone,

String homePhone,

TaxId taxIdNumber,

JobClassification jobClass

);

Virtual ~Employee ();

// public routines

FullName GetName() const;

String GetAddress () const;


6

String GetWorkPhone () const;

String GetHomePhone () const;

TaxId GetTaxIdNumber () const;

JobClassification GetJobClassification () const;

...

private:

...

};

134

Internamente, esta clase puede tener rutinas y datos adicionales para soportar estos servicios,

pero los usuarios de la clase no necesitan saber nada sobre ellos. La abstracción de la interfaz

de clase es excelente porque cada rutina en la interfaz está trabajando hacia un fin

consistente.

Una clase que presenta una abstracción pobre sería una que contuviera una colección de

funciones misceláneas. Aquí hay un ejemplo:


7

Ejemplo de C ++ de una interfaz de clase que presenta una abstracción pobre

class Program {

public:

...

// public routines

void InitializeCommandStack();

void PushCommand( Command command );

Command PopCommand();

void ShutdownCommandStack();

void InitializeReportFormatting();

void FormatReport( Report report );

void PrintReport( Report report );

void InitializeGlobalData();

void ShutdownGlobalData();

...

private:

...

};
8

Supongamos que una clase contiene rutinas para trabajar con una pila de comandos, formatear

informes, imprimir informes e inicializar datos globales. Es difícil ver cualquier conexión entre

la pila de comandos y las rutinas de informe o los datos globales. La interfaz de clase no presenta

una abstracción consistente, por lo que la clase tiene una cohesión deficiente. Las rutinas deben

reorganizarse en clases más enfocadas, cada una de las cuales proporciona una mejor abstracción

en su interfaz.

Si estas rutinas formaran parte de una clase de Programa, podrían revisarse para presentar una

abstracción consistente, como por ejemplo:135

C ++ Ejemplo de una interfaz de clase que presenta una mejor abstracción

class Program {

public:

...

// public routines

void InitializeUserInterface();

void ShutDownUserInterface();

void InitializeReports();

void ShutDownReports();

...

private:
9

...

};

Aquí hay un ejemplo de una clase que presenta una interfaz que es inconsistente porque su

nivel de abstracción no es uniforme:

class EmployeeCensus: public ListContainer {

public:

// public routines

void AddEmployee( Employee employee );

void RemoveEmployee( Employee employee );

Employee NextItemInList();

Employee FirstItem();

Employee LastItem();

...

private:

...

};

136
10

Esta clase presenta dos ADT: un empleado y un ListContainer. Este tipo de abstracción mixta

suele surgir cuando un programador utiliza una clase contenedora u otras clases de biblioteca

para la implementación y no oculta el hecho de que se utiliza una clase de biblioteca.

Por lo general, ese es un detalle de la implementación que debe ocultarse del resto del

programa, como este: 136

Ejemplo de C ++ de una interfaz de clase con niveles consistentes de abstracción

class EmployeeCensus {

public:

...

// public routines

void AddEmployee( Employee employee );

void RemoveEmployee( Employee employee );

Employee NextEmployee();

Employee FirstEmployee();

Employee LastEmployee();

...

private:

ListContainer m_EmployeeList;
11

...

};

2.3 Razones para crear una clase 152

Las clases se crean por muchas razones más que eso. Aquí hay una lista de buenas razones

para crear una clase.

- Reducir la complejidad.
- Complejidad de aislamiento.
- Ocultar detalles de implementación.
- Limitar los efectos de los cambios.
- Ocultar datos globales.
- Racionalizar el paso de parámetros.
- Hacer puntos centrales de control.
- Facilitar código reutilizable.
- Plan de una familia de programas.
- Paquete de operaciones relacionadas.

3. Parametrización y genéricos

Los tipos parametrizados, también conocidos como genéricos (Ada, Eiffel) y templates

(C++), permiten la definición de un tipo o clase sin especificar todos los otros tipos que

utiliza. Los tipos no especificados se suministran como parámetros en el punto de uso. Los

tipos parametrizados proporcionan una tercera forma (además de la herencia de clase y la

composición de objetos) para componer comportamientos en software orientado a objetos.

3.1 ¿Qué es un patrón de diseño? 2 gamma

"Cada patrón describe un problema que ocurre una y otra vez en nuestro entorno, y luego

describe el núcleo de la solución a ese problema, de tal manera que puede utilizar esta

solución un millón de veces, sin tener que hacerlo. de la misma manera dos veces "
12

En general, un patrón tiene cuatro elementos esenciales:

- El nombre del patrón es un identificador que podemos usar para describir un

problema de diseño, sus soluciones y consecuencias en una o dos palabras.


- El problema describe cuándo aplicar el patrón.
- La solución describe los elementos que conforman el diseño, sus relaciones,

responsabilidades y colaboraciones.
- Las consecuencias son los resultados y las compensaciones de aplicar el patrón.

3.2 Patrones de diseño en Smalltalk MVC 4

MVC consiste en tres tipos de objetos. El Modelo es el objeto de la aplicación, la Vista es

la presentación en pantalla y el Controlador define la forma en que la interfaz de usuario

reacciona a la entrada del usuario. Antes de MVC, los diseños de interfaz de usuario tendían a

agrupar estos objetos. MVC los desacopla para aumentar la flexibilidad y reutilizarlos.

3.3 Describiendo patrones de diseño 6

Describimos patrones de diseño utilizando un formato consistente. Cada patrón se divide

en secciones de acuerdo con la siguiente plantilla. La plantilla presta una estructura uniforme

a la información, haciendo que los patrones de diseño sean más fáciles de aprender, comparar

y usar.

3.4 Cómo los patrones de diseño resuelven problemas de diseño 11

Los patrones de diseño resuelven muchos de los problemas cotidianos que enfrentan los

diseñadores orientados a objetos, y de muchas maneras diferentes. Aquí hay varios de estos

problemas.

- Encontrar objetos apropiados


- Determinación de la granularidad del objeto
- Especificar interfaces de objetos
- Especificar implementaciones de objetos
- Herencia de clase versus interfaz
13

- Programación a una interfaz, no una implementación


- Poner en marcha mecanismos de reutilización
- Delegación
- Herencia versus tipos parametrizados
- Relacionar las estructuras de tiempo de ejecución y compilación
- Diseñando para el cambio
- Programas de aplicación
- Toolkits
- Frameworks

3.5 Cómo seleccionar un patrón de diseño 28 gamma

Con más de 20 patrones de diseño en el catálogo para elegir, puede ser difícil

encontrar el que resuelva un problema de diseño en particular, especialmente si el

catálogo es nuevo y desconocido. Aquí hay varios enfoques diferentes para encontrar el

patrón de diseño adecuado para los diferentes problemas:

- Considerar cómo los patrones de diseño resuelven problemas de diseño.


- Escanear las secciones de Intención.
- Estudiar cómo se interrelacionan los patrones.
- Estudiar patrones de propósito similar.
- Examinar una causa de rediseño.
- Considera lo que debería ser variable en tu diseño.

3.6 Cómo usar un patrón de diseño 29

Una vez se haya elegido un patrón de diseño, se debe tener un enfoque paso a paso para

aplicar un patrón de diseño de manera efectiva:

- Leer el patrón una vez para obtener una visión general.


- Regresar y estudiar las secciones de Estructura, Participantes y Colaboraciones.
- Mirar la sección de Código de muestra para ver un ejemplo concreto del patrón en el

código.
- Elegir nombres para los participantes del patrón que sean significativos en el contexto de

la aplicación.
- Definir las clases.
- Definir nombres específicos de la aplicación para las operaciones en el patrón.
14

- Implementar las operaciones para llevar a cabo las responsabilidades y colaboraciones en

el patrón.

4. Aserciones, diseño por contrato y programación defensiva

4.1 Aserciones 189 mc

Una aserción es un ejecutable que se coloca en un programa, generalmente una rutina o

macro que permite verificaciones en tiempo de ejecución del programa. Las aserciones son

especialmente útiles en programas de alta confiabilidad. Permiten a los programadores

eliminar más rápidamente las suposiciones de interfaz no coincidentes, los errores que surgen

cuando se modifica el código, etc. Las aserciones normalmente se compilan en el código en

el momento del desarrollo y luego se compilan fuera del código para que no degraden el

rendimiento.

Una aserción es un código que se usa durante el desarrollo, generalmente una rutina o

macro que permite que un programa se verifique a sí mismo mientras se ejecuta. Cuando

una aserción es verdadera, eso significa que todo funciona como se espera. Cuando es

falso, eso significa que ha detectado un error inesperado en el código. Por ejemplo, si el

sistema asume que un archivo de información del cliente nunca tendrá más de 50,000

registros, el programa podría contener una afirmación de que el número de registros es

menor o igual a 50,000. Mientras el número de registros sea menor o igual a 50,000, la
15

afirmación será silenciosa. Sin embargo, si encuentra más de 50,000 registros, "afirmará"

en voz alta que hay un error en el programa.

190 mc

Las aserciones son especialmente útiles en programas grandes y complicados y en

programas de alta confiabilidad. Permiten a los programadores eliminar más rápidamente las

suposiciones de interfaz no coincidentes, los errores que surgen cuando se modifica el código,

etc. Una aserción generalmente toma dos argumentos: una expresión booleana que describe la

suposición que se supone que es cierta y un mensaje para mostrar si no lo es.

4.2 Diseño por contrato

El diseño por contrato es un enfoque de desarrollo en el que se incluyen condiciones

previas y condiciones posteriores para cada rutina. Cuando se usan condiciones previas y

posteriores, se dice que cada rutina o clase forma un contrato con el resto del programa.

Además, un contrato proporciona una especificación precisa de la semántica de una rutina, y

por lo tanto ayuda a la comprensión de su comportamiento. El diseño por contrato está

pensado para mejorar la calidad de la construcción del software.

4.3 Programación defensiva 211 mc

La programación defensiva significa proteger una rutina para que no se rompa con entradas

no válidas. Las formas comunes de manejar entradas inválidas incluyen verificar los valores de

todos los parámetros de entrada y decidir cómo manejar entradas incorrectas. Las aserciones se

usan a menudo en la programación defensiva para verificar los valores de entrada.

Demasiada programación defensiva crea problemas propios. Si verifica los datos pasados

como parámetros de todas las formas posibles en cada lugar concebible, su programa será lento y
16

gordo. Lo que es peor, el código adicional necesario para la programación defensiva agrega

complejidad al software. El código instalado para la programación defensiva no es inmune a los

defectos, y es tan probable que encuentre un defecto en el código de programación defensiva

como en cualquier otro código, más probablemente si escribe el código de manera casual. Piense

dónde necesita estar a la defensiva y establezca sus prioridades de programación defensiva en

consecuencia.

5. Gestión de errores, excepción y tolerancia al fallo

La forma en que se manejan los errores afecta la capacidad del software para cumplir con

los requisitos relacionados con la corrección, la solidez y otros atributos no funcionales. Las

aserciones se utilizan a veces para comprobar errores. También se utilizan otras técnicas de

manejo de errores, como devolver un valor neutral, sustituir la siguiente pieza de datos

válidos, registrar un mensaje de advertencia, devolver un código de error o apagar el software.

Las excepciones se utilizan para detectar y procesar errores o eventos excepcionales. La

estructura básica de una excepción es que una rutina usa lanzar para lanzar una excepción

detectada y un bloque de manejo de excepciones detectará la excepción en un bloque try-

catch. El bloque try catch puede procesar la condición errónea en la rutina o puede devolver el

control a la rutina de llamada. Las políticas de manejo de excepciones deben diseñarse

cuidadosamente siguiendo principios comunes tales como incluir en el mensaje de excepción

toda la información que condujo a la excepción, evitando bloqueos vacíos, sabiendo las

excepciones que arroja el código de la biblioteca, tal vez la creación de un reportero

centralizado de excepciones y la estandarización del uso de excepciones por parte del

programa.
17

La tolerancia a fallas es una colección de técnicas que aumentan la confiabilidad del

software al detectar errores y luego recuperarse de ellos si es posible o contener sus efectos si

la recuperación no es posible. Las estrategias de tolerancia a fallas más comunes incluyen

realizar copias de seguridad y reintentar, usar código auxiliar, usar algoritmos de votación y

reemplazar un valor erróneo con un valor falso que tendrá un efecto benigno.

5.1 Técnicas de manejo de errores 194

Las aserciones se utilizan para manejar errores que nunca deberían ocurrir en el

código. ¿Cómo maneja los errores que espera que ocurran? Dependiendo de las

circunstancias específicas, es posible que desee devolver un valor neutral, sustituir el

siguiente fragmento de datos válidos, devolver la misma respuesta que la vez anterior,

sustituir el valor legal más cercano, registrar un mensaje de advertencia en un archivo,

devolver un código de error , llame a una rutina u objeto de procesamiento de errores,

muestre un mensaje de error o apague, o tal vez quiera usar una combinación de estas

respuestas. Estas opciones según McConell pueden ser: 195

- Devuelve un valor neutral


- Sustituye la siguiente pieza de datos válidos.
- Devuelve la misma respuesta que la vez anterior.
- Sustituir el valor legal más cercano.
- Registrar un mensaje de advertencia en un archivo
- Devuelve un código de error
- Llamar a una rutina de procesamiento de errores / objeto
- Mostrar un mensaje de error donde sea que se encuentre el error
- Manejar el error de la manera que mejor funcione localmente
- Apagar