programa de computador -Computer program

Na programação imperativa , um programa de computador é uma sequência de instruções em uma linguagem de programação que um computador pode executar ou interpretar. Na programação declarativa , um programa de computador é um conjunto de instruções. Um programa de computador é um componente de software – que também inclui documentação e outros componentes intangíveis.

Um programa de computador em sua forma legível por humanos é chamado de código-fonte . O código-fonte precisa de outro programa de computador para ser executado porque os computadores só podem executar suas instruções de máquina nativas . Portanto, o código-fonte pode ser traduzido para instruções de máquina usando o compilador da linguagem . ( Os programas em linguagem de máquina são traduzidos usando um montador .) O arquivo resultante é chamado de executável . Alternativamente, o código-fonte pode ser executado dentro do interpretador da linguagem . A linguagem de programação Java compila em uma forma intermediária que é então executada por um interpretador Java .

Se o executável for solicitado para execução, o sistema operacional o carregará na memória e iniciará um processo . A unidade central de processamento em breve mudará para esse processo para que possa buscar, decodificar e executar cada instrução de máquina.

Se o código-fonte for solicitado para execução, o sistema operacional carrega o interpretador correspondente na memória e inicia um processo. O interpretador então carrega o código-fonte na memória para traduzir e executar cada instrução . A execução do código-fonte é mais lenta do que a execução de um executável. Além disso, o intérprete deve estar instalado no computador.

programa Olá mundo

O "Olá, Mundo!" programa é usado para ilustrar a sintaxe básica de uma linguagem . A sintaxe da linguagem interpretada Basic (1964) foi intencionalmente limitada para tornar a linguagem fácil de aprender. Por exemplo, as variáveis ​​não são declaradas antes de serem usadas. Além disso, as variáveis ​​são inicializadas automaticamente em zero. Aqui está um programa básico para calcular a média de uma lista de números:

10 INPUT "How many numbers to average?", A
20 FOR I = 1 TO A
30 INPUT "Enter number:", B
40 LET C = C + B
50 NEXT I
60 LET D = C/A
70 PRINT "The average is", D
80 END

Uma vez que a mecânica da programação básica de computadores é aprendida, linguagens mais sofisticadas e poderosas estão disponíveis para construir grandes sistemas de computador.

História

As melhorias no desenvolvimento de software são o resultado de melhorias no hardware do computador . Em cada estágio da história do hardware, a tarefa de programação de computadores mudou drasticamente.

Motor analítico

A descrição de Lovelace da Nota G.

Em 1837, Charles Babbage inspirou-se no tear de Jacquard para tentar construir a Máquina Analítica . Os nomes dos componentes do dispositivo de cálculo foram emprestados da indústria têxtil. Na indústria têxtil, o fio era trazido da loja para ser moído. O dispositivo tinha um "armazenamento" que era uma memória para armazenar 1.000 números de 50 dígitos decimais cada. Os números da "loja" foram transferidos para a "fábrica" ​​para processamento. Foi programado usando dois conjuntos de cartões perfurados. Um conjunto dirigiu a operação e o outro conjunto inseriu as variáveis. No entanto, depois de mais de 17.000 libras do dinheiro do governo britânico, as milhares de engrenagens e engrenagens nunca funcionaram totalmente juntas.

Ada Lovelace trabalhou para Charles Babbage para criar uma descrição da Máquina Analítica (1843). A descrição continha a Nota G que detalhava completamente um método para calcular os números de Bernoulli usando a Máquina Analítica. Esta nota é reconhecida por alguns historiadores como o primeiro programa de computador do mundo.

Máquina de Turing Universal

Universal Turing machine.svg

Em 1936, Alan Turing introduziu a máquina de Turing Universal – um dispositivo teórico que pode modelar cada computação. É uma máquina de estado finito que possui uma fita de leitura/gravação infinitamente longa. A máquina pode mover a fita para frente e para trás, alterando seu conteúdo à medida que executa um algoritmo . A máquina inicia no estado inicial, passa por uma sequência de etapas e para quando encontra o estado de parada. Todos os computadores atuais são Turing completos .

ENIAC

Glenn A. Beck está trocando um tubo no ENIAC.

O Integrador Numérico Eletrônico e Computador (ENIAC) foi construído entre julho de 1943 e outono de 1945. Era um computador Turing completo , de uso geral, que usava 17.468 tubos de vácuo para criar os circuitos . Em sua essência, era uma série de Pascalines conectadas. Suas 40 unidades pesavam 30 toneladas, ocupavam 1.800 pés quadrados (167 m 2 ) e consumiam US$ 650 por hora ( na moeda da década de 1940 ) em eletricidade quando ociosas. Tinha 20 acumuladores de base 10 . A programação do ENIAC levou até dois meses. Três mesas de função estavam sobre rodas e precisavam ser enroladas em painéis de função fixos. As mesas de funções eram conectadas aos painéis de funções conectando-se cabos pretos pesados ​​em painéis de tomadas . Cada mesa de função tinha 728 botões giratórios. A programação do ENIAC também envolveu a configuração de alguns dos 3.000 interruptores. A depuração de um programa levava uma semana. Ele funcionou de 1947 a 1955 no Campo de Provas de Aberdeen , calculando parâmetros de bombas de hidrogênio, prevendo padrões climáticos e produzindo tabelas de tiro para apontar armas de artilharia.

