Mostrando postagens com marcador Automação OLE. Mostrar todas as postagens
Mostrando postagens com marcador Automação OLE. Mostrar todas as postagens

domingo, 13 de maio de 2007

Private, Public, Published ... Escopo de visibilidade

Um conceito muito importante do paradigma OO é o encapsulamento. Ele define a visibilidade dos membros de uma classe. Cabe lembrar que esse conceito não é exclusivo da orientação a objetos. A preocupação com o escopo e visibilidade, já na estruturação era uma questão extremamente relevante. Na verdade, uma das razões de ser da estruturação é justamente uma adequação melhor da questão da visibilidade. Que tinha na organização modular, conjugada com os conceitos de coesão e acoplamento, a representação lógica dos seus princípios.
Eu costumo “dramatizar” para meus alunos, como recurso didático, que a orientação a objetos, com relação ao encapsulamento, não propôs nada de novo. Não menos importante por isso, o que ela faz é simplesmente pegar esse conceito e leva-lo as últimas conseqüências. Aperfeiçoando, na minha opinião, o que já havia sido proposto pela Teoria Geral de Sistemas. Um sistema é sempre um subsistema de um outro em nível hierárquico mais alto (isso me lembra o final do filme MIB... hehehe ... mas sem cao, isso é importante). Amigo, isso era vanguarda no império do Cobol! Se liga!!!! Entretanto, ainda hoje, parece, e não sou eu o único a falar sobre isso, que a ficha ainda não caiu. Eu estou cansado de ver programas em Java que começam com um “public static void main(String args[])”, dentro dele vc pode encontrar de tudo, parece até a bolsa do “gato felix”. Na mesma e única classe você encontra desde

public static Connection getConnection()
throws ClassNotFoundException, SQLException {
String connectStr = "jdbc:odbc:BancoDoido ";

String username = "";
String password = "";
if (c == null) {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
c = DriverManager.getConnection(connectStr);
}
return c;
}


até comando SQL .... creeedooo!!!!

public void cadastar(dado1, dado2, ... dadoN)
{
‘Insert into ......’
}

public void alterar(dado1, dado2, ... dadoN)
{
‘Update tabela set......’
}

public void excluir(dado)
{
‘Delete from tabela where ....’
}


Isso não é um problema RESTRITO a uma tecnologia específica, seja em Delphi, VB, ASP, passando pelo PHP ao C++, observamos recorrentemente essa falha. Com um agravante, hoje é grande a parcela dos programadores, que a pesar de freqüentarem, desde a graduação as pós e MBAs da vida, aulas de AOO e POO, justificarem (com a maior cara de pau) a modularização digamos pouco ortodoxa, para não dizer porca, de seus sistemas, que por uma questão de produtividade assim o fazem. Respaldados por um reducionismo digno da mais pura filosofia de botequim, cujo o genial objeto de argumentação é sustentado pela cínica pergunta retórica: “Até que ponto não perderemos produtividade ... nos abstendo do “rococó Bizonho”?”. Os açougueiros de toga com seu objetos perfurocortantes assassinam Yourdon, Page Jones, Chris Gane, Pressman e est ... até o Tanenbaum sai decepado nesse cenário Tarantiniano patético.
Então ... voltando ao assunto ... Por isso, justamente para possibilitar ao programador/analista uma opção dele não ser lembrado como exímio representante do estilo rococó bizonho D’Mono Neurônio, existe o encapsulamento. Que, por sua vez, para ser feito de forma adequada deve seguir harmoniosamente o conceito de escopo de visibilidade.
Entretanto, existe um porém, infelizmente você não tem uma fórmula para se construir classes, ou módulos, que equacionem esse conceito perfeitamente, sob um ponto de vista absoluto. Nenhuma heurística de encpasulamento vai ser garantida de nada, porque em última análise quem vai definir o que vai ficar visível, ou não, é você. Portanto, alcançar um grau satisfatório de coesão dos seus módulos depende, em parte (uma boa parte, na minha opnião), de bom senso. Em contrapartida, a boa notícia é que a outra parte depende de você entender bem as definições que veremos a seguir:

Primeiro, leia o artigo que o Felipe escreveu sobre isso, em seguida volte.
Uma regra básica, que ajuda bastante: A interface de cada módulo, ou para cada módulo, deve ser definida de forma que não revele nada sobre o funcionamento do mesmo. A velha idéia de caixa preta. O Exemplo que o Felipe colocou sobre a televisão foi show!

Quando estamos especificamente definindo uma classe, podemos entender encapsulamento como a forma de se harmonizar os membros dessa classe, ou seja, os atributos, dados da classe, e as funções, operações que serão feitas sobre esses dados. Sobre uma definição que oculte, eficientemente, os detalhes dessa implementação. Lembre-se da “caixa preta”.

Em Delphi language, as palavras chaves que definem o escopo de visibilidade dos membros da classe, na seção delimitada por elas. Vejamos:

  • Private – Visibilidade exclusiva a própria classe. Tudo que estiver declarado na seção private da classe o escopo de visibilidade estará restrito a própria classe. Nem mesmo a instância enxerga.
  • Protected – Tudo que estiver declarado em protected o escopo de visibilidade estará restrito somente a própria classe e aos seus descendentes. Ou seja, somente a própria classe e as que estenderem dela conseguem acessar o que esta definido em protected.
  • Public – Nenhuma restrição de visibilidade. Conforme o próprio significado da palvra chave, público, indica que todos tem acesso ao que estiver definido ali.
  • Published – Visibilidade idêntica ao escopo definido pela public. Ou seja visibilidade irrestrita. O que difere uma da outra é que o Delphi gera RTTI para os membros definidos dentro do escopo dessa seção. Por isso esses membros podem ser listados pelo Object Inpector e serem acessados em design-time.
  • Automated – Mesma visibilidade dos membros public, com uma característica: Informação se automação é gerada para os membros nela declarados. É mantida por questões de compatibilidade com versões anteriores. Infromações de automação é pertinente a API OLE Automation.

Até aqui tudo bem? Quase! Seria perfeito se não fosse um probleminha. Existe um conceito em OO sobre classes amigas, que cada linguagem de programação deu suporte a ele de forma diferente. No Delphi, a Borland, na época, implementou da seguinte forma: Não há restrição se visibilidade para classes definidas na mesma unit. Na prática isso joga todo o discurso sobre encapsulamento por água abaixo.
Só que o homem evolui, o mundo evolui e a Borland também evoluiu. Por conta do frame work .Net, a Borland teve que, para manter compatibilidade com a CLS (Common Language Specification) da .Net, introduzir dois escopos novos: Strict private e Strict protected. Eles podem ser usados também em aplicações win32 e fazem rigorosamente o que o private e o protected não fazem. Eles acabam com a visibilidade das classes amigas. Os membros declarados dentro do escopo de strict private possuem visibilidade restrita a classe mesmo para as classes definidas na mesma unit. O mesmo para strict protected, os membros declarados nela somente são acessíveis a própria classe e aos seus descendentes.

O objetivo do encapsulamento é o ocultamento de informações específicas. De que forma podemos fazer isso? Restringindo o escopo, restringindo a visibilidade. Qual o objetivo disso? Conseguir um isolamento das funcionalidades de um determinado módulo, de maneira que o entendimento (legibilidade) seja fácil, a manutenção também seja pouco custosa (não reflita para outros módulos). Atingindo esse grau de isolamento esse módulo poderá ser reutilizado. Portanto, concluindo, o encapsulamento traz, imediatamente, para o desenvolvedor três vantagens ao ser empregado: Fácil entendimento, maior manutenibilidade e reuso. Voltando ao exemplo da Tv, quando vc for comprar um aparelho novo, pouco vai importar a tecnologia empregada no produto. Seja plasma, LCD, ou sei lá o que, o usabilidade dos controles remotos são quase que padronizadas. Por isso você vai confiante comprar o produto sabendo que sem o menor problema, em poucos minutos você estará assistido seu programa favorito.

