¿Principio de KISS aplicado al diseño del lenguaje de programación?

14

KISS ("mantenerlo simple, estúpido" o "mantenerlo simple estúpido", ver, por ejemplo, aquí ) es un principio importante en el desarrollo de software, aunque aparentemente se originó en la ingeniería. Citando del artículo de Wikipedia:

El principio se ejemplifica mejor con la historia de Johnson entregando a un equipo de ingenieros de diseño un puñado de herramientas, con el desafío de que el avión a reacción que estaban diseñando debe ser reparable por un mecánico promedio en el campo en condiciones de combate con solo estas herramientas. Por lo tanto, lo 'estúpido' se refiere a la relación entre la forma en que las cosas se rompen y la sofisticación disponible para arreglarlas.

Si quisiera aplicar esto al campo del desarrollo de software, reemplazaría "avión a reacción" con "pieza de software", "mecánico promedio" con "desarrollador promedio" y "en condiciones de combate" con "bajo el desarrollo / mantenimiento de software esperado condiciones "(plazos, limitaciones de tiempo, reuniones / interrupciones, herramientas disponibles, etc.).

Por lo tanto, es una idea comúnmente aceptada que uno debe tratar de mantener una pieza de software simple (o simple estúpida , en caso de que omita la coma) para que sea fácil trabajar en ella más tarde.

Pero, ¿puede aplicarse el principio KISS también al diseño del lenguaje de programación? ¿Conoce algún lenguaje de programación que haya sido diseñado específicamente con este principio en mente, es decir, para "permitir que un programador promedio en condiciones de trabajo promedio escriba y mantenga tanto código como sea posible con el menor esfuerzo cognitivo"?

Si cita algún idioma específico, sería genial si pudiera agregar un enlace a algún documento en el que los diseñadores del lenguaje expresen claramente esta intención. En cualquier caso, me interesaría conocer las intenciones (documentadas) de los diseñadores en lugar de su opinión personal sobre un lenguaje de programación en particular.

Giorgio
fuente
44
¿Has explorado la familia básica de idiomas (o al menos, la intención original detrás de ellos)?
44
BÁSICO y Pascal ... ambos diseñados como lenguajes de instrucción.
Michael Brown
1
¿Qué quieres decir con simple? La mayoría de los idiomas son bastante simples, ya que no hay mucho para ellos. Nada era menos complejo que el ensamblador. Los marcos a menudo son complicados, pero están diseñados para permitir "escribir y mantener la mayor cantidad de código posible con el menor esfuerzo cognitivo".
pdr
77
Scheme (r) se utilizó como lenguaje de enseñanza durante años (¿décadas?) Y se desarrolló simplificando LISP y Algol (y puede ser más). El libro SICP toma mucho menos tiempo para enseñar el idioma en sí. Además, las DSL vienen a la mente.
vpit3833
3
@Giorgio echa un vistazo a Haskell. Tiene muy y quiero decir muy poco bits incorporados. La mayoría de los operadores son funciones que se encuentran en la biblioteca principal, pero que no son necesarias para el lenguaje en sí, ha hecho todo lo posible para eliminar todas las piezas innecesarias
Jimmy Hoffa

Respuestas:

15

Cuando pienso en el minimalismo, pienso en Lisp y Go . Con Lisp, todo lo que tiene son funciones y listas, que es lo más simple que puede obtener (bueno, hay un poco más, pero lo que sea). Sin embargo, creo que el caso Go es más interesante.

Go fue diseñado para ser simple (es una lectura decente). El término que utilizan es "ortogonalidad de características", lo que significa que cualquier característica solo debe agregarse si proporciona algo realmente único. Esto parece surgir con la participación de los autores ( Russ Cox y Rob Pike vienen a mi mente) con Plan9 , que fue una reinvención de UNIX con la simplicidad en mente. (Si está interesado en un diseño minimalista, el artículo de Rob Pike sobre un sistema simple de ventanas es una buena lectura).

Aquí hay algunos ejemplos simples de la sintaxis:

Solo una construcción en bucle

Un bucle puede verse como uno de los siguientes:

Bucle infinito

for {
}

Mientras bucle

for <conditional> {
}

Tradicional para loop

for i := 0; i < 10; i++ {
}

Bucle foreach

// works for maps or arrays
for k, v := range arr {
}

Interruptor multiusos

switch {
    // cases must be evaluate to a boolean
}

switch <value> {
}

switch t := <value>; t {
    // can use t inside
}

Retorno múltiple

