Folclore de programadores e enxeñeiros (parte 1)

Folclore de programadores e enxeñeiros (parte 1)

Esta é unha selección de historias de Internet sobre como os erros ás veces teñen manifestacións completamente incribles. Quizais tamén teñas algo que contar.

Alerxia de coche ao xeado de vainilla

Unha historia para enxeñeiros que entenden que o obvio non sempre é a resposta, e que por moi descabellados que parezan os feitos, seguen sendo os feitos. A División Pontiac de General Motors Corporation recibiu unha queixa:

Esta é a segunda vez que che escribo, e non che culpo por non contestar, porque soa unha tolemia. A nosa familia ten a tradición de comer xeados todas as noites despois da cea. Os tipos de xeados cambian cada vez, e despois da cea toda a familia elixe que xeado comprar, despois eu vou á tenda. Merquei recentemente un Pontiac novo e desde entón as miñas viaxes para conseguir xeados convertéronse nun problema. Xa ves, cada vez que merco xeado de vainilla e volvo da tenda, o coche non arranca. Se traio algún outro xeado, o coche arranca sen problema. Quero facer unha pregunta seria, por moi estúpido que pareza: "¿Que ten o Pontiac que fai que non arranque cando traio xeado de vainilla, senón que empece facilmente cando traio outro sabor de xeado?".

Como podedes imaxinar, o presidente da división mostrouse escéptico sobre a carta. Non obstante, por se acaso, enviei un enxeñeiro para comprobar. Sorprendeulle que se atopase con un home rico e ben educado que vive nunha fermosa zona. Acordaron reunirse inmediatamente despois da cea para que os dous puideran ir á tenda a tomar un xeado. Aquela noite era vainilla, e cando volveron ao coche, non arrancou.

O enxeñeiro veu tres noites máis. A primeira vez que o xeado foi de chocolate. O coche arrancou. A segunda vez houbo xeado de amorodo. O coche arrancou. Na terceira noite pediu tomar vainilla. O coche non arrancou.

Razoando racionalmente, o enxeñeiro negouse a crer que o coche fose alérxico ao xeado de vainilla. Polo tanto, acordei co propietario do coche que continuaría as súas visitas ata que atopase unha solución ao problema. E polo camiño, comezou a tomar notas: anotou toda a información, a hora do día, o tipo de gasolina, a hora de chegada e volta da tenda, etc.

O enxeñeiro pronto decatouse de que o propietario do coche pasaba menos tempo comprando xeado de vainilla. O motivo foi o deseño dos produtos na tenda. O xeado de vainilla era o máis popular e gardábase nun conxelador separado na parte frontal da tenda para que fose máis doado de atopar. E todas as outras variedades estaban na parte traseira da tenda, e levou moito máis tempo atopar a variedade adecuada e pagar.

Agora a pregunta era para o enxeñeiro: por que non arrancou o coche se pasara menos tempo desde o momento en que se apagou o motor? Dado que o problema era o tempo e non o xeado de vainilla, o enxeñeiro atopou rapidamente a resposta: era unha esclusa de gas. Ocorría todas as noites, pero cando o propietario do coche pasaba máis tempo buscando xeados, o motor conseguiu arrefriar o suficiente e arrancou con facilidade. E cando o home comprou xeado de vainilla, o motor aínda estaba demasiado quente e o bloqueo de gas non tivo tempo de disolverse.

Moral: ata os problemas completamente tolos ás veces son reais.

Crash Bandicoot

É doloroso experimentar isto. Como programador, te acostumas a culpar ao teu código primeiro, segundo, terceiro... e nalgún lugar do décimo milésimo lugar culpa ao compilador. E máis abaixo na lista xa botas a culpa ao equipo.

Aquí está a miña historia sobre o erro do hardware.

Para o xogo Crash Bandicoot, escribín código para cargar e gardar nunha tarxeta de memoria. Para un desenvolvedor de xogos tan presumido, foi como un paseo polo parque: pensei que o traballo levaría varios días. Non obstante, acabei depurando o código durante seis semanas. Durante o camiño, resolvín outros problemas, pero cada poucos días volvía a este código durante unhas horas. Foi unha agonía.

O síntoma era o seguinte: cando gardas a partida actual do xogo e accedes á tarxeta de memoria, case sempre todo vai ben... Pero ás veces o tempo de espera da operación de lectura ou escritura non é obvio. Unha gravación curta adoita danar a tarxeta de memoria. Cando un xogador tenta salvar, non só non consegue salvar, senón que tamén destrúe o mapa. Merda.

Despois dun tempo, a nosa produtora de Sony, Connie Bus, comezou a entrar en pánico. Non puidemos enviar o xogo con este erro, e seis semanas despois non entendín o que estaba a causar o problema. A través de Connie, contactamos con outros desenvolvedores de PS1: alguén atopou algo semellante? Non. Ninguén tivo problemas coa tarxeta de memoria.

Cando non tes ideas para a depuración, o único método que queda é "dividir e vencer": elimina cada vez máis código do programa defectuoso ata que quede un fragmento relativamente pequeno que aínda causa o problema. É dicir, cortas o programa peza por peza ata que quede a parte que contén o erro.

Pero o caso é que é moi difícil cortar anacos dun videoxogo. Como executalo se eliminaches o código que emula a gravidade? Ou debuxar personaxes?

Polo tanto, temos que substituír módulos enteiros por stubs que pretenden facer algo útil, pero de feito facer algo moi sinxelo que non pode conter erros. Temos que escribir tales muletas para que o xogo funcione polo menos. Este é un proceso lento e doloroso.

En resumo, fíxeno. Eliminaba cada vez máis anacos de código ata quedar co código inicial que configura o sistema para executar o xogo, inicializa o hardware de renderizado, etc. Por suposto, nesta fase non puiden crear un menú para gardar e cargar, porque tería que crear un esbozo para todo o código gráfico. Pero podería finxir ser un usuario usando a pantalla de gardar e cargar (invisible) e pedir para gardar e despois escribir na tarxeta de memoria.

Isto deixoume cun pequeno anaco de código que aínda tiña o problema anterior, pero aínda estaba ocorrendo ao azar! Na maioría das veces todo funcionaba ben, pero ás veces había fallos. Quitei case todo o código do xogo, pero o erro aínda estaba vivo. Isto foi desconcertante: o código restante non fixo nada.

Nalgún momento, probablemente sobre as tres da mañá, ocorréuseme un pensamento. As operacións de lectura e escritura (entrada/saída) implican tempos de execución precisos. Cando traballas cun disco duro, tarxeta de memoria ou módulo Bluetooth, o código de baixo nivel responsable da lectura e escritura faino de acordo cos pulsos do reloxo.

