¿Cuáles son ejemplos de inconsistencia e incompletitud en Unix / C?

20

En el famoso ensayo de Richard Gabriel The Rise of Worse is Better , contrasta las versiones caricaturizadas de las filosofías de diseño del MIT / Stanford (Lisp) y Nueva Jersey (C / Unix) a lo largo de los ejes de simplicidad, corrección, coherencia e integridad. Da el ejemplo del "problema de pérdida de PC" ( discutido en otro lugar por Josh Haberman ) para argumentar que Unix prioriza la simplicidad de implementación sobre la simplicidad de la interfaz.

Otro ejemplo que he encontrado son los diferentes enfoques de los números. Lisp puede representar números arbitrariamente grandes (hasta el tamaño de la memoria), mientras que C limita los números a un número fijo de bits (generalmente 32-64). Creo que esto ilustra el eje de corrección.

¿Cuáles son algunos ejemplos de consistencia e integridad? Aquí están todas las descripciones de Gabriel (que él admite son caricaturas):

El enfoque MIT / Stanford

  • Simplicidad: el diseño debe ser simple, tanto en la implementación como en la interfaz. Es más importante que la interfaz sea simple que la implementación.
  • Corrección: el diseño debe ser correcto en todos los aspectos observables. La incorrección simplemente no está permitida.
  • Consistencia: el diseño no debe ser inconsistente. Se permite que un diseño sea un poco menos simple y menos completo para evitar inconsistencias. La consistencia es tan importante como la corrección.
  • Integridad: el diseño debe cubrir tantas situaciones importantes como sea práctico. Todos los casos razonablemente esperados deben estar cubiertos. La simplicidad no permite reducir demasiado la integridad.

El enfoque de Nueva Jersey

  • Simplicidad: el diseño debe ser simple, tanto en la implementación como en la interfaz. Es más importante que la implementación sea simple que la interfaz. La simplicidad es la consideración más importante en un diseño.
  • Corrección: el diseño debe ser correcto en todos los aspectos observables. Es un poco mejor ser simple que correcto.
  • Consistencia: el diseño no debe ser demasiado inconsistente. La consistencia se puede sacrificar por simplicidad en algunos casos, pero es mejor descartar aquellas partes del diseño que se ocupan de circunstancias menos comunes que introducir complejidad de implementación o inconsistencia.
  • Integridad: el diseño debe cubrir tantas situaciones importantes como sea práctico. Todos los casos razonablemente esperados deben estar cubiertos. La integridad se puede sacrificar en favor de cualquier otra cualidad. De hecho, la integridad debe sacrificarse siempre que se ponga en peligro la simplicidad de implementación. La consistencia se puede sacrificar para lograr la integridad si se conserva la simplicidad; especialmente inútil es la consistencia de la interfaz.

Tenga en cuenta que no estoy preguntando si Gabriel tiene razón (que es una pregunta no apropiada para StackExchange), sino ejemplos de a qué se podría haber referido.

Ellen Spertus
fuente
66
En caso de que tenga curiosidad, este no es un problema de tarea. Soy la maestra :-) Pensándolo bien, tal vez sea mi tarea.
Ellen Spertus
44
Me cuesta ver por qué esta pregunta no está en Unix y Linux (¿o tal vez Ingeniería de Software ?). ¿Puede explicar de qué manera necesita una perspectiva CS sobre el tema? Además, aclare si desea ejemplos positivos o negativos.
Raphael
¿No es esa pregunta más adecuada en programmers.stackexchange.com ?
Basile Starynkevitch
Publiqué esto en CS porque considero que el diseño del lenguaje es una de las áreas profundas fundamentales de la informática, que abarca la computabilidad, la complejidad, la arquitectura, la usabilidad, etc. Podría haberlo publicado en Unix / Linux, aunque estaba buscando un programa más amplio ver. En cuanto a los programadores, la gente casi siempre es hostil conmigo cuando publico allí, incluso cuando creo que estoy en el tema, así que me mantengo alejado de allí.
Ellen Spertus

Respuestas:

15

El título de la pregunta sugiere que algunas inconsistencias básicas de la interfaz de usuario pueden interesarle:

Los comandos de Unix no siguen ninguna sintaxis particular para especificar opciones y marcas. Por ejemplo, la mayoría de los comandos usan letras simples precedidas por '-' como indicador: cat -n some_filepero existen excepciones como tar tf some_file.tary dd in=some_file out=some_other_file count=2existen en los comandos de uso común.

Unix y sus descendientes y parientes tienen múltiples sintaxis de expresión regular ligeramente diferentes. Los shells usan "*" donde otros programas (grep, egrep, vi) usan '. *'. egrep tiene '+' y '|' como operadores, grep no.

La interfaz de llamada básica del sistema "todo es un archivo" podría verse como incompleta: leer / escribir / buscar / cerrar no se adapta a todos los dispositivos de E / S. Excepciones muy necesarias se agrupan en llamadas "ioctl", pero dispositivos como las tarjetas de sonido ni siquiera encajan muy bien.

Bruce Ediger
fuente
Buena respuesta. Cuando vi el título, inmediatamente pensé "ioctl" (y fcntl) pero ahora no tengo que escribir una respuesta.
Louis
1
los patrones globales no son expresiones regulares
jk.
8

Consistencia

Lisp tiene una sintaxis muy consistente, todas las extensiones de lenguaje se pueden incrustar naturalmente a través de macros y demás. C, por otro lado, tiene una sintaxis de código bastante, lo que le permite a uno tomar algunos "atajos", por lo que en algunos casos el código C parece más simple.