return val1, val2, ...
  • Elimina la necesidad de lanzar (pasar el error como último valor de retorno)
  • Elimina la necesidad de parámetros
  • Elimina la necesidad de tuplas.

Interfaces

type X interface {
    DoSomething()
    String() string
}
  • Resuelve problemas similares a los genéricos.
  • Permite la abstracción.

Incrustación

type A struct {
    Thing string
}

type B struct {
    A // embeds A in B, so B.Thing refers to A.Thing
}
  • Resuelve el mismo problema que la herencia
  • Evita la necesidad de clases

Canales

Se puede usar para implementar semáforos

var c = make(chan bool, 1)
c<-true // semaphore lock
<-c // semaphore free

Se usa para el mensaje que pasa entre hilos

func produce(c chan<- bool) {
    for {
        c <- true
    }
}
func consume(c <-chan bool) {
    for {
        <-c
    }
}

var c = make(chan bool)
go produce(c)
go consume(c)

Se puede usar para manejar eventos asincrónicos

func async() chan bool {
    var c = make(chan bool)
    go doSomethingAsync(c)
    return c
}

// wait for long async process to finish
c := async()
select {
    case _ = <-c:
}

Conclusión

No voy a entrar en cada parte de la sintaxis, pero espero que puedan ver lo que puede hacer el minimalismo. El lenguaje es intrigante no porque agrega un montón de nuevas características, sino porque usa las mejores características de otros idiomas sin nada adicional.

Generalmente hay una "mejor" forma de resolver un problema. Por ejemplo, en la lista de correo, muchos usuarios se quejan de no tener genéricos. Después de la discusión, se dan cuenta de que todo lo que quieren hacer se puede hacer con interfaces. Lea sobre ir efectivo para obtener ejemplos de sintaxis idiomática.

El beneficio de los idiomas de KISS es que es posible escribir código idiomático, porque el estilo de código está restringido por el idioma. Por ejemplo, en Go, no puedes escribir algo como esto:

if <condition>
    statement;

Tienes que usar llaves:

if <condition> {
    statement;
}

Hay muchos otros ejemplos de esto en la sintaxis, lo que facilita la lectura del código de otras personas.

Beneficios del lenguaje KISS sobre los lenguajes característicos:

  • más fácil de entender el código de otros
  • más fácil de asimilar todo el lenguaje (C ++ es conocido por ser difícil de entender)
  • centrarse en el algoritmo, no en la sintaxis
beatgammit
fuente
55
En mi humilde opinión, la sintaxis del bucle for tradicional no es ese KISS. Por supuesto, es familiar para todos los programadores tipo C, pero recuerdo la primera vez que aprendí esto: estaba muy confundido. BÁSICO es más KISS: for i=1 to 10o python:for item in group
mouviciel
3
@mouviciel: casi nunca uso el bucle for tradicional. El problema for i = 1 to 10es si ialguna vez será 10. Esto puede depender del idioma (bash incluye 10, python no). El bucle for tradicional es universal.
beatgammit
+1, especialmente para el resumen sobre los beneficios del minimalismo.
Giorgio
1
Ir como caso de estudio es interesante porque sus detractores no lo consideran un idioma de KISS. De hecho, el argumento es el siguiente: un lenguaje "simple" no conduce a un código "simple" ni a una comprensión más fácil. A veces debe haber más complejidad (digamos, buen soporte de genéricos) para que el código sea más fácil de entender.
Andres F.
14

Creo que el Zen de Python indicará por qué Python es un lenguaje simple mucho mejor de lo que puedo:

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Editar en respuesta a @Giorgio

Como dice tu pregunta,

"¿Conoce algún lenguaje de programación que haya sido diseñado específicamente con este principio en mente, es decir, 'permitir que un programador promedio en condiciones de trabajo promedio escriba y mantenga tanto código como sea posible con el menor esfuerzo cognitivo'"

Python es, para mí, lo que inmediatamente me viene a la mente. El diseño de Python responde directamente a la metodología de Perl, el famoso "Hay más de una forma de hacerlo". Si bien eso es genial, ya que permite a los programadores escribir código muy fácilmente, no ayuda con el mantenimiento. Habiendo administrado antes un programa (muy mal escrito, lo admito) escrito en Perl, aprecio que Python fuerce tanto buenas prácticas de codificación como un lenguaje conciso.