Pra finalizar, a maior e mais aprazível vantagem de você dedicar o devido cuidado com encapsulamento nos seus programas é, por exemplo: num conturbado dia 23 de dezembro, às 15:00, às margens do dead line, terminar o módulo previsto e de repente, involuntariamente, escapar em voz alta: “Pronto!!! Está funcionando!! Eu amo isso!!!!”. Duvido, e faço pouco, se o adepto do rococó bizonho D’Mono Neurônio é capaz da mesma coisa.


Artigo completo (View Full Post)

terça-feira, 23 de janeiro de 2007

Evoluindo o Programa de Impressão

                          Delphi Automação OLE - Pate II

Construi esses exemplos a partir de uma experiência no trabalho. Certa vez,
o lider da equipe entra na sala bem nervoso, semi-desesperado, pedidinod que nós
interronpessemos o que estavamos fazendo por conta de uma situação administrativa.
Toda a documentação de um sistema gigante deveria ser impressa. Não havia, é claro
profissionais específicamente designados para tal tarefa, ou pelo menos não o
sufiente. Portanto, toda a fabrica de software estaria convocada a imprimir toda
documentação. Fui rememetido as profundesas do meu pensamento, indignado,
ainda indeciso sobre como responderia a essa situação, quando o Daniel,
compartinhando da mesma indignação sugeriu que fosse codificado um programa tal
realizar tal tarefa ...
(continua nos próximos post - O desafio ... tchan
tchan tchan!!)

1) Inicie uma applicação no Delphi
No menu principal selecione: File - New - Application
2) Adicione no Form1 os seguintes componentes, seguindo exatamente a ordem abaixo,
e configure suas respectivas propriedades conform listado:

I Panel (Palheta Standard):
BevelOuter = bvNone
Name = PnlTreeView
Align = alLeft

II Splitter(Palheta Additional):
Name = Splitter1
Beveled = True
Align = alLeft

III Panel (Palheta Standard):
Name = PnlListView
BevelOuter = bvNone
Align = alLeft

IV Splitter(Palheta Additional):
Name = Splitter2
Beveled = True
Align = alLeft

V PopUpMenu(Palheta Standard):
Name = PopupMenu
Com o botão direito do mouse no PopupMenu selecione Menu Designer.
Adicione os Seguntes Itens de menu:
- Imprimir Todos
- Imprimir Selecionados
- Excluir Todos
- Excluir Selecionados

VI Panel (Palheta Standard):

Name = PnlLstFile
BevelOuter = bvNone
Align = alClient

VII FileListBox(Palheta Win3.1)
Coloque o FileListBox no PnlLstFile
Name = LstFile
PopupMenu = PopupMenu //Para associar o PopupMenu ao LstFile
Align = alClient

VIII ShellTreeView (Palheta Samples):
Coloque o ShelTreeView no PnlTreeView
Name = ShellTreeView
Align = alClient

XIII ShellListView (Palheta Samples):
Coloque o ShelTreeView no PnlListView
Name = ShellListView
Align = alClient

IX WordApplication (Palheta Servers):

X WordDocument (Palheta Servers):

XI ExcelWorkbook (Palheta Servers):

XII ExcelApplication (Palheta Servers):


3) Vamos oo Código agora.
A seção Type na unit do Fomr1 deverá estar assim
  Type          