Coa axuda dun reloxo, un dispositivo que non está conectado directamente ao procesador sincronízase co código que se executa no procesador. O reloxo determina a velocidade en baudios, a velocidade á que se transfiren os datos. Se hai confusión cos tempos, o hardware ou o software, ou ambos, tamén se confunden. E isto é moi malo, porque os datos poden danar.

E se algo no noso código confunde os tempos? Comprobei todo o relacionado con isto no código do programa de proba e notei que configuramos o temporizador programable en PS1 a 1 kHz (1000 ticks por segundo). Isto é bastante; por defecto, cando se inicia a consola, funciona a 100 Hz. E a maioría dos xogos usan esta frecuencia.

Andy, o desenvolvedor do xogo, axustou o temporizador a 1 kHz para que os movementos se calculasen con máis precisión. Andy adoita ir por riba, e se imitamos a gravidade, facémolo coa maior precisión posible!

Pero que pasaría se acelerar o temporizador afectase dalgún xeito ao tempo xeral do programa e, polo tanto, ao reloxo que regula a velocidade en baudios da tarxeta de memoria?

Comentei o código do temporizador. O erro non volveu ocorrer. Pero isto non significa que o solucionemos, porque o fallo ocorreu de forma aleatoria. E se tivera sorte?

Uns días despois volvín experimentar co programa de proba. O erro non volveu repetirse. Volvín á base de códigos do xogo completo e modifiquei o código de gardar e cargar para que o temporizador programable restablecese ao seu valor orixinal (100 Hz) antes de acceder á tarxeta de memoria e, a continuación, reinicie a 1 kHz. Non houbo máis accidentes.

Pero por que pasou isto?

Volvín ao programa de probas de novo. Tentei atopar algún patrón na aparición dun erro cun temporizador de 1 kHz. Finalmente notei que o erro ocorre cando alguén xoga cun controlador PS1. Xa que raramente o faría eu mesmo, por que necesitaría un controlador ao probar o código de gardar e cargar? - Nin sequera notei esta dependencia. Pero un día un dos nosos artistas agardaba a que rematase as probas -probablemente estaba maldicindo nese momento- e fixo xirar nerviosamente o mando nas súas mans. Produciuse un erro. "Espera, que?!" Ben, faino de novo!"

Cando me decatei de que estes dous eventos estaban interconectados, puiden reproducir facilmente o erro: comecei a gravar na tarxeta de memoria, movo o controlador e estraguei a tarxeta de memoria. A min pareceume un erro de hardware.

Vin a Connie e falei do meu descubrimento. Transmitiu a información a un dos enxeñeiros que deseñou a PS1. "Imposible", respondeu, "Non pode ser un problema de hardware". Pedinlle a Connie que nos organizase unha conversación.

O enxeñeiro chamoume e discutimos no seu inglés roto e no meu xaponés (extremadamente) roto. Finalmente dixen: "Déixame enviar o meu programa de proba de 30 liñas onde mover o controlador provoca un erro". El aceptou. Dixo que era unha perda de tempo e que estaba terriblemente ocupado traballando nun novo proxecto, pero que cedería porque eramos un programador moi importante para Sony. Limpei o meu programa de proba e envieille.

Á noite seguinte (estabamos en Los Ángeles e el estaba en Tokio) chamoume e pediu desculpas tímidamente. Foi un problema de hardware.

Non sei cal foi exactamente o erro, pero polo que escoitei na sede de Sony, se configuras o temporizador nun valor suficientemente alto, interferiu cos compoñentes da placa base nas proximidades do cristal do temporizador. Un deles era un controlador de velocidade en baudios para a tarxeta de memoria, que tamén estableceu a velocidade en baudios para os controladores. Non son enxeñeiro, así que podería ter equivocado algo.

Pero a conclusión é que houbo interferencias entre os compoñentes da placa base. E ao transmitir datos simultaneamente a través do porto do controlador e do porto da tarxeta de memoria cun temporizador a 1 kHz, perdéronse bits, perdéronse datos e danouse a tarxeta.

Malas vacas

Na década de 1980, o meu mentor Sergei escribiu software para o SM-1800, un clon soviético do PDP-11. Este microordenador acaba de instalarse nunha estación de ferrocarril preto de Sverdlovsk, un importante centro de transporte da URSS. O novo sistema foi deseñado para encamiñar vagóns e tráfico de mercadorías. Pero contiña un erro molesto que provocou fallos e fallos aleatorios. As caídas sempre se producían cando alguén ía á casa pola noite. Pero a pesar dunha investigación exhaustiva ao día seguinte, o ordenador funcionou correctamente en todas as probas manuais e automáticas. Isto xeralmente indica unha condición de carreira ou algún outro erro competitivo que ocorre baixo certas condicións. Canso de chamadas a última hora da noite, Sergei decidiu chegar ao fondo e, en primeiro lugar, comprender cales son as condicións do patio de clasificación que levaron á avaría do ordenador.

En primeiro lugar, recolleu estatísticas de todas as caídas inexplicables e creou un gráfico por data e hora. O patrón era obvio. Despois de observar uns días máis, Sergei deuse conta de que podía predecir facilmente o momento dos futuros fallos do sistema.

Pronto soubo que as interrupcións só se producían cando a estación estaba a clasificar os trens cargados de gando do norte de Ucraína e o oeste de Rusia que se dirixían a un matadoiro próximo. Isto en si mesmo era estraño, porque o matadoiro era abastecido por granxas situadas moito máis preto, en Casaquistán.

A central nuclear de Chernóbil explotou en 1986 e as precipitacións radioactivas fixeron que as zonas circundantes fosen inhabitables. Amplísimas áreas do norte de Ucraína, Bielorrusia e o oeste de Rusia foron contaminadas. Sospeitando altos niveis de radiación nos vagóns que chegaban, Sergei desenvolveu un método para probar esta teoría. A poboación tiña prohibido ter dosímetros, polo que Sergei rexistrouse con varios militares na estación de ferrocarril. Despois de varias copas de vodka, conseguiu convencer a un soldado para que medira o nivel de radiación nun dos vagóns sospeitosos. Descubriuse que o nivel era varias veces superior aos valores normais.

O gando non só emitía moita radiación, o seu nivel era tan alto que provocou a perda aleatoria de bits na memoria do SM-1800, que estaba situado nun edificio próximo á estación.