Python tampoco lo obliga a seguir una metodología particular al escribir programas. Puedo elegir seguir un estricto estilo de programación orientado a objetos, o puedo escribir un script simple para ejecutar de forma secuencial. No tener que inicializar una clase, luego llamar al main()método como se ve obligado a hacerlo en Java es muy bueno. (Además, imprimir en stdout en Python es maravilloso, pero ese es un punto bastante nulo).

Finalmente, la metodología "Baterías incluidas" de incluir una biblioteca estándar expansiva con el lenguaje es maravillosa. En lugar de buscar en algún repositorio externo de paquetes, la mayoría de lo que necesito ya está incluido en el lenguaje. También es bueno tener ese repositorio externo, pero no tener que buscarlo para hacer una operación básica es realmente útil.

Zach Dziura
fuente
3
Gracias por la cita útil. ¿Es esta la intención oficial de los diseñadores de Python? Además, tenga en cuenta que no todos los lectores pueden estar de acuerdo con su opinión sobre Python, por lo que quizás sea un poco demasiado fuerte afirmar que "Python es un lenguaje simple" como un hecho conocido y aceptado. ¿Sería posible formularlo como "Python fue diseñado teniendo en cuenta la simplicidad"?
Giorgio
@Giorgio - Es la experiencia de muchos desarrolladores por aquí que Python es en realidad un lenguaje simple. Simple de aprender, simple de escribir y simple de leer. Sobre la cita, como Python es "baterías incluidas", puede obtenerlo directamente desde el idioma con el import thiscomando.
mouviciel
1
TCL también es una buena respuesta para esto y IIRC también fue una respuesta a la complejidad de PERL.
jk.
@mouviciel Después de encontrar un código de espagueti de Python increíblemente complicado en múltiples lugares, ya no creo que Python tenga éxito en sus objetivos aquí. Python no es mejor que la mayoría de los lenguajes cuando se trata de simplicidad: puede ser muy bueno para la ofuscación accidental.
Izkata
1
Python es simple siempre que las personas se mantengan alejadas de la mayoría de las __funciones_mágicas __ () y @decoradores.
weberc2
3

Una clave importante para mantener la "simplicidad" es reconocer cuándo será necesaria la complejidad y hacer que las partes del sistema que mejor puedan manejarla lo hagan. Tener un solo tipo de referencia de objeto que no hace distinción entre valores inmutables, valores mutables y entidades, hace que Java sea "simple", no elimina la necesidad de distinguir entre valores y entidades; simplemente priva a los programadores de herramientas para ayudarlos a hacerlo.

En términos más generales, si se intenta que un lenguaje de programación o una función de marco admitan múltiples casos de uso, se debe garantizar que no haya situaciones en las que diferentes comportamientos sean apropiados en diferentes casos de uso, pero el compilador no podrá determinar ellos aparte. Agregar más tipos a un lenguaje o marco puede parecer una complicación, pero en muchos casos en realidad puede facilitar las cosas.

Considere, por ejemplo, el desorden de las reglas que rodean los tipos con signo y sin signo en C. La complejidad de estas reglas se debe al hecho de que algunos códigos usan tipos enteros sin signo para representar números, mientras que otros códigos los usan para representar miembros de un anillo algebraico envolvente (específicamente, el conjunto de enteros congruentes mod 2ⁿ). Las reglas de conversión de tipos se comportan de maneras que a veces son apropiadas para un uso, y a veces de maneras apropiadas para el otro. Tener distintos tipos de envoltura y no envoltura duplicaría el número de tipos enteros, pero podría simplificar las reglas asociadas con ellos:

  • Cualquier tipo entero sin anillo de cualquier tamaño puede asignarse a un anillo de cualquier tamaño; un anillo puede asignarse solo a un anillo de igual o menor tamaño.

  • Las operaciones que no sean operadores relacionales que involucren un número entero sin anillo y un anillo convertirán implícitamente el número entero al tipo de anillo.

  • Los anillos se pueden lanzar explícitamente a números o a anillos más grandes; El valor de un anillo sin signo es el número entero no negativo más pequeño que, cuando se agrega al cero del anillo, daría el valor del anillo. El valor de un anillo con signo es el entero de menor magnitud que, cuando se agrega al cero del anillo, daría el valor del anillo, prefiriéndose el valor negativo en caso de empate.

  • Excepto como se mencionó anteriormente, los anillos están limitados a operaciones con anillos del mismo tamaño o más pequeños.

  • Las operaciones en enteros que no son de anillo de diferentes tipos deben convertir los números a un tipo que pueda acomodar todos los valores de cualquier operando, o el compilador debe rechazarlos si no existe un tipo adecuado

