Chapter 1.
Introduction to Object
Oriented Programming
Aunque los lenguajes orientados a objetos existen desde la década de 1960, en los últimos 10
años se ha visto un crecimiento sin precedentes en el uso y aceptación de las tecnologías
orientadas a objetos en toda la industria del software. Aunque comenzó como un desvalido,
éxitos recientes como Java, CORBA y C++ han impulsado las técnicas orientadas a objetos (OO)
a nuevos niveles de aceptación. Eso no es casualidad. Después de años de estar atrapada en el
ámbito académico y de tener que luchar contra prácticas arraigadas, la programación orientada a
objetos (OOP) ha madurado hasta el punto en que la gente finalmente puede darse cuenta de las
promesas que la técnica ofrece. En el pasado, tenías que convencer a tu jefe para que te dejara
usar un lenguaje orientado a objetos. Hoy en día, muchas empresas mandatan su uso. Es seguro
decir que la gente finalmente está escuchando.
Si estás leyendo este libro, finalmente has llegado. Probablemente eres alguien con un nivel
intermedio de experiencia en programación. Ya sea que tu experiencia sea en C, Visual Basic o
FORTRAN, tienes experiencia pero has decidido que debes darle un vistazo serio a la
programación orientada a objetos y hacerla parte de tu conjunto de habilidades.
Incluso si tienes algo de experiencia con un lenguaje orientado a objetos, este libro puede
ayudarte a solidificar tu comprensión de OO. Pero no te asustes si no estás familiarizado con un
lenguaje OO. Aunque este libro usa Java para enseñar conceptos OO, no es necesario tener
conocimientos previos de Java. Si en algún momento te sientes confundido o necesitas un repaso
de la sintaxis, simplemente consulta el Apéndice B, "Introducción a Java".
Ya sea que necesites OO para mantenerte competitivo en el mercado, para llevar a cabo tu nuevo
proyecto o para satisfacer tu propia curiosidad, has llegado al lugar correcto. Aunque ningún
libro puede enseñarte todo lo que hay que saber sobre OO, este libro promete darte una base
sólida en OO. Con esta base, puedes comenzar a practicar OOP. Más importante aún, esta base te
proporcionará el fundamento duradero que necesitas para seguir aprendiendo y eventualmente
dominar este paradigma de programación.
Hoy aprenderás
La programación orientada a objetos en un contexto histórico
Los conceptos básicos de la programación orientada a objetos
Los beneficios y objetivos de la programación orientada a objetos
Los errores y falacias comunes asociados con la programación orientada a objetos
Object Oriented Programming in a
Historical Context
Para entender el estado actual de la programación orientada a objetos (OOP), es necesario conocer un
poco sobre la historia de la programación. Nadie concibió la OOP de la noche a la mañana. En cambio, la
OOP es solo otra etapa en la evolución natural del desarrollo de software. Con el tiempo, se vuelve más
fácil distinguir las prácticas que funcionan de aquellas que demuestran ser fallidas. La OOP combina
prácticas probadas y comprobadas de la manera más eficiente posible.
OO es la abreviatura de orientado a objetos. OO es un término general que incluye cualquier estilo de
desarrollo basado en el concepto de "objeto", una entidad que exhibe características y comportamiento.
Puedes aplicar un enfoque orientado a objetos tanto a la programación como al análisis y diseño.
También se puede decir que OO es un estado mental, una forma de ver el mundo y de ver todo en
términos de objetos.
Simplemente, OO contiene todo lo que puede ser prefijado como orientado a objetos. Verás el término
OO muchas veces en este libro.
### Precursores de la OOP
Hoy en día, cada vez que usas una computadora te beneficias de 50 años de refinamiento. La
programación temprana era ingeniosa: los programadores ingresaban programas directamente en la
memoria principal de la computadora a través de bancos de interruptores. Los programadores escribían
sus programas en los lenguajes binarios de la máquina. Tal programación en lenguaje máquina era
extremadamente propensa a errores, y la falta de una estructura general hacía que el mantenimiento
del código fuera casi imposible. Además, el código en lenguaje máquina no era muy accesible.
A medida que las computadoras se volvieron más comunes, comenzaron a aparecer lenguajes
procedimentales de más alto nivel; el primero fue FORTRAN. Sin embargo, lenguajes procedimentales
posteriores, como ALGOL, tuvieron más influencia en OO. Los lenguajes procedimentales permiten al
programador descomponer un programa en una serie de procedimientos detallados para procesar
datos. Estos procedimientos detallados definen la estructura general del programa. Las llamadas
secuenciales a estos procedimientos impulsan la ejecución del programa procedimental. El programa
termina una vez que ha terminado de llamar a su lista de procedimientos.
Este paradigma presentó una serie de mejoras sobre el lenguaje máquina, incluida la adición de una
estructura general: el procedimiento. Las funciones más pequeñas no solo son más fáciles de entender,
sino que también son más fáciles de depurar. Por otro lado, la programación procedimental limita la
reutilización del código. Y, con demasiada frecuencia, los programadores producían código espagueti:
código cuyo camino de ejecución se asemejaba a un plato de espagueti. Finalmente, la naturaleza
centrada en los datos de la programación procedimental causó algunos problemas propios. Debido a
que los datos y el procedimiento están separados, no hay encapsulación de datos. Esto requiere que
cada procedimiento sepa cómo manipular correctamente los datos. Desafortunadamente, una función
que se comporte mal podría introducir errores si no manipula los datos correctamente. Dado que cada
procedimiento necesitaba duplicar el conocimiento de cómo acceder a los datos, un cambio en la
representación de los datos requeriría cambios en cada lugar que accede a los datos. Así, incluso un
pequeño cambio puede... llevar a una cascada de cambios en todo el programa, en otras palabras, una
pesadilla de mantenimiento.
La programación modular, con un lenguaje como Modula-2, intenta mejorar algunas de las deficiencias
encontradas en la programación procedimental. La programación modular descompone los programas
en varios componentes constituyentes o módulos. A diferencia de la programación procedimental, que
separa datos y procedimientos, los módulos combinan ambos. Un módulo consiste en datos y los
procedimientos para manipular esos datos. Cuando otras partes del programa necesitan usar un
módulo, simplemente ejercen la interfaz del módulo. Debido a que los módulos ocultan todos los datos
internos del resto del programa, es fácil introducir la idea de estado: un módulo mantiene información
de estado que podría cambiar con el tiempo.
El estado de un objeto es el significado combinado de las variables internas de un objeto. Una variable
interna es un valor mantenido dentro de un objeto.
Pero la programación modular sufre de importantes deficiencias propias. Los módulos no son
extensibles, lo que significa que no puedes hacer cambios incrementales a un módulo sin abrir el código
y hacer cambios directamente. Tampoco puedes basar un módulo en otro, excepto a través de la
delegación. Y, aunque un módulo puede definir un tipo, un módulo no puede compartir el tipo de otro
módulo.
En lenguajes modulares y procedimentales, los datos estructurados y no estructurados tienen un "tipo".
El tipo se puede considerar como el formato en memoria de los datos. Los lenguajes fuertemente
tipados requieren que cada objeto tenga un tipo específico y definido. Sin embargo, los tipos no se
pueden extender para crear otro tipo, excepto a través de un estilo llamado "agregación". Por ejemplo,
en C, podríamos tener dos tipos de datos relacionados:
typedef struct {
int a;
int b;
} aBaseType;
typedef struct {
aBaseType Base;
int c;
} aDerivedType;
```
En este ejemplo, `aDerivedType` se basa en `aBaseType`, pero una estructura de `aDerivedType` no se
puede tratar directamente como una estructura de `aBaseType`. Solo se puede referenciar el miembro
`Base` de una estructura `aDerivedType`. Desafortunadamente, este arreglo lleva a un código que
depende en gran medida de bloques `case` y `if/else` porque la aplicación debe saber cómo manipular
cada módulo que encuentra.
Finalmente, la programación modular también es un híbrido procedimental que aún divide un programa
en una serie de procedimientos. Ahora, en lugar de actuar sobre datos en bruto, estos procedimientos
manipulan módulos.
### Programación Orientada a Objetos
La OOP da el siguiente paso lógico después de la programación modular al agregar herencia y
polimorfismo al módulo. La OOP estructura un programa dividiéndolo en una serie de objetos de alto
nivel. Cada objeto modela algún aspecto del problema que intentas resolver. Escribir una lista secuencial
de llamadas a procedimientos para dirigir el flujo del programa ya no es el enfoque principal de la
programación bajo OO. En su lugar, los objetos interactúan entre sí para impulsar el flujo general del
programa. De cierta manera, un programa OOP se convierte en una simulación viviente del problema
que intentas resolver.
### Un Enfoque OOP para el Software Usando Objetos
Imagina que tienes que desarrollar un programa OOP para implementar un carrito de compras en línea
o un terminal de punto de venta. Un programa OOP contendrá objetos de artículo, carrito de compras,
cupón y cajero. Cada uno de estos objetos interactuará entre sí para impulsar el programa. Por ejemplo,
cuando el cajero totaliza un pedido, verificará el precio de cada artículo.
Definir un programa en términos de objetos es una forma profunda de ver el software. Los objetos te
obligan a ver todo a nivel conceptual en términos de lo que hace un objeto: sus comportamientos. Ver
un objeto desde el nivel conceptual es un cambio respecto a mirar cómo se hace algo: la
implementación. Esta mentalidad te obliga a pensar en tus programas en términos naturales y del
mundo real. En lugar de modelar tu programa como un conjunto de procedimientos y datos separados
(términos del mundo de la computadora), modelas tu programa en objetos. Los objetos te permiten
modelar tus programas en los sustantivos, verbos y adjetivos de tu dominio del problema.
La implementación define cómo se hace algo. En términos de programación, la implementación es el
código.
El dominio es el espacio donde vive un problema. El dominio es el conjunto de conceptos que
representan los aspectos importantes del problema que estás tratando de resolver.
Cuando das un paso atrás y piensas en términos del problema que estás resolviendo, evitas quedar
atrapado en los detalles de la implementación. Claro, algunos de tus objetos de alto nivel necesitarán
interactuar con la computadora de algunas maneras de bajo nivel, orientadas a la computadora. Sin
embargo, el objeto aislará esas interacciones del resto del sistema. (El Día 2, "Encapsulación: Aprende a
Mantener los Detalles para Ti", explora estos beneficios más a fondo.)
NOTA
En términos del carrito de compras, ocultar la implementación significa que el cajero no mira los datos
en bruto al totalizar un pedido. El cajero no sabe que debe verificar un cierto array de ubicaciones de
memoria para los números de artículos y otra variable para un cupón. En cambio, el cajero interactúa
con objetos de artículos. Sabe que debe preguntar al artículo cuánto cuesta.
En este punto, puedes definir formalmente un objeto:
**Un objeto es una construcción de software que encapsula estado y comportamiento. Los objetos te
permiten modelar tu software en términos y abstracciones del mundo real.**
Estrictamente hablando, un objeto es una instancia de una clase. La siguiente sección introducirá el
concepto de clase en la OOP.
Así como el mundo real está compuesto por objetos, también lo está el software orientado a objetos. En
un lenguaje de programación OO puro, todo es un objeto, desde los tipos más básicos como enteros y
booleanos hasta las instancias de clases más complejas; no todos los lenguajes orientados a objetos
llegan tan lejos. En algunos (como Java), los primitivos simples como `int` y `float` no se tratan como
objetos.
### ¿Qué es una Clase?
Al igual que los objetos en el mundo real, el mundo de la OOP agrupa objetos por sus comportamientos
y atributos comunes.
La biología clasifica a todos los perros, gatos, elefantes y humanos como mamíferos. Las características
compartidas dan a estas criaturas una comunidad. En el mundo del software, las clases agrupan objetos
relacionados de la misma manera.
**Una clase define todas esas características comunes a un tipo de objeto.** Específicamente, la clase
define todos esos atributos y comportamientos expuestos por el objeto. La clase define específicamente
a qué mensajes responden sus objetos. Cuando un objeto quiere ejercer el comportamiento de otro
objeto, no lo hace directamente, sino que le pide al otro objeto que se cambie a sí mismo, generalmente
basado en alguna información adicional. A menudo, esto se conoce como "enviar un mensaje."
**Una clase define los atributos y comportamientos comunes compartidos por un tipo de objeto.** Los
objetos de un cierto tipo o clasificación comparten los mismos comportamientos y atributos. Las clases
actúan muy similar a una plantilla o cortador de galletas en el sentido de que usas una clase para crear o
instanciar instancias de objetos.
**Los atributos son las características visibles externamente de una clase.** El color de ojos y el color de
cabello son ejemplos de atributos.
Un objeto puede exponer un atributo proporcionando un enlace directo a alguna variable interna o
devolviendo el valor a través de un método.
Un comportamiento es una acción realizada por un objeto cuando se le envía un mensaje o en respuesta
a un cambio de estado: es algo que hace un objeto.
Un objeto puede ejercitar el comportamiento de otro objeto realizando una operación sobre ese objeto.
Puedes ver los términos llamada de método, llamada de función o pasar un mensaje utilizados en lugar
de realizar una operación. Lo importante es que cada una de estas acciones provoca el comportamiento
de un objeto.
**Nota**:
El paso de mensajes, operación, llamada de método y llamada de función; cuál utilizas a menudo
depende de tu formación.
Pensar en términos de paso de mensajes es una manera muy orientada a objetos de pensar. El paso de
mensajes es dinámico. Conceptualmente separa el mensaje del objeto. Tal mentalidad puede ayudar al
pensar sobre las interacciones de tus objetos.
Lenguajes como C++ y Java provienen de herencias procedimentales donde las llamadas a funciones son
estáticas. Como resultado, estos lenguajes a menudo se refieren a que un objeto realiza una llamada de
método sobre otro. Una llamada de método está fuertemente acoplada al objeto.
Este libro normalmente utilizará llamada de método debido a sus estrechos vínculos con Java. Sin
embargo, puede haber momentos en los que se use mensaje de manera intercambiable.
### Poniéndolo Todo Junto: Clases y Objetos
Tomemos un objeto de artículo como ejemplo. Un artículo tiene una descripción, identificación, precio
unitario, cantidad y un descuento opcional. Un artículo sabrá cómo calcular su precio con descuento.
En el mundo de la OOP, dirías que todos los objetos de artículo son instancias de la clase `Item`. Una
clase `Item` podría verse algo así:
```java
public class Item {
private double unit_price;
private double discount; // a percentage discount to apply to
the price
private int quantity;
private String description;
private String id;
public Item( String id, String description, int quantity, double
price ) {
this.id = id;
this.description = description;
if( quantity >= 0 ) {
this.quantity = quantity;
}
else {
this.quantity = 0;
}
this.unit_price = price;
public double getAdjustedTotal() {
double total = unit_price * quantity;
double total_discount = total * discount;
double adjusted_total = total - total_discount;
return adjusted_total;
// applies a percentage discount to the price
public void setDiscount( double discount ) {
if( discount <= 1.00 ) {
this.discount = discount;
}
else {
this.discount = 0.0;
}
}
public double getDiscount() {
return discount;
public int getQuantity() {
return quantity;
public void setQuantity( int quantity ) {
if( quantity >= 0 ) {
this.quantity = quantity;
}
}
public String getProductID() {
return id;
public String getDescription() {
return description;
}
Methods such as
public Item( String id, String description, int quantity, double price
)
### Constructores
Los constructores son métodos que se utilizan para inicializar objetos durante su creación. Se les llama
constructores porque inicializan un objeto durante su instanciación. Instanciación se refiere a la creación
de una instancia de objeto de la clase.
**Nota**:
En el constructor y a lo largo del ejemplo de `Item` podrías notar el uso de `this`. `this` es una referencia
que apunta a la instancia del objeto. Cada objeto tiene su propia referencia a sí mismo. La instancia usa
esa referencia para acceder a sus propias variables y métodos.
Métodos como `setDiscount()`, `getDescription()`, y `getAdjustedTotal()` son todos comportamientos de
la clase `Item` que devuelven o establecen atributos. Cuando un cajero quiere totalizar el carrito,
simplemente toma cada artículo y envía el mensaje `getAdjustedTotal()` al objeto.
`unit_price`, `discount`, `quantity`, `description` e `id` son todas variables internas de la clase `Item`.
Estos valores comprenden el estado del objeto. El estado de un objeto puede variar con el tiempo. Por
ejemplo, mientras compra, un comprador puede aplicar un cupón al artículo. Aplicar un cupón al
artículo cambiará el estado del artículo, ya que cambiará el valor de `discount`.
### Accesores y Mutadores
Comportamientos como `getAdjustedTotal()` y `getDiscount()` se llaman accesores, ya que te permiten
acceder a los datos internos de un objeto. El acceso puede ser directo, como en el caso de
`getDiscount()`. Por otro lado, el objeto puede realizar un procesamiento antes de devolver un valor,
como en el caso de `getAdjustedTotal()`.
**Accesores**:
Los accesores te permiten acceder a los datos internos de un objeto. Sin embargo, los accesores ocultan
si los datos están en una variable, en una combinación de variables o si se calculan. Los accesores te
permiten cambiar o recuperar el valor y tener "efectos secundarios" sobre el estado interno.
Comportamientos como `setDiscount()` se llaman mutadores, ya que te permiten alterar el estado
interno del objeto. Un mutador puede procesar su entrada como lo considere apropiado antes de
alterar el estado interno del objeto. Tomemos por ejemplo `setDiscount()`. `setDiscount()` se asegura de
que el descuento no sea mayor del 100% antes de aplicar el descuento.
**Mutadores**:
Los mutadores te permiten alterar el estado interno de un objeto.
Cuando se ejecutan, tus programas utilizan clases como `Item` para crear o instanciar los objetos que
componen la aplicación. Cada nueva instancia es un duplicado de la anterior. Sin embargo, una vez
instanciada, la instancia lleva a cabo comportamientos y mantiene su estado. Así que lo que comienza su
vida como un clon puede comportarse de manera muy diferente a lo largo de su vida útil.
Putting Objects to Work
Consider the following main() method:
public static void main( String [] args ) {
// create the items
Item milk = new Item( "dairy-011", "1 Gallon Milk", 2, 2.50
);
Item yogurt = new Item( "dairy-032", "Peach Yogurt", 4, 0.68 );
Item bread = new Item( "bakery-023", "Sliced Bread", 1, 2.55
);
Item soap = new Item( "household-21", "6 Pack Soap", 1, 4.51
);
// apply coupons
milk.setDiscount( 0.15 );
// get adjusted prices
double milk_price = milk.getAdjustedTotal();
double yogurt_price = yogurt.getAdjustedTotal();
double bread_price = bread.getAdjustedTotal();
double soap_price = soap.getAdjustedTotal();
// print receipt
System.out.println( "Thank You For Your Purchase." );
System.out.println( "Please Come Again!" );
System.out.println( milk.getDescription() + "\t $" +
milk_price );
System.out.println( yogurt.getDescription() + "\t $" +
yogurt_price );
System.out.println( bread.getDescription() + "\t $" +
bread_price );
System.out.println( soap.getDescription() + "\t $" +
soap_price );
// calculate and print total
double total = milk_price + yogurt_price + bread_price +
soap_price;
System.out.println( "Total Price\t $" + total );
}
Este método te muestra cómo podría lucir un pequeño programa que utiliza objetos de tipo `Item`.
Primero, el programa instancia cuatro objetos de tipo `Item`. En un programa real, estos objetos podrían
crearse mientras un usuario navega por un catálogo en línea o mientras un cajero escanea comestibles.
Este programa crea varios artículos, aplica descuentos y luego imprime un recibo. Todas las
interacciones con los objetos las realiza el programa enviando diversos mensajes a los artículos. Por
ejemplo, el programa aplica un descuento del 15% a la leche enviando el mensaje `setDiscount()` al
artículo. Luego, el programa totaliza los artículos enviando a cada uno el mensaje `getAdjustedTotal()`.
Finalmente, este programa muestra un recibo en pantalla. La Figura 1.1 ilustra la salida de muestra.
Es importante darse cuenta de que toda la programación se realizó en términos de objetos `Item` y los
comportamientos expuestos por los métodos de `Item`; los sustantivos y verbos del dominio del carrito
de compras.
### Relaciones entre Objetos
Cómo se relacionan los objetos es un componente muy importante de la POO. Los objetos pueden
relacionarse de dos maneras importantes.
Primero, los objetos pueden existir independientemente uno del otro. Dos objetos `Item` pueden
aparecer en el carrito de compras al mismo tiempo. Si estos dos objetos separados alguna vez necesitan
interactuar, lo harán pasándose mensajes.
Los objetos se comunican entre sí a través de mensajes. Los mensajes hacen que un objeto haga algo.
"Enviar un mensaje" es lo mismo que llamar a un método para cambiar el estado del objeto o para
ejercer un comportamiento.
Segundo, un objeto puede contener otros objetos. Así como los objetos componen un programa de
POO, los objetos pueden componer otros objetos mediante la agregación. Del ejemplo del `Item`,
puedes notar que el objeto `item` contiene muchos otros objetos. Por ejemplo, el objeto `item` también
contiene una descripción y un ID. La descripción y el ID son ambos objetos `String`. Cada uno de estos
objetos tiene una interfaz que ofrece métodos y atributos. Recuerda, ¡en POO todo es un objeto, incluso
las piezas que componen un objeto!
La comunicación funciona de la misma manera entre un objeto y los objetos que contiene. Cuando los
objetos necesitan interactuar, lo hacen enviándose mensajes entre ellos.
Los mensajes son un concepto importante en la POO. Permiten que los objetos permanezcan
independientes. Cuando un objeto envía un mensaje a otro objeto, generalmente no le importa cómo el
objeto elige llevar a cabo el comportamiento solicitado. El objeto solicitante solo se preocupa de que el
comportamiento ocurra.
Aprenderás más sobre cómo se relacionan los objetos la próxima semana.
### Precaución
La definición de objeto está abierta a debate. Algunas personas no definen un objeto como una
instancia de una clase. En cambio, definen todo en términos de ser un objeto: desde este punto de vista,
una clase es un objeto que crea otros objetos. Tratar una clase como un objeto es importante para
conceptos como la metaclase.
Cada vez que este libro encuentre un desacuerdo en la terminología, elegiremos una definición y nos
adheriremos a ella. La elección será muy a menudo pragmática. Aquí, hemos optado por usar la
definición de objeto como instancia. Esta es la definición del Lenguaje Unificado de Modelado (UML) y la
más comúnmente encontrada en la industria. (Aprenderás más sobre UML más adelante).
Desafortunadamente, la otra definición es una definición más pura de orientación a objetos. Sin
embargo, no te encontrarás con ella muy a menudo, y el concepto de metaclase está fuera del alcance
de este libro.
### Cómo la Programación Orientada a Objetos se Basa en el Pasado
Así como los otros paradigmas intentan aprovechar las fortalezas y corregir las fallas de los paradigmas
anteriores, la POO se basa en la programación procedural y modular.
La programación modular estructura un programa en una serie de módulos. De manera similar, la POO
divide un programa en una serie de objetos que interactúan entre sí. Así como los módulos ocultan las
representaciones de datos detrás de procedimientos, los objetos encapsulan su estado detrás de su
interfaz. La POO toma este concepto de encapsulamiento directamente de la programación modular.
El encapsulamiento difiere mucho de la programación procedural. La programación procedural no
encapsula datos. En cambio, los datos están abiertos para que todos los procedimientos accedan. A
diferencia de la programación procedural, la programación orientada a objetos acopla estrechamente
datos y comportamiento.
Juntos en el objeto. Aprenderás más sobre encapsulamiento en el Día 2 y el Día 3, "Encapsulamiento: Es
hora de escribir código".
Aunque los objetos son similares en concepto a los módulos, difieren en varios aspectos importantes.
Primero, los módulos no admiten fácilmente la extensión. La programación orientada a objetos
introduce el concepto de herencia para solucionar esta deficiencia. La herencia te permite extender y
mejorar fácilmente tus clases. También te permite clasificar tus clases. Aprenderás más sobre la
herencia en el Día 4, "Herencia: Obtener algo por nada", y en el Día 5, "Herencia: Es hora de escribir
código".
La POO también aprovecha el concepto de polimorfismo, que ayuda a construir programas flexibles que
no resisten al cambio. El polimorfismo añade esta flexibilidad limpiando el sistema de tipos limitado del
módulo. Aprenderás más sobre el polimorfismo en el Día 6, "Polimorfismo: Aprender a predecir el
futuro", y en el Día 7, "Polimorfismo: Es hora de escribir código".
La POO ciertamente no inventó el encapsulamiento y el polimorfismo. En cambio, la POO combina estos
conceptos en un solo lugar. Añade la noción de objetos de la POO, y unes estas tecnologías de una
manera nunca antes vista.
### Beneficios y Objetivos de la POO
La programación orientada a objetos establece seis objetivos principales para el desarrollo de software.
La POO se esfuerza por producir software que tenga las siguientes características:
1. Natural
2. Confiable
3. Reutilizable
4. Mantenible
5. Ampliable
6. Oportuno
Veamos cómo trabaja para cumplir cada uno de estos objetivos.
#### Natural
La POO produce software natural. Los programas naturales son más comprensibles. En lugar de
programar en términos de un arreglo o región de memoria, puedes programar usando la terminología
de tu problema particular. No tienes que enredarte en los detalles de la computadora mientras diseñas
tu programa. En lugar de forzar tus programas en el lenguaje del mundo informático, la POO te libera
para expresar tu programa en los términos de tu problema.
La programación orientada a objetos te permite modelar un problema a nivel funcional, no a nivel de
implementación. No necesitas saber cómo funciona alguna pieza de software para poder usarla:
simplemente te concentras en lo que hace.
#### Confiable
Para crear software útil, necesitas crear software tan confiable como otros productos, como
refrigeradores y televisores. ¿Cuándo fue la última vez que tu microondas se colgó?
Los programas orientados a objetos, bien diseñados y cuidadosamente escritos, son confiables. La
naturaleza modular de los objetos te permite hacer cambios en una parte de tu programa sin afectar
otras partes. Los objetos aíslan el conocimiento y la responsabilidad donde pertenecen.
Una forma de aumentar la confiabilidad es a través de pruebas exhaustivas. La POO mejora las pruebas
al permitirte aislar el conocimiento y la responsabilidad en un solo lugar. Tal aislamiento te permite
probar y validar cada componente de forma independiente. Una vez que validas un componente,
puedes reutilizarlo con confianza.
#### Reutilizable
¿Un constructor inventa un nuevo tipo de ladrillo cada vez que construye una casa? ¿Un ingeniero
eléctrico inventa un nuevo tipo de resistor cada vez que diseña un circuito? Entonces, ¿por qué los
programadores siguen "reinventando la rueda"? Una vez que se resuelve un problema, debes reutilizar
la solución.
Puedes reutilizar fácilmente clases orientadas a objetos bien elaboradas. Al igual que con los módulos,
puedes reutilizar objetos en muchos programas diferentes. A diferencia de los módulos, la POO
introduce la herencia para permitirte extender objetos existentes y el polimorfismo para permitirte
escribir código genérico.
La POO no garantiza código genérico. Crear clases bien elaboradas es una habilidad difícil que requiere
enfoque y atención a la abstracción. Los programadores no siempre encuentran eso fácil. A través de la
POO, puedes modelar ideas generales y usar esas ideas generales para resolver problemas específicos.
Aunque construirás objetos para resolver un problema específico, a menudo construirás estos objetos
específicos usando piezas genéricas.
#### Mantenible
El ciclo de vida de un programa no termina cuando lo envías por la puerta. En cambio, debes mantener
tu base de código. De hecho, entre el 60% y el 80% del tiempo dedicado a trabajar en un programa es
mantenimiento. ¡El desarrollo es solo el 20% de la ecuación!
El código orientado a objetos bien diseñado es mantenible. Para corregir un error, simplemente corriges
el problema en un solo lugar. Dado que un cambio en la implementación es transparente, todos los
demás objetos se beneficiarán automáticamente de la mejora. El lenguaje natural del código debería
permitir que otros desarrolladores lo entiendan también.
Extensible
Así como debes mantener un programa, tus usuarios te pedirán que añadas nuevas funcionalidades a tu
sistema. A medida que construyes una biblioteca de objetos, también querrás extender la funcionalidad
de tus propios objetos.
La POO aborda estas realidades. El software no es estático. El software debe crecer y cambiar con el
tiempo para seguir siendo útil. La POO presenta al programador una serie de características para
extender el código. Estas características incluyen la herencia, el polimorfismo, la anulación, la delegación
y una variedad de patrones de diseño.
Oportuno
El ciclo de vida del proyecto de software moderno a menudo se mide en semanas. La POO ayuda en
estos ciclos de desarrollo rápidos. La POO acorta el tiempo del ciclo de desarrollo al proporcionar
software fiable, reutilizable y fácilmente extensible.
El software natural simplifica el diseño de sistemas complejos. Aunque no puedes ignorar el diseño
cuidadoso, el software natural puede agilizar los ciclos de diseño porque puedes concentrarte en el
problema que estás tratando de resolver.
Cuando descompones un programa en varios objetos, el desarrollo de cada parte puede avanzar en
paralelo. Múltiples desarrolladores pueden trabajar en clases de forma independiente. Este desarrollo
en paralelo conduce a tiempos de desarrollo más rápidos.
Pitfall 2: Temor al Reuso
Debes aprender a reutilizar código. Aprender a reutilizar sin culpa suele ser una de las lecciones más
difíciles de aprender cuando empiezas a usar la POO. Tres problemas conducen a esta dificultad.
Primero, a los programadores les gusta crear. Si miras el reuso de la manera incorrecta, parecerá que
quita parte de la alegría de la creación. Sin embargo, debes recordar que estás reutilizando piezas para
crear algo más grande que la pieza que reutilizas. Puede que no parezca emocionante reutilizar un
componente, pero te permitirá construir algo aún mejor.
Segundo, muchos programadores sufren del sentimiento de "no escrito aquí", lo que significa que no
confían en el software que no escribieron. Si un componente de software está bien probado y cumple
con tu necesidad, debes reutilizarlo. No descartes un componente de inmediato porque no lo escribiste.
Recuerda que reutilizar un componente te liberará para escribir otro software maravilloso.
Pitfall 3: Pensar en la POO como una Solución Universal
Aunque la POO ofrece muchos beneficios, no es la solución universal del mundo de la programación.
Hay momentos en los que no debes usar la POO. Aún necesitas usar el juicio para elegir la herramienta
adecuada para el trabajo en cuestión. Lo más importante es que la POO no garantiza el éxito de tu
proyecto. Tu proyecto no tendrá éxito automáticamente solo porque uses un lenguaje orientado a
objetos. El éxito solo viene con una planificación cuidadosa, diseño y codificación.
Pitfall 4: Programación Egoísta
No seas egoísta al programar. Así como debes aprender a reutilizar, también debes aprender a
compartir el código que creas. Compartir significa que animarás a otros desarrolladores a usar tus clases.
Sin embargo, compartir también significa que facilitarás que otros reutilicen esas clases.
Ten en cuenta a otros desarrolladores cuando programes. Crea interfaces limpias y comprensibles. Lo
más importante, escribe documentación. Documenta suposiciones, documenta los parámetros de los
métodos, documenta tanto como puedas. La gente no reutilizará lo que no puede encontrar o entender.
La Semana que Viene
En la semana que viene, continuarás tu introducción a la POO aprendiendo sobre los tres pilares que
forman la base de la teoría de la POO: encapsulación, herencia y polimorfismo.
Cada pilar se dividirá en dos lecciones. La primera lección presentará el pilar y la teoría detrás de él. La
segunda lección le brindará experiencia práctica con los conceptos introducidos el día anterior. Este
enfoque refleja el enfoque de conferencia / laboratorio utilizado con éxito por muchas universidades y
colegios.
Completará todos estos laboratorios utilizando el lenguaje de programación Java de Sun Microsystems.
Puede obtener todas las herramientas utilizadas en este libro de forma gratuita a través de la World
Wide Web. El Día 3, así como el Apéndice B, "Primer Java", al final del libro, lo guiarán para obtener y
configurar su entorno de desarrollo.
Nota: ¿Por qué Java?
Hay dos razones para usar Java como herramienta de enseñanza. En primer lugar, Java lo aleja
hábilmente de los detalles de la máquina y del sistema operativo. En lugar de tener que preocuparse por
la asignación y desasignación de memoria, simplemente puede concentrarse en aprender sobre objetos.
Finalmente, aprender prácticas de programación orientada a objetos en Java es práctico. Puede llevar el
conocimiento y conseguir un trabajo. Algunos lenguajes son más orientados a objetos que Java. Sin
embargo, es fácil encontrar trabajo en Java.
Resumen
Hoy realizaste un recorrido por la programación orientada a objetos. Comenzaste echando un vistazo a
la evolución de los principales paradigmas de programación, y aprendiste algunos de los conceptos
básicos de OOP. En este momento deberías entender las ideas conceptuales detrás de OO, como lo que
es una clase y cómo se comunican los objetos.
Las definiciones son importantes, pero nunca debemos perder de vista lo que estamos tratando de
lograr usando OO al quedarnos atrapados en los "cómos" de lo que estamos haciendo. Los seis
beneficios y objetivos resumen lo que la programación orientada a objetos espera lograr:
1. Natural
2. Confiable
3. Reutilizable
4. Mantenible
5. Extensible
6. Oportuno
Nunca debes perder de vista estos objetivos.
Preguntas y respuestas
P: ¿Qué puedo hacer para dominar OOP?
R: Los libros como este son una buena manera de comenzar en tu camino hacia el dominio de OO.
También es importante practicar la codificación regularmente y trabajar en proyectos que te permitan
aplicar principios orientados a objetos en escenarios del mundo real. Además, busca mentoría o únete a
comunidades en línea donde puedas discutir y aprender de las experiencias de los demás. Finalmente,
no dudes en adentrarte en temas avanzados y expandir continuamente tus conocimientos y habilidades.
Workshop
Quiz
1. ¿Qué es la programación procedural?
2. ¿Qué beneficio tiene la programación procedural sobre la programación no estructurada?
3. ¿Qué es la programación modular?
4. ¿Qué beneficios tiene la programación modular sobre la programación procedural?
5. Enumera una desventaja de la programación procedural y modular.
6. ¿Qué es la programación orientada a objetos?
7. ¿Cuáles son los seis beneficios y objetivos de la programación orientada a objetos?
8. Explica uno de los objetivos de la programación orientada a objetos.
9. Define los siguientes términos:
- Clase
- Objeto
- Comportamiento
10. ¿Cómo se comunican los objetos entre sí?
11. ¿Qué es un constructor?
12. ¿Qué es un accessor?
13. ¿Qué es un mutator?
14. ¿Qué es 'this'?
Ejercicios
Rejoice! For today, you have no written exercises. Instead, go for a walk.