Houbo unha escaseza de alimentos na URSS e as autoridades decidiron mesturar carne de Chernobyl con carne doutras rexións do país. Isto permitiu reducir o nivel global de radioactividade sen perder recursos valiosos. Despois de enterarse diso, Sergei encheu inmediatamente documentos para a emigración. E os fallos do ordenador paráronse por si só cando o nivel de radiación diminuíu co paso do tempo.

A través dos tubos

Érase unha vez, Movietech Solutions creou software para cines, pensado para a contabilidade, a venda de entradas e a xestión xeral. A versión DOS da aplicación insignia era moi popular entre as cadeas de cines de tamaño medio e pequeno de América do Norte. Polo tanto, non é de estrañar que cando se anunciou unha versión de Windows 95, integrada coas últimas pantallas táctiles e quioscos de autoservizo, e equipada con todo tipo de ferramentas de informes, tamén se popularizou rapidamente. Na maioría das veces, a actualización foi sen problemas. O persoal de TI local instalou novos equipos, migrou os datos e continuou o negocio. Excepto cando non durou. Cando isto ocorreu, a compañía enviaría a James, alcumado "O Limpador".

Aínda que o alcume suxire un tipo nefasto, o limpador é só unha combinación de instrutor, instalador e todo o mundo. James pasaba uns días no sitio do cliente xuntando todos os compoñentes, e despois pasaría un par de días máis ensinando ao persoal como usar o novo sistema, resolvendo os problemas de hardware que xurdisen e, esencialmente, axudando ao software durante a súa infancia.

Polo tanto, non é de estrañar que durante estes tempos axitados, James chegase á oficina pola mañá, e antes de que puidese chegar á súa mesa, foi recibido polo xerente, cheo de cafeína máis aló do habitual.

"Témome que teñas que ir a Annapolis, Nova Escocia, canto antes". Todo o seu sistema caeu e despois dunha noite de traballo cos seus enxeñeiros, non podemos descubrir o que pasou. Parece que a rede fallou no servidor. Pero só despois de que o sistema estivera funcionando durante varios minutos.

- Non volveron ao sistema antigo? - contestou James completamente serio, aínda que mentalmente abriu os ollos sorprendido.

— Exactamente: o seu especialista en TI "cambiou as prioridades" e decidiu marchar co seu antigo servidor. James, instalaron o sistema en seis sitios e só pagaron por asistencia premium, e o seu negocio agora está a funcionar como na década de 1950.

James ergueuse lixeiramente.

- Iso é outro asunto. Vale, imos comezar.

Cando chegou a Annapolis, o primeiro que fixo foi atopar o primeiro teatro do cliente que tiña un problema. No mapa tomado no aeroporto, todo parecía decente, pero a zona ao redor do enderezo desexado parecía sospeitoso. Non gueto, pero lembra o cine negro. Mentres James estacionaba na beiravía do centro, unha prostituta achegouse a el. Dado o tamaño de Annapolis, probablemente fose o único de toda a cidade. A súa aparición inmediatamente recordou ao famoso personaxe que ofrecía sexo por diñeiro na gran pantalla. Non, non sobre Julia Roberts, senón sobre Jon Voight [alusión á película "Midnight Cowboy" - aprox. carril].

Despois de enviar á prostituta de camiño, James foi ao cine. A contorna mellorara, pero aínda daba a impresión de estar atropelada. Non é que James estivese demasiado preocupado. Xa estivo en lugares miserables antes. E este foi Canadá, onde ata os atracadores son o suficientemente educados como para dicir "grazas" despois de levar a carteira.

A entrada lateral do cine estaba nunha rúa húmida. James chegou á porta e chamou. Axiña renxou e abriuse lixeiramente.

-¿Es limpadora? - veu dende dentro unha voz rouca.

- Si, son eu... vin para arranxar todo.

James entrou no vestíbulo do cine. Ao parecer, non tiña outra opción, o persoal comezou a repartir entradas en papel aos visitantes. Isto dificultou os informes financeiros, e moito menos os detalles máis interesantes. Pero o persoal saudou a James con alivio e inmediatamente levouno á sala de servidores.

A primeira vista, todo estaba ben. James iniciou sesión no servidor e comprobou os lugares sospeitosos habituais. Sen problema. Non obstante, por moita precaución, James apagou o servidor, substituíu a tarxeta de rede e fixo retroceder o sistema. Inmediatamente comezou a traballar por completo. O persoal comezou a vender entradas de novo.

James chamou a Mark e informoulle da situación. Non é difícil imaxinar que James pode querer quedarse e ver se ocorre algo inesperado. Baixou as escaleiras e comezou a preguntarlles aos empregados que pasou. Obviamente o sistema deixou de funcionar. Apagárono e acenderon, todo funcionou. Pero despois de 10 minutos o sistema caeu.

Xusto neste momento aconteceu algo semellante. De súpeto, o sistema de billetes comezou a lanzar erros. O persoal suspirou e colleu os billetes de papel, e James correu á sala de servidores. Todo estaba ben co servidor.

Entón entrou un dos empregados.

- O sistema está a funcionar de novo.

James estaba desconcertado porque non fixera nada. Máis precisamente, nada que faga funcionar o sistema. Pechou sesión, colleu o seu teléfono e chamou á liña de asistencia da súa empresa. Pronto o mesmo empregado entrou na sala de servidores.

- O sistema está caído.

James mirou o servidor. Un patrón interesante e familiar de formas multicolores bailaba na pantalla: caóticamente retorciéndose e entrelazándose tubos. Todos vimos este salvapantallas nalgún momento. Foi moi ben representado e literalmente hipnotizante.


James presionou un botón e o patrón desapareceu. Correu ao despacho de billetes e no camiño atopouse cun empregado que regresaba a el.

- O sistema está a funcionar de novo.

Se podes facer un facepalm mental, iso é exactamente o que fixo James. Protector de pantalla. Usa OpenGL. E polo tanto, durante o funcionamento, consome todos os recursos do procesador do servidor. Como resultado, cada chamada ao servidor remata cun tempo de espera.

James volveu á sala de servidores, iniciou sesión e substituíu o protector de pantalla polos fermosos tubos cunha pantalla en branco. É dicir, en lugar dun salvapantallas que consome o 100% dos recursos do procesador, instalei outro que non consume recursos. Entón esperei 10 minutos para comprobar a miña suposición.

Cando James chegou ao seguinte cine, preguntábase como explicarlle ao seu director que acababa de voar 800 km para desactivar o protector de pantalla.

Choque durante unha determinada fase da lúa