La definición de los tipos de anillo parecería duplicar el número de tipos enteros, pero simplificaría enormemente la escritura de código portátil. El uso de los mismos tipos sin signo para números y anillos reduce el número de tipos, pero conduce a reglas complicadas que hacen casi imposible escribir código portátil eficiente.

Super gato
fuente
+1 Totalmente de acuerdo. Un lenguaje "simple" (simple en el sentido de tener una pequeña especificación) no necesariamente conduce a un código simple, o facilidad de razonamiento para el programador.
Andres F.
Gran comentario Agregar complejidad debe verse en términos de costos y beneficios.
usuario1071847
2

Podría decirse que Tcl se desarrolló a lo largo de estas líneas. El lenguaje completo se puede describir en solo 12 reglas en una sola página de manual . Es notablemente simple y consistente.

El creador de Tcl afirmó lo siguiente como los objetivos originales:

  • El lenguaje debe ser extensible: debe ser muy fácil para cada aplicación agregar sus propias características a las características básicas del lenguaje, y las características específicas de la aplicación deben parecer naturales, como si hubieran sido diseñadas en el idioma desde el principio.
  • El lenguaje debe ser muy simple y genérico, para que pueda funcionar fácilmente con muchas aplicaciones diferentes y para no restringir las características que las aplicaciones pueden proporcionar.
  • Como la mayor parte de la funcionalidad interesante vendrá de la aplicación, el propósito principal del lenguaje es integrar o "pegar" las extensiones. Por lo tanto, el lenguaje debe tener buenas facilidades para la integración.

De " Historia de Tcl " - http://www.tcl.tk/about/history.html

Bryan Oakley
fuente
2

Si un idioma tiene un diseño fijo debido a KISS, no puede crecer. Un lenguaje que no puede crecer morirá.

En el siguiente video, Guy Steele explica ingeniosamente que se debe permitir que crezca un lenguaje de programación y por qué. Si aplica KISS, entonces, ¿cómo puede crecer un idioma porque una vez lanzado, su conjunto de herramientas es fijo y nunca se le permite cambiar?

La nota clave de Guy Steele en la conferencia ACM OOPSLA de 1998 sobre "Growing a Language" discute la importancia y los problemas asociados con el diseño de un lenguaje de programación que sus usuarios puedan cultivar.

Es un video de una hora pero vale la pena verlo. Si no sabes quién es Guy Steele, deberías saberlo cuando hablas del diseño del lenguaje.

Elijo este video como respuesta porque creo que aplicar KISS al diseño del lenguaje en general es incorrecto, y espero que ver un discurso de una persona destacada en el diseño del lenguaje ayude a ampliar su comprensión del futuro del diseño del lenguaje.

Desde que vino aquí para aprender sobre el diseño del lenguaje y le di una razón para no usar KISS, es justo que señale algo que encuentro de ayuda en el diseño del lenguaje. Dimensiones cognitivas de notaciones

EDITAR

Cuando escribí la respuesta anterior, se basó en el razonamiento de: si un motor solo se puede mantener con un conjunto fijo de herramientas, entonces mi reformulación de ese significado con respecto al diseño del lenguaje es que un idioma no puede cambiar una vez lanzado. Los comentarios indican que eso no era lo que se quería decir. Permítanme presentar esta respuesta modificada que estará más en línea con la comprensión revisada.

Si se observan las dimensiones cognitivas de las notaciones , se aprende que hay muchas dimensiones competitivas asociadas con el diseño del lenguaje que la simpleza y si se enfoca demasiado en una, sufrirá en otras. Con la cuestión de centrarse en gran medida en la simplicidad (KISS) buena, y respaldada por personas notables del diseño del lenguaje, presenté el discurso de Guy Steele para mostrar que tratar de mantener un diseño únicamente simple afectará otras dimensiones. Más importante aún, estoy tratando de transmitir que necesitas mirar muchas dimensiones y sopesar los pros y los contras de ellas, no solo la simplicidad.

