quarta-feira, 17 de junho de 2020

API Rest usando TypeScript

Olá pessoal, estou reativando o meu blog para falarmos sobre tecnologia e desenvolvimento, muitos assuntos foram obtidos durante esse tempo, e decidi que seria a melhor hora para voltar a falar sobre o que eu estudo/aprendo.

Neste post de retorno, gostaria de falar sobre Javascript, mas específico usando ele no back-end para criação de uma API REST.
Nesses meses e semanas de quarentena, decidi escolher uma stack de desenvolvimento para me aprofundar e desenvolver alguns projetos, venho estudado alguns tutoriais, vídeos aulas, e na primeira semana de junho, participei do evento gratuito da Rocketseat chamado: Next Level Week (NLW), que foi proposto um desafio de criar uma aplicação em uma semana, usando TypeScript, Knex e SQLite para a criação da API, e o sistema no Front-End e Mobile.

Neste projeto, o intuito inicial, foi a criação de um marketplace para coleta de resíduos, onde o usuário poderá cadastrar pontos de coleta e informar quais os tipos de resíduos que o ponto recebe.

Tendo ciência sobre o projeto, podemos iniciar com o gerenciador de pacotes:

NPM:

npm init            ou

YARN:

yarn init -y


Após o rodar o comando no terminal será criado o arquivo package.json
Recomendável realizar a instalação do TypeScript, podendo usar o comando:

yarn add -D typescript


Após a instalação do Typescript, podemos adicionar o Express (servidor)

yarn add express


Após as primeiras instalações, podemos estruturar as pastas do projeto, criando a pasta:

/src


Podemos criar o arquivo server.ts, como estamos trabalhando com TypeScript a extensão do arquivo é “.ts

Após a criação, iremos importar o Express:

import express from 'express';

const app = express();  -> Criação do app

app.use(express.json()); -> Esta linha serve para que o express entenda a

que as requisições em formato JSON.


Para utilizarmos as funções do Express, junto com o TypeScript, podemos instalar o pacote das tipagens, assim quando digitamos por exemplo “app.”, o VSCode (ou outra IDE de desenvolvimento), conseguirá identificar quais são as funções disponíveis do express().

Para instalar o pacote de tipagens usando:

NPM:

npm i @types/express            ou

YARN:

yarn add @types/express -D


Após instalar, já podemos ver a função listen, que escutará a porta “3333”, conforme código abaixo:

app.listen(3333); -> Execução do app na porta 3333

Após definido a porta de comunicação do servidor, já podemos criar as nossas rotas da aplicação

Rotas: Quando acessamos algum endereço por exemplo: localhost:3333/users, essa url seria uma rota, no exemplo abaixo a rota seria apenas "/", mais conhecido como rota raiz.