Historia verdadeira. Un día xurdiu un erro de software que dependía da fase da lúa. Había unha pequena rutina que se usaba habitualmente en varios programas do MIT para calcular a aproximación á verdadeira fase da Lúa. GLS construíu esta rutina nun programa LISP que, ao escribir un ficheiro, saía unha liña cunha marca de tempo de case 80 caracteres. Era moi raro que a primeira liña dunha mensaxe acabase sendo demasiado longa e levase á seguinte liña. E cando máis tarde o programa leu este ficheiro, maldiciu. A lonxitude da primeira liña dependía da data e hora exactas, así como da lonxitude da especificación da fase no momento en que se imprimiu a marca de tempo. É dicir, o erro depende literalmente da fase da lúa!

Primera edición en papel Arquivo de xergas (Steele-1983) contiña un exemplo de tal liña que levou ao erro descrito, pero o tipógrafo "arranxouno". Desde entón describiuse como un "error da fase lunar".

Non obstante, teña coidado coas suposicións. Hai uns anos, enxeñeiros do CERN (Centro Europeo de Investigación Nuclear) atoparon erros nos experimentos realizados no Gran Colisionador Electrón-Positrono. Dado que os ordenadores procesan activamente a enorme cantidade de datos xerados por este dispositivo antes de mostrar o resultado aos científicos, moitos especularon con que o software era dalgún xeito sensible á fase da lúa. Varios enxeñeiros desesperados chegaron ao fondo da verdade. O erro xurdiu debido a un lixeiro cambio na xeometría do anel de 27 km de lonxitude debido á deformación da Terra durante o paso da Lúa! Esta historia entrou no folclore da física como "A vinganza de Newton sobre a física de partículas" e un exemplo da conexión entre as leis máis sinxelas e antigas da física e os conceptos científicos máis avanzados.

Tirar o inodoro para o tren

O mellor erro de hardware do que oín falar foi nun tren de alta velocidade en Francia. O erro provocou a freada de emerxencia do tren, pero só se había pasaxeiros a bordo. En cada caso, o tren foi saído do servizo, revisado, pero non se atopou nada. Entón foi enviado de novo á liña, e inmediatamente detivo un accidente.

Durante un dos controis, un enxeñeiro que viaxaba no tren foi ao baño. Pronto se lavou, BOOM! Parada de emerxencia.

O enxeñeiro púxose en contacto co condutor e preguntou:

—¿Que estabas facendo antes de frear?

- Pois baixei a velocidade na baixada...

Isto era estraño, porque durante o funcionamento normal o tren frea nos descensos ducias de veces. O tren avanzou, e no seguinte descenso o condutor avisou:

- Vou baixar o ritmo.

Non pasou nada.

— Que fixeches durante a última freada? - preguntou o condutor.

- Pois... estaba no baño...

- Pois vai ao baño e fai o que fixeches cando baixemos de novo!

O enxeñeiro foi ao baño, e cando o condutor avisou: "Vou a diminuír a velocidade", tirou a auga. Por suposto, o tren parou inmediatamente.

Agora podían reproducir o problema e necesitaban atopar a causa.

Despois de dous minutos, decatáronse de que o cable do mando a distancia do freo motor (o tren tiña un motor en cada extremo) estaba desconectado da parede do armario eléctrico e estaba tirado sobre o relé que controlaba o solenoide do enchufe do inodoro... Cando o relé estaba activado, creou interferencias no cable do freo e a protección do sistema contra fallos simplemente incluía a freada de emerxencia.

A porta de entrada que odiaba a FORTRAN

Hai uns meses observamos que as conexións de rede no continente [esto foi en Hawai] estaban a ser moi, moi lentas. Isto pode durar de 10 a 15 minutos e, de súpeto, ocorrer de novo. Despois dun tempo, o meu colega queixouse comigo de que as conexións de rede no continente en xeral non funciona. Tiña algún código FORTRAN que necesitaba ser copiado nunha máquina no continente, pero non puido porque "a rede non aguantou o tempo suficiente para que se completase a carga por FTP".

Si, resultou que se produciron fallos na rede cando un compañeiro intentou enviar por FTP un ficheiro con código fonte en FORTRAN a unha máquina do continente. Tentamos arquivar o ficheiro: despois copiouse sen problemas (pero a máquina de destino non tiña un descomprimidor, polo que o problema non se solucionou). Finalmente "dividimos" o código FORTRAN en anacos moi pequenos e enviamos un a un. A maioría dos fragmentos foron copiados sen problemas, pero algunhas pezas non pasaron, ou pasaron despois numerosos intentos.

Cando examinamos as pasaxes problemáticas, descubrimos que tiñan algo en común: todas contiñan bloques de comentarios que comezaban e remataban con liñas formadas por C maiúscula (como prefería comentar un compañeiro en FORTRAN). Enviamos un correo electrónico a expertos en redes do continente e pedimos axuda. Por suposto, querían ver mostras dos nosos arquivos que non se podían transferir por FTP... pero as nosas cartas non chegaron a elas. Finalmente chegamos a un sinxelo describircomo son os ficheiros intransferibles. Funcionou :) [Atrévome a engadir aquí un exemplo dun dos comentarios problemáticos de FORTRAN? Probablemente non paga a pena!]

Ao final conseguimos descifralo. Recentemente instalouse unha nova pasarela entre a nosa parte do campus e a rede continental. Tivo ENORMES dificultades para transmitir paquetes que contiñan bits repetidos de C en maiúscula! Só algúns destes paquetes poderían ocupar todos os recursos da pasarela e impedir que a maioría dos outros paquetes pasen. Queixamos ao fabricante da pasarela... e estes responderon: "Oh, si, estás ante un erro de C repetido! Xa sabemos del". Finalmente resolvemos o problema comprando unha nova pasarela doutro fabricante (en defensa do primeiro, a incapacidade de transferir programas FORTRAN pode ser unha vantaxe para algúns!).

Momentos difíciles

Hai uns anos, mentres traballaba na creación dun sistema ETL en Perl para reducir os custos dos ensaios clínicos da fase 40, necesitaba procesar unhas 000 datas. Dous deles non superaron a proba. Isto non me molestou demasiado porque estas datas foron tomadas de datos proporcionados polo cliente que moitas veces eran, digamos, sorprendentes. Pero cando comprobei os datos orixinais, resultou que estas datas eran o 1 de xaneiro de 2011 e o 1 de xaneiro de 2007. Pensei que o erro estaba contido no programa que acababa de escribir, pero resultou que xa había 30 anos. vello. Isto pode parecer misterioso para aqueles que non estean familiarizados co ecosistema de software. Debido á longa decisión doutra empresa de gañar cartos, o meu cliente pagoume para que corrixese un erro que unha empresa introducira por accidente e a outra adrede. Para que entendades do que falo, teño que falar da compañía que engadiu a función que acabou converténdose nun erro, así como doutros eventos interesantes que contribuíron ao misterioso erro que solucionei.

