Ir para o conteúdo
bioshock

Edição 44 - opinião acerca do artigo "Quero fazer uma aplicação simples (...)", de Rita Peres

Mensagens Recomendadas

bioshock    169
bioshock

Antes de mais não é meu intuito denegrir a imagem de ninguém. http://revista-programar.info/?action=editions&type=viewmagazine&n=44

Li o texto na diagonal escrito desde a página 21 até à 35, e a única coisa que tenho a reclamar e que me chamou à atenção foi o código exemplo em C#.

Pessoalmente acredito que ao escrever um artigo estão incutidas as melhores práticas de código mesmo não sendo esse o ponto fulcral no artigo. A estrutura de código considero-a horrível bem com a extensão e código desnecessário, sem esquecer o nome dado às variáveis..

1) - O objectivo do código abaixo é de preencher uma DataGridView com alguns dados da tabela Carros.

//Separador Tabela Litros
SqlConnection conexao = new SqlConnection();
conexao.ConnectionString = @"Data
Source=artigoprogramar.no-ip.biz;user
id=sa;password=p@ppassword;Trusted_Connection=no;
database=PAP;connection timeout=30";
conexao.Open();
string sql2 = "select * from Carro";
SqlCommand cmd2 = new SqlCommand(sql2,
conexao);
cmd2.Connection = conexao;
cmd2.CommandText = sql2;
// cria o dataadapter...
SqlDataAdapter adapter2 = new
SqlDataAdapter();
adapter2.SelectCommand = cmd2;
try
{
// preenche o dataset...
System.Data.DataSet dataSet2 = new
System.Data.DataSet();
adapter2.Fill(dataSet2);
dataGridView1.DataSource =
dataSet2;
dataGridView1.DataMember =
dataSet2.Tables[0].TableName

Este código poderia, para além de estar mais organizado, ser muito mais reduzido.

/* Variáveis globais dado as mesmas serem utilizadas em vários pontos */
Private SqlConnection connection = new SqlConnection("@DataSource=artigoprogramar.no-ip.biz;userid=sa;password=p@ppassword;Trusted_Connection=no;database=PAP;connection timeout=30");
Private SqlCommand cmd;
Private SqlDataAdapter dataAdapter;
Private Dataset dSet;

/* Utilizado em qualquer lado */
string query = "SELECT * FROM Carro";
cmd = new SqlCommand(queyr, connection);

dSet = new DataSet();
dataAdapter = new SqlDataAdapter(query, connection);
dataAdapter.fill(dSet, 0); // 0 = Carro

this.DataGridView1.DataSource = dSet.tables[0];

Com os datasets não é preciso abrir a connection à base de dados, pois o método Fill já faz esse procedimento. MSDN

The Fill method implicitly opens the Connection that the DataAdapter is using if it finds that the connection is not already open. If Fill opened the connection, it will also close the connection when Fill is finished. This can simplify your code when dealing with a single operation such as a Fill or an Update.

2) - Não passar os parâmetros por referência é outro aspecto negativo a ter em consideração, por questões de segurança.

String sql = "INSERT INTO Utilizador (Nome, Contacto)" + " VALUES('" + nometextBox.Text + "'," + contactotextBox.Text + ")";

Sendo a solução indicada:

string query = "INSERT INTO Utilizador (Nome, Contacto) VALUES(@nome, @contacto)";
cmd = new SqlCommand(queyr, connection);
cmd.Parameters.Add("@Nome", SqlDbType.VarChar).value = nometextBox.Text;
cmd.Parameters.Add("@Contacto", SqlDbType.VarChar).value = contactotextBox.Text;

3) - Por favor não utilizar metodologias diferentes, Bindingsources com código unha-a-unha, mais tarde ou mais cedo acaba por dar barraca.

4) - O uso dos TryCatch() não está completamente certo.