Computadores de programa armazenado

Em vez de conectar cabos e girar interruptores, um computador com programa armazenado carrega suas instruções na memória da mesma forma que carrega seus dados na memória. Como resultado, o computador pode ser programado rapidamente e realizar cálculos em velocidades muito rápidas. Presper Eckert e John Mauchly construíram o ENIAC. Os dois engenheiros introduziram o conceito de programa armazenado em um memorando de três páginas datado de fevereiro de 1944. Mais tarde, em setembro de 1944, o Dr. John von Neumann começou a trabalhar no projeto ENIAC. Em 30 de junho de 1945, von Neumann publicou o primeiro rascunho de um relatório sobre o EDVAC que equiparava as estruturas do computador com as estruturas do cérebro humano. O projeto ficou conhecido como a arquitetura de von Neumann . A arquitetura foi implantada simultaneamente nas construções dos computadores EDVAC e EDSAC em 1949.

O IBM System/360 (1964) era uma linha de seis computadores, cada um com a mesma arquitetura de conjunto de instruções . O Modelo 30 foi o menor e menos caro. Os clientes podem atualizar e manter o mesmo software de aplicativo . O Modelo 75 foi o mais premium. Cada modelo System/360 apresentava multiprogramação — com vários processos na memória ao mesmo tempo. Quando um processo estava esperando por entrada/saída , outro poderia computar.

A IBM planejou que cada modelo fosse programado usando PL/1 . Foi formado um comitê que incluiu programadores COBOL , Fortran e ALGOL . O objetivo era desenvolver uma linguagem abrangente, fácil de usar, extensível e que substituísse o Cobol e o Fortran. O resultado foi uma linguagem grande e complexa que levou muito tempo para compilar .

Interruptores para entrada manual em um Data General Nova 3, fabricado em meados da década de 1970

Os computadores fabricados até a década de 1970 tinham interruptores no painel frontal para programação manual. O programa de computador foi escrito em papel para referência. Uma instrução foi representada por uma configuração de configurações de ligar/desligar. Após definir a configuração, um botão de execução foi pressionado. Este processo foi então repetido. Os programas de computador também eram inseridos automaticamente por meio de fita de papel ou cartões perfurados . Depois que a mídia foi carregada, o endereço inicial foi definido por meio de interruptores e o botão de execução foi pressionado.

integração em larga escala

Uma matriz de circuito integrado VLSI .

Um marco importante no desenvolvimento de software foi a invenção do circuito Very Large Scale Integration (VLSI) (1964). Após a Segunda Guerra Mundial , a tecnologia baseada em tubos foi substituída por transistores de contato pontual (1947) e transistores de junção bipolar (final da década de 1950) montados em uma placa de circuito . Durante a década de 1960 , a indústria aeroespacial substituiu a placa de circuito por um chip de circuito integrado .

Robert Noyce , co-fundador da Fairchild Semiconductor (1957) e da Intel (1968), alcançou uma melhoria tecnológica para refinar a produção de transistores de efeito de campo (1963). O objetivo é alterar a resistividade elétrica e a condutividade de uma junção semicondutora . Primeiro, os minerais de silicato de ocorrência natural são convertidos em barras de polissilício usando o processo Siemens . O processo Czochralski então converte as hastes em um silício monocristalino , cristal boule . O cristal é então cortado em fatias finas para formar um substrato de wafer . O processo planar de fotolitografia então integra transistores unipolares, capacitores , diodos e resistores no wafer para construir uma matriz de transistores de metal-óxido-semicondutor (MOS). O transistor MOS é o componente primário em chips de circuito integrado .

Originalmente, os chips de circuito integrado tinham sua função definida durante a fabricação. Durante a década de 1960, o controle do fluxo elétrico migrou para a programação de uma matriz de memória somente leitura (ROM). A matriz se assemelhava a uma matriz bidimensional de fusíveis. O processo para incorporar instruções na matriz era queimar as conexões desnecessárias. Havia tantas conexões que os programadores de firmware escreveram um programa de computador em outro chip para supervisionar a queima. A tecnologia ficou conhecida como ROM programável . Em 1971, a Intel instalou o programa de computador no chip e o nomeou microprocessador Intel 4004 .

A CPU System/360 (1964) da IBM não era um microprocessador.

Os termos microprocessador e unidade de processamento central (CPU) são agora usados ​​de forma intercambiável. No entanto, as CPUs são anteriores aos microprocessadores. Por exemplo, o IBM System/360 (1964) tinha uma CPU feita de placas de circuito contendo componentes discretos em substratos cerâmicos .

Saco Estado 8008

Representação artística do microcomputador Intel 8008 da Sacramento State University (1972).

O Intel 4004 (1971) era um microprocessador de 4 bits projetado para executar a calculadora Busicom . Cinco meses após seu lançamento, a Intel lançou o Intel 8008 — um microprocessador de 8 bits. Bill Pentz liderou uma equipe na Sacramento State para construir o primeiro microcomputador usando o Intel 8008 — o Sac State 8008 (1972). Seu objetivo era armazenar os prontuários médicos dos pacientes. O computador suportava um sistema operacional de disco para executar uma unidade de disco rígido Memorex de 3 megabytes . Ele tinha uma tela colorida e teclado que foi empacotado em um único console. O sistema operacional do disco foi programado usando o Basic Assembly Language (BAL) da IBM . A aplicação do prontuário foi programada por meio de um intérprete BASIC . No entanto, o computador era um beco sem saída evolucionário porque era extremamente caro. Além disso, foi construído em um laboratório de uma universidade pública para uma finalidade específica. No entanto, o projeto contribuiu para o desenvolvimento do conjunto de instruções Intel 8080 (1974) .