app.get('/', (request,response=> {

    
    /* Ação quando o usuário acessar a rota definida no primeiro 
    parâmetro, após o verbo HTTP GET. */
    
    return response.json( {message: "Olá Mundo"});
});

Caso precisamos que a API retorne todos os usuários, podemos fazer uma rota semelhante a essa:

Para atender a rota:  localhost:3333/users

app.get('/users', (request,response=> {
    
    /* Irei criar um objeto JSON apenas para exemplificar, 
    mas no cenário real, esse objeto seria retornado através 
    de uma pesquisa no banco. */
    
    return response.json( {
        'Gabriel',
        'Fernando',
        'José',
        'Joaquim'
    });
});

Caso precisamos que a API cadastre um usuário, podemos fazer uma rota semelhante a essa:

app.post('/users', (request,response=> {
    
    /* Quando acesso request.body, ele retornará os dados (corpo) 
    da requisição, que nesse caso seria o usuário informado 
    para ser cadastrado. */

    const {nomesobrenome,idadecidade= request.body; 

    /* Tendo esses dados em um objeto, podemos definir como salvar
    esses dados em algum banco e até realizarmos as validações, 
    após esse processo, podemos retornar o usuário salvo. */

    const usuarioCadastrado = {nome,sobrenome,idade,cidade};
    
    return response.json (usuarioCadastrado);
});

Existem mais conceitos que foram usados e que irei citar em novas publicações como o Knex e SQLite e etc., e também pretendo complementar esse projeto com novas funcionalidades. 
O código completo da API já está no meu github.

Sigam-me nas redes sociais:


segunda-feira, 10 de julho de 2017

Clean Code: Um livro necessário

Olá novamente, neste post irei falar sobre código limpo, um assunto que assim como testes, é de extrema importância, para qualquer desenvolvedor trabalhando em qualquer linguagem. Desde a última postagem estou lendo um livro que é muito falado na comunidade de desenvolvimento, chamado: Clean Code do Robert C. Martin.
 
As primeiras afirmações citadas no livro, me fez dar continuidade na minha leitura, e acredito que o fato de você ter clicado no link e está lendo esse post devem ser por esses dois motivos:


    - Há duas razões pelas quais você está lendo esse livro:
    1- Você é um programador;
    2 - Você deseja se tornar um programador melhor;


Se realmente forem esses os motivos por você está aqui, continue lendo esse post. 😅

Uma breve bibliografia do Robert Martin:
Robert C Martin, mais conhecido como Uncle Bob, é um profisional de software desde 1970, e consultor internacional desde 1990. Desde 70's ele já trabalhou em centenas de projetos. E em 2001, ele deu inicio a manifesto ágil, a partir das técnicas de programação Extreme. Ele também é membro do World Software Craftsmanship Movement - Clean Code. Ele já escreveu vários livros como: Programação Agile, Programação Extrema, UML, Programação Orientada a Objetos, Programação C ++. 


A razão por me basear neste livro, é porque durante a leitura, ele não fala sobre o que pode ser feito, dando recomendações, mas o que ele fez, comprovando que obteve sucesso. 

O que é Clean code (código limpo)?

  • É ser eficiente;
  • Simples;
  • Direto ao ponto;
  • Mínimas dependências;
  • Sem duplicação;
  • Fácil manutenção;
  • Padrões definidos;
  • Fácil leitura e entendimento;
  • Ser coberto por testes;
  • Elegante.
Já ouviu falar na síndrome das janelas?
Deixo um link para você entender que essa síndrome, tem tudo a ver com o assunto.
(http://justificando.cartacapital.com.br/2015/05/26/a-desordem-gera-desordem-conheca-a-teoria-das-janelas-quebradas/)


"Qualquer um consegue escrever código que um computador entende. Bons programadores escrevem código que humanos entendem". 
Martin Fowler.

Muitas vezes, não temos muito tempo para desenvolvermos uma feature, por n motivos, que já foram citados no meu post anterior falando sobre testes. (http://devhiranneri.blogspot.com.br/2017/06/testes-uma-pratica-necessaria.html)

Quando nós desenvolvemos um código ruim, feio, a nossa primeira intenção é tirar a culpa. Mas afinal, de quem é a culpa?
 

NOSSA!

OK, Agora que já entendemos o que é um código limpo, como eu consigo mensurar a qualidade de um código? Como eu consigo atingir os requisitos de um código limpo citados acima? 
É isso que veremos agora, que são alguns capítulos abordados pelo livro.

1 - Os nomes
 

Uma prática muito comum no desenvolvimento é querer simplificar o nome das variáveis, funções, nome de arquivos e etc. E isso uma má prática, pois somente você, ou no máximo a equipe de desenvolvimento saberá o que ela é, para o que serve. Caso entre novos(as) devs. na equipe, será um retrabalho para passar o todo o contexto, todos os significados do que pode ser aquela variável e etc. (que deveria ser simples, já que está se contratando um dev.).

Então use nomes que expressam alguma intenção:


int d;

int distanciaPecorridaEmKM;

A primeira variável (d), não consigo saber o real sentido dela, já a segunda (distanciaPecorridaEmKM), fica muito mais claro e objetivo.

2 - Funções 
NÃO IMPLEMENTE FUNÇÕES ENORMES, SEPARE-AS!

Seja pequeno!

 

Você terá mais facilidade de entender o que cada função faz, deixando-as menores, fazendo apenas 1 coisa.
 

Exemplo:
 

Tenho uma função de efetuarPedido(), nessa função deixe somente a implementação de efetuar um pedido, e não efetuar pedido, dar baixa no estoque, enviar mensagem ao usuário, tudo isso em uma função. Caso ocorra algum erro, você saberá exatamente onde refatorar o código desenvolvido.
Uma dica dada, é observar os níveis de endentação do código, se você perceber que está com muitos níveis, é bem provável que a função está fazendo mais de uma coisa.
 

Repetindo: AS FUNÇÕES DEVEM FAZER UMA COISA E DEVEM FAZÊ-LA BEM.

Só para complementar, argumentos booleanos, em geral, não são bons e o número ideal de argumentos para uma função é 0(zero). 

Depois vem um mônade(1), seguido de díade(2). Sempre que possível devem-se evitar três parâmetros. Para mais de três deve-se ter um motivo muito especial (políade) - mesmo assim não devem ser usados.

3 - DRY (Don't repeat yourself) - Não se repita 
Comentários não ajudam um código sujo. Como foi dito acima, caso o programador (ser humano, conhecedor da sintaxe da linguagem) não conseguiu enteder o código, então não será um comentário que ele entenderá.


Os comentários são aceitáveis quando:
  • Explicarem sobre a licença, direitos de uso de uma lib, por exemplo.
  • Comentários que explique a regra de negócio;
  • Comentários informativos.
O DRY não termina por aqui, ainda tem mais um conceito importante, que em breve vou comentar sobre ele.


4- Classes 
Devemos sempre seguir a convenção padrão do Java. Uma classe deve começar com uma lista de variáveis. As constantes estáticas públicas, se houver, devem vir primeiro. 
Então variáveis ​​estáticas privadas, seguidas por variáveis ​​de instância privadas. Raramente há uma boa razão para ter uma variável pública.
As funções públicas devem seguir a lista de variáveis. As funções utilitárias deverão ser privadas, assim ajuda o programa a ler como um artigo de jornal.


AS CLASSES DEVEM SER PEQUENAS. 


Assim como foi dito nas funções, que elas devem ser pequenas e realizar uma coisa de maneira correta, para a classe contamos quantas responsabilidades ela excerce.
O nome de uma classe deve descrever quais as responsabilidades que ela cumpre. 


No decorrer do livro ainda existem muitos assuntos que são tratados, como Responsabilidade Única, Exceção, Concorrência e etc...

Confesso que a leitura desse livro pude aprender muita coisa sobre desenvolvimento, as quais implementava de maneira incorreta, apenas fazendo com o que a máquina entendesse o meu código, e acredito que assim como você, estamos sempre em crescimento e melhorando o nosso trabalho, e os meus projetos serão mais bem pensados e avaliados. Vale a pena ler, e aprender ainda mais.

Siga-me nas redes sociais:
Twitter: devhiranneri
Github: github.com/hiranneri
Linkedin: linkedin.com/in/hiranneri 


Muito Obrigado e até a próxima! :)

Referências:
Livro Clean Code: https://www.amazon.com.br/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882

https://pt.slideshare.net/rodrigokono/boas-prticas-tcnica-para-um-cdigo-limpo-clean-code

https://vidadeprogramador.com.br/

quinta-feira, 22 de junho de 2017

Testes: Uma prática necessária

Dando uma breve pausa nos posts sobre lógica, hoje falo sobre testes, uma prática de desenvolvimento muito importante na construção de um sistema.
Nos dias atuais implementar o teste de software no ciclo de vida do sistema é de extrema importância, porém ainda existem muitas barreiras, por conta de recursos humanos, disponibilidade de tempo, e até recursos financeiros reduzidos.
Agora pare e pense, para ser construído um navio, avião, carro. Será que cada peça não precisa ser passada por constantes testes?
Será que um avião é simplesmente montado e já está autorizado e apto para voar com dezenas ou centenas de pessoas dentro?
No mundo do desenvolvimento, é comum estudar o problema (fazendo levantamento dos requisitos), pensar na solução e em seguida implementá-la, e depois fazer vários testes manuais na procura de algum erro e corrigindo aos poucos. Só que esse processo, principalmente na fase de testes finais tende a levar muito tempo, gera-se uma grande quantidade de erros no sistema, e afeta a manutenibilidade. E é por isso e por outras problemáticas que é necessário ter uma ou mais fases de teste.
Existem vários tipos de testes como: Testes Unitários, Teste de carga, Testes de Performance e entre outros:

Teste Unitário - O teste unitário irá testar a menor parte do sistema, que seriam os métodos. Irá avaliar se tal método atende ao que ele diz o que faz e qual o seu retorno (independente de seus parâmetros).




(Teste manual simples para inserir um cliente) 


Nesse caso, após a execução do script seria necessário olhar no console se a lista retornada condiz com o que esperamos.

A principio resolvemos parte da problemática em não testar o método utilizando-se de métodos manuais, mas será que esse(s) teste(s) manterão a sua qualidade durante muito tempo? E se fosse repetido todos os dias? Com certeza, alguma regra iria mudar e com isso o teste manual perderia a sua confiabilidade. Para que isso não ocorra, no mundo Java, existe um framework de testes unitários que trabalha com testes automatizados.

JUnit 


JUnit é um framework de testes que fornece uma API para construir os testes unitários automatizados e ajuda na visualização dos resultados. É possível verificar se cada método, está sendo executado da forma esperada.


Abaixo tem o passo a passo de como utilizar o JUnit na IDE Eclipse e um exemplo de teste (happy path) com a ferramenta.

1 - Clique em File, New, Other, Pesquise Por JUnit Test Case e clique em Next. 













2- Digite o nome da classe de teste (Recomendado ser o nome da classe a qual você quer testar + a palavra 'Test'), após no campo Class under test, clique em Browser e pesquise o nome da classe, a qual você irá testar, após clique em Next.

3- Escolha os métodos que você quer testar e depois clique em Finish.


4- Nesse passo, a classe já foi criada e já implementei o teste, no caso como eu escolhi o método inserir(), então desenvolvi o cenário, ação e a validação (utilizando o método assertEquals() da classe Assert).


5- Ao executar a classe ClienteDAOTest, o Eclipse mostra a tela do JUnit, informando quantos testes foram executados, e se houve algum erro ou alguma falha:


Testes de Performance.

O teste de perfomance consiste em verificar o quanto a aplicação se mantém durante um determinado tempo. Falando em testes de performances, existem alguns como: carga, stress e etc.

Teste de Carga

O teste de carga, irá verificar o quanto a aplicação comporta, porém o número de usuários, ou transações é aumentado gradativamente.
 

Teste de Stress

O teste de Stress, irá verificar o quanto a aplicação comporta, porém com um número x de usuários, fazendo n transações ao mesmo tempo.
 

JMeter. 
Para realizar esses testes, temos uma aplicação open source desenvolvida em Java que mensura o nível de performance, trabalhando com protocolos HTTP e HTTPS, Webservices (SOAP e REST), JDBC e etc.
(http://jmeter.apache.org/)
Nas próximas publicações, irei mostrar como utilizar o JMeter para realizar esses testes. Fique ligado!

Como vimos,é importante adotar a prática de desenvolvimento junto com testes, para que tenhamos produtividade, e que o nosso trabalho tenha mais qualidade. Os próximos posts práticos utilizaremos a metodoogia TDD - Desenvolvimento Orientado a Testes. 


Siga-me nas redes sociais:
Twitter: @devhiranneri
Github:github.com/hiranneri
Linkedin: linkedin.com/in/hiranneri


Obrigado pela leitura e até a próxima :)

segunda-feira, 19 de junho de 2017

#3: Desafios de Lógica: Remover elementos repetidos

Olá novamente, neste post, darei prosseguimento na série de posts sobre lógica, e agora vamos complementar o exercício anterior:

- Precisamos ordernar os elementos de um array e remover os elementos repetidos.


Para ordernar os elementos iremos utilizar a mesma resolução do problema anterior utilizando algoritmo bolha para ordenação.

Após solicitar um número x de nomes para o usuário e orderná-los, iremos remover eventuais elementos repetidos neste array.
A principio é necessário a criação:

String nomesSemRepeticao[] = new String[nomes.length];
int quantidadeDeElementosUnicos = 0;

 

Logo abaixo do algoritmo eu explico como foi pensado. 

for( int i = 0 ; i < original.length ; i++ ) {
                boolean existe = false;
                for( int j = 0 ; j < quantidadeDeElementosUnicos ; j++ ) {
                   
                    if( elementosSemRepeticao[ j ] .equals( original[ i ] )) {
                        existe = true;
                        break;
                    }
                }
               
                if( !existe ) {
                    elementosSemRepeticao[ quantidadeDeElementosUnicos++ ] = original[ i ];
                }
               
            }
         for(String nomes:elementosSemRepeticao){
             System.out.println(nomes);
         }

Explicação:
 

Foi criado um novo array que conterá somente elementos não repetidos, com o tamanho igual ao o array que armazenou os nomes digitados.

Foi criada a variável quantidadeDeElementosUnicos para termos ciência em qual índice o valor está sendo adicionado no array de elementos unicos.
 

A seguir foi criado uma estrutura de repetição para pecorrermos o array nomes[]. Na linha abaixo foi criada uma variável booleana para sabermos se foi encontrado algum valor repetido.

O segundo for só poderá ser executado na segunda iteração, pois j (j=0) não será menor do que quantidadeDeElementosUnicos(=0), sendo assim, cairá no segundo if, e caso o valor inverso da variável existe for igual a true, o primeiro elemento é adicionado no array.

Na segunda iteração, o j valerá 0 e quantidadeDeElementosUnicos será iterado valendo 1, assim os próximos elementos serão avaliados e se o valor do array de quantidadeDeElementosUnicos[] for igual ao valor do array nome[], então a variável existe será true, e o break da linha abaixo irá parar a condição, e a execução irá para o segundo if. (Nestas iterações, quando é encontrado um valor igual, o elemento não é adicionado, porque como a variável existe é igual a true, o valor inverso de true não executará o if que adiciona o elemento).

Após todas as iterações ocorrerem e somente os elementos forem adicionados, no final tem um for each que apresenta os valores em ordem alfabética e sem repetição.

Assim concluímos mais um desafio!

O código para resolução deste problema foi localizado no:
 https://pt.stackoverflow.com/questions/14339/eliminar-valores-repetidos-array-java


Siga-me nas redes sociais:
Twitter: @devhiranneri
Github:github.com/hiranneri
Linkedin: linkedin.com/in/hiranneri


Obrigado pela leitura e até a próxima :)

segunda-feira, 22 de maio de 2017

#2: Desafios de Lógica: Ordenação de nomes

Olá novamente, continuando com a série de Estrutura de Dados, hoje vou falar sobre ordenação.

Problema: Precisa-se que ordene um array de 20 nomes em ordem alfabética.

Resolução:
 Primeiro temos que criar um array de 20 posições para
resolução do problema:

 String nomes[] = new String [20];

Após isso, vamos solicitar ao usuário que informe os 20 nomes.
Como já expliquei essa parte de solicitar ao usuário utilizando a classe Scanner,  não vou entrar em mais detalhes nela. (Caso você queira entender um pouco melhor,  tem no meu post sobre Conversão de minutos para horas e minutos  (https://goo.gl/nQ0QEX)

Scanner sc = new Scanner(System.in);
for(int i=0;i<nomes.length;i++){
   System.out.println("Digite o nome");
   nomes[i] = sc.next();
}
//Somente para mostrar, que foi salvo os nomes
for(String valores:nomes){
  System.out.println(valores);
}

//Agora, independente da ordem que o usuário informou precisamos ordenar,
//e utilizaremos o algoritmo BubbleSort (ou conhecido também como:  Algoritmo Bolha)

* for (int i = 0; i < nomes.length - 1; i++) 
                for (int j = i + 1; j < nomes.length; j++) 
                    if (nomes[i].compareTo(nomes[j]) > 0) { 
                        String temporario = nomes[i]; 
                        nomes[i] = nomes[j]; 
                        nomes[j] = temporario; 
                    }

for(String nomesOrdenados:nome){
     System.out.println(nomesOrdenados);
}

* O algoritmo bolha, irá verificar de dois em dois se os elementos são maiores  ou menores entre eles, caso o primeiro elemento seja maior que o segundo  (o método compareTo irá retornar um número positivo (maior que 0(zero))).

Para a comparação entre os dois elementos, eu utilizo dois for's encadeados,  sendo que o segundo, irá iteirar + 1 com o índice do primeiro for, para que  consiga ler o próximo elemento.

nomes.lenght-1 - É para que o índice da variável j não passe do maior número  do array, e não lance uma exceção ArrayIndexOutOfBoundsException.

Assim independente da ordem que o usuário for passar os nomes, o algoritmo irá  verificar caractere por caractere e ordenando de forma alfabética.

Este código e outros estão disponíveis no meu github, caso queira analisar, basta clicar no link abaixo:

Projeto Ordenação - Bolha

Até + ;)
devhiranneri.eti.br

quarta-feira, 3 de maio de 2017

#1: Lógica - Conversão de minutos para hora e minutos

Olá novamente, durante esse tempo estava planejando alguns assuntos para postar aqui no meu blog que estarei estudando e transmitindo conhecimento:
A partir desse post vou falar sobre lógica de programação, resolvendo alguns problemas comuns do dia a dia do desenvolvimento. Para esta postagem vou falar sobre Conversão de minutos para horas e minutos.

O problema: (Conversão de minutos para horas e minutos)

O usuário irá digitar seja no console ou em alguma interface, o valor em minutos e o sistema deverá retornar o valor em horas e minutos.

Resolução:
Vamos pensar...















A principio teremos que criar três variáveis (horas,minutos,valorEmMinutosInformado):

int horas = 0,minutos=0,valorEmMinutosInformado=0; 
//Em JAVA, existe a possibilidade da declaração 
de variáveis em uma linha, caso as mesmas sejam 
do mesmo tipo, int.
E uma variável do tipo boolean para controlar a futura iterações, 
caso o usuário informe um valor incorreto.
boolean statusDoValor=true; 
Após a criação das variáveis iremos instanciar um objeto da classe Scanner para 
obtermos o valor passado pelo usuário.
Scanner sc = new Scanner(System.in); //No construtor da classe Scanner, existe um parâmetro que "obriga" para quem for instanciar o objeto deverá passar uma instância de InputStream,
ou outras como: Readable, File e etc. Você pode conferir na própria
documentação em:
https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html#constructor.detail
Essa linha serve para avisar ao usuário que já é possível informar o valor.
System.out.println("Digite o valor em minutos"); 
A estrutura de repetição do while servirá para no caso do usuário informar qualquer valor diferente de um número válido (e.x: número por extenso), irá ser lançado uma exceção, e a execução será abortada, e para que o usuário não necessite executar o código novamente, colocamos o código dentro do try..catch (Tratador de exceções).
 
while(statusDoValor){
try{

Essa linha abaixo irá ler o valor passado e atribuir a váriável 
valorEmMinutosInformado.

  valorEmMinutosInformado = sc.nextInt();

Vou precisar fazer uma "cópia" do valor em valorEmMinutosInformado para a variável minutos, para que no final eu consiga informar o tempo que o usuário passou via console.

  minutos=valorEmMinutosInformado;

A cada 60 minutos que equivale a 1 hora, a variável horas é incrementada e a variável minutos é reduzida de 60 em 60, até o valor dela ser menor que 60, ou seja, menor que 1 hora.


while(minutos>=60){
  horas++;
  minutos-=60;
}
  statusDoValor=false;
}catch(InputMismatchException e){
     System.out.println("Valor informado está incorreto. Digite novamente");
    valorErrado=true;
sc.next();

 
 }
}

System.out.println(valorEmMinutosInformado+" minutos equivale a "
+horas+" horas e "+minutos+"minutos");
 
}

Obs: Não se esqueçam dos imports para não apresentar erro de compilação.
" import java.util.Scanner;
import java.util.InputMismatchException; "
Esse foi um de uma série de 5 posts sobre lógica de programação. Em breve vou postar o segundo. Caso você queira contribuir com esse código ou outros, tenho ele no meu github. É só clicar no link abaixo: Projeto de Lógica de programação

Até mais...

terça-feira, 4 de abril de 2017

#2: Paradigma: Orientação a Objetos

Olá novamente, hoje eu irei falar de um assunto muito interessante que é sobre Programação Orientada a Objetos, um paradigma que é largamente utilizado nos dias atuais para o desenvolvimento de sistemas, aplicativos e etc.

Bom, lá na década de 60, o paradigma bastante utilizado para desenvolvimento ainda era o estruturado, que a programação segue uma estrutura lógica e sequencial, utilizando as principais linguagens: Pascal e Cobol. Porém o tempo foi passando e os desenvolvedores da época, sentiram de resolver as principais desvantagens do Estruturado como:  O tempo de entendimento do fluxo do código para novos desenvolvedores que forem dar manutenção, mudanças bruscas que acarretavam a alteração em todos os arquivos e funções relacionados.

Para Oliveira (2011, p. 68):
[...] a orientação a objetos surgiu com a necessidade de se criar um
paradigma de programação simples, baseado na percepção humana dos objetos ao seu redor. Este novo paradigma não é apenas um modo de programar, mas uma maneira de pensar e conceber as ideias. 
[...] a utilização do paradigma orientado a objetos está presente em todas as etapas do processo de desenvolvimento [de sistemas], indo
da análise, passando pelo projeto, até as fases de teste e implementação. É um fator decisivo para a construção de sistemas, visando alcançar os objetivos esperados no determinado espaço de tempo com determinado custo (OLIVEIRA, 2011, p. 70). 

E então a orientação a objeto foi criada para tentar compreender, interpretar as características do mundo real para o mundo virtual (classes, objetos, atributos e métodos). (Mais abaixo, explico sobre esses nomes).

 "O termo Programação Orientada a Objetos (POO) foi criado por Alan Kay, autor da linguagem de programação Smalltalk. Mas mesmo antes da criação do Smalltalk, algumas das idéias da POO já eram aplicadas, sendo que a primeira linguagem a realmente utilizar estas idéias foi a linguagem Simula 67, criada por Ole-Johan Dahl e Kristen Nygaard em 1967. Entretanto só veio a ser aceito realmente nas grandes empresas de desenvolvimento de Software por volta dos anos 90." 
 "Alguns exemplos de linguagens orientadas a objetos modernas utilizadas por grandes empresas em todo o mundo são: Java, C#, C++, Object Pascal (Delphi), Ruby, Python, Lisp, etc".
(Wikipédia).

Definições:
Classes: 
As Classes são representações de "coisas" do mundo real, para o mundo virtual, composto por atributos e métodos.

Atributos são as características, dados do que foi representado do mundo real. (Nome, idade, sexo e etc).

Método é como uma atividade, função será executado.

Objetos: É uma ocorrência de uma classe(representação, modelo), que possuem dados (atributos).

Para que a linguagem seja considerada, e entendida como Orientada a objetos é necessário que ela siga os 4 pilares que são: Abstração, Encapsulamento, Herança e Polimorfismo.

Abstração: 
A definição apresentada por Rumbaugh et al. (1994, p. 9) no livro Modelagem e projetos baseados em objetos diz que:

"A abstração consiste na concentração dos aspectos essenciais, próprios, de uma entidade e em ignorar suas propriedades acidentais. No desenvolvimento de sistemas, isso significa concentrar-se no que um objeto é e faz, antes de decidir como ele deve ser implementado. O uso da abstração preserva a liberdade de se tomar decisões evitando, tanto quanto possível,
comprometimentos prematuros com detalhes."
 
Abstração é a técnica de se concentrar no que o objeto irá realizar no sistema, qual será a sua função, ignorando a princípio, os detalhes desse objeto.

Encapsulamento:
O encapsulamento é uma técnica  que dão mais segurança ao sistema, pelo o fato de não permitir, que os detalhes da implementação sejam abertos, visíveis para qualquer desenvolvedor que for utilizar a classe. Um exemplo muito citado é o funcionamento do carro. O motorista não é obrigado a saber, o que de fato acontece quando ele gira o volante a esquerda ou a direita, a única certeza é que ao girar o volante, o carro também virará.

Herança: Conforme definição de Rumbaugh et al. (1994, p. 4),
"Herança é  [...] o compartilhamento de atributos e operações entre classes, com base em um relacionamento hierárquico. "
"Uma classe pode ser  definida de forma abrangente e depois refinada em sucessivas subclasses mais definidas.  [...]  "
Herança é um tipo de relacionamento entre classes. Após a análise do que será desenvolvido, e da abstração do conhecimento sobre a regra de negócio, esse relacionamento propõe hierarquias entre as classes, gerando um reuso de código (ou seja, o mesmo código não precisa ser digitado várias vezes em classes diferentes).

Polimorfismo: É o principio pelo o qual o objeto/classe se comporta ao invocar um método. Dependendo do tipo do objeto, um método mais original, mais "correto" é invocado.
O polimorfismo é a capacidade de que uma superclasse, possua classes filhas com a mesma assinatura de método, mas com implementação diferentes. Um exemplo é da Concessionária de carros, que pretende aumentar o valor dos carros de acordo com cada tipo.
                                   Diagrama de Classes - Concessionária

Neste exemplo, ao invocar o método: carroFerrari.aumentarValor() será diferente de carroFusca.aumentarValor(), pois a linguagem irá analisar de qual tipo é cada objeto e invocar o seu respectivo método.

Esse foi mais um artigo explicando um pouco sobre a história da Orientação a Objetos e alguns conceitos sobre ela. Espero que tenham gostado. Caso tenham alguma dúvida pode comentar abaixo que eu respondo, quando puder.
Até mais ;)

Bibliografias:
RUMBAUGH, James et al. Modelagem e projetos baseados em objetos. Rio de
Janeiro: Campus, 1994



https://pt.wikibooks.org/wiki/Programa%C3%A7%C3%A3o_Orientada_a_Objetos/Introdu%C3%A7%C3%A3o

OLIVEIRA, Artur Elias Hayne. Introdução à orientação a objetos. Revista SQL
Magazine, Rio de Janeiro, n. 89, p. 68-74, 2011.