Try{
  doSomethingToDatabase();
}Catch (Exception ex){
  MessageBox.Show("Error: " + ex.Message);
}finally{
  connection.close();
  // dispose, etc
  // tudo o que for para fazer clean coloca-se aqui pois será executado caso haja ou não excepção.
}

5) - Por último, até custa a olhar para isto:

SqlConnection conexao = new
SqlConnection();
conexao.Open();
string sql1 = "select SUM(Janeiro) AS
Janeiro from KmsAnuais;";
SqlCommand cmd1 = new SqlCommand
(sql1, conexao);
cmd1.Connection = conexao;
cmd1.CommandText = sql1;
String janeiro = cmd1.ExecuteScalar()
.ToString();
string sql2 = "select SUM(Fevereiro)
AS Fevereiro from KmsAnuais;";
SqlCommand cmd2 = new SqlCommand
(sql2, conexao);
cmd2.Connection = conexao;
cmd2.CommandText = sql2;
String fevereiro =
cmd2.ExecuteScalar().ToString();
string sql3 = "select SUM(Marco) AS
Marco from KmsAnuais;";
SqlCommand cmd3 = new SqlCommand
(sql3, conexao);
cmd3.Connection = conexao;
cmd3.CommandText = sql3;
String marco =
cmd3.ExecuteScalar().ToString();
string sql4 = "select SUM(Abril) AS
Abril from KmsAnuais;";
SqlCommand cmd4 = new SqlCommand
(sql4, conexao);
cmd4.Connection = conexao;
cmd4.CommandText = sql4;
String abril =
cmd4.ExecuteScalar().ToString();
string sql5 = "select SUM(Maio) AS
Maio from KmsAnuais;";
SqlCommand cmd5 = new SqlCommand
(sql5, conexao);
cmd5.Connection = conexao;
cmd5.CommandText = sql5;
String maio =
cmd5.ExecuteScalar().ToString();
string sql6 = "select SUM(Junho) AS
Junho from KmsAnuais;";
SqlCommand cmd6 = new SqlCommand
(sql6, conexao);
cmd6.Connection = conexao;
cmd6.CommandText = sql6;
String junho =
cmd6.ExecuteScalar().ToString();
string sql7 = "select SUM(Julho) AS
Julho from KmsAnuais;";
SqlCommand cmd7 = new SqlCommand
(sql7, conexao);
cmd7.Connection = conexao;
cmd7.CommandText = sql7;
String julho =
cmd7.ExecuteScalar().ToString();


string sql8 = "select SUM(Agosto) AS
Agosto from KmsAnuais;";
SqlCommand cmd8 = new SqlCommand(sql8,
conexao);
cmd8.Connection = conexao;
cmd8.CommandText = sql8;
String agosto =
cmd8.ExecuteScalar().ToString();
string sql9 = "select SUM(Setembro) AS
Setembro from KmsAnuais;";
SqlCommand cmd9 = new SqlCommand(sql9,
conexao);
cmd9.Connection = conexao;
cmd9.CommandText = sql9;
String setembro =
cmd9.ExecuteScalar().ToString();
string sql10 = "select SUM(Outubro) AS
Outubro from KmsAnuais;";
SqlCommand cmd10 = new SqlCommand
(sql10, conexao);
cmd10.Connection = conexao;
cmd10.CommandText = sql10;
String outubro =
cmd10.ExecuteScalar().ToString();
string sql11 = "select SUM(Novembro) AS
Novembro from KmsAnuais;";
SqlCommand cmd11 = new SqlCommand
(sql11, conexao);
cmd11.Connection = conexao;
cmd11.CommandText = sql11;
String novembro =
cmd11.ExecuteScalar().ToString();
string sql12 = "select SUM(Dezembro) AS
Dezembro from KmsAnuais;";
SqlCommand cmd12 = new SqlCommand
(sql12, conexao);
cmd12.Connection = conexao;
cmd12.CommandText = sql12;
String dezembro =
cmd12.ExecuteScalar().ToString();

