.NET

26 dez, 2017

VB .NET – Enviando SMS – criando um projeto mais robusto

Publicidade

Neste artigo, vou mostrar como aplicar boas práticas ao projeto de envio de SMS usando o padrão Strategy.

No artigo anterior eu mostrei como enviar mensagens SMS usando o serviço da ViaNett com a linguagem VB .NET.

Criamos uma conta na ViaNett. Em seguida, criamos uma aplicação Windows Forms, referenciamos o web service e enviamos mensagens SMS para um celular. Como o objetivo era apenas mostrar como enviar mensagens SMS, podemos dizer que a aplicação funciona.

Se a aplicação for vista como apenas um protótipo de testes tudo bem. Mas se desejarmos criar uma aplicação mais robusta e aderente às boas práticas de programação, não está aderente aos princípios SOLID, e, para contotnar isso, vamos ter que alterar muita coisa em nosso código.

O que há de errado com o nosso projeto?

  1. O projeto fere princípio da responsabilidade única ou SRP, pois apresenta muitas responsabilidades reunidas na camada de interface do usuário;
  2. O nosso código não esta aderente ao príncipio Aberto-Fechado ou Open Close, pois qualquer nova implementação vai requerer alteração no código;
  3. Não estamos programando para uma interface e sim para uma implementação;
  4. Não estamos usando a injeção de dependência para termos um baixo acoplamento entre os objetos usados.

Esses são alguns dos problemas que podemos identificar no código usado.

Imagine que agora precisamos enviar mensagens SMS usando o serviço de outra empresa. Como faríamos? Basta colocar um if no código e pronto? Pensando e agindo assim, o seu código vai requerer uma constante manutenção e pode apresentar diversos problemas no futuro. Vamos, então, mostrar como melhorar o nosso projeto.

Analisando o problema e se antecipando a mudanças

Para não tornar o problema muito abrangente, vou focar apenas na tarefa de enviar mensagens SMS.

Focando nisso, podemos antever que temos diversos opções para realizar essa tarefa e cada opção vai ter, assim, a sua implementação no código. Podemos enviar SMS usando um modem 3G ou o serviço da ViaNett, da Twilio, da Ipipi, da LocaSMS (Brasil), da Zenia (Brasil) etc.

Então, vamos ter algoritmos diferentes para cada implementação. Pensando nisso, podemos usar o padrão de projeto Estratégia ou Strategy. Eu já apresentei esse padrão neste artigo: Strategy – Macoratti.net.

Apenas para constar: “O padrão Strategy define uma familia de algoritmos intercambiáveis de forma que estes sejam independentes dos clientes que os utilizam”.

Resumindo:

  • Objetivo: Encapsular um algoritmo em um objeto;
  • Fornecer interfaces genéricas o suficiente para suportar uma variedade de algorítmos;
  • Facilitar a escolha e troca (intercâmbio) de algoritmos criados com uma mesma função.

Implementando o padrão Strategy

Vamos abrir o projeto criado no artigo anterior e criar uma pasta chamada Service no projeto.

A seguir, vamos criar uma interface chamada IEnviaSMS onde vamos definir o método EnviarSMS  conforme mostrado a seguir:

Public Interface IEnviaSMS
    Sub EnviaSMS(telefone As Long, mensagem As String)
End Interface

Estamos agora programando para um interface e veremos que isso vai desacoplar os objetos usados em nossa aplicação.

Vamos agora criar na pasta Service a classe EnviaSMSViaNett que vai implementar essa interface:

Public Class EnviaSMSViaNett
    Implements IEnviaSMS
    Public Sub EnviaSMS(telefone As Long, mensagem As String) Implements IEnviaSMS.EnviaSMS
        Try
            Dim usuario As String = ""
            Dim senha As String = ""
            Using ViaNettClient = New ViaNett.CPAWebServiceSoapClient("CPAWebServiceSoap12")
                Dim Resultado = ViaNettClient.SendSMS_Simple1(usuario, senha, telefone, mensagem)
            End Using
        Catch
            Throw
        End Try
    End Sub
End Class

Neste código, estamos isolando a implementação específica da ViaNett em uma classe encapsulando, assim, o nosso código. Qualquer alteração na metodologia da ViaNett vai afetar somente esta classe.

Se no futuro você precisar enviar SMS usando outro serviço, como o da LocaSMS que veremos no próximo artigo, basta criar uma nova classe e implementar a mesma interface. Assim, nosso código ficou aderente ao princípio Open-Closed, pois agora podemos estender o comportamento do nossa aplicação sem ter que modificar código.

Além disso, isso vai facilitar os testes unitários da nossa aplicação.

Vamos criar no projeto uma classe chamada Comunicacao, que fara o papel da Strategy com o seguinte código:

Public Class Comunicacao
    Dim _enviaSMS As IEnviaSMS
    Sub New(enviaSMS As IEnviaSMS)
        _enviaSMS = enviaSMS
    End Sub
    Public Sub EnviaMensagemSMS(fone As Long, msg As String)
        _enviaSMS.EnviaSMS(fone, msg)
    End Sub
End Class

Observe que não temos nenhum acoplamento forte no código desta classe, pois no construtor da classe estamos injetando uma instância do serviço para enviar SMS definido na interface IEnviaSMS.

Agora, só falta definir o código no formulário Form1.vb que é a nossa interface com o usuário. Nossa interface agora não sabe como enviar SMS, ela apenas usa a classe Comunica que é responsável por realizar essa tarefa. Qualquer alteração na metodologia de enviar SMS não vai afetar nossa interface.

Veja como ficou o código:

Imports System.Text.RegularExpressions
Public Class Form1
    Private Sub btnEnviarSMS_Click(sender As Object, e As EventArgs) Handles btnEnviarSMS.Click
        Dim fone As Long = 0
        Dim msg As String = ""
        If Not ValidaTelefone(txtTelefone.Text) Then
            MessageBox.Show("Número de telefone inválido. Use o formato 55XX999999999.")
            txtTelefone.Text = ""
            txtTelefone.Focus()
            Return
        Else
            fone = Convert.ToInt64(txtTelefone.Text.Replace("+", String.Empty))
        End If
        If String.IsNullOrEmpty(txtMensagem.Text) Then
            MessageBox.Show("Informe a mensagem a ser enviada ")
            txtMensagem.Focus()
            Return
        Else
            msg = txtMensagem.Text
        End If
        Try
           Dim comunica As Comunicacao
         comunica = New Comunicacao(New EnviaSMSViaNett)
         comunica.EnviaMensagemSMS(fone, msg)
            MessageBox.Show("Mensagem enviada para  : " & txtTelefone.Text)
        Catch ex As Exception
            MessageBox.Show("Erro : " & ex.Message)
        End Try
    End Sub
    Function ValidaTelefone(fone As String) As Boolean
        Dim pattern As String = "^[0-9]*quot;
        'cria o objeto regex
        Dim check As New Regex(pattern)
        Dim valid As Boolean = False
        'verifica se um valor foi fornecido e se é maior que 8 caracteres
        If Not String.IsNullOrEmpty(fone) And fone.Length > 8 Then
            valid = check.IsMatch(fone)
        Else
            valid = False
        End If
        Return valid
    End Function
End Class

É claro que poderíamos continuar a aplicar outros padrões (como a injeção de dependência), mas com apenas essas alterações nosso projeto ficou muito melhor

Na próxima parte do artigo vou mostrar como enviar SMS usando o serviço da LocaSMS que é uma empresa localizada no Brasil.