Guy Coder
fuente
3
Entonces, ¿qué sucede si el video no está disponible? ¿O si no es accesible en algunos países? Su respuesta debe ser completa y autónoma, actualícela para al menos darnos un breve resumen del video, las respuestas de solo enlace no son realmente útiles y pueden eliminarse en cualquier momento.
yannis
3
@AndreasScheinert La guía de cómo responder deja en claro que los enlaces siempre deben ir acompañados de resúmenes y / o citas relevantes.
Thomas Owens
3
No estoy seguro de poder estar de acuerdo con su evaluación. Tcl, por ejemplo, es notablemente simple. Duró años con solo 11 reglas que rigen su uso. Sin embargo, tan simple como es, ha crecido considerablemente en los más de 20 años de su existencia. Ahora tiene 12 reglas, lo que demuestra que no solo ha crecido su biblioteca, sino que también se ha permitido que su naturaleza fundamental crezca sin perder toda su simplicidad.
Bryan Oakley
1
"Si aplica KISS, entonces, ¿cómo puede crecer un lenguaje porque una vez lanzado, su conjunto de herramientas es fijo y nunca se le permite cambiar?": Depende de lo que quiera decir con simple y con crecimiento. ¿Quiere decir agregar nuevas bibliotecas (en inglés, agregar nuevas palabras al vocabulario) o agregar nuevas construcciones del lenguaje (en inglés esto significa agregar, por ejemplo, nuevos tiempos verbales, nuevas preposiciones, etc.). Los lenguajes naturales eventualmente dejan de agregar nuevas reglas gramaticales mientras continúan agregando nuevas palabras. Entonces, en mi intuición, simple se refiere al número de reglas gramaticales, más que al número de bibliotecas / palabras.
Giorgio
3
@Guy Coder: Por otro lado, el video en el que ha publicado un enlace parece decir algo diferente de lo que dice al comienzo de su respuesta, a saber, que un idioma debe proporcionar ciertas características básicas que permiten a sus usuarios (programadores) ampliar el idioma (agregar nuevas bibliotecas). No dice que el lenguaje central deba crecer indefinidamente.
Giorgio
1

Aquí hay una gran cita de Hardcore Visual Basic de Bruce McKinney , que a su vez pone palabras en boca de los diseñadores de BASIC, Kemeny y Kurtz . Destaca el mío.

Cada lenguaje de computadora tiene su propia sensación, su propia atmósfera, su propio espíritu. Realmente no puedes definir este espíritu, pero sabes lo que es cuando lo ves. Pienso en Basic como la antítesis de una declaración atribuida a Albert Einstein:

Haga las cosas lo más simple posible, pero no más simple.

Si esa cita hubiera sido escrita por los diseñadores originales de Basic, John Kemeny y Thomas Kurtz, se habría simplificado aún más:

Haz las cosas más simples de lo posible.

Esa es la contradicción con la que viven los programadores hardcore de Visual Basic. Queremos que las cosas sean simples, elegantes e intuitivas, pero no lo son. Queremos que nuestros programas modelen la realidad, pero no lo hacen. Queremos que nuestro lenguaje funcione de la manera en que pensamos, no de la manera en que las computadoras o los sistemas operativos quieren que pensemos, pero no estamos dispuestos a pagar el precio .

AakashM
fuente
En una nota relacionada, el hecho de que una construcción de lenguaje "pueda" hacerse para servir a múltiples propósitos no significa que tal diseño sea preferible a tener diferentes construcciones para esos diferentes propósitos. Por ejemplo, C usa tipos sin signo tanto para representar cantidades numéricas como para representar miembros de un anillo algebraico envolvente. Agregar un número de cualquier tamaño o firma a un anillo debería producir un miembro del mismo anillo, mientras que agregar dos números de cualquier tamaño y firma debería producir un resultado lo suficientemente grande como para manejar cualquier valor de cualquier operando. Uso de tipos sin signo para ambos propósitos ...
supercat
... significa que las reglas de C tienen que considerarlos a veces como números y otras como miembros del anillo, de manera que sea casi imposible escribir código limpio y portátil.
supercat
1

Pero, ¿puede aplicarse el principio KISS también al diseño del lenguaje de programación? ¿Conoce algún lenguaje de programación que haya sido diseñado específicamente con este principio en mente, es decir, para "permitir que un programador promedio en condiciones de trabajo promedio escriba y mantenga tanto código como sea posible con el menor esfuerzo cognitivo"?

Es bueno que haya aclarado lo que quiere decir con "simple", porque en mi opinión, un lenguaje de programación simple es uno con una sintaxis mínima y pocas características (Scheme, Forth, ML), que no se traduce directamente a su definición. Creo que realmente está buscando un diseño de idiomas con RAD (desarrollo rápido de aplicaciones) en mente, y hay bastantes. Vea este hilo de StackOverflow, por ejemplo: /programming/66227/what-is-the-best-multi-platform-rad-language

