-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path02_segundo_capitulo.tex
418 lines (288 loc) · 53.5 KB
/
02_segundo_capitulo.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
Neste capítulo são apresentados os conceitos básicos utilizados ao longo do trabalho, situando-os dentro do problema a ser resolvido.
%--- Inserir os conceitos de orientação a objetos
\section{Orientação a Objetos}
\label{sec:oop}
Um conceito bastante difundido tanto no meio acadêmico quanto no mercado são as \textbf{Linguagens Orientadas a Objetos}. Essas são linguagens de programação que utilizam um paradigma ou padrão de estruturação de código que permite que o desenvolvedor crie abstrações no contexto do software para modelar objetos ou entidades do mundo real \cite{oopSurvey}.
Não existe uma definição universal que diga quais são as características ou funcionalidades que uma linguagem de programação deve apresentar para ser considerada orientada a objetos \cite{oopSurvey}. Porém, de maneira geral, elas possuem mecanismos que permitem agrupar dentro de uma unidade de \textit{software}, estruturas para prover informações de \textbf{estado}, \textbf{comportamento} e \textbf{identidade} \cite{ormPaper}. Este agrupamento de estruturas dentro de uma unidade é conhecido como \textbf{encapsulamento}.
Esta unidade de \textit{software} que representa o estado, comportamento e identidade de uma entidade é conhecida como \textbf{objeto}. Um objeto é criado a partir de um modelo preestabelecido que define todas as estruturas internas que o compõe. Este modelo é conhecido como \textbf{classe} \cite{oopSurvey}. Algumas linguagens não oferecem mecanismos explícitos para criação de classes, porém oferecem suporte à instanciação de objetos. Um exemplo de linguagem que apresenta esta característica é a linguagem \textbf{\textit{Javascript}}\footnote{Linguagem interpretada com tipagem dinâmica baseada em \textit{scripts} muito utilizada em programação para a WEB e como complemento para interfaces com linguagens e/ou programas complexos.}.
O estado de um objeto é definido a partir da adição de variáveis em sua estrutura interna para armazenamento de valores. Estes valores podem ser unitários (onde são armazenados dados do tipo texto ou numérico, por exemplo), ou podem ser compostos (onde são utilizados outros objetos para compor a estrutura interna). As variáveis internas de um objeto são conhecidas como \textbf{atributos} ou \textbf{propriedades} e a utilização de valores compostos na definição da estrutura de uma classe é um mecanismo conhecido como \textbf{composição} \cite{oopSurvey}.
O comportamento de um objeto é definido a partir da adição de funções em sua estrutura interna. Elas são utilizadas para efetuar operações sobre os atributos que o objeto contém, ou para efetuar processamento de dados baseados no estado ou objetivo do objeto ao qual ela pertence. Estas funções são conhecidas como \textbf{métodos} \cite{oopSurvey}.
O conjunto de atributos e métodos de uma classe define o que chamamos de \textbf{interface}. Algumas linguagens permitem reduzir a interface de um objeto de forma que nem todas as estruturas internas sejam acessíveis externamente. Um exemplo é a linguagem C++, que nos permite utilizar os modificadores \textit{\textbf{``private''}} (estruturas não acessíveis externamente) e \textit{\textbf{``public''}} (estruturas acessíveis externamente). Nesse caso a interface será formada apenas pelos atributos e métodos marcados com o modificador ``\textit{public}''
A identidade de um objeto se refere à capacidade de se referenciar instâncias de objetos de maneira unívoca, ou seja, se refere à capacidade de se distinguir diversas instâncias de objetos entre si através de algum mecanismo de comparação \cite{oopSurvey}. Em algumas linguagens este mecanismo se baseia no endereçamento de memória ocupado pela instância do objeto, como é o caso da linguagem C++. Já em outras linguagens existem mecanismos que permitem a criação de funções de comparação, como acontece por exemplo na linguagem \textbf{\textit{JAVA}} onde podemos definir o método \textbf{\textit{"equals"}} das classes criadas.
Um exemplo de definição de uma classe utilizando a linguagem C++ é apresentado no trecho de código \ref{lst:simpleclass}, para demonstrar os conceitos explicados anteriormente. No código é definida a estrutura de uma classe que representa uma pessoa. A classe foi definida com o identificador Pessoa (linha 1), possui dois atributos internos para armazenar o nome e sobrenome (linhas 3 e 4) e um método que retorna o nome completo de uma pessoa através da combinação do seu nome e sobrenome (linha 6). Os atributos não são acessíveis externamente devido ao modificador de acesso \textit{"private"} utilizado na linha 2. Já o método é acessível devido ao modificador de acesso \textit{"public"} utilizado na linha 5.
\begin {algorithm}
\caption{Definição de uma classe simples em C++}
\label{lst:simpleclass}
\begin{lstlisting}[]
class Pessoa {
private:
string m_nome;
string m_sobrenome;
public:
string nomeCompleto() { return m_nome + m_sobrenome; }
}
\end{lstlisting}
\end{algorithm}
Mecanismos de encapsulamento (métodos, atributos e restrição de interface), definição de classes e instanciação de objetos são as características mais comumente encontradas nas linguagens consideradas como orientadas a objetos. Porém, existem mecanismos mais avançados que permitem uma melhoria na definição do comportamento das classes e promovem reaproveitamento de código. Entre os principais estão a \textbf{herança} e o \textbf{polimorfismo} \cite{oopSurvey}.
A herança consiste na capacidade de uma classe estender a estrutura de uma classe já definida. Isso significa que a nova classe mantém a interface da anterior e tem a capacidade de adicionar novos atributos e métodos a ela \cite{oopSurvey}. Algumas linguagens oferecem somente suporte para herança simples, onde uma classe pode herdar de somente uma outra classe, porém geralmente definem mecanismos alternativos de extensão. Um exemplo é a linguagem JAVA. Outras linguagens oferecem suporte para herança múltipla, onde uma classe pode estender as funcionalidades de uma ou mais classes já definidas. Um exemplo de linguagem com esta característica é a linguagem C++.
Algumas notações são utilizadas para demonstrar a utilização do mecanismo de herança. Por exemplo, quando criamos uma classe ``B'' que herda de uma classe ``A'', dizemos que ``A'' é a classe \textbf{base} ou \textbf{pai}, enquanto a ``B'' é uma classe \textbf{derivada} ou \textbf{filha}. Uma característica importante a observar é que ao declararmos um objeto da classe ``B'', este objeto poderá ser utilizado em contextos onde é esperado um objeto da classe ``A'', esse mecanismo é conhecido como \textbf{\textit{upcasting}} \cite{oopSurvey}.
Ao utilizar o mecanismo de herança, algumas linguagens permitem a modificação de um método existente na classe base. Este mecanismo é utilizado para especializar o comportamento herdado na nova classe, mantendo um mesmo padrão de interface. Quando isto acontece temos um impasse a ser resolvido. Quando um objeto de uma classe filha com métodos especializados for utilizado em um contexto como um objeto da classe pai, ao chamar este método, deverá ser executada a implementação da classe pai ou da classe filha? Quando desejamos que a implementação da classe filha seja utilizada, surge o conceito de polimorfismo, onde o comportamento de um objeto é mantido consistente em relação à sua definição não importa em qual contexto ele seja utilizado \cite{oopSurvey}.
Em algumas linguagens como JAVA o polimorfismo é implícito, ou seja, na pergunta anterior se desejássemos que a implementação da classe pai fosse executada, isso não seria possível. Já em outras linguagens como C++, o polimorfismo é definido explicitamente através do uso de palavras-chave da linguagem.
Ao analisar todas estas características citadas, percebemos que as linguagens orientadas a objetos promovem a criação de entidades de \textit{software} bem descritivas. Isto facilita sua utilização por arquitetos e engenheiros de \textit{software}, que podem visualizar os elementos envolvidos no desenvolvimento com uma visão de mais alto nível. Talvez esta seja a razão da vasta aceitação e utilização destas linguagens. Neste trabalho é utilizada a linguagem orientada a objetos C++, a qual é detalhada na seção \ref{sec:cpp}.
%--- Introduzindo a linguagem C++
\section{A Linguagem de Programação C++}
\label{sec:cpp}
A linguagem \textbf{C++} é uma linguagem orientada a objetos criada em 1980 por \textit{Bjarne Stroustrup}. É uma linguagem compilada, ou seja, o código criado pelo desenvolvedor é convertido através de um programa denominado \textbf{compilador} para uma linguagem nativa de uma plataforma alvo, gerando um ou mais arquivos executáveis. Estes arquivos são passíveis de execução direta na plataforma sem a intervenção de ferramentas externas \cite{bueno2002apostila}.
A linguagem C++ foi construída com base na linguagem \textbf{C}. Inicialmente o código escrito em C++ era traduzido para C e compilado com compiladores desta linguagem. Com o aumento da complexidade de implementação das características e funcionalidades que foram surgindo na linguagem ao longo de sua existência, surgiram compiladores específicos para C++ \cite{cppAnnotations}.
Dentre as características da linguagem estão a capacidade de definição de classes, utilização de herança múltipla, utilização de polimorfismo, gerenciamento de memória controlado pelo desenvolvedor e compatibilidade com códigos escritos em C. Outra importante característica da linguagem é a sua não portabilidade, ou seja, o código gerado para uma plataforma (sistema operacional e/ou hardware específico) geralmente não é compatível com outras plataformas. Devido a isso, a linguagem possui uma biblioteca padrão bem reduzida, não oferecendo, por exemplo, bibliotecas de comunicação em rede e utilização de banco de dados \cite{bueno2002apostila}.
Existe uma grande dificuldade em se desenvolver programas voltados para diversas plataformas utilizando a linguagem, pois quando começamos a utilizar funcionalidades um pouco mais avançadas temos que utilizar implementações específicas para cada plataforma. Como tentativa de diminuir esta dificuldade foram criadas bibliotecas e \textit{frameworks}\footnote{Um conjunto de bibliotecas que implementam funcionalidades frequentemente utilizadas no desenvolvimento de \textit{software}, como por exemplo, acesso a banco de dados e comunicação em redes.} multiplataformas para a linguagem \cite{qtFoundations}. Neste trabalho é utilizado o \textbf{\textit{Framework} Qt} que será descrito na seção \ref{sec:qt}.
A seguir são descritas características da linguagem presentes em contextos bem específicos e que interferiram bastante no desenvolvimento da biblioteca ORM proposta neste trabalho. Também é descrito o modelo de projeção do processo evolutivo da linguagem, onde são ressaltados mecanismos introduzidos na especificação \textbf{C++11} que contribuíram para eliminar ou amenizar algumas limitações da linguagem.
\subsection{Reflexão ou Introspecção}
\label{sec:reflexaoIntrospeccao}
Algumas vezes nos deparamos com a tarefa de desenvolver rotinas que dependem do conhecimento da estrutura de um objeto qualquer. Problemas como ``escreva uma função que mostre o nome dos atributos de um objeto'' ou ``escreva uma função que armazene em um arquivo o valor de todos os atributos de um objeto'' são alguns exemplos de rotinas deste tipo. São nestes momentos que a utilização de mecanismos de \textbf{introspecção} ou \textbf{reflexão} se torna útil.
Estes mecanismos consistem na disponibilização, por parte da linguagem de programação, de estruturas que permitem analisar a especificação de um objeto e acessar seus recursos; tudo em tempo de execução. Desta forma podemos escrever rotinas genéricas que podem trabalhar com qualquer tipo de objeto para executar diversos tipos de tarefas, como listar os atributos de um objeto, acessar e alterar o valor destes atributos, listar os métodos de um objeto e até mesmo executá-los \cite{expertCSharpObjects}.
Geralmente as linguagens híbridas e as interpretadas oferecem métodos de reflexão completos, pois as informações da estrutura dos objetos são utilizadas pelas próprias máquinas virtuais e pelos interpretadores em tempo de execução. Neste caso, uma vez que a informação já está presente e formatada durante a execução, basta a linguagem criar mecanismos de disponibilização dos mesmos \cite{expertCSharpObjects}.
Já no cenário das linguagens compiladas, a situação é bem diferente. Não há a necessidade de geração de informações sobre estruturas de objetos para o código ser executado, visto que o programa é gerado em código nativo \cite{professionalCpp}. A linguagem C++ é do tipo compilada, portanto, também sofre com a falta de mecanismos de reflexão nativos.
\subsection{Processo Evolutivo da Linguagem}
\label{sec:processoEvolutivoCpp}
A linguagem C++ foi criada para ser uma linguagem de propósito geral, com o objetivo principal de apresentar mecanismos para programação com alto nível de abstração, porém, ao mesmo tempo sem privar o desenvolvedor da capacidade de acessar rotinas e recursos de baixo nível. Sendo assim é possível obter programas de alto desempenho em diversas plataformas diferentes \cite{cppAnnotations}.
Para a linguagem ser utilizada em múltiplas plataformas é necessário que exista um compilador que suporte a criação de programas a partir da análise de código fonte em C++ para cada plataforma. Para evitar variações na implementação destes compiladores existe uma especificação oficial de todo o conjunto de recursos oferecidos pela linguagem bem como sua sintaxe \cite{cppAnnotations}. Esta especificação é mantida pela \textit{\textbf{International Organization for Standardization}} (\textbf{ISO}).
As linguagens de programação evoluem com a passar do tempo. Em alguns momentos é preciso acrescentar novos recursos para alinhar a linguagem com os padrões atuais, outras vezes é necessário melhorar recursos existentes ou até mesmo corrigir erros na especificação \cite{cppAnnotations}.
A especificação da linguagem C++ passou por uma grande atualização em 1998 (conhecida como \textbf{C++98}), seguida de algumas correções em 2003 (especificação conhecida como \textbf{C++03}). Desde então a especificação não sofria alterações significativas, o que levou a linguagem a ficar um pouco desatualizada de acordo com os conceitos que foram surgindo ao longo dos anos. Até que em meados de 2011 um comitê de especialistas começou a agir com o intuito de trazer novos recursos para a linguagem. Isso levou à publicação da especificação \textbf{C++11} no final do ano de 2011 e à projeção de atualizações da linguagem para os anos de 2014 e 2017, especificações conhecidas como \textbf{C++14} e \textbf{C++17} \cite{cppAnnotations}.
A figura \ref{fig:evolucaoCpp} mostra a linha do tempo da evolução da especificação da linguagem C++. Nela é possível perceber a grande concentração de tarefas previstas para os anos entre 2014 e 2017. Durante a finalização deste trabalho (novembro de 2014) a especificação C++14 estava prevista para ser publicada em breve\footnote{Para mais informações acesse o site https://isocpp.org/std/status.}.
\begin{figure}[!htb]
\centering
\includegraphics[scale=0.6]{imagens/evolucaoCpp.png}
\caption{Linha do tempo: evolução da especificação da linguagem C++}
\label{fig:evolucaoCpp}
\end{figure}
Muitos recursos adicionados na linguagem pelas especificações C++11 e C++14 foram utilizados no desenvolvimento deste trabalho. Nas seções seguintes serão descritos alguns destes recursos, e como eles contribuem para melhorar algumas limitações que eram impostas pela linguagem.
\subsubsection{Listas de Inicialização}
\label{sec:listasInicializacao}
Um recurso simples e ao mesmo tempo bastante útil, as \textbf{listas de inicialização} foram criadas com o objetivo de facilitar a instanciação de estruturas do tipo \textit{container} (lista, pilha, fila, tabelas \textit{hash}, etc.) com um conjunto de elementos adicionados. É importante ressaltar que a linguagem na especificação C++98 já permitia a inicialização de vetores com uma lista de elementos \cite{professionalCpp}.
Este recurso se baseia na utilização de uma nova classe chamada \textit{\textbf{``initializer\_list''}} definida dentro do \textit{namespace}\footnote{Mecanismo presente na linguagem C++ que permite agrupar estruturas dentro de um espaço de resolução de nomes comum. É utilizado para evitar conflitos de nomes entre estruturas.} ``\textit{std}''. Esta classe implementa um \textit{container} de dados simples, que suporta o acesso aos seus elementos através do uso de \textbf{iteradores}. Quando o compilador encontra algum trecho de código com o padrão ``\{x, y, z\}'' onde ``x'', ``y'' e ``z'' são valores literais ou variáveis que podem ser convertidas para um tipo de dado ``T'' comum de forma implícita, ele constrói um objeto do tipo ``\textit{initializer\_list<T>}''. Sendo assim, para que um objeto possa ser construído com uma lista de inicialização, basta que sua classe contenha um construtor que recebe como parâmetro um objeto do tipo ``\textit{initializer\_list<T>}'' \cite{cppAnnotations}.
No trecho de código \ref{lst:initializerListExample} é demonstrado a utilização das listas de inicialização. Primeiramente temos a inicialização de um vetor de números inteiros (linha 2) utilizando a sintaxe já suportada pela linguagem na especificação C++98. Em seguida temos a inicialização de um objeto do tipo \textit{\textbf{vector\footnote{Classe presente na biblioteca padrão de C++, e que implementa uma estrutura de lista de elementos utilizando áreas de memória contíguas.}}} (linha 4) utilizando o novo recurso adicionado na especificação C++11. Por último, temos a definição de uma classe projetada para suportar o recurso de listas de inicialização (linhas 7 a 9) e em seguida a inicialização de um objeto desta classe (linha 13).
\begin{algorithm}
\caption{Inicialização de vetores e estruturas \textit{container}}
\label{lst:initializerListExample}
\lstinputlisting[]{codigos/initializerListExample.cpp}
\end{algorithm}
\subsubsection{Navegação em Grupos de Elementos}
\label{sec:forRangeBasedLoop}
Quando precisamos acessar os elementos de um vetor ou de alguma estrutura do tipo \textit{container} utilizando a linguagem C++, temos basicamente duas opções:
\begin{description}
\item[1)Acesso sequencial via índice:]
Utilizamos um laço de repetição para gerar valores numéricos sequenciais dentro do intervalo de posições ou índices dos elementos que desejamos acessar na estrutura. De posse dos índices, podemos acessar os elementos utilizando a sintaxe ``estrutura[índice]''. Esta técnica pode ser utilizada em vetores e em estruturas \textit{container} que implementam o operador ``[]'' \cite{professionalCpp}. Um exemplo da utilização desta técnica é apresentado no trecho de código \ref{lst:acessoSeqIndice}.
\begin{algorithm}
\caption{Acesso sequencial via índice}
\label{lst:acessoSeqIndice}
\lstinputlisting[]{codigos/acessoSeqIndiceExample.cpp}
\end{algorithm}
\item[2)Acesso sequencial via iteradores:]
As estruturas \textit{container} presentes na linguagem C++ disponibilizam o acesso a um ponteiro especial que permite navegar entre os elementos que ele contém. Estes ponteiros são chamados de \textbf{iteradores} e podem ser de dois tipos: constantes e não constantes. Os iteradores constantes permitem acessar os elementos em modo somente leitura. Enquanto os não constantes permitem a modificação dos valores destes elementos \cite{professionalCpp}. Um exemplo da utilização desta técnica é apresentado no trecho de código \ref{lst:acessoSeqIterador}.
\begin{algorithm}
\caption{Acesso sequencial via iteradores}
\label{lst:acessoSeqIterador}
\lstinputlisting[]{codigos/acessoSeqIteradorExample.cpp}
\end{algorithm}
\end{description}
Na especificação C++11 foi adicionada uma variação do laço de repetição \textit{\textbf{``for''}} que é basicamente uma simplificação das técnicas 1 e 2 descritas anteriormente. Considerando que temos um grupo de elementos do tipo ``T'' armazenados em uma estrutura (vetor ou \textit{container}) com uma instância chamada ``elementos'', podemos navegar sobre os elementos desta instância utilizando um trecho de código no formato ``for (T e : elementos) \{...\}''. Neste caso, o código contido entre as chaves será executado uma vez para cada elemento contido em ``elementos'', onde a variável ``e'' assume o valor de cada um destes elementos \cite{professionalCpp}.
Esta nova variação pode ser utilizada tanto com vetores quanto com estruturas do tipo \textit{container}, e também é possível navegar sobre os elementos em modo somente leitura. No trecho de código \ref{lst:forNovaSintaxe} é demonstrada a utilização desta nova sintaxe de diferentes formas.
\begin{algorithm}
\caption{Acesso sequencial com nova sintaxe (C++11)}
\label{lst:forNovaSintaxe}
\lstinputlisting[]{codigos/forNovaSintaxe.cpp}
\end{algorithm}
\subsubsection{Novo Identificador para Ponteiros Nulos}
\label{sec:nullptr}
A linguagem C++ permite a manipulação direta de memória a partir da utilização de \textbf{ponteiros}, variáveis estas que armazenam o endereço inicial da porção de memória em que uma estrutura de dados está sendo armazenada durante a execução de um programa \cite{professionalCpp}.
A manipulação de ponteiros é uma tarefa complexa, que deve ser feita com muito cuidado. Uma tentativa de acesso a uma região de memória inválida pode gerar problemas graves durante a execução do programa. Para evitar este tipo de problema, uma boa prática consiste em invalidar ou anular ponteiros durante a sua inicialização e quando o seu uso chegou ao fim (o que acontece por exemplo quando desalocamos a região de memória apontada por ele) \cite{professionalCpp}.
Para anular um ponteiro, simplesmente atribuímos a ele o valor 0. Porém, na maioria dos ambientes de desenvolvimento, temos a presença de uma macro chamada ``NULL'' que é utilizada no local do valor 0 durante a anulação de um ponteiro para fins de legibilidade.
Esta metodologia pode levar a comportamentos inesperados do código durante a execução, visto que a macro é expandida para o valor inteiro 0 durante a compilação. Se temos duas funções com o mesmo nome, onde uma recebe um ponteiro como parâmetro e a outra recebe um número inteiro, ao executar esta função passando a macro ``NULL'', a versão que recebe o número inteiro será executada, gerando assim um comportamento inesperado.
Com o objetivo de resolver este problema a especificação C++11 prevê a existência do identificador \textbf{``nullptr''} para ser utilizado com o significado de ponteiro nulo. Então se no mesmo problema citado executássemos a função passando ``nullptr'' como parâmetro, a versão que recebe o ponteiro será executada \cite{professionalCpp}. O exemplo citado pode ser observado no trecho de código \ref{lst:nullptr}.
\begin{algorithm}
\caption{Novo identificador para ponteiros nulos}
\label{lst:nullptr}
\lstinputlisting[]{codigos/nullptr.cpp}
\end{algorithm}
\subsubsection{Inferência de Tipos}
\label{sec:inferenciaTipos}
A linguagem C++ é uma linguagem de tipagem estática, ou seja, todas as variáveis declaradas no código devem ter seu tipo de dado especificado em momento de compilação \cite{cppAnnotations}. Esta característica acaba, em certas situações, deixando o código de declaração de variáveis muito grande. Veja por exemplo o trecho de código \ref{lst:declaracaoGrande}, onde são declarados um \textit{container} para uma lista de inteiros e um iterador para esta lista.
\begin{algorithm}
\caption{Trecho de declaração longo}
\label{lst:declaracaoGrande}
\lstinputlisting[]{codigos/declaracaoLonga.cpp}
\end{algorithm}
Com a finalidade de reduzir estes trechos de código, a especificação C++11 introduziu um mecanismo de inferência ou detecção automática de tipos de variáveis através do uso das palavras-chave \textbf{``auto''} e \textbf{``decltype''} \cite{professionalCpp}.
A primeira é utilizada durante a atribuição de valores que já tem um tipo de dado definido por outro mecanismo, como por exemplo, pelo retorno de uma função ou pelo uso do operador de instanciação \textit{\textbf{``new''}}. O trecho de código \ref{lst:declaracaoGrande} poderia ser simplificado para o código em \ref{lst:declaracaoPequena}.
\begin{algorithm}
\caption{Trecho de declaração curto usando \textbf{``auto''}}
\label{lst:declaracaoPequena}
\lstinputlisting[]{codigos/declaracaoCurta.cpp}
\end{algorithm}
O uso da palavra-chave ``auto'' tem uma particularidade importante que deve ser levada em consideração durante o seu uso. O tipo deduzido é o resultado do tipo do valor atribuído à variável após a remoção do modificador \textbf{``const''}\footnote{Utilizado para declarar constantes, ou seja, que não podem ser usadas para modificar valores.} e do modificador \textbf{``\&''}\footnote{Neste contexto se refere ao modificador para declaração de variáveis do tipo referência na linguagem C++.} \cite{professionalCpp}. Esta particularidade pode levar a resultados inesperados, como o que pode ser observado no trecho de código \ref{lst:autoParticularidade} na linha 10, onde a dedução de tipo irá levar a criação de uma variável do tipo inteiro com o valor copiado do retorno da função ``constRef'', enquanto que o valor atribuído originalmente é de uma referência para um valor inteiro constante.
\begin{algorithm}
\caption{Particularidade do uso da palavra-chave \textbf{``auto''}}
\label{lst:autoParticularidade}
\lstinputlisting[]{codigos/autoParticularidade.cpp}
\end{algorithm}
Nestas situações podemos utilizar a palavra-chave ``decltype'' para alcançar o comportamento requerido. A função desta palavra-chave é avaliar o tipo de dado do resultado de uma expressão qualquer \cite{professionalCpp}. Ela pode ser utilizada em qualquer lugar do código onde se espera a especificação de um tipo de dado, como por exemplo em declarações de variáveis e como parâmetros para estruturas genéricas (que utilizam o mecanismo de \textbf{``templates''}\footnote{Mecanismo presente na linguagem C++ que permite o desenvolvimento de código que pode trabalhar com diferentes tipos de dados. É muito utilizado na construção de estruturas do tipo \textit{container}.}).
No trecho de código \ref{lst:decltype} podemos ver a utilização desta palavra-chave. Neste caso a variável ``numero'' (linha 10) irá ser deduzida como uma referência para um valor inteiro constante, que é exatamente o tipo retornado pela função ``constRef''. Porém o código gerado para a dedução não é tão simplificado, o que levou a proposta da adição da construção \textbf{``decltype(auto)''} (linha 12) pela especificação C++14, que tem o mesmo resultado neste caso \cite{professionalCpp}.
\begin{algorithm}
\caption{Dedução de tipo com o uso da palavra-chave \textbf{``decltype''}}
\label{lst:decltype}
\lstinputlisting[]{codigos/decltype.cpp}
\end{algorithm}
\subsubsection{Programação Funcional}
\label{sec:programacaoFuncional}
O conceito de programação funcional propõe que funções e métodos sejam tratados de forma igualitária com variáveis e objetos, no aspecto de poderem ser transportados entre contextos de execução, ser armazenados em estruturas específicas, ser criados sob demanda e ser utilizados como parâmetros para outras funções e/ou métodos \cite{fastDelegates}.
A maneira tradicional utilizada para manipular funções e métodos na linguagem C++ consiste no uso de ponteiros. Porém esta metodologia utiliza uma sintaxe bem difícil e existem vários problemas ou limitadores em relação à conversão destes ponteiros. Um grande problema encontrado é que ponteiros para funções (declaradas no contexto global) e métodos (declarados dentro de classes, exceto os estáticos neste caso) possuem sintaxe de declaração diferentes e não são convertíveis entre si \cite{fastDelegates}.
No trecho de código \ref{lst:ponteiroFuncoesMetodos} é demonstrada a sintaxe do uso de ponteiros para funções e métodos. Na linha 16 é declarado um ponteiro para a função ``getTexto'', e na linha 18 é declarado um para o método de mesmo nome presente na classe ``Exemplo''. Note que apesar da função e do método possuírem o mesmo protótipo (tipo de retorno e parâmetro) a sintaxe para declaração de seus ponteiros é diferente e eles não podem ser convertidos entre si.
\begin{algorithm}
\caption{Sintaxe para utilização de ponteiros para funções e métodos}
\label{lst:ponteiroFuncoesMetodos}
\lstinputlisting[]{codigos/ponteiroFuncoesMetodos.cpp}
\end{algorithm}
A especificação C++11 propõe a unificação da representação destes ponteiros como instâncias da classe \textbf{``function''} que é definida dentro do \textit{namespace} ``std''. Esta classe consegue representar ponteiros para funções, métodos e referências para \textit{\textit{``function objects''}}\footnote{Instâncias de classes que reimplementam a função do operador parênteses.} \cite{professionalCpp}.
O trecho de código \ref{lst:ponteiroFuncoesMetodos} pode ser reescrito com o uso desta classe conforme o exemplo \ref{lst:stdFunction}. Note que para atribuir um ponteiro para método é preciso utilizar a função \textbf{``bind''} para associar um objeto com o método a ser apontado (linha 22). Com esta nova sintaxe, apontadores para métodos e funções com o mesmo protótipo podem ser convertidos entre si.
\begin{algorithm}
\caption{Unificação da representação de ponteiros para métodos e funções}
\label{lst:stdFunction}
\lstinputlisting[]{codigos/stdFunction.cpp}
\end{algorithm}
Outra funcionalidade adicionada pela especificação C++11 foi o suporte à definição de métodos anônimos, também conhecidos como \textbf{expressões lambda}. Esta funcionalidade consiste na capacidade de criar funções sob demanda durante blocos de execução do programa. Expressões lambda também podem ser armazenadas em instâncias da classe \textit{``function''} \cite{professionalCpp}.
A sintaxe básica para utilização de expressões lambda é demonstrada na figura \ref{fig:lambdaExpression}. Os blocos presentes nesta construção são explicados em seguida:
\begin{figure}[!htb]
\centering
\includegraphics[scale=0.55]{imagens/LambdaExpression.png}
\caption{Sintaxe básica das expressões lambda}
\label{fig:lambdaExpression}
\end{figure}
\begin{description}
\item[1) Área de captura (\textit{Capture specification}):]
As expressões lambda podem capturar as variáveis presentes no contexto atual de execução para utilizar seus valores no seu bloco de execução. Esta captura pode feita por valor, onde é efetuado uma cópia dos valores das variáveis do contexto alvo, ou pode ser feita por referência, onde as variáveis serão referenciadas no bloco de execução da expressão, ou seja, podemos trabalhar com modificação de valores das variáveis originais.
Neste último caso é importante garantir que as variáveis capturadas existem no momento de execução da expressão, caso contrário teremos uma exceção de acesso a posição inválida de memória. A captura pode ser feita especificando cada variável que queremos capturar, como por exemplo no trecho ``[a, \&b]'' capturamos a variável ``a'' por valor e ``b'' por referência. Ou podemos capturar todas as variáveis do contexto utilizando ``[=]'' para capturar todas as variáveis por valor ou ``[\&]'' para capturar por referência. Caso não seja necessário capturar variáveis, utilizamos colchetes sem conteúdo, assim ``[]'' \cite{cppAnnotations}.
\item[2) Lista de parâmetros (\textit{Parameter specification}):]
É onde é especificada a lista de parâmetros que a expressão lambda recebe. A sintaxe é a mesma utilizada na definição de protótipos de funções e métodos. Por exemplo no trecho ``(int a, char b)'' dizemos que a expressão recebe um número inteiro que será referenciado no corpo da expressão como ``a'' e também recebe um caractere que será referenciado como ``b'' \cite{cppAnnotations}.
\item[3) Especificação \textit{Mutable} (\textit{Mutable specification}):]
Por padrão, variáveis capturadas por valor são tratadas dentro do bloco de execução da expressão como do tipo constante, ou seja, não podemos modificar seus valores. Caso utilizemos o modificador \textbf{``mutable''} elas não serão mais tratadas como do tipo constante, então poderemos manipular os valores copiados no bloco de execução da expressão \cite{cppAnnotations}.
\item[4) Especificação do tipo de retorno (\textit{Return type specification}):]
Neste ponto devemos especificar o tipo de dado que será retornado pela expressão lambda. Caso a expressão não retorne valores ou o tipo do valor retornado pode ser deduzido pelo compilador, podemos omitir esta parte \cite{cppAnnotations}.
\item[5) Bloco de execução (\textit{Lambda body}):]
Consiste do bloco de código que será executado quando a expressão for utilizada. Assim como a lista de parâmetros, este trecho de definição segue a mesma sintaxe da definição de funções e métodos comuns. Podem ser utilizadas quaisquer construções válidas para blocos de execução na linguagem C++. É importante ressaltar também que não há um limite de tamanho para o bloco, porém expressões lambda geralmente são bem concisas e simplificadas, ocupando poucas linhas. Caso a expressão comece a ficar muito grande e complexa, talvez seja melhor definir uma função comum para que possa ser reutilizada por outros componentes do programa \cite{cppAnnotations}.
\end{description}
No trecho de código \ref{lst:lambdaExpression} temos um exemplo de definição de uma expressão lambda com o mesmo protótipo utilizado nos exemplos anteriores. Note que a expressão pode ser armazenada em uma instância da classe ``\textit{function}'' e a sua execução é feita da mesma maneira que os ponteiros para funções e métodos, armazenados nestas instâncias.
\begin{algorithm}
\caption{Exemplo de definição de uma expressão lambda}
\label{lst:lambdaExpression}
\lstinputlisting[]{codigos/lambdaExpression.cpp}
\end{algorithm}
\subsubsection{Ponteiros Inteligentes (\textit{Smart Pointers})}
\label{sec:ponteirosInteligentes}
Um dos maiores desafios enfrentados por desenvolvedores que utilizam a linguagem C++ consiste na garantia da liberação de blocos de memória alocados dinamicamente a partir do uso de ponteiros. Sempre que alocamos uma região de memória a partir do uso do operador \textbf{\textit{``new''}}, temos que garantir que em algum ponto do código aquela região será liberada, tarefa que deve ser realizada explicitamente com o uso do operador \textbf{\textit{``delete''}} \cite{cppAnnotations}.
Regiões de memória alocada que não são liberadas, irão persistir marcadas como utilizadas durante todo o fluxo de execução do programa, causando assim um efeito de utilização extra de memória indevida conhecido como \textbf{\textit{``memory leak''}}, ou vazamento de memória \cite{professionalCpp}.
Com o objetivo de evitar este tipo de problema, a especificação C++11 prevê a criação de ponteiros inteligentes ou \textit{``smart pointers''}, que são basicamente estruturas que simulam o funcionamento de um ponteiro comum, porém adicionando mecanismos de gerenciamento de memória. Do ponto de vista de padrões de projeto, um \textit{smart pointer} seria um \textit{proxy} para a interface de ponteiros comuns \cite{cppAnnotations}.
A especificação C++11 define a presença de três \textit{smart pointers}, sendo eles:
\begin{description}
\item[1) \textbf{\textit{``unique\_ptr''}}:]
Este ponteiro têm basicamente as mesmas características de um ponteiro comum. A única diferença é que ele automaticamente libera a região de memória apontada por ele quando ele é deletado ou quando o escopo de sua utilização chega ao fim \cite{professionalCpp}.
\item[2) \textbf{\textit{``shared\_ptr''}}:]
Este ponteiro possui uma funcionalidade um pouco mais avançada. Ele mantém um contador interno que armazena a quantidade de referências que existem para a região de memória apontada por ele, ou seja, ele armazena quantas instâncias do tipo ``shared\_ptr'' se encontram ativas no momento para aquela região de memória. O contador é incrementado quando o ponteiro é copiado e decrementado quando instâncias de ponteiros são deletadas ou perdem escopo. Somente quando o contador chegar a zero, ou seja, quando não existir mais nenhuma cópia do ponteiro original ativa, a região de memória será automaticamente liberada \cite{professionalCpp}.
\item[3) \textbf{\textit{``weak\_ptr''}}:]
Este ponteiro é utilizado para testar se uma instância de ``shared\_ptr'' ainda é válida (ainda não foi desalocada), e caso o for, permite efetuar uma cópia desta instância para acessar a região de memória apontada \cite{professionalCpp}.
\end{description}
O trecho de código \ref{lst:smartPointer} demonstra a utilização dos três tipos de \textit{smart pointers} descritos anteriormente. Nele são alocados dois espaços de memória para armazenar dados do tipo inteiro dentro de um escopo de execução delimitado por chaves. Assim que o escopo é finalizado, ambos os ponteiros desalocam a região de memória apontada por eles automaticamente. No código também é mostrado como utilizar um ``weak\_ptr'' para verificar se um ``shared\_ptr'' ainda é válido a partir da utilização do método \textbf{``lock''} que retorna uma cópia deste segundo ponteiro no caso de validação ou retorna ``nullptr'' caso contrário.
\begin{algorithm}
\caption{Utilizando \textit{smart pointers}}
\label{lst:smartPointer}
\lstinputlisting[]{codigos/smartPointers.cpp}
\end{algorithm}
\section{O \textit{Framework} Qt}
\label{sec:qt}
Qt é um \textit{framework} multiplataforma voltado para a criação de aplicativos com interface gráfica utilizando a linguagem C++. Sua primeira versão foi lançada em 1995 pelos seus criadores \textit{Haavard Nord} e \textit{Eirik Chambe-Eng} em sua empresa chamada \textit{Trolltech} \cite{qtGuiProgramming}.
O objetivo do \textit{framework} é basicamente prover uma interface de programação padrão para executar tarefas como criação de interface gráfica, programação paralela e acesso a banco de dados, para todas as plataformas suportadas. Esse comportamento é alcançado através do direcionamento da execução das tarefas para implementações específicas existentes na plataforma alvo \cite{qtGuiProgramming}. Uma característica interessante do \textit{framework} é a adaptação da interface gráfica criada ao seu ambiente de execução. Uma janela executada em um sistema operacional suportado assume a aparência nativa do mesmo, como é possível verificar nas figuras \ref{fig:windowLinux}, \ref{fig:windowWindows} e \ref{fig:windowMac}, onde temos uma janela de um programa sendo exibida nos três sistemas suportados da plataforma \textit{desktop}: Linux, Microsoft Windows e Mac OS, respectivamente.
\begin{figure}[!htb]
\centering
\includegraphics{imagens/windowLinux.png}
\caption{Janela no GNU/Linux}
\label{fig:windowLinux}
\end{figure}
\begin{figure}[!htb]
\centering
\includegraphics[scale=0.8]{imagens/windowWindows.png}
\caption{Janela no Microsoft Windows XP}
\label{fig:windowWindows}
\end{figure}
\begin{figure}[!htb]
\centering
\includegraphics[scale=0.8]{imagens/windowMac.png}
\caption{Janela no Mac Os}
\label{fig:windowMac}
\end{figure}
Inicialmente o \textit{framework} era totalmente focado na padronização do processo de criação de interface gráfica entre diferentes plataformas, porém ao longo de sua existência foram sendo adicionadas novas funções voltadas para tarefas rotineiras no desenvolvimento de \textit{software}, como por exemplo acesso a banco de dados, programação paralela e manipulação de arquivos multimídia (vídeos e imagens). Com a adição destes novos componentes, o \textit{framework} acabou crescendo muito, o que levou aos desenvolvedores o reestruturarem em forma de módulos de forma que o desenvolvedor possa adicionar em seu projeto somente os módulos que pretende utilizar, diminuindo o tamanho final do executável gerado para distribuição de seu aplicativo \cite{qtGuiProgramming}.
Neste trabalho são utilizados basicamente três dos módulos existentes no \textit{framework}: \textbf{QtSql}, \textbf{QtTest} e \textbf{QtCore}. O QtSql é um módulo voltado para utilização de \textbf{Sistemas Gerenciadores de Bancos de Dados Relacionais} (ver seção \ref{sec:sgbd}) como forma de persistência dos dados gerados pelo aplicativo. Ele provê suporte para utilização dos sistemas mais populares, como \textbf{MySQL}, \textbf{Oracle}, \textbf{PostgreSQL},
\textbf{Sybase}, \textbf{DB2}, \textbf{SQLite}, \textbf{Interbase} e \textbf{ODBC} \cite{qtFoundations}. Esse módulo será utilizado como apoio para utilização de bancos de dados relacionais nas plataformas \textbf{Microsoft Windows} e \textbf{GNU/Linux}.
O QtTest é um módulo voltado para a criação de testes unitários. Os testes são utilizados para validar o funcionamento do \textit{software} desenvolvido ao longo de sua existência. Geralmente são executados quando é feita alguma modificação no código, como por exemplo adição de novos componentes. E, por fim, QtCore é o módulo principal do \textit{framework}. Ele é responsável por prover rotinas para programação paralela, conversão de tipos, além de adicionar tipos de dados muito importantes na utilização de bancos de dados, como o \textbf{\textit{QDateTime}}\footnote{Tipo de dado que armazena um valor de data e hora. Não existe um tipo de dado nativo em C++ para esta finalidade.} \cite{qtFoundations}.
No momento da criação deste documento, o framework estava em sua versão 5.3 (versão que é utilizada no trabalho), e é compatível com os sistemas operacionais \textit{GNU/Linux}, \textit{Microsoft Windows} e \textit{Mac OS} na plataforma \textit{desktop}. Ele oferece também suporte a dispositivos embarcados com sistema operacional \textit{GNU/Linux} e para dispositivos móveis com os sistemas \textit{Android}, \textit{IOS} e \textit{Windows Phone}.
\section {Sistemas Gerenciadores de Bancos de Dados Relacionais}
\label{sec:sgbd}
Assim como as linguagens orientadas a objetos são consideradas um padrão para desenvolvimento de \textit{software}, os Sistemas Gerenciadores de Bancos de Dados Relacionais ou \textbf{SGBD}s são considerados um padrão para armazenamento estruturado de informações \cite{ormPaper}.
Os SGBDs utilizam um modelo de persistência denominado \textbf{modelo relacional}, que se baseia no uso de \textbf{tabelas} e \textbf{colunas}. As tabelas representam entidades, ou um grupo de informação a ser armazenado, e podem se relacionar com outras tabelas para promover regras de armazenamento. As colunas representam as características da entidade armazenada. Neste modelo, quando armazenamos um registro, ele é acrescentado como uma linha em uma ou mais tabelas relacionadas. Nas tabelas, pode ser aplicado o conceito de unicidade dos registros armazenados, através da definição de um conjunto de colunas que deve representar uma combinação de valores única dentre os registros armazenados. Este conjunto de colunas define o que chamamos de \textbf{chave primária} da tabela ou, em inglês,
\textbf{\textit{``primary key''}} \cite{ormPaper}.
A definição de chaves primárias nas tabelas criadas permite a criação de relações entre elas através do uso de referências entre suas chaves. A referência em uma tabela para uma chave primária de outra tabela é conhecida como \textbf{chave estrangeira} ou, em inglês, \textbf{\textit{``foreign key''}} \cite{ormPaper}. Na figura \ref{fig:modeloRelacional} temos um exemplo de definição de duas tabelas, uma representando registros de pessoas e outra de telefones. Elas estão relacionadas, de modo que um registro de telefone pertence a uma pessoa. Este comportamento é obtido através da definição da chave estrangeira ``TelefoneId'' na tabela ``Pessoa'', que se refere à chave ``Id'' na tabela ``Telefone''.
\begin{figure}[!htb]
\centering
\includegraphics{imagens/modeloRelacional.png}
\caption{Exemplo de definição de tabelas e relações}
\label{fig:modeloRelacional}
\end{figure}
Uma das funcionalidades mais importantes apresentada pelos SGBDs é a capacidade de aplicação de rotinas complexas de pesquisa usando a linguagem \textbf{SQL}. Esta linguagem define um conjunto de operações que permite executar inserções, modificações, remoção e busca de registros armazenados em um SGBD \cite{ormPaper}. Talvez esta funcionalidade seja a causa de sua grande utilização e aceitação. Neste trabalho é utilizado o SGBD \textbf{PostgreSQL} (ver seção \ref{sec:postgresql}).
\section{O PostgreSQL}
\label{sec:postgresql}
O PostgreSQL é um SGBD de código aberto, e com licença de uso gratuita para qualquer pessoa sobre qualquer propósito. Ele pode ser utilizado, modificado e redistribuído livremente. Este SGBD é derivado do projeto \textbf{POSTGRES} desenvolvido na Universidade de Berkeley na Califórnia no ano de 1986. Por ser um \textit{software} de código aberto desenvolvido em comunidade, ele é conhecido por ser pioneiro na adição de novas funcionalidades, e se mantém sempre atualizado em relação aos conceitos e especificações da linguagem SQL \cite{postgresqlDoc}.
\section{A combinação de SGBDs com Linguagens Orientadas a Objetos}
\label{sec:sgbdWithOop}
A princípio, os programas trabalham com dados em memória principal, que é volátil. Isto é, ao desligarmos o equipamento todos os dados são perdidos. Devido a isso, necessitamos de algum mecanismo de persistência, ou seja, que permita a gravação de dados importantes em memória secundária, não volátil \cite{ormPaper}.
A combinação mais comumente utilizada para alcançar este cenário é o uso de linguagens orientadas a objetos para desenvolver o \textit{software} e o uso de SGBDs para armazenar os dados gerados pelo \textit{software} \cite{hibernateInAction}. Porém, os dados no contexto orientado a objetos e no contexto relacional são estruturados de maneiras diferentes, portanto precisamos realizar uma conversão ou mapeamento dos dados durante a transição de contextos.
Quando estamos trabalhando com classes simples (não compostas por membros de outras classes), o mapeamento segue uma lógica simples. Podemos criar uma correspondência entre a classe e sua respectiva tabela, onde os atributos da classe são mapeados para colunas de uma tabela. Porém quando começamos a utilizar mecanismos mais avançados da orientação a objetos como herança e composição, o mapeamento entre os contextos se torna mais complexo \cite{ormPaper}.
Mesmo quando temos um cenário onde o mapeamento é simples, precisamos gerar código de conversão. As linguagens de programação fornecem bibliotecas ou \textbf{\textit{APIs}}\footnote{\textit{Application Programming Interface}. Define uma interface de um conjunto de bibliotecas de \textit{software}.} que permitem a comunicação com SGBDs através do envio de comandos em linguagem SQL \cite{ormPaper}. O código gerado para executar a transição de dados entre os dois contextos geralmente segue a seguinte sequência de passos:
\begin{enumerate}
\item Carregar um \textit{driver} de comunicação com o SGBD utilizado e abrir a conexão;
\item Criar um objeto que permita a montagem de código SQL;
\item Enviar o comando para o SGBD para que seja executado;
\item Recuperar e processar os dados ou resposta gerados pelo SGBD;
\item Liberar os recursos alocados para execução da tarefa, como por exemplo fechar a conexão com SGDB.
\end{enumerate}
No trecho de código \ref{lst:qtsql_mapclasse} temos um esboço de como estas etapas são realizadas utilizando a linguagem C++ em conjunto com o módulo QtSql do framework Qt (ver seção \ref{sec:qt}) e comunicando com o SGBD PostgreSQL (ver seção \ref{sec:postgresql}).
\begin{algorithm}
\caption{Exemplo de comunicação com SGBD utilizando o módulo QtSql}
\label{lst:qtsql_mapclasse}
\lstinputlisting[]{codigos/qtsql_mapclasse.cpp}
\end{algorithm}
A utilização deste tipo de código se torna repetitiva, visto que temos que executar estes passos para todas as classes que armazenam dados utilizando SGBDs. Este tipo de comportamento é indesejado, pois diminui a produtividade do desenvolvimento, além do fato de que tarefas repetitivas tem grande potencial de gerarem erros. Outro grande problema que encontramos é que os comandos em linguagem SQL variam entre os SGBDs, portanto ao mudar o SGBD utilizado pelo programa, temos de reescrever os comandos SQL utilizados. Este é outro fator com grande potencial de geração de erros, além de diminuir a flexibilidade do \textit{software}, tornando, em alguns casos, inviável a mudança de SGBD \cite{ormPaper}.
Para otimizar a combinação do uso de linguagens de programação orientadas a objetos em conjunto com SGBDs, surgiu o conceito de \textbf{Biblioteca de Mapeamento Objeto Relacional} ou \textbf{ORM} (\textbf{\textit{Object Relational Mapping}}), assunto abordado na seção \ref{sec:orm}.
%--- Explicar o que é ORM de maneira simples e direta
\section{Bibliotecas de Mapeamento Objeto Relacional}
\label{sec:orm}
As bibliotecas ORM têm como objetivo principal automatizar as tarefas relacionadas com a transição de informações entre os contextos orientado a objetos e relacional. Não existe um conceito universal que defina quais são as funcionalidades que uma biblioteca ORM deve oferecer \cite{ormPaper}, porém as três funcionalidades mais comumente encontradas são:
\begin{description}
\item[1) Definição de mapeamento:]
As bibliotecas ORM permitem a definição explícita da correspondência entre entidades no contexto orientado a objetos (classes) e entidades no contexto relacional (tabelas). Os mecanismos de definição deste mapeamento variam entre as implementações;
\item[2) Geração de banco de dados:]
As bibliotecas ORM geralmente permitem a geração automática do banco de dados equivalente às estruturas do contexto orientado a objetos;
\item[3) Definição de uma API:]
Geralmente as bibliotecas ORM disponibilizam interfaces padronizadas para realização de tarefas que envolvam a transição de dados entre os dois contextos. Operações como salvar, deletar ou pesquisar registros são encapsuladas em classes de propósito geral que conseguem trabalhar sobre qualquer entidade mapeada.
\end{description}
Nem todas as bibliotecas existentes oferecem as três funcionalidades descritas, mas o mais comum é encontrar uma combinação das três. Existem ainda bibliotecas que permitem gerar o código de mapeamento e até mesmo gerar o código das classes a partir da análise de um banco de dados existente. Esta funcionalidade é conhecida como \textbf{Mapeamento Reverso} ou \textbf{Engenharia Reversa} \cite{ormPaper}.
As bibliotecas ORM divergem bastante na forma de implementação e funcionalidades disponibilizadas. Isso se deve principalmente ao fato da divergência de recursos entre as próprias linguagens de programação em que são implementadas. Porém uma decisão comum a ser tomada no desenvolvimento de uma biblioteca ORM em qualquer linguagem é a definição do ponto de partida para obtenção das informações de mapeamento \cite{ormPaper}. Os paradigmas mais utilizados são:
\begin{description}
\item[1) Orientado a metadados:]
Neste paradigma, o desenvolvedor informa a estrutura das entidades envolvidas no \textit{software} que devem ser mapeadas através de alguma fonte externa, como um arquivo XML. Neste arquivo são informados metadados\footnote{Informações complementares sobre outro conjunto de dados. Podem ser utilizados, por exemplo, para descrever a estrutura destes.} sobre as entidades nos dois contextos, o que permite a biblioteca ORM criar o código de definição das classes e do código de mapeamento. Neste modelo podemos utilizar um banco de dados já existente, ou a biblioteca ORM pode construí-lo a partir da análise dos metadados. A vantagem deste paradigma é a abstração total da geração de código de manipulação do banco de dados. E sua grande desvantagem é a limitação de edição do código gerado pela biblioteca. Os códigos das classes mapeadas serão gerados automaticamente pela biblioteca e não poderão ser editados pelo desenvolvedor \cite{ormPaper}.
\item[2) Orientado à aplicação:]
Neste paradigma o desenvolvedor deve escrever o código das classes de todo o programa normalmente, porém sem se preocupar com as operações de persistência. Após a definição das classes, a biblioteca ORM, através da análise do código e opcionalmente metadados, consegue criar o código de persistência. É possível utilizar um banco de dados existente ou a biblioteca pode construí-lo. A vantagem deste paradigma é a total abstração da geração de código de manipulação do banco de dados, e sua grande desvantagem é a alta complexidade de desenvolver o mecanismo de análise do código escrito pelo desenvolvedor para inferir informações de mapeamento. A definição deste mecanismo pode influenciar bastante no desempenho final da aplicação que utiliza a biblioteca ORM \cite{ormPaper}.
\item[3) Orientado ao banco de dados:]
Neste paradigma o desenvolvedor deve primeiramente criar o banco de dados. Então a biblioteca ORM auxiliada por metadados consegue gerar o código das classes a serem mapeadas e das operações de persistência. A grande desvantagem deste paradigma é a não abstração do conhecimento de banco de dados, visto que o desenvolvedor deve primeiramente definir a estrutura da base de dados a ser utilizada. Outra desvantagem é o desenvolvedor não ter a permissão de modificar o código das classes mapeadas pela biblioteca ORM. Sua vantagem consiste no melhor controle da definição da estrutura da base de dados sendo utilizada \cite{ormPaper}.
\end{description}
As bibliotecas de mapeamento mais robustas possuem a possibilidade de operar nos três paradigmas citados. Em alguns casos, elas ainda permitem que o desenvolvedor tenha controle dos três componentes principais citados pelos paradigmas, ou seja, o desenvolvedor pode definir o código das classes a serem mapeadas, os metadados e construir o banco de dados a ser utilizado, deixando para a biblioteca ORM somente a tarefa de adicionar o código de persitência \cite{ormPaper}.
Existe ainda o conceito de \textbf{transparência}, que é aplicado a bibliotecas que utilizam o paradigma orientado à aplicação. Uma biblioteca ORM é transparente quando não requer que classes implementem interfaces, ou sigam um modelo específico de código para serem mapeadas \cite{ormPaper}. Estas bibliotecas seguem a filosofia de que as classes envolvidas no \textit{software} não precisam saber como, porque ou quando elas serão persistidas, ou seja, elas devem se comportar como ``classes ordinárias'' ou comuns.
Analisando as principais funcionalidades que as bibliotecas ORM possuem, podemos perceber que elas promovem uma melhoria considerável de produtividade (economia de tempo de desenvolvimento) além de diminuir a complexidade do desenvolvimento de sistemas que lidam com gerenciamento constante de dados persistidos em bancos de dados relacionais \cite{ormPaper}.