TForm1 = class(TForm)
PnlTreeView: TPanel;
PnlListView: TPanel;
Splitter1: TSplitter;
PnlListFile: TPanel;
ShellTreeView1: TShellTreeView;
ShellListView1: TShellListView;
Splitter2: TSplitter;
LstFile: TFileListBox;
PopupMenu: TPopupMenu;
ImprimirTodos1: TMenuItem;
ImprimirSelecionados1: TMenuItem;
N1: TMenuItem;
ExcluirTodos1: TMenuItem;
ExcluirSelecionados1: TMenuItem;
WordApplication1: TWordApplication;
WordDocument1: TWordDocument;
ExcelWorkbook1: TExcelWorkbook;
ExcelApplication1: TExcelApplication;
private
{ Digite as Funções em vermelho codificadas abaixo,
em seguida pressione "CTRL + SHIFT + C" }

procedure FindFiles(FilesList: TListBox; StartDir,
FileMask: string);
procedure PrintFile(SelectedOnly: Boolean = False);

public
{ Public declarations }
end;

3.1) Uma função que listará os arquivos que serão impressos - FindFiles

procedure TForm1.FindFiles(FilesList: TListBox; StartDir, FileMask: string);
var
SR: TSearchRec;
DirList: TStringList;
IsFound: Boolean;
i: integer;
begin
if StartDir[length(StartDir)] <> '\' then
StartDir := StartDir + '\';


{ Contruindo a Lista de Diretórios - StartDir}

IsFound :=
FindFirst(StartDir+FileMask, faAnyFile - faDirectory, SR) = 0;
while IsFound do
begin
FilesList.Items.Add(StartDir + SR.Name);
IsFound := FindNext(SR) = 0;
end;
FindClose(SR);

// Contruindo a listagem dos Subdiretórios
DirList := TStringList.Create;
IsFound := FindFirst(StartDir + '*.*', faAnyFile, SR) = 0;
while IsFound do
begin
if ((SR.Attr and faDirectory) <> 0) and (SR.Name[1] <> '.') then
DirList.Add(StartDir + SR.Name);

IsFound := FindNext(SR) = 0;
end;
FindClose(SR);

for i := 0 to DirList.Count - 1 do
FindFiles(FilesList, DirList[i], FileMask);

DirList.Free;

end;



3.2) Codificando o evento OnClick do item do menu Popup "Excluir Selecionados"

procedure TForm1.ExcluirSelecionados1Click(Sender: TObject);
begin
LstFile.DeleteSelected;
end;


3.3) Codificando o evento OnClick do item do menu Popup "Excluir Selecionados"

procedure TForm1.PrintFile(SelectedOnly: Boolean);
const

LCID: DWORD = LOCALE_SYSTEM_DEFAULT;
var
i: Integer;
MyDoc: _Document;
MyExel: _Workbook;
MyPath: String;
MyArq, ASave, AReadOnly: OleVariant;
Printed: Boolean;
StatusImpressora: TWMSpoolerStatus;
begin
Printed := False;
Asave := False;
AReadOnly := True;

(* A função IncludeTrailingPathDelimiter garante no final do path name a presensa do "\" *)
MyPath := IncludeTrailingPathDelimiter(ShellTreeView1.Path);

for i := 0 to Pred(LstFile.Items.Count) do
begin
if (SelectedOnly and LstFile.Selected[i]) xor not(SelectedOnly) then
begin
MyArq := MyPath + LstFile.Items[i];
if (pos(UpperCase('.doc'), UpperCase(LstFile.Items[i])) > 0) then
begin
MyDoc := WordApplication1.Documents.Open(MyArq, EmptyParam,
AReadOnly, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam);
WordDocument1.ConnectTo(MyDoc);
WordDocument1.Activate;
WordDocument1.PrintOut;
WordApplication1.Disconnect;
WordDocument1.Close(ASave);
WordDocument1.Disconnect;
Self.Caption := MyArq;
end
else if pos(UpperCase('.xls'), UpperCase(LstFile.Items[i])) > 0 then
begin
MyExel := ExcelApplication1.Workbooks.Open(MyArq , EmptyParam,
AReadOnly, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam, LCID);
ExcelWorkbook1.ConnectTo(MyExel);
ExcelWorkbook1.Activate;
ExcelWorkbook1.PrintOut;
ExcelWorkbook1.Close(ASave);
ExcelWorkbook1.Disconnect;
Self.Caption := MyArq;
end;
end;
end;

end;

3.5) Codificando o evento OnClick do item do menu Popup "Excluir Todos"