Nos bos tempos, os ordenadores Apple ás veces restablecían espontaneamente a súa data ao 1 de xaneiro de 1904. O motivo era sinxelo: utilizaba un "reloxo do sistema" alimentado por batería para facer un seguimento da data e da hora. Que pasou cando a batería morreu? Os ordenadores comezaron a rastrexar a data segundo o número de segundos desde o inicio dunha época. Por época entendíamos a data orixinal de referencia, e para Macintosh era o 1 de xaneiro de 1904. E despois de que a batería morrese, a data actual restableceuse á especificada. Pero por que pasou isto?

Anteriormente, Apple utilizaba 32 bits para almacenar o número de segundos desde a data orixinal. Un bit pode almacenar un dos dous valores: 1 ou 0. Dous bits poden almacenar un dos catro valores: 00, 01, 10, 11. Tres bits: un valor de oito: 000, 001, 010, 011, 100 , 101, 110, 111, etc. E 32 podería almacenar un dos 232 valores, é dicir, 4 segundos. Para as datas de Apple, isto equivale a uns 294 anos, polo que os Mac máis antigos non poden xestionar datas posteriores a 967. E se a batería do sistema esgota, a data restablece a 296 segundos desde o inicio da época, e ten que configurar a data manualmente cada vez que acende o ordenador (ou ata que compre unha batería nova).

Non obstante, a decisión de Apple de almacenar datas como segundos desde a época fixo que non puidésemos manexar datas anteriores á época, o que tivo consecuencias de gran alcance, como veremos. Apple presentou unha función, non un erro. Entre outras cousas, isto significaba que o sistema operativo Macintosh era inmune ao "error do milenio" (o que non se podía dicir de moitas aplicacións de Mac que tiñan os seus propios sistemas de datas para sortear as restricións).

Adiante. Usamos Lotus 1-2-3, a "aplicación asasina" de IBM que axudou a lanzar a revolución dos ordenadores, aínda que os ordenadores de Apple tiñan VisiCalc, o que fixo que o ordenador persoal fose un éxito. Para ser xusto, se non aparecese o 1-2-3, os ordenadores dificilmente despegarían e a historia dos ordenadores persoais podería desenvolverse de forma moi diferente. Lotus 1-2-3 tratou incorrectamente 1900 como un ano bisiesto. Cando Microsoft lanzou a súa primeira folla de cálculo, Multiplan, capturou unha pequena parte do mercado. E cando lanzaron o proxecto Excel, decidiron non só copiar o esquema de nomeamento de filas e columnas de Lotus 1-2-3, senón tamén garantir a compatibilidade de erros tratando deliberadamente 1900 como un ano bisiesto. Este problema aínda existe hoxe en día. Entón, en 1-2-3 foi un erro, pero en Excel foi unha decisión consciente asegurarse de que todos os usuarios de 1-2-3 puidesen importar as súas táboas a Excel sen cambiar os datos, aínda que fose incorrecto.

Pero había outro problema. En primeiro lugar, Microsoft lanzou Excel para Macintosh, que non recoñeceu datas anteriores ao 1 de xaneiro de 1904. E en Excel, o 1 de xaneiro de 1900 considerouse o inicio da era. Polo tanto, os desenvolvedores fixeron un cambio para que o seu programa recoñecese o tipo de época e almacenase os datos dentro de si de acordo coa época desexada. Microsoft ata escribiu un artigo explicativo sobre isto. E esta decisión levou ao meu erro.

O meu sistema ETL recibiu follas de cálculo Excel de clientes que se crearon en Windows, pero tamén se podían crear nun Mac. Polo tanto, o inicio da época na táboa podería ser o 1 de xaneiro de 1900 ou o 1 de xaneiro de 1904. Como descubrir? O formato de ficheiro de Excel mostra a información necesaria, pero o analizador que utilicei non a amosou (agora si), e supuña que coñeces a época dunha táboa específica. Probablemente podería ter pasado máis tempo entendendo o formato binario de Excel e enviando un parche ao autor do analizador, pero tiña moito máis que facer para o cliente, así que escribín rapidamente unha heurística para determinar a época. Ela era sinxela.

En Excel, a data do 5 de xullo de 1998 pódese representar no formato "07-05-98" (sistema americano inútil), "5 de xullo de 98", "5 de xullo de 1998", "5 de xullo de 98" ou algún outro formato, outro formato inútil (ironicamente, un dos formatos que non ofrecía a miña versión de Excel era ISO 8601). Non obstante, dentro da táboa, a data sen formato gardouse como "35981" para a época-1900 ou "34519" para a época-1904 (os números representan o número de días desde a época). Simplemente usei un analizador sinxelo para extraer o ano da data con formato e despois usei o analizador de Excel para extraer o ano da data sen formato. Se os dous valores diferían en 4 anos, entón sabía que estaba a usar un sistema coa época-1904.

Por que non usei só datas con formato? Porque o 5 de xullo de 1998 pódese formatar como "xullo do 98" co día do mes perdido. Recibimos táboas de tantas empresas que as crearon de tantas formas diferentes que nos correspondeu a nós (neste caso, a min) descubrir as datas. Ademais, se Excel acerta, nós tamén debemos!

Ao mesmo tempo atopei 39082. Permíteme lembrar que Lotus 1-2-3 consideraba 1900 un ano bisiesto, e isto repetiuse fielmente en Excel. E xa que isto engadiu un día ao ano 1900, moitas funcións de cálculo de datas poderían estar equivocadas para ese mesmo día. É dicir, 39082 podería ser o 1 de xaneiro de 2011 (en Mac) ou o 31 de decembro de 2006 (en Windows). Se o meu "analizador de anos" extraeu o ano 2011 do valor formateado, entón todo está ben. Pero como o analizador de Excel non sabe que época se está a usar, por defecto é epoch-1900, devolvendo o ano 2006. A miña aplicación viu que a diferenza era de 5 anos, considerouno un erro, rexistrouno e devolveu un valor sen formato.

Para evitar isto, escribín isto (pseudocódigo):

diff = formatted_year - parsed_year
if 0 == diff
    assume 1900 date system
if 4 == diff
    assume 1904 date system
if 5 == diff and month is December and day is 31
    assume 1904 date system

E entón as 40 datas foron analizadas correctamente.

No medio de traballos de impresión grande

A principios dos anos 1980, o meu pai traballaba en Storage Technology, unha división xa desaparecida que creaba unidades de cinta e sistemas pneumáticos para a alimentación de cinta a alta velocidade.