O ideal é a construção de uma classe e de uma função capaz de tratar da informação de forma mais simplificada.

/// <summary>
/// Get results from database
/// </summary>
/// <param name="query"></param>
/// <param name="param">Crucial Parameters[] As SqlParameter[]</param>
/// <param name="cn"></param>
/// <returns></returns>
public String get(string query, [Optional] SqlParameter[] param, SqlConnection cn)
{
SqlCommand cmd = new SqlCommand(query, cn);

if (param != null) { cmd.Parameters.AddRange(param); }
if (cn.State != ConnectionState.Open) { cn.Open(); }

return cmd.ExecuteScalar().ToString();
}

Onde a utilização bem como chamada desta função é muito mais fácil e perceptível e podemos, inclusive, passar parâmetros por referência. Também o ideal será utilizar um Dictionary para reter os valores.


DBHandler db = new DBHandler();

/* Dictionary TKey, TValue */
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.add("Janeiro", db.get("SELECT SUM(Janeiro) AS Janeiro FROM KmsAnuais", null, connection));

/* Com parâmetros */
SqlParameter[] sqlParams = new SqlParameter[] {
 new SqlParameter("@id_cliente", Convert.ToInt32(textBox1.Text)),
};
dict.add("Agosto", db.get("SELECT SUM(Agosto) AS Agosto FROM KmsAnuais WHERE id_cliente = @id_cliente", sqlParams, connection));

Ainda podíamos simplificar mais o processo passando directamente a connection para a classe.

Para concluir, como disse no inicio, o meu objectivo não é criticar o tempo e esforço despendido pela a autora do artigo, mas sim salientar que numa revista devem estar incutidas as boas práticas de código, porque a revista é uma referência.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
apocsantos    211
apocsantos

Bom dia,

Obrigado pela criticia. Em muitos aspectos tens razão, e para quem já tem experiência em C# faz todo sentido, mas para quem está a dar os primeiros passos, muita coisa é "confusa".

Sinceramente eu evito usar databindings, prefiro escrever tudo "à pata", e não vejo onde dê "barraca". Alias para mim os databindings são um "wizard" que consome demaisados recursos. Até à presente data, nunca tive problemas em fazer as coisas "à pata" e nunca me deu barraca. Não estou imune a ela, mas neste aspecto, confesso que não entendi bem o motivo pelo qual se preterir databindings em vez de "código feito à pata".

Quanto ao SQL, sim os parametros seriam porreiros, e já que se fala em segurança, bem o ideial seria armazenar os dados da connection string cifrados com uma hash por exemplo, num ficheiro, tipo o app.conf ou outro. Assim evitava-se ter de alterar código, quando se pretende-se alterar a connection-string e ela deixava de estar "explicita" na source (pelo menos o login e pass).

Tens razão, a revista deve ser uma referência, e deve abordar sempre as melhores práticas. Mas neste momento também creio que compeenderás que não temos assim tantos autores disponiveis para escrever artigos.

Agradeço o comentário construtivo e aproveito para te convidar a escrever para a revista!

Cordiais cumprimentos,

Apocsantos


"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

assinatura.jpg

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
bioshock    169
bioshock

Viva,

Bom dia,

Obrigado pela criticia. Em muitos aspectos tens razão, e para quem já tem experiência em C# faz todo sentido, mas para quem está a dar os primeiros passos, muita coisa é "confusa".

Sim claro, daí até ter salientado o esforço e tempo despendido para escrever o artigo. Mas não há ninguém que avalia o conteúdo antes de ser publicado? Conheço duas ou três pessoas, tu incluído, do staff da revista que têm experiência em C# e que poderia ter sugerido outro tipo de abordagem à autora (pelo menos é assim que penso que as coisas funcionam).