série x86

O IBM Personal Computer original (1981) usava um microprocessador Intel 8088.

Em 1978, o ambiente moderno de desenvolvimento de software começou quando a Intel atualizou o Intel 8080 para o Intel 8086 . A Intel simplificou o Intel 8086 para fabricar o Intel 8088 mais barato . A IBM abraçou o Intel 8088 quando entrou no mercado de computadores pessoais (1981). À medida que a demanda do consumidor por computadores pessoais aumentou, o mesmo aconteceu com o desenvolvimento de microprocessadores da Intel. A sucessão de desenvolvimento é conhecida como a série x86 . A linguagem assembly x86 é uma família de instruções de máquina compatíveis com versões anteriores . As instruções de máquina criadas em microprocessadores anteriores foram mantidas durante as atualizações do microprocessador. Isso permitiu que os consumidores comprassem novos computadores sem precisar comprar um novo software de aplicativo . As principais categorias de instruções são:

Ambiente de programação

O DEC VT100 (1978) foi um terminal de computador amplamente utilizado .

Os circuitos VLSI permitiram que o ambiente de programação avançasse de um terminal de computador (até a década de 1990) para um computador com interface gráfica do usuário (GUI). Os terminais de computador limitavam os programadores a um único shell rodando em um ambiente de linha de comando . Durante a década de 1970, a edição de código-fonte em tela cheia tornou-se possível por meio de uma interface de usuário baseada em texto . Independentemente da tecnologia disponível, o objetivo é programar em uma linguagem de programação .

Linguagens de programação

Uma linguagem de programação é um conjunto de palavras- chave , símbolos , identificadores e regras pelas quais os programadores podem comunicar instruções ao computador. Eles seguem um conjunto de regras chamado sintaxe .

As linguagens de programação são baseadas em linguagens formais . O objetivo de definir uma solução em termos de sua linguagem formal é gerar um algoritmo para resolver o problema de sublinhado. Um algoritmo é uma sequência de instruções simples que resolvem um problema.

Gerações de linguagem de programação

A evolução da linguagem de programação começou quando o EDSAC (1949) utilizou o primeiro programa de computador armazenado em sua arquitetura von Neumann . A programação do EDSAC estava na primeira geração de linguagem de programação .

  • A estrutura básica de uma instrução em linguagem assembly é rótulo, operação, operando e comentário.
  • Os rótulos permitem que o programador trabalhe com nomes de variáveis . O montador posteriormente traduzirá os rótulos em endereços de memória física .
  • As operações permitem que o programador trabalhe com mnemônicos. O montador posteriormente traduzirá mnemônicos em números de instruções.
  • Operandos informam ao montador quais dados a operação processará.
  • Os comentários permitem ao programador articular uma narrativa porque as instruções por si só são vagas.
A principal característica de um programa em linguagem assembly é que ele forma um mapeamento um-para-um para seu destino de linguagem de máquina correspondente.
  • A terceira geração de linguagem de programação usa compiladores e interpretadores para executar programas de computador. A característica distintiva de uma linguagem de terceira geração é sua independência de um hardware específico. Eles começaram com as linguagens de Fortran (1958), COBOL (1959), ALGOL (1960) e BASIC (1964). Em 1973, a linguagem de programação C surgiu como uma linguagem de alto nível que produzia instruções eficientes em linguagem de máquina. Enquanto as linguagens de terceira geração historicamente geraram muitas instruções de máquina para cada instrução, C tem instruções que podem gerar uma única instrução de máquina. Além disso, um compilador otimizado pode anular o programador e produzir menos instruções de máquina do que instruções. Hoje, todo um paradigma de linguagens preenche o espectro imperativo da terceira geração .

Idiomas imperativos

Um programa de computador escrito em uma linguagem imperativa

As linguagens imperativas especificam um algoritmo sequencial usando declarações , expressões e instruções :

  • Uma declaração introduz um nome de variável ao programa de computador e o atribui a um tipo de dados – por exemplo:var x: integer;
  • Uma expressão produz um valor – por exemplo: 2 + 2produz 4
  • Uma instrução pode atribuir uma expressão a uma variável ou usar o valor de uma variável para alterar o fluxo de controle do programa – por exemplo:x := 2 + 2; if x = 4 then do_something();

Para obter exemplos de linguagens imperativas, visite Imperative_programming#Examples .

Idiomas declarativos

As linguagens imperativas têm uma crítica importante: atribuir uma expressão a uma variável não local pode produzir um efeito colateral indesejado . As linguagens declarativas geralmente omitem a instrução de atribuição e o fluxo de controle. Eles descrevem qual computação deve ser realizada e não como calculá-la. Duas grandes categorias de linguagens declarativas são linguagens funcionais e linguagens lógicas .

Em matemática, uma função é uma regra que mapeia elementos de uma expressão para um intervalo de valores . Considere a função:

times_10(x) = 10 * x

A expressão 10 * x é mapeada pela função times_10()para um intervalo de valores . Um valor é 20. Isso ocorre quando x é 2. Assim, a aplicação da função é escrita matematicamente como:

times_10(2) = 20

Um compilador de linguagem funcional não armazenará esse valor em uma variável. Em vez disso, ele enviará o valor para a pilha do computador antes de definir o contador do programa de volta para a função de chamada. A função de chamada então retirará o valor da pilha.

As linguagens imperativas suportam funções. Portanto, a programação funcional pode ser alcançada em uma linguagem imperativa, se o programador usar disciplina. No entanto, uma linguagem funcional forçará essa disciplina no programador por meio de sua sintaxe. As linguagens funcionais têm uma sintaxe adaptada para enfatizar o quê .

Um programa funcional é desenvolvido com um conjunto de funções primitivas seguidas por uma única função de driver. Considere o trecho :

function max(a,b){ /* code omitted */}

function min(a,b){ /* code omitted */}

function difference_between_largest_and_smallest(a,b,c) {

return max(a,max(b,c)) - min(a, min(b,c));

}

As primitivas são max()e min(). A função do motorista é difference_between_largest_and_smallest(). Executando:

put(difference_between_largest_and_smallest(10,4,7));produzirá 6.

As linguagens funcionais são usadas na pesquisa em ciência da computação para explorar novos recursos de linguagem. Além disso, sua falta de efeitos colaterais os tornou populares em programação paralela e programação simultânea . No entanto, os desenvolvedores de aplicativos preferem os recursos orientados a objetos das linguagens imperativas .

Para obter exemplos de linguagens declarativas, visite Declarative_programming#Examples .

Programação de computadores

Antes das linguagens de programação, Betty Jennings e Fran Bilas programavam o ENIAC movendo cabos e definindo interruptores.

A programação de computadores (parte do desenvolvimento de software e engenharia de software ) é o processo de escrever ou editar o código-fonte . Em um ambiente formal, um analista de sistemas reunirá informações dos gerentes sobre todos os processos da organização para automatizar. Este profissional elabora então um plano detalhado para o sistema novo ou modificado. O plano é análogo ao projeto de um arquiteto.

Objetivos de desempenho

O analista de sistemas tem o objetivo de entregar a informação certa para a pessoa certa no momento certo. Os fatores críticos para atingir esse objetivo são:

  1. A qualidade da saída. A saída é útil para a tomada de decisão?
  2. A precisão da saída. Reflete a situação real?
  3. O formato da saída. A saída é facilmente compreendida?
  4. A velocidade da saída. Informações sensíveis ao tempo são importantes ao se comunicar com o cliente em tempo real.

Objetivos de custo

Atingir os objetivos de desempenho deve ser equilibrado com todos os custos, incluindo:

  1. Custos do desenvolvimento.
  2. Custos de exclusividade. Um sistema reutilizável pode ser caro. No entanto, pode ser preferível a um sistema de uso limitado.
  3. Custos de hardware.
  4. Custos operacionais.

A aplicação de um processo de desenvolvimento de sistemas mitigará o axioma: quanto mais tarde no processo um erro for detectado, mais caro será a correção.

Modelo cascata

O modelo cascata é uma implementação de um processo de desenvolvimento de sistemas . Como o rótulo da cascata indica, as fases básicas se sobrepõem:

  1. A fase de investigação é entender o problema subjacente.
  2. A fase de análise é entender as possíveis soluções.
  3. A fase de projeto é planejar a melhor solução.
  4. A fase de implementação consiste em programar a melhor solução.
  5. A fase de manutenção dura toda a vida útil do sistema. Alterações no sistema após sua implantação podem ser necessárias. Podem existir falhas, incluindo falhas de especificação, falhas de projeto ou falhas de codificação. Melhorias podem ser necessárias. A adaptação pode ser necessária para reagir a um ambiente em mudança.

Programador de computador

Um programador de computador é um especialista responsável por escrever ou modificar o código-fonte para implementar o plano detalhado. É provável que uma equipe de programação seja necessária porque a maioria dos sistemas é grande demais para ser concluída por um único programador. No entanto, adicionar programadores a um projeto pode não reduzir o tempo de conclusão. Em vez disso, pode diminuir a qualidade do sistema. Para serem eficazes, os módulos do programa precisam ser definidos e distribuídos aos membros da equipe. Além disso, os membros da equipe devem interagir uns com os outros de maneira significativa e eficaz.

Programming-in-the-small é a programação de computadores dentro de um único módulo. É provável que um módulo execute módulos localizados em outros arquivos de código-fonte. Programar em grande escala é projetar módulos para que eles se acoplem efetivamente uns aos outros.

Módulos do programa

A programação modular é uma técnica para refinar programas de linguagem imperativa para mitigar o envelhecimento do software . Um módulo de programa é uma sequência de instruções que são limitadas dentro de um bloco e identificadas juntas por um nome. Os módulos têm uma função , contexto e lógica :

  • A função de um módulo é o que ele faz.
  • O contexto de um módulo são os elementos que estão sendo executados.
  • A lógica de um módulo é como ele executa a função.

O nome do módulo deve ser derivado primeiro por sua função , depois por seu contexto . Sua lógica não deve fazer parte do nome. Por exemplo, function compute_square_root( x )ou function compute_square_root_integer( i : integer )são nomes de módulo apropriados. No entanto, function compute_square_root_by_division( x )não é.