Rediseñaron as unidades para que puidesen ter unha unidade central "A" conectada a sete unidades "B" e o pequeno sistema operativo en RAM que controlaba a unidade "A" podería delegar as operacións de lectura e escritura en todas as unidades "B".

Cada vez que se iniciaba a unidade “A”, era necesario inserir un disquete na unidade periférica conectada a “A” para cargar o sistema operativo na súa memoria. Era extremadamente primitivo: a potencia de cómputo era proporcionada por un microcontrolador de 8 bits.

O público obxectivo destes equipos eran empresas con almacéns de datos moi grandes -bancos, cadeas de venda polo miúdo, etc.- que precisaban imprimir moitas etiquetas de enderezos ou extractos bancarios.

Un cliente tivo un problema. No medio dun traballo de impresión, unha determinada unidade "A" podería deixar de funcionar, o que provocaría que todo o traballo se paralizase. Para restablecer o funcionamento da unidade, o persoal tivo que reiniciar todo. E se isto ocorreu no medio dunha tarefa de seis horas, perdeuse unha enorme cantidade de tempo de ordenador caro e interrompeuse a programación de toda a operación.

Enviáronse técnicos de Storage Technologies. Pero a pesar dos seus mellores esforzos, non puideron reproducir o erro en condicións de proba: parecía que se producía no medio de traballos de impresión grande. O problema non foi o hardware, substituíron todo o que podían: RAM, microcontrolador, disquete, todas as partes concebibles da unidade de cinta, o problema persistiu.

Entón os técnicos chamaron á sede e chamaron ao Perito.

O experto colleu unha cadeira e unha cunca de café, sentouse na aula de informática —naqueles tempos había salas dedicadas a informática— e observou como o persoal facía fila un traballo de impresión grande. O experto estaba á espera de que se producise un fallo, e así foi. Todos miraron ao Experto, pero non tiña nin idea de por que ocorreu isto. Así que mandou facer cola de novo o traballo, e todo o persoal e técnicos volveron a traballar.

O experto volveu sentar na cadeira e comezou a esperar un fallo. Pasaron unhas seis horas e produciuse o fallo. O Experto volveu non ter ideas, salvo que todo aconteceu nunha sala chea de xente. Ordenou que se reiniciase a misión, volveu sentar e esperou.

No terceiro fallo, o Experto notou algo. O fallo ocorreu cando o persoal cambiou as cintas nunha unidade allea. Ademais, o fallo produciuse en canto un dos empregados atravesou unha determinada tella do chan.

O chan elevado estaba feito de baldosas de aluminio colocadas a unha altura de 6 a 8 polgadas. Numerosos fíos dos ordenadores corrían baixo o chan elevado para evitar que alguén pise accidentalmente un cable importante. As tellas foron colocadas moi firmemente para evitar que os restos entren debaixo do chan elevado.

O experto decatouse de que unha das tellas estaba deformada. Cando un empregado pisaba a súa esquina, os bordos da tella fregaban contra as tellas adxacentes. Tamén se fregaban con elas as pezas de plástico que conectaban as tellas, o que provocaba microdescargas estáticas que creaban interferencias de radiofrecuencia.

Hoxe, a memoria RAM está moito mellor protexida das interferencias de radiofrecuencia. Pero naqueles anos non era así. O experto deuse conta de que esta interferencia interrompía a memoria e, con ela, o funcionamento do sistema operativo. Chamou ao servizo de asistencia, encargou tellas novas, instalounas el mesmo e o problema desapareceu.

É a marea alta!

A historia tivo lugar nunha sala de servidores, no cuarto ou quinto piso dunha oficina de Portsmouth (creo), na zona dos peiraos.

Un día fallou o servidor Unix coa base de datos principal. Reiniciárono, pero felizmente seguiu caendo unha e outra vez. Decidimos chamar a alguén do servizo de asistencia.

O tipo de apoio... Creo que se chamaba Mark, pero iso non importa... Creo que non o coñezo. Non importa, de verdade. Quedemos con Mark, vale? Genial.

Entón, unhas horas despois chegou Mark (non hai moito camiño de Leeds a Portsmouth, xa sabes), acendeu o servidor e todo funcionou sen problemas. Maldito apoio típico, o cliente está moi molesto por iso. Mark mira os ficheiros de rexistro e non atopa nada desagradable. Entón, Mark volve no tren (ou con calquera medio de transporte no que chegou, podería ser unha vaca coxa polo que eu sei... de todos os xeitos, non importa, vale?) e volve a Leeds, desperdiciado. o día.

Esa mesma noite o servidor volve fallar. A historia é a mesma... o servidor non se levanta. Mark tenta axudar de forma remota, pero o cliente non pode iniciar o servidor.

Outro tren, autobús, merengue de limón ou algunha outra merda, e Mark está de volta en Portsmouth. Mira, o servidor arranca sen problemas! Milagre. Mark pasa varias horas comprobando que todo está en orde co sistema operativo ou software e parte cara a Leeds.

Ao mediodía, o servidor falla (tranquilo!). Esta vez parece razoable traer persoas de soporte de hardware para substituír o servidor. Pero non, despois dunhas 10 horas tamén cae.

A situación repetiuse durante varios días. O servidor funciona, falla despois dunhas 10 horas e non se inicia durante as próximas 2 horas. Revisaron o arrefriamento, as fugas de memoria, comprobaron todo, pero non atoparon nada. Entón os accidentes pararon.

A semana pasou despreocupada... todos estaban contentos. Feliz ata que todo comece de novo. A imaxe é a mesma. 10 horas de traballo, 2-3 horas de inactividade...

E entón alguén (creo que me dixeron que esa persoa non tiña nada que ver con TI) dixo:

"É a marea!"

A exclamación foi recibida con miradas en branco, e a man de alguén probablemente dubidou no botón de chamada de seguridade.

"Deixa de funcionar coa marea".

Este parece ser un concepto completamente alleo para os traballadores de soporte informático, que é pouco probable que lean o Tide Yearbook mentres se sentan a tomar un café. Explicaron que isto non podía estar relacionado de ningún xeito coa marea, pois o servidor levaba unha semana traballando sen fallos.

"A semana pasada a marea foi baixa, pero esta semana é alta".