Sinceramente eu evito usar databindings, prefiro escrever tudo "à pata", e não vejo onde dê "barraca". Alias para mim os databindings são um "wizard" que consome demaisados recursos. Até à presente data, nunca tive problemas em fazer as coisas "à pata" e nunca me deu barraca. Não estou imune a ela, mas neste aspecto, confesso que não entendi bem o motivo pelo qual se preterir databindings em vez de "código feito à pata".

Esquecendo que o artigo é um exemplo simples de aplicação, os databindings podem (mas não devem) ser utilizados nas seguintes circunstâncias:

  1. Aplicações muito simples

E chega. :cheesygrin:

Agora os contras:

  1. Quando o método de actualização (UPDATE) ou inserção (INSERT) é feito pela via dos bindings, os valores são guardados num sistema temporário e não fixos nas tabelas. Para detectares esta anomalia, basta que após a inserção ou actualização, mexas em alguma parte do teu código e voltes a correr a aplicação.
  2. Não tens controlo total sobre o código, logo não o consegues optimizar.
  3. A interacção entre dados de tabelas diferentes passa a ser um desafio (relações).
  4. Debug do código.
  5. Não fazes a mínima ideia do tipo de query que está a ser executado, nem do código necessário para isso.

E certamente haverão mais..mas eu deixei de utilizar os bindings nessa altura. :D

Um pouco mais a sério: qualquer pessoa é livre de utilizar o sistema que melhor lhe convêm, mas se essa pessoa apenas e só conhecer os wizards, pessoalmente acredito que não faz em pleno ideia do que está a fazer.

Quanto ao SQL, sim os parametros seriam porreiros, e já que se fala em segurança, bem o ideial seria armazenar os dados da connection string cifrados com uma hash por exemplo, num ficheiro, tipo o app.conf ou outro. Assim evitava-se ter de alterar código, quando se pretende-se alterar a connection-string e ela deixava de estar "explicita" na source (pelo menos o login e pass).

Para além do que sugeriste, também evita a string/variável se tornar repetitiva, tendo em conta que o source é sempre o mesmo.

Tens razão, a revista deve ser uma referência, e deve abordar sempre as melhores práticas. Mas neste momento também creio que compeenderás que não temos assim tantos autores disponiveis para escrever artigos.

Aqui tenho de te contrariar. Prefiro ter uma revista de 6 em 6 meses de qualidade do que mensalmente e pobre.

Agradeço o comentário construtivo e aproveito para te convidar a escrever para a revista!

Cordiais cumprimentos,

Apocsantos

Agradeço o convite, mas para isso precisava de algum tema do meu leque de conhecimentos (que é curto :D) Se encontrar algo decente e que ainda não tenha sido escrito, a proposta será feita. :thumbsup:

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
apocsantos    211
apocsantos

Boa tarde,

@Bioshock,

O staff da revista está extremamente reduzido, logo não existe um controlo de proximidade tão bom quando seria desejado. Por isso mesmo se mudou a periodicidade da revista de bimestral para trimestral, e mesmo assim acredita a tarefa de rever tudo não é fácil.

Eu não analisei o artigo em detalhe, por falta de tempo, mas deveria ter feito. Assumo essa falha que é minha. Eu programo C# todos os dias, pelo menos umas 10h por dia, e tinha mais que obrigação de ver o artigo com atenção.

De futuro estarei mais atento ao que for publicado.

Tens razão sobre os databindings! Eu "detesto", alais deixei de usar pouco depois de ter experimentado. Mas cada vez mais vejo pessoal "dependente" deles, ao ponto de não saberem escrever uma connection string e pior nem um select simples sem clausulas... Imagina!

O convite foi sincero! Podias escrever um artigo estilo "how-to" para o pessoal que quer começar a programar C#, mas "com boas práticas e segundo o paradigma de OOP" e não "C# em forma "hibrida" com tiques que OOP e Procedimental". Creio que entendes o que quero dizer.