Nemanja Trifunovic
fuente
"porque, en mi opinión, un lenguaje de programación simple es uno con una sintaxis mínima y pocas características (Scheme, Forth, ML)": Bueno, en realidad copié la definición de Wikipedia pero tiendo a identificar las dos cosas. Por ejemplo, Scheme se puede aprender muy rápido y luego puedo concentrarme en el problema a resolver. Otros lenguajes (como C ++, que uso en el trabajo) siguen creciendo y tienes que aprender cosas nuevas todo el tiempo. Además, el código se vuelve menos mantenible porque diferentes programadores tienden a usar diferentes subconjuntos del lenguaje. Por lo tanto, consideraría que SML y Scheme son "simples".
Giorgio
1

Me sorprende que nadie haya mencionado aún C, aunque pone la simplicidad primero de varias maneras importantes, a menudo de una manera tan radical que los programadores no pueden apreciar la simplicidad:

  • No hay magia oculta. Si escribe a + ben C, tiene la garantía de que se compilará como máximo en una sola instrucción de ensamblador.

    Incluso en lenguajes relativamente simples como Java, una declaración simple como a + bpuede tomar varios microsegundos (si las variables son cadenas). Otros lenguajes agregan mucho, mucho más a esto con el ejemplo extremo de C ++, donde a + bpuede sobrecargarse para que aparezcan elefantes rosados. No es así en C: si no es una llamada a función, no tomará más de unos pocos nanosegundos. Esta previsibilidad del rendimiento es una de las características clave de C, y ciertamente es una forma de simplicidad.

  • Los tipos de datos son tan simples como pueden ser, al tiempo que describen todas las estructuras de datos interesantes que es posible que desee construir en la memoria: solo hay los tipos fundamentales que una CPU puede manejar + agregación ( struct) + repetición (matrices) + referencias (punteros )

    Es cierto que los diversos lenguajes basados ​​en lisp son mucho más simples que C a este respecto. Sin embargo, no intentan permitir que el programador manipule libremente la memoria como lo hace C.

  • Ortogonalidad de funciones: puede combinar libremente las funciones y funcionarán juntas como se espera. Muchos lenguajes fallan esto al permitir que ciertas construcciones solo aparezcan en contextos definidos.

    Tomemos, por ejemplo, matrices de longitud variable en C y C ++: C permite longitudes de tiempo de ejecución en todas partes, mientras que las solicitudes más liberales para expandir el estándar C ++ solo las permiten en ciertos contextos como las matrices automáticas e incluso allí solo en la primera dimensión. Esto permite que C maneje matrices multidimensionales verdaderas con tamaños conocidos solo en tiempo de ejecución, mientras que los programadores de C ++ se reducen para escribir data[k + (j + i*lineLength)*lineCount]una y otra vez.

    Otro ejemplo de esto es el puntero: un puntero de datos en C realmente no es más o menos que una variable que contiene una dirección de memoria de alguna otra variable. Como el puntero es en sí mismo una variable, el puntero doble es una cosa bien definida. Es decir, qué inty qué int*es, está claro lo que int**debe ser. Compare esto con las referencias de C ++ donde no tiene absolutamente ninguna idea de qué int&&se le da el significado de inty int&!)

Es cierto que es precisamente esta simplicidad la que le ha ganado tanto odio a C: la simplicidad del lenguaje permite a los programadores más libertad de la que es buena para ellos, lo que genera muchos problemas con comportamientos indefinidos y punteros mal manejados. Especialmente la simplicidad de la ortogonalidad que permite a un programador definir una variable como int (*array[m])(struct foo* (*arg)[n])es del tipo que tiende a causar dolores de cabeza a los lectores porque las cosas realmente complejas se pueden expresar de forma muy concisa mediante una combinación liberal de algunas características simples. . Este es el tipo de simplicidad en el que C sobresale y que le da la reputación de ser un lenguaje difícil de usar.

Además, la simplicidad del lenguaje obliga al programador a escribir mucho más código que más lenguajes ricos en funciones, lo que proporciona un terreno más fértil para que florezcan los errores. Sin embargo, sigue siendo el lenguaje de alto nivel más simple posible si su objetivo principal es programar una computadora real y no una máquina virtual.