Un pouco de terminoloxía para os que non teñen carné de iate. As mareas dependen do ciclo lunar. E mentres a Terra xira, cada 12,5 horas a atracción gravitatoria do Sol e da Lúa crea un maremoto. Ao comezo do ciclo de 12,5 horas hai unha marea alta, na metade do ciclo hai un refluxo e ao final volve a marear. Pero a medida que cambia a órbita da lúa, tamén cambia a diferenza entre a marea baixa e a marea alta. Cando a Lúa está entre o Sol e a Terra ou no lado oposto da Terra (lúa chea ou sen lúa), obtemos mareas Syzygyn: as mareas máis altas e as baixas máis baixas. Na media lúa temos mareas en cuadratura, as mareas máis baixas. A diferenza entre os dous extremos diminúe moito. O ciclo lunar dura 28 días: sizigo - cuadratura - sicigo - cuadratura.

Cando se lles explicou aos técnicos a esencia das mareas, de inmediato pensaron que había que chamar á policía. E bastante lóxico. Pero resulta que o tipo tiña razón. Dúas semanas antes, un destrutor atracou non moi lonxe da oficina. Cada vez que a marea o subía a certa altura, o posto de radar do barco remataba ao nivel do piso da sala de servidores. E o radar (ou equipos de guerra electrónica, ou algún outro xoguete militar) creou o caos nos ordenadores.

Misión de voo para o foguete

Encargáronme a porta dun gran (unhas 400 mil liñas) sistema de control e seguimento do lanzamento de foguetes a novas versións do sistema operativo, compilador e linguaxe. Máis precisamente, dende Solaris 2.5.1 ata Solaris 7, e dende o Verdix Ada Development System (VADS), escrito en Ada 83, ata o sistema Rational Apex Ada, escrito en Ada 95. VADS foi adquirido por Rational e o seu produto foi obsoleto, aínda que Rational intentou implementar versións compatibles de paquetes específicos de VADS para facilitar a transición ao compilador Apex.

Tres persoas axudáronme a compilar o código de forma limpa. Levou dúas semanas. E despois traballei pola miña conta para facer funcionar o sistema. En definitiva, era a peor arquitectura e implementación dun sistema de software que me atopara, polo que tardou outros dous meses en completar o porto. O sistema foi entón sometido a proba, que levou varios meses máis. Inmediatamente corrixín os erros que se atopaban durante as probas, pero o seu número diminuíu rapidamente (o código fonte era un sistema de produción, polo que a súa funcionalidade funcionaba de xeito bastante fiable, só tiven que eliminar os erros que xurdiron durante a adaptación ao novo compilador). Finalmente, cando todo funcionaba como debía, trasladáronme a outro proxecto.

E o venres antes do Día de Acción de Grazas, soou o teléfono.

O lanzamento do foguete debía ser probado nunhas tres semanas, e durante as probas de laboratorio da conta atrás, a secuencia de comandos bloqueouse. Na vida real, isto abortaría a proba e, se o bloqueo se producise aos poucos segundos de arrancar o motor, produciríanse varias accións irreversibles nos sistemas auxiliares, o que requiriría unha longa -e custosa- preparación do foguete. Non comezaría, pero moita xente estaría moi molesta pola perda de tempo e moito, moito diñeiro. Non deixes que ninguén che diga que o Departamento de Defensa gasta diñeiro de forma imprudente: nunca coñecín a un director de contratación que non puxese o orzamento en primeiro lugar ou segundo, seguido do calendario.

Nos meses anteriores, este desafío de conta atrás realizouse centos de veces en moitas variacións, con só algúns pequenos eivas. Polo que a probabilidade de que isto ocorrese era moi baixa, pero as súas consecuencias foron moi importantes. Multiplica estes dous factores, e entenderás que a noticia prevía unha semana de vacacións en ruínas para min e para decenas de enxeñeiros e xestores.

E prestouse atención a min como a persoa que portou o sistema.

Como coa maioría dos sistemas críticos para a seguridade, rexistráronse moitos parámetros, polo que foi bastante sinxelo identificar as poucas liñas de código que se executaban antes de que o sistema fallase. E, por suposto, non había absolutamente nada inusual neles; as mesmas expresións foran executadas con éxito literalmente miles de veces durante a mesma carreira.

Chamamos á xente de Apex a Rational porque foron eles os que desenvolveron o compilador e algunhas das rutinas que desenvolveron chamábanse no código sospeitoso. Eles (e todos os demais) quedaron impresionados da necesidade de chegar á raíz dun problema de importancia literalmente nacional.

Como non había nada interesante nas revistas, decidimos tentar reproducir o problema nun laboratorio local. Non foi unha tarefa sinxela xa que o evento ocorreu aproximadamente unha vez por cada 1000 carreiras. Un motivo sospeitoso foi que unha chamada a unha función mutex desenvolvida polo provedor (parte do paquete de migración VADS) Unlock non levou ao desbloqueo. O fío de procesamento que chamou a función procesaba as mensaxes de latido do corazón, que nominalmente chegaban cada segundo. Subimos a frecuencia a 10 Hz, é dicir, 10 veces por segundo, e comezamos a correr. Aproximadamente unha hora despois, o sistema bloqueouse. No rexistro, vimos que a secuencia de mensaxes gravadas era a mesma que durante a proba fallida. Fixemos varias carreiras máis, o sistema bloqueouse constantemente 45-90 minutos despois do inicio e cada vez que o rexistro contiña a mesma ruta. Aínda que tecnicamente estabamos executando código diferente (a frecuencia das mensaxes era diferente), o comportamento do sistema era o mesmo, polo que estabamos seguros de que este escenario de carga estaba a causar o mesmo problema.

Agora necesitabamos descubrir onde se produciu exactamente o bloqueo na secuencia de expresións.

Esta implementación do sistema utilizou o sistema de tarefas Ada, e utilizouno moi mal. As tarefas son unha construción de alto nivel executable simultáneamente en Ada, algo así como fíos de execución, só incorporada na propia linguaxe. Cando hai que comunicar dúas tarefas, "establecen unha cita", intercambian os datos necesarios e, a continuación, deteñen a cita e volven ás súas execucións independentes. Non obstante, o sistema implementouse de forma diferente. Despois de que unha tarefa de destino fose a cita, esa tarefa de destino reuníase con outra tarefa, que logo se encontraba cunha terceira tarefa, e así sucesivamente ata que se completou algún procesamento. Despois diso, todas estas citas foron completadas e cada tarefa tiña que volver á súa execución. É dicir, estabamos ante o sistema de chamadas de funcións máis caro do mundo, que detivo todo o proceso de "multitarefa" mentres procesaba parte dos datos de entrada. E antes isto non provocou problemas só porque o rendemento era moi baixo.