Eu com a falta de tempo com que ando, não sei se conseguirei escrever a tempo, mas pelo que tenho visto nos teus posts sobre C#, sinceramente acho que estás mais do que prnto para escrever um bom artigo estilo how-to sobre programação em C#, em que no final do artigo além de se perceberem boas práticas de C#, teria-se uma "mini-app" feita, algo simples, que até um iniciante entendesse, eventualmente com MySQL ou SQL Embeded. Que te parece ?

Cordiais cumprimentos,

Apocsantos


"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

assinatura.jpg

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
bioshock    169
bioshock

Olá,

Não me importo de todo fazer isso até porque tenho tempo mais do que suficiente depois do trabalho..e até porque já tenho saudades de passar umas horas com o C# :D.

A minha única dúvida reside no interesse por parte dos leitores. Não achas que esse tópico que referiste não está já muito falado?

Estive aqui à procura na Wiki e encontrei na secção do C# o artigo http://wiki.portugal-a-programar.pt/dev_net:csharp:poo_em_csharp, que até me parece que foi escrito para a revista (?) porque ao longo do artigo faz referência a "SoftRevistaProgramar".


Li com mais atenção o que escreveste e estás a sugerir a criação, como foi feito pela a autora do artigo da revista que mencionei neste tópico, de uma aplicação exemplo que proceda aos métodos de CRUD (Create, Read, Update & Delete) e que seja totalmente vocacionada para programação orientada a objectos?

Se sim, parece-me bem. Acho que ainda não foi feito.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
thoga31    594
thoga31

A minha única dúvida reside no interesse por parte dos leitores. Não achas que esse tópico que referiste não está já muito falado?

Eu não posso comentar acerca do assunto do tópico, mas posso deixar aqui uma nota acerca disto.

Há tópicos que podem estar muito falados, mas muitas vezes o que interessa é o como são abordados, e daí fazes do velho novo e fresco ;)

Cumprimentos.

Editado por thoga31

Knowledge is free!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
RitaPeres    3
RitaPeres

Bioshock antes de mais agradeço a tua critica construtiva, estou sempre aberta a isso e vou leva-la em consideração pois estou sempre disposta a aprender algo melhor!

E concordo também com o thoga31 "Há tópicos que podem estar muito falados, mas muitas vezes o que interessa é o como são abordados", força a avançar com o artigo!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
thoga31    594
thoga31

Já solicitei o artigo para aprovação. Se acham que pode haver outros tipos de assunto de interesse, apitem.

É bom ver mais autores interessados em colaborar na Revista :)

Os temas são propostos pelos próprios autores. Se te lembrares de um tema potencialmente interessante, força ;)


Knowledge is free!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
bioshock    169
bioshock

É bom ver mais autores interessados em colaborar na Revista :)

Os temas são propostos pelos próprios autores. Se te lembrares de um tema potencialmente interessante, força ;)

Temas temas tenho..mas pensar que será benéfico para quem os lê é que não tenho tanta certeza, porque a informação na internet é vasta e acessível a qualquer pessoa. O artigo pode diferenciar-se em alguns pontos mas o conteúdo no seu todo acaba por estar escarrapachado no google.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
thoga31    594
thoga31

Eu também tenho escrito artigos cujos assuntos estão na sua maioria escarrapachados no Google, mas isso não me impediu de os escrever e até de já ter ficado no Top 3 de melhores artigos. ;)

As pessoas gostam de ver estes assuntos abordados na Revista pois é considerado um local com conteúdo (ainda) de confiar.

Na Internet encontras muita coisa, mas é preciso filtrar muito bem. Há lá com cada coisa que valha-nos Nossa Senhora da Internet. :D

Editado por thoga31

Knowledge is free!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
bioshock    169
bioshock

Sim concordo. Outro dos problemas poderá ser o conteúdo que se encontra estar em inglês e para algumas pessoas poderá não ser tão acessível.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.