cmaster - restablecer monica
fuente
¿El votante puede dejar un mensaje explicando la razón de su voto?
Giorgio
C es un desastre. Intente calcular lo que obtendrá si agrega un corto firmado a un largo sin firmar, y almacene el resultado en un int. Incluso sin "long long", tiene ocho tipos enteros diferentes. Eso no es simple.
Simon B
@SimonB Claramente no has entendido de qué se trata mi publicación. La simplicidad sobre los tipos enteros es la siguiente: un tipo entero tiene un tamaño (en bytes y bits) y puede estar firmado o no. Puede usar cualquier combinación de estas dos características ortogonales. Es esta ortogonalidad de la que estoy hablando. C tiene todas las características que se requieren para explotar completamente el hardware real, y eso conlleva una cierta complejidad. Sin embargo, la forma en que C trata esta complejidad es combinando conceptos simples de manera ortogonal para permitir que el programador haga cosas complejas.
cmaster - reinstalar a monica
0

Wikipedia en Java : aunque no se establece explícitamente en Wikipedia, la simplificación se menciona varias veces y fue un objetivo de diseño original, ya que el único lenguaje serio capaz de OO (término utilizado libremente) en esos días era C ++, que como todos sabemos, es poderoso pero tiene más de unas pocas trampas para los incautos.

La JVM fue pensada como una forma de simplificar el desarrollo multiplataforma, y ​​"Escribir una vez Ejecutar en cualquier lugar" se convirtió en un mantra de Java durante unos años.

Creo que C # cae en esa categoría de simplificación del lenguaje.

Mattnz
fuente
¿Quiere decir que C # también se diseñó inicialmente como una simplificación de C ++?
Giorgio
2
C ++ y OO? Alan Kay no lo cree así. C # Sinplyfication ???? No sé a qué te refieres con simple. Creo que sería mejor decirlo antes de declarar las cosas como tales. LISP es simple ya que tiene muy poca sintaxis. C # por el contrario tiene TONELADAS de sintaxis y palabras clave.
AndreasScheinert
La capacidad de simplificar el desarrollo multiplataforma no significa que el lenguaje en sí sea simple. Algo puede ser multiplataforma pero aún no es simple en sí mismo.
Bryan Oakley
@Bryan estuvo de acuerdo: el diseño de Java tuvo en cuenta que los programas multiplataforma no eran (en ese momento) simples, y para crear programas simples, se necesitaba un lenguaje simple y se necesitaba eliminar la complejidad del manejo del código específico de la plataforma en el propio programa.
mattnz
2
@Giorgio C # fue una reinvención de Java. Se pretendía que Java fuera menos complejo que C ++ (por ejemplo, sin herencia múltiple) y algo mucho mayor (por ejemplo, una gran biblioteca estándar, recolección de basura).
Sean McSomething
-2

Hm ... esta es realmente una pregunta difícil de responder 'positivamente', porque cuando pienso en la simplicidad en el diseño del lenguaje de programación (y en qué es 'más fácil' trabajar), inmediatamente pienso en:

  1. "Legibilidad" del código: qué tan bien encapsula el lenguaje objetos, métodos, etc.
  2. La consistencia de las API e interfaces de lenguaje.

Hay varios lenguajes que hacen bien estas cosas, pero lo que me viene a la cabeza es un lenguaje que no hace bien las cosas 'como lenguaje de programación': PHP.

[Descargo de responsabilidad: he escrito PHP y PHP sigue siendo mi 'ir al lenguaje' para proyectos web simples. Esta es una crítica del amor ...]

Primero, PHP funciona bien para el entorno en el que normalmente se ejecuta: servidores web. Es fácil de configurar, fácil de mantener, etc.

Donde lucho con PHP: cuando quieres hacer algo "inusual", algo que normalmente no haces de forma regular (en el caso de que esté pensando que estaba consumiendo un servicio web SOAP), no es algo que yo haya hecho. hecho mucho con PHP), te enfrentas a dos opciones:

1) Varias extensiones de código abierto para PHP. El modelo de objetos PHP es lo suficientemente flexible donde el diseño de la interfaz tampoco es terriblemente consistente de biblioteca a biblioteca, de desarrollador a desarrollador. Cuando te enfrentas a un conjunto de códigos donde alguien usó una biblioteca de la que nunca has oído hablar, pasas mucho tiempo descubriendo "qué diablos hace esto" porque el lenguaje permite la creación de API / biblioteca suelta.

2) Las funciones "incorporadas", de las cuales hay muchas . He pasado por algunas dificultades para encontrar otra biblioteca o implementar un poco de funcionalidad para luego tropezar conimpossiblyfound_basefunction()

En mi opinión, la simplicidad es consistencia.

Chad Thompson
fuente
-3