Describín este mecanismo de tarefas porque cando se solicitaba unha cita ou se esperaba que se completase, podía producirse un "cambio de tarefas". É dicir, o procesador podería comezar a procesar outra tarefa que estea lista para ser executada. Acontece que cando unha tarefa está lista para reunirse con outra tarefa, pode comezar a executarse unha tarefa completamente diferente e, finalmente, o control volve á primeira cita. E poden ocorrer outros eventos que fagan que a tarefa cambie; un destes eventos é unha chamada a unha función do sistema, como imprimir ou executar un mutex.

Para comprender que liña de código estaba a causar o problema, necesitaba atopar un xeito de rexistrar o progreso a través dunha secuencia de instrucións sen activar un cambio de tarefa, o que evitaría que se producise un fallo. Así que non puiden aproveitar Put_Line()para evitar realizar operacións de E/S. Podería establecer unha variable de contador ou algo semellante, pero como podo ver o seu valor se non o podo mostrar na pantalla?

Ademais, ao examinar o rexistro, resultou que, a pesar da conxelación no procesamento das mensaxes de latido do corazón, que bloqueaba todas as operacións de E/S do proceso e impediu que se realizaran outros procesamentos, seguían executándose outras tarefas independentes. É dicir, o traballo non estaba totalmente bloqueado, só unha cadea (crítica) de tarefas.

Esta era a pista necesaria para avaliar a expresión de bloqueo.

Fixen un paquete Ada que contiña unha tarefa, un tipo enumerado e unha variable global dese tipo. Enumerables literais estaban ligados a expresións específicas da secuencia problemática (p. ex. Incrementing_Buffer_Index, Locking_Mutex, Mutex_Unlocked), e despois inseriu nela expresións de asignación que asignaron a enumeración correspondente a unha variable global. Dado que o código obxecto de todo isto simplemente almacenaba unha constante na memoria, o cambio de tarefa como resultado da súa execución era moi improbable. Principalmente desconfiamos das expresións que puidesen cambiar a tarefa, xa que o bloqueo produciuse na execución en lugar de volver ao cambiar a tarefa (por varias razóns).

A tarefa de seguimento simplemente executouse nun bucle e comprobouse periodicamente se o valor da variable global cambiara. Con cada cambio, o valor gardábase nun ficheiro. Despois unha pequena espera e unha nova comprobación. Escribín a variable no ficheiro porque a tarefa só se executou cando o sistema a seleccionou para a súa execución ao cambiar a tarefa na área do problema. O que acontecese nesta tarefa non afectaría a outras tarefas bloqueadas non relacionadas.

Esperábase que cando o sistema chegase ao punto de executar o código problemático, a variable global restablecese ao pasar a cada expresión seguinte. Entón ocorrerá algo que faga que a tarefa cambie, e dado que a súa frecuencia de execución (10 Hz) é menor que a da tarefa de monitorización, o monitor podería capturar o valor da variable global e escribilo. Nunha situación normal, podería obter unha secuencia repetida dun subconxunto de enumeracións: os últimos valores da variable no momento do cambio de tarefa. Ao colgar, a variable global xa non debería cambiar e o último valor escrito indicará que expresión non se completou.

Executei o código con seguimento. Conxelouse. E o seguimento funcionou como un reloxo.

O rexistro contiña a secuencia esperada, que foi interrompida por un valor que indicaba que se chamara un mutex Unlock, e a tarefa non está rematada, como é o caso de miles de convocatorias anteriores.

Os enxeñeiros de Apex estaban a analizar febrilmente o seu código neste momento e atoparon un lugar no mutex onde, teoricamente, podería producirse un bloqueo. Pero a súa probabilidade era moi baixa, xa que só unha determinada secuencia de eventos que ocorresen nun momento determinado podía levar ao bloqueo. A lei de Murphy, rapaces, é a lei de Murphy.

Para protexer a peza de código que necesitaba, substituín as chamadas de función mutex (construídas sobre a funcionalidade mutex do SO) por un pequeno paquete nativo de mutex de Ada para controlar o acceso mutex a esa peza.

Insereino no código e executei a proba. Sete horas despois o código seguía funcionando.

O meu código foi enviado a Rational, onde o compilaron, desmontaron e comprobaron que non utilizaba o mesmo enfoque que se usaba nas funcións mutex problemáticas.

Esta foi a revisión de código máis multitudinaria da miña carreira 🙂 Había uns dez enxeñeiros e xestores na sala comigo, outras dez persoas estaban nunha conferencia telefónica e todas examinaron unhas 20 liñas de código.

Revisouse o código, recompiláronse novos ficheiros executables e enviáronse para probas de regresión formal. Un par de semanas despois, a proba de conta atrás foi exitosa e o foguete despegou.

Está ben, todo está ben, pero cal é o sentido da historia?

Foi un problema absolutamente noxento. Centos de miles de liñas de código, execución paralela, máis dunha ducia de procesos interactivos, mala arquitectura e mala implementación, interfaces para sistemas integrados e millóns de dólares gastados. Sen presión, certo.

Non fun o único que traballaba neste problema, aínda que estaba no punto de mira mentres facía a portabilidade. Pero aínda que o fixen, iso non significa que entendín todos os centos de miles de liñas de código, nin sequera as descreme. O código e os rexistros foron analizados por enxeñeiros de todo o país, pero cando me dixeron as súas hipóteses sobre as causas do fallo, só tardei medio minuto en refutalos. E cando me pedían analizar teorías, pasaballo a outra persoa, porque era obvio para min que estes enxeñeiros ían polo camiño equivocado. Soa presuntuoso? Si, isto é certo, pero rexeitei as hipóteses e as peticións por outro motivo.

Entendín a natureza do problema. Non sabía exactamente onde estaba a suceder nin por que, pero sabía o que estaba a pasar.

Ao longo dos anos, acumulei moito coñecemento e experiencia. Fun un dos pioneiros en usar Ada e entendín as súas vantaxes e inconvenientes. Sei como as bibliotecas de tempo de execución de Ada xestionan tarefas e xestionan a execución paralela. E entendo a programación de baixo nivel a nivel de memoria, rexistros e ensamblador. Noutras palabras, teño un profundo coñecemento no meu campo. E useinos para atopar a causa do problema. Non só traballei para evitar o erro, entendín como atopalo nun ambiente de execución moi sensible.

Tales historias de loita co código non son moi interesantes para aqueles que non están familiarizados coas características e condicións de tal loita. Pero estas historias axúdannos a comprender o que fai falta para resolver problemas realmente difíciles.

Para resolver problemas realmente difíciles, cómpre ser algo máis que un programador. Debes comprender o "destino" do código, como interactúa co seu entorno e como funciona o propio ambiente.

E entón terás a túa propia semana de vacacións en ruínas.

Continuar.

Fonte: www.habr.com

Engadir un comentario