procedure TForm1.ExcluirTodos1Click(Sender: TObject);

begin
LstFile.Clear;
end;


3.6) Codificando o evento OnClick do item do menu Popup "Imprimir Selecionados"


procedure TForm1.ImprimirSelecionados1Click(Sender: TObject);

begin
PrintFile(True);
end;


3.7) Codificando o evento OnClick do item do menu Popup "Imprimir Todos"


procedure TForm1.ImprimirTodos1Click(Sender: TObject);

begin
PrintFile;
end;


3.8) Codificando o evento OnChange do ShellTreeView1 - " ShellTreeView1Change "

procedure TForm1.ShellTreeView1Change(Sender: TObject; Node: TTreeNode);

begin
if (ShellListView1.ShellTreeView.Path = '') or
(Pos(':\', ShellListView1.ShellTreeView.Path) = 0) then Exit;
LstFile.Directory := ShellListView1.ShellTreeView.Path;
end;


3.9) Codificando o evento OnClick do item do menu Popup "Imprimir Todos"

procedure TForm1.ImprimirTodos1Click(Sender: TObject);
begin
PrintFile;
end;

Artigo completo (View Full Post)

sexta-feira, 19 de janeiro de 2007

Delphi: Usando compenentes da Palheta Servers (TWordApplication; TWordDocumen )




Desenvolvendo um exemplo de um programa para imprimirdocumentos word, usando Delphi 7
1°) Inicie uma aplicação: No menu: "File - New - Application"
2°)Adicione no Form os seguintes componentes:
  Palheta Standard:Button1: TButton; Label1: TLabel;
  Palheta win 31:FileListBox1: TFileListBox; DirectoryListBox1: TDirectoryListBox; DriveComboBox1:TDriveComboBox;
  Palheta Servers:WordApplication1:TWordApplication; WordDocument1: TWordDocument;


3°) Configure as propriedades de cada um doscomponentes seguindo a listagem abaixo:
  Form1:Left = 262; Top = 142; Width = 350; Height = 370
  Label1:Left = 12; Top = 56
  FileListBox1:Left = 12; Top = 196; Width = 268; Height = 113; Mask = '*.doc'
  DirectoryListBox1: Left = 12; Top = 80; Width = 268; Height = 97; DirLabel = Label1
  DriveComboBox1:Left = 12; Top = 24; Width = 268; Height = 19; DirList = DirectoryListBox1
  Button1:Left = 320; Top = 24; Caption = 'Imprimir'
4°) No evento onChange do DirectoryListBox1 codifique como exemplificado abaixo:
 

procedureTForm1.DirectoryListBox1Change(Sender: TObject);
begin 
 FileListBox1.Directory := DirectoryListBox1.Directory;
end; 


5°)Codifique o evento onClick do Button1 comoexemplificado abaixo:
 



procedureTForm1.Button1Click(Sender: TObject);
var
 i: Integer;
 MyDoc: _Document;
 MyPath: String;
 AReadOnly, MyArq, ASave: OleVariant;
 
begin
 Printed := False;
 Asave := False;
 AReadOnly := True;
 fori := 0 toPred(FileListBox1.Items.Count)do
 begin  
  MyArq := DirectoryListBox1.Directory + FileListBox1.Items[i];
  MyDoc := WordApplication1.Documents.Open(MyArq, EmptyParam, AReadOnly, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam);
  WordDocument1.ConnectTo(MyDoc);
  WordDocument1.Activate;
  WordDocument1.PrintOut;
   WordDocument1.Close(ASave);
  WordDocument1.Disconnect;
  Self.Caption := MyArq;
 end;  
end;   
 

Artigo completo (View Full Post)

 
BlogBlogs.Com.Br