O grau de interação dentro de um módulo é seu nível de coesão . Coesão é um julgamento da relação entre o nome de um módulo e sua função . O grau de interação entre os módulos é o nível de acoplamento . O acoplamento é um julgamento da relação entre o contexto de um módulo e os elementos que estão sendo executados.

Coesão

Os níveis de coesão do pior para o melhor são:

  • Coesão Coincidental : Um módulo tem coesão coincidente se executa várias funções e as funções são completamente não relacionadas. Por exemplo, function read_sales_record_print_next_line_convert_to_float(). Coincidência de coesão ocorre na prática se a administração impõe regras tolas. Por exemplo, "Cada módulo terá entre 35 e 50 instruções executáveis".
  • Coesão Lógica: Um módulo tem coesão lógica se dispõe de uma série de funções, mas apenas uma delas é executada. Por exemplo, function perform_arithmetic( perform_addition, a, b ).
  • Coesão Temporal : Um módulo tem coesão temporal se desempenha funções relacionadas ao tempo. Um exemplo, function initialize_variables_and_open_files(). Outro exemplo, stage_one(), stage_two(), ...
  • Coesão Procedimental : Um módulo tem coesão procedimental se executa múltiplas funções, mas apenas vagamente relacionadas. Por exemplo, function read_part_number_update_employee_record().
  • Coesão Comunicacional : Um módulo tem coesão comunicacional se desempenha múltiplas funções, mas intimamente relacionadas. Por exemplo, function read_part_number_update_sales_record().
  • Coesão Informacional : Um módulo tem coesão informacional se executa múltiplas funções, mas cada função tem seus próprios pontos de entrada e saída. Além disso, as funções compartilham a mesma estrutura de dados. As classes orientadas a objetos funcionam nesse nível.
  • Coesão Funcional : um módulo tem coesão funcional se atinge um único objetivo trabalhando apenas em variáveis ​​locais. Além disso, pode ser reutilizável em outros contextos.

Acoplamento

Os níveis de acoplamento do pior para o melhor são:

  • Acoplamento de conteúdo : Um módulo tem acoplamento de conteúdo se modificar uma variável local de outra função. COBOL costumava fazer isso com o verbo alter .
  • Acoplamento comum : Um módulo tem acoplamento comum se modificar uma variável global.
  • Acoplamento de controle : Um módulo possui acoplamento de controle se outro módulo puder modificar seu fluxo de controle . Por exemplo, perform_arithmetic( perform_addition, a, b ). Em vez disso, o controle deve estar na composição do objeto retornado.
  • Stamp Coupling : Um módulo tem Stamp Coupling se um elemento de uma estrutura de dados passado como parâmetro for modificado. As classes orientadas a objetos funcionam nesse nível.
  • Acoplamento de dados : Um módulo possui acoplamento de dados se todos os seus parâmetros de entrada forem necessários e nenhum deles for modificado. Além disso, o resultado da função é retornado como um único objeto.

Análise de fluxo de dados

Um exemplo de diagrama de fluxo de dados em nível de função.

A análise de fluxo de dados é um método de design usado para obter módulos de coesão funcional e acoplamento de dados . A entrada para o método é um diagrama de fluxo de dados . Um diagrama de fluxo de dados é um conjunto de ovais representando módulos. O nome de cada módulo é exibido dentro de seu oval. Os módulos podem estar no nível executável ou no nível de função.

O diagrama também tem setas conectando os módulos entre si. As setas apontando para os módulos representam um conjunto de entradas. Cada módulo deve ter apenas uma seta apontando para representar seu único objeto de saída. (Opcionalmente, uma seta de exceção adicional aponta.) Uma série de ovais transmitirá um algoritmo inteiro . Os módulos de entrada devem iniciar o diagrama. Os módulos de entrada devem se conectar aos módulos de transformação. Os módulos de transformação devem se conectar aos módulos de saída.

Programação orientada a objetos