Lo completo

En Lisp, si no tiene una función de idioma específica que necesita, puede implementarla usted mismo con macros. C también tiene preprocesador, pero es bastante desconcertante.

Daniil
fuente
8

Las cadenas de C no pueden contener el carácter 0 y sus funciones de biblioteca no son adecuadas para tratar con datos binarios.

Los nombres de archivo en sistemas Unix no pueden contener el carácter 0 o el carácter 47 (la barra inclinada).

En la implementación original de Unix, los nombres de los archivos estaban limitados a 14 caracteres. Las versiones posteriores solo relajaron esta limitación; No lo eliminaron.

Agregado : La E2BIGcondición de error del sistema, cuando se intentó execcon una lista de argumentos que tenía demasiados argumentos, u ocupaba demasiada memoria, o un entorno que era demasiado grande.

Unix es conocido por este tipo de limitación arbitraria. Hasta la llegada de Perl en 1987, manejar grandes conjuntos de datos, o conjuntos de datos con registros largos o datos binarios, era extremadamente poco confiable.

Mark Dominus
fuente
No permitir /no es arbitrario, es necesario (?) Resolver ambigüedades como lo /es el separador de ruta. Acabo de crear un archivo 000, aparentemente esa restricción específica ha desaparecido en los días de un GNU / Linux moderno.
Raphael
No quise decir que la prohibición de /era arbitraria, solo que la longitud de la línea y los límites del tamaño del archivo eran arbitrarios. Sin embargo, el punto es que un diseño diferente podría haber permitido que los nombres de archivo contengan barras, pero los diseñadores de Unix no lo hicieron. considéralo importante.
Mark Dominus el
Estoy seguro de que en ese momento, esos límites se introdujeron debido a consideraciones de rendimiento; las técnicas no desarrolladas también pueden jugar en ello. Desde el punto de vista de hoy, parecen cuestionables, eso es seguro. En cuanto a /, tengo curiosidad: suponiendo que una ruta se codifique como cadena, ¿cómo se hace sin un carácter reservado para la separación de ruta?
Raphael
No entiendo cuál es tu punto. La pregunta pide "ejemplos de inconsistencia e incompletitud en Unix / C"; No menciona el rendimiento.
Mark Dominus el
1
@Raphael: Elimina los problemas tontos del separador definiendo un pathtipo de datos abstracto y utilizándolo en sus interfaces en lugar de exponer una implementación particular (cadenas ascii terminadas en nulo).
Wandering Logic
4

Mi maestro del IIRC dijo que la incapacidad para usar char *variables en las switchdeclaraciones en C es una cuestión de inconsistencia, pero para mí eso fue un problema de generalidad (integridad). Creo que es mejor usar "consistencia" solo en sus algoritmos o diseño de software, no en el lenguaje de programación en sí (al menos no en lenguajes como C. tal vez un lenguaje defectuoso tenga problemas de consistencia), porque los lenguajes de programación tienen estándares sólidos que definen el dominio de las reglas y trabajar aplicando información a las reglas. Entonces, si algo no está permitido en el lenguaje, planeó no permitirse y no hay inconsistencia en el lenguaje, en mi humilde opinión.


  1. He usado la generalidad como integridad. Creo que son lo mismo. puede ser que esté equivocado.
  2. Esta no es una respuesta. tal vez sugerencia o mi opinión.
fanático
fuente
3

El mejor ejemplo que tengo es el usuario pobre que tenía un archivo llamado .. -ry escrito rm *.

Ya sea que esta historia sea cierta o no, se ha convertido en un clásico del enemigo de Unix.

Vea el Manual de Unix-Haters , que tiene una introducción del propio Dennis Ritchie, para muchos de estos ejemplos.

Además, agregaré que evitar este tipo de problemas fue una fuerza importante en el diseño de Power Shell de Microsoft.

S. Robert James
fuente
Leí el ensayo de Richard Gabriel en la parte posterior del Manual de Unix-Haters. :-)
Ellen Spertus
3
  • Ciertamente, los innumerables significados de los mismos indicadores (cortos) a los comandos son una inconsistencia.
  • Cada programa que usa expresiones regulares tiene su propia sintaxis
  • Los archivos de configuración para los servicios tienen una sintaxis diferente (que se puede perdonar en parte, su demonio de correo tiene poco en común con su servidor web o inicio del sistema, pero aún así)
  • ¡Hay diferentes editores! ¡Los usuarios usan diferentes shells! ¿Por qué hay tantos entornos de escritorio?

OTOH, el hecho de que el caparazón expanda los globos, y no el programa, elimina muchas inconsistencias irritantes presentes en otros sistemas. Lo mismo ocurre con el hecho de que puede usar el mismo comando para copiar un archivo de un lugar a otro en el sistema de archivos, a un disquete o desde un disco Zip a una cinta.

Entonces, sí, Unix es inconsistente. También lo son los otros sistemas, de manera diferente ;-)

vonbrand
fuente
2

LISP que admite números de precisión infinita versus C que admite solo enteros de máquina no es un ejemplo de "corrección" del lenguaje. Es una cuestión simple que surge del hecho de que los idiomas tenían objetivos de diseño muy diferentes.

El punto de C era ser un lenguaje cercano a la máquina que pudiera usarse para implementar sistemas operativos. Las máquinas (en su mayoría) no admiten números decimales de precisión infinita. Las máquinas (en su mayoría) tienen enteros de longitudes de bits fijas.

Dave
fuente