Ahora, el enfoque de KISS para los lenguajes de programación es una noción divertida, al menos si considera que los lenguajes de programación son una capa de abstracción para el conjunto de instrucciones de una CPU, etc. Si no define "KISS" más de cerca. Solo digo aquí, que una carreta de bueyes es KISS aplicada a un automóvil al máximo.

Ahora, otra interpretación de KISS podría ser algo así como "hecho inteligentemente sin adornos innecesarios y no demasiado complicado". Especialmente se podría argumentar que no debería haber demasiados casos específicos para cosas similares, etc. Por lo general, las matemáticas son bastante buenas para resumir las cosas en su esencia, y, sorprende, los matemáticos también han pasado algún tiempo pensando en la programación y las computadoras. .

Para la programación, existen 2 modelos abstractos bastante famosos:

  • Una es la máquina de Turing que define una máquina y un modelo de instrucción simple que es capaz de calcular todo lo que una computadora podría hacer.
  • El otro es el cálculo Lambda de Church et. Alabama. eso es equivalente en poder

Lo divertido es: si bien la máquina de Turing es bastante simple en su diseño, no es un sistema fácil de manejar y no creo que califique para "KISS inteligente". Pero el cálculo Lambda tiene más que ver con los lenguajes de programación que conocemos, y con las características pioneras de Lisp y Scheme del cálculo lambda, ha llegado a muchos lenguajes.

Lisp y Scheme son REALMENTE simples, al menos en cuanto a sintaxis. La sintaxis es un problema importante con los lenguajes de programación (por lo que probablemente se reinventan todo el tiempo). En el caso de C ++, es casi inmanejable para el cerebro humano predecir cómo el compilador interpreta algunas líneas de origen).

Lisps está reduciendo la complejidad sintáctica por completo mediante la introducción de una forma común para los comandos:

(command param1 param2 ...)

Esto puede ser una llamada a un método, como

(max 1 2 3 4)

así como una rama, bucle, etc.

(if (< 1 2) 
    (write 4)
    (write 5))

(todo el código aquí es pseudo-Lisp / Dialect agnóstico)

La forma

(command param1 param2 ...)

también se puede interpretar como una lista

(item1 item2 item3)

Y esa es la base de la simplicidad y belleza de Lisps. Debido a que las listas anidadas (como en el ifejemplo de la declaración) constituyen árboles y esos pueden ser fácilmente entendidos tanto por la máquina como por el humano frente a la máquina.

Otra característica de Lisps son las macros . No entraré en detalles sucios aquí, pero dado que no hay una diferencia sintáctica entre las llamadas a funciones normales y "Sintaxis (huevo para bucles, declaración de variables, etc.), todo lo que el analizador tiene que manejar en otros lenguajes de programación) puede crear su propia sintaxis Las macros son en esencia Manipulaciones del árbol que constituye su programa.

Creo que Lisp tiene un BESO para programar. El hecho de que pueda manipular la sintaxis mediante el uso de macros ha llevado a un fenómeno que Lisp ha evolucionado de forma bastante dinámica. Necesita una nueva función de lenguaje como, digamos orientación de objeto, ¡simplemente escriba un sistema OOP con macros!

Si bien C se extendió en la rotonda 2 veces con las características de OOP (C ++, Obj. C) Lisp se extendió varias veces, al final hubo un ganador.

Esa es otra peculiaridad de Lisp, evoluciona (ver Clojure y Clojurescript para una nueva mutación interesante de lisp).

Por sus propiedades KISS, Lisps es favorecido como enseñanza de idiomas por algunos. Como Fogus describe en su plano de un lenguaje educativo ( http://blog.fogus.me/2013/01/21/enfield-a-programming-language-designed-for-pedagogy/ )

Para empezar, creo firmemente que al aprender temas nuevos y, a veces, complejos, es totalmente perjudicial sobrecargar a los estudiantes con reglas de sintaxis frívolas. Por lo tanto, Enfield está diseñado con reglas de sintaxis mínimas y lo que es más mínimo que una sintaxis similar a Lisp.
wirrbel
fuente
2
OP define KISS para el contexto de esta pregunta con bastante claridad, "permite que un programador promedio bajo condiciones de trabajo promedio escriba y mantenga tanto código como sea posible con el menor esfuerzo cognitivo" . OP también menciona "interesados ​​en conocer las intenciones (documentadas) de los diseñadores en lugar de su opinión personal sobre un lenguaje de programación en particular"
mosquito