A programação orientada a objetos está executando operações ( funções ) em objetos . A ideia básica é agrupar as características de um fenômeno em um recipiente de objetos e dar um nome ao recipiente. As operações sobre o fenômeno também são agrupadas no container. Programação orientada a objetos desenvolvida combinando a necessidade de contêineres e a necessidade de programação funcional segura . Este método de programação não precisa ser confinado a uma linguagem orientada a objetos . Em uma linguagem orientada a objetos, um contêiner de objetos é chamado de classe . Em uma linguagem não orientada a objetos, uma estrutura de dados (que também é conhecida como registro ) pode se tornar um contêiner de objetos. Para transformar uma estrutura de dados em um contêiner de objetos, as operações precisam ser escritas especificamente para a estrutura. A estrutura resultante é chamada de tipo de dados abstrato . No entanto, a herança estará ausente. (Para um ponto de referência, visite Imperative_programming#C++ .) No entanto, essa deficiência pode ser superada.

Aqui está um arquivo de cabeçalho da linguagem de programação C para o tipo de dados abstrato GRADE em um aplicativo escolar simples:

/* grade.h */
/* ------- */

/* Used to allow multiple source files to include */
/* this header file without duplication errors.   */
/* ---------------------------------------------- */
#ifndef GRADE_H
#define GRADE_H

typedef struct
{
    char letter;
} GRADE;

/* Constructor */
/* ----------- */
GRADE *grade_new( char letter );

int grade_numeric( char letter );
#endif

A grade_new()função executa o mesmo algoritmo que a operação do construtor C++ .

Aqui está um arquivo de origem da linguagem de programação C para o tipo de dados abstrato GRADE em um aplicativo escolar simples:

/* grade.c */
/* ------- */
#include "grade.h"

GRADE *grade_new( char letter )
{
    GRADE *grade;

    /* Allocate heap memory */
    /* -------------------- */
    if ( ! ( grade = calloc( 1, sizeof( GRADE ) ) ) )
    {
        fprintf(stderr,
                "ERROR in %s/%s/%d: calloc() returned empty.\n",
                __FILE__,
                __FUNCTION__,
                __LINE__ );
        exit( 1 );
    }

    grade->letter = letter;
    return grade;
}

int grade_numeric( char letter )
{
    if ( ( letter == 'A' || letter == 'a' ) )
        return 4;
    else
    if ( ( letter == 'B' || letter == 'b' ) )
        return 3;
    else
    if ( ( letter == 'C' || letter == 'c' ) )
        return 2;
    else
    if ( ( letter == 'D' || letter == 'd' ) )
        return 1;
    else
    if ( ( letter == 'F' || letter == 'f' ) )
        return 0;
    else
        return -1;
}

No construtor, a função calloc()é usada em vez de malloc()porque cada célula de memória será definida como zero.

Aqui está um arquivo de cabeçalho da linguagem de programação C para o tipo de dados abstrato PERSON em um aplicativo escolar simples:

/* person.h */
/* -------- */
#ifndef PERSON_H
#define PERSON_H

typedef struct
{
    char *name;
} PERSON;

/* Constructor */
/* ----------- */
PERSON *person_new( char *name );
#endif

Aqui está um arquivo de origem da linguagem de programação C para o tipo de dados abstrato PERSON em um aplicativo escolar simples:

/* person.c */
/* -------- */
#include "person.h"

PERSON *person_new( char *name )
{
    PERSON *person;

    if ( ! ( person = calloc( 1, sizeof( PERSON ) ) ) )
    {
        fprintf(stderr,
                "ERROR in %s/%s/%d: calloc() returned empty.\n",
                __FILE__,
                __FUNCTION__,
                __LINE__ );
        exit( 1 );
    }

    person->name = name;
    return person;
}

Aqui está um arquivo de cabeçalho da linguagem de programação C para o tipo de dados abstrato STUDENT em um aplicativo escolar simples:

/* student.h */
/* --------- */
#ifndef STUDENT_H
#define STUDENT_H

#include "person.h"
#include "grade.h"

typedef struct
{
    /* A STUDENT is a subset of PERSON. */
    /* -------------------------------- */
    PERSON *person;

    GRADE *grade;
} STUDENT;

/* Constructor */
/* ----------- */
STUDENT *student_new( char *name );
#endif

Aqui está um arquivo de origem da linguagem de programação C para o tipo de dados abstrato STUDENT em um aplicativo escolar simples:

/* student.c */
/* --------- */
#include "student.h"
#include "person.h"

STUDENT *student_new( char *name )
{
    STUDENT *student;

    if ( ! ( student = calloc( 1, sizeof( STUDENT ) ) ) )
    {
        fprintf(stderr,
                "ERROR in %s/%s/%d: calloc() returned empty.\n",
                __FILE__,
                __FUNCTION__,
                __LINE__ );
        exit( 1 );
    }

    /* Execute the constructor of the PERSON superclass. */
    /* ------------------------------------------------- */
    student->person = person_new( name );
    return student;
}

Aqui está um programa de driver para demonstração:

/* student_dvr.c */
/* ------------- */
#include <stdio.h>
#include "student.h"

int main( void )
{
    STUDENT *student = student_new( "The Student" );
    student->grade = grade_new( 'a' );

    printf( "%s: Numeric grade = %d\n",
            /* Whereas a subset exists, inheritance does not. */
            student->person->name,
            /* Functional programming is executing functions just-in-time (JIT) */
            grade_numeric( student->grade->letter ) );

	return 0;
}

Aqui está um makefile para compilar tudo:

# makefile
# --------
all: student_dvr

clean:
    rm student_dvr *.o

student_dvr: student_dvr.c grade.o student.o person.o
    gcc student_dvr.c grade.o student.o person.o -o student_dvr

grade.o: grade.c grade.h
    gcc -c grade.c

student.o: student.c student.h
    gcc -c student.c

person.o: person.c person.h
    gcc -c person.c

A estratégia formal para construir objetos orientados a objetos é:

  • Identifique os objetos. Muito provavelmente estes serão substantivos.
  • Identifique os atributos de cada objeto. O que ajuda a descrever o objeto?
  • Identifique as ações de cada objeto. Muito provavelmente estes serão verbos.
  • Identifique as relações de objeto para objeto. Muito provavelmente estes serão verbos.

Por exemplo:

  • Uma pessoa é um ser humano identificado por um nome.
  • Uma nota é uma conquista identificada por uma letra.
  • Um aluno é uma pessoa que ganha uma nota.

Categorias funcionais

Um diagrama mostrando que o usuário interage com o software aplicativo . O software aplicativo interage com o sistema operacional , que interage com o hardware .

Os programas de computador podem ser categorizados ao longo de linhas funcionais. As principais categorias funcionais são software aplicativo e software de sistema . O software do sistema inclui o sistema operacional , que combina o hardware do computador com o software do aplicativo. O objetivo do sistema operacional é fornecer um ambiente onde o software aplicativo seja executado de maneira conveniente e eficiente. Tanto o software aplicativo quanto o software do sistema executam programas utilitários . No nível do hardware, um programa de microcódigo controla os circuitos em toda a unidade central de processamento .

Software aplicativo

O software aplicativo é a chave para desbloquear o potencial do sistema de computador. O software de aplicativos corporativos agrupa aplicativos de contabilidade, pessoal, clientes e fornecedores. Os exemplos incluem planejamento de recursos empresariais , gerenciamento de relacionamento com o cliente e software de gerenciamento da cadeia de suprimentos .

Os aplicativos corporativos podem ser desenvolvidos internamente como um software proprietário único . Alternativamente, eles podem ser adquiridos como software de prateleira . O software adquirido pode ser modificado para fornecer software personalizado . Se a aplicação for customizada, ou os recursos da empresa são utilizados ou os recursos são terceirizados. O desenvolvimento de software terceirizado pode ser do fornecedor de software original ou de um desenvolvedor de terceiros.

As vantagens do software proprietário são os recursos e os relatórios podem ser exatos de acordo com a especificação. A gerência também pode estar envolvida no processo de desenvolvimento e oferecer um nível de controle. A administração pode decidir contrariar a nova iniciativa de um concorrente ou implementar um requisito de cliente ou fornecedor. Uma fusão ou aquisição exigirá alterações de software empresarial. As desvantagens do software proprietário são os custos de tempo e recursos que podem ser extensos. Além disso, riscos relacionados a recursos e desempenho podem estar se aproximando.

As vantagens do software de prateleira são seus custos iniciais identificáveis, as necessidades básicas devem ser atendidas e seu desempenho e confiabilidade têm um histórico. As desvantagens do software de prateleira são que ele pode ter recursos desnecessários que confundem os usuários finais, pode não ter recursos de que a empresa precisa e o fluxo de dados pode não corresponder aos processos de trabalho da empresa.

Uma abordagem para obter economicamente um aplicativo corporativo personalizado é por meio de um provedor de serviços de aplicativos . Empresas especializadas fornecem hardware, software personalizado e suporte ao usuário final. Eles podem acelerar o desenvolvimento de novos aplicativos porque possuem pessoal especializado em sistemas de informação. A maior vantagem é que ele libera recursos internos da equipe e do gerenciamento de projetos complexos de computador. Muitos provedores de serviços de aplicativos têm como alvo empresas pequenas e de rápido crescimento com recursos limitados de sistemas de informação. Por outro lado, empresas maiores com grandes sistemas provavelmente terão sua infraestrutura técnica instalada. Um risco é ter que confiar em uma organização externa com informações confidenciais. Outro risco é ter que confiar na confiabilidade da infraestrutura do provedor.

Sistema operacional

Um sistema operacional é o software de baixo nível que suporta as funções básicas de um computador, como agendamento de processos e controle de periféricos .

Na década de 1950, o programador, que também era o operador, escrevia um programa e o executava. Depois que o programa terminou de ser executado, a saída pode ter sido impressa ou pode ter sido perfurada em fita de papel ou cartões para processamento posterior. Na maioria das vezes, o programa não funcionava. O programador então olhou para as luzes do console e brincou com os interruptores do console. Se menos afortunado, uma impressão de memória era feita para um estudo mais aprofundado. Na década de 1960, os programadores reduziram a quantidade de tempo desperdiçado automatizando o trabalho do operador. Um programa chamado sistema operacional foi mantido no computador o tempo todo.

O termo sistema operacional pode se referir a dois níveis de software. O sistema operacional pode se referir ao programa do kernel que gerencia os processos , memória e dispositivos . Mais amplamente, o sistema operacional pode se referir a todo o pacote do software central. O pacote inclui um programa de kernel, interpretador de linha de comando , interface gráfica do usuário , programas utilitários e editor .

Programa Kernel

Um kernel conecta o software aplicativo ao hardware de um computador.

O principal objetivo do kernel é gerenciar os recursos limitados de um computador:

A memória física está espalhada pela RAM e pelo disco rígido. A memória virtual é um bloco contínuo.
  • Quando o kernel carrega inicialmente um executável na memória, ele divide o espaço de endereço logicamente em regiões . O kernel mantém uma tabela de região mestre e muitas tabelas por região de processo (pregion) — uma para cada processo em execução . Essas tabelas constituem o espaço de endereço virtual . A tabela master-region é usada para determinar onde seu conteúdo está localizado na memória física . As tabelas de pregão permitem que cada processo tenha sua própria região de programa (texto), região de dados e região de pilha.
  • A região do programa armazena instruções de máquina. Como as instruções de máquina não mudam, a região do programa pode ser compartilhada por muitos processos do mesmo executável.
  • Para economizar tempo e memória, o kernel pode carregar apenas blocos de instruções de execução da unidade de disco, não todo o arquivo de execução completamente.
  • O kernel é responsável por traduzir endereços virtuais em endereços físicos . O kernel pode solicitar dados do controlador de memória e, em vez disso, receber uma falha de página . Nesse caso, o kernel acessa a unidade de gerenciamento de memória para preencher a região de dados físicos e traduzir o endereço.
  • O kernel aloca memória do heap mediante solicitação de um processo. Quando o processo é finalizado com a memória, o processo pode solicitar sua liberação . Se o processo sair sem solicitar que toda a memória alocada seja liberada, o kernel realizará a coleta de lixo para liberar a memória.
  • O kernel também garante que um processo acesse apenas sua própria memória, e não a do kernel ou de outros processos.
  • O programa do kernel deve executar o gerenciamento do sistema de arquivos . O kernel tem instruções para criar, recuperar, atualizar e excluir arquivos.
  • O programa do kernel deve executar o gerenciamento de dispositivos . O kernel fornece programas para padronizar e simplificar a interface do mouse, teclado, unidades de disco, impressoras e outros dispositivos. Além disso, o kernel deve arbitrar o acesso a um dispositivo se dois processos o solicitarem ao mesmo tempo.
  • O programa do kernel deve executar o gerenciamento de rede . O kernel transmite e recebe pacotes em nome dos processos. Um serviço importante é encontrar uma rota eficiente para o sistema de destino.
  • O programa do kernel deve fornecer funções de nível de sistema para os programadores usarem.
    • Os programadores acessam os arquivos por meio de uma interface relativamente simples que, por sua vez, executa uma interface de E/S de baixo nível relativamente complicada. A interface de baixo nível inclui criação de arquivos, descritores de arquivos, busca de arquivos, leitura física e gravação física.
    • Os programadores criam processos por meio de uma interface relativamente simples que, por sua vez, executa uma interface de baixo nível relativamente complicada.
    • Os programadores executam a aritmética de data/hora por meio de uma interface relativamente simples que, por sua vez, executa uma interface de tempo de baixo nível relativamente complicada.
  • O programa do kernel deve fornecer um canal de comunicação entre os processos em execução. Para um grande sistema de software, pode ser desejável projetar o sistema em processos menores. Os processos podem se comunicar entre si enviando e recebendo sinais .

Originalmente, os sistemas operacionais eram programados em assembly ; no entanto, os sistemas operacionais modernos são normalmente escritos em linguagens de nível superior como C , Objective-C e Swift .

Programa de utilidade

Um programa utilitário é projetado para auxiliar a administração do sistema e a execução do software. Os sistemas operacionais executam programas utilitários de hardware para verificar o status das unidades de disco, memória, alto-falantes e impressoras. Um programa utilitário pode otimizar o posicionamento de um arquivo em um disco lotado. Os programas utilitários do sistema monitoram o desempenho do hardware e da rede. Quando uma métrica está fora de um intervalo aceitável, um alerta de gatilho é gerado.

Os programas utilitários incluem programas de compactação para que os arquivos de dados sejam armazenados em menos espaço em disco. Os programas compactados também economizam tempo quando os arquivos de dados são transmitidos pela rede. Os programas utilitários podem classificar e mesclar conjuntos de dados. Os programas utilitários detectam vírus de computador .

Programa de microcódigo

NÃO portão.
porta NAND.
porta NOR.
E portão.
OU portão.

Um programa de microcódigo é o interpretador de nível inferior que controla o caminho de dados de computadores acionados por software. (Os avanços em hardware migraram essas operações para circuitos de execução de hardware .) As instruções de microcódigo permitem que o programador implemente mais facilmente o nível lógico digital — o hardware real do computador. O nível lógico digital é o limite entre a ciência da computação e a engenharia da computação .

Uma porta lógica é um minúsculo transistor que pode retornar um de dois sinais: ligado ou desligado.

  • Ter um transistor forma a porta NOT .
  • A conexão de dois transistores em série forma a porta NAND .
  • Conectar dois transistores em paralelo forma a porta NOR .
  • Conectar uma porta NOT a uma porta NAND forma a porta AND .
  • Conectar uma porta NOT a uma porta NOR forma a porta OR .

Essas cinco portas formam os blocos de construção da álgebra binária — as funções lógicas digitais do computador.

As instruções de microcódigo são mnemônicos que os programadores podem usar para executar funções lógicas digitais em vez de formá-las em álgebra binária. Eles são armazenados no armazenamento de controle de uma unidade central de processamento (CPU) . Essas instruções de nível de hardware movem dados por todo o caminho de dados .

O ciclo de microinstrução começa quando o microsequenciador usa seu contador de microprograma para buscar a próxima instrução de máquina da memória de acesso aleatório . O próximo passo é decodificar a instrução de máquina selecionando a linha de saída apropriada para o módulo de hardware. A etapa final é executar a instrução usando o conjunto de portas do módulo de hardware.

Uma representação simbólica de uma ULA.

As instruções para realizar aritmética são passadas através de uma unidade lógica aritmética (ALU). A ULA possui circuitos para realizar operações elementares para adicionar, deslocar e comparar inteiros. Ao combinar e fazer um loop das operações elementares através da ALU, a CPU executa sua aritmética complexa.

As instruções de microcódigo movem os dados entre a CPU e o controlador de memória . As instruções de microcódigo do controlador de memória manipulam dois registradores . O registrador de endereço de memória é usado para acessar o endereço de cada célula de memória. O registrador de dados da memória é usado para definir e ler o conteúdo de cada célula.

As instruções de microcódigo movem os dados entre a CPU e os vários barramentos do computador . O barramento do controlador de disco grava e lê de unidades de disco rígido . Os dados também são movidos entre a CPU e outras unidades funcionais através do barramento expresso de interconexão de componentes periféricos.

Notas

Referências