c#

...now browsing by tag

 
 

Kinect Hack

Quinta-feira, Fevereiro 2nd, 2012

33ª Edição - Fevereiro 2012

Para esta edição da Revista Programar, resolvi escrever um artigo sobre um dispositivo de hardware que está a mudar a forma como os utilizadores interagem com  jogos e  aplicações.

O Kinect é um dispositivo para a consola Microsoft Xbox 360, que através da detecção de movimentos e gestos realizados pelo utilizador ou até através do reconhecimento por voz, permite que o leitor consiga interagir com a consola e com os jogos de vídeo que suportam este hardware de uma forma natural, substituindo assim os controlos tradicionais que as consolas disponibilizam.
Foi anunciado pela primeira vez em Junho de 2009 conferência E3 sob o nome de código “Natal”. Colocado à venda em Novembro de 2010, o Kinect garantiu um lugar na história, em apenas 60 dias foram comercializados 8 milhões de unidades.
À primeira vista, o Kinect assemelha-se a uma webcam com um formato não muito convencional, mas na verdade, trata-se de muito mais do que isso. É composto por uma câmara RGB, um projector de raios IR que em conjunto com uma segunda câmara monocromática de IR constrói a informação em 3D com os metadados e um microfone vectorial (composto por quatro microfones colocados estrategicamente no dispositivo), que o tornam capaz de isolar e identificar as vozes dos vários jogadores e, para finalizar, possui um pequeno motor que lhe permite ajustar automaticamente o seu ângulo de visão para detectar todos os jogadores presentes.
As características técnicas que o Kinect apresenta a um preço acessível, suscitaram imediatamente muito interesse a uma comunidade que reconheceu de imediato as potencialidades que um dispositivo como este proporciona.
Sendo assim, ainda durante o mês de lançamento, uma empresa ofereceu uma recompensa a quem conseguisse desenvolver um driver open-source que permitisse o Kinect ser utilizado foram do seu âmbito, ou seja, fora do ecossistema da Xbox 360, para que o dispositivo pudesse ser utilizado para outros fins que não o entretenimento.
Apenas alguns dias após o seu lançamento, foi disponibilizado um driver para o Sistema Operativo Linux (Libfreenect) que permitia a utilização tanto da câmara RGB como dos sensores de profundidade 3-D. Em Dezembro do mesmo ano, a empresa PrimeSense, que é proprietária de tecnologia semelhante à apresentada pelo Kinect, lançou a sua própria versão do driver Open-Source para Kinect, bem como um Middleware dotado de um conjunto de funcionalidades até então apenas disponíveis na consola da Microsoft, como a capacidade de detecção de gestos e tracking de indivíduos.

Toda esta comoção gerada à volta do Kinect e a sua utilização fora do seu ambiente natural, levou à criação da organização sem fins lucrativos OpenNI (Open Natural Interaction) e em última instância, pressionou a Microsoft para relevar/alterar os seus planos para o Kinect e disponibilizar o Microsoft Kinect SDK.
Assim, o leitor tem ao seu dispor a escolha entre duas soluções para desenvolver as suas aplicações com o Kinect, a Framework OpenNI ou o Kinect SDK da Microsoft, atualmente em versão Beta, no entanto já foi anunciado que a versão comercial vai estar disponível em Fevereiro de 2012, acompanhada de uma nova versão de hardware, suportado oficialmente Microsoft.

Para ler mais sobre este e sobre outros temas, não deixe de descarregar a Revista Programar Nº33, disponível aqui.

kinect_hack_01.png

A aplicação descrita no decorrer de este artigo encontra-se disponível em http://kinecthack.codeplex.com

 

Artigos incluídos nesta edição:

Tema de capa
Kinect Hack

A programar
Geração de Números Aleatórios – Parte 3
Programação Orientada aos Objectos em Pascal
Herança com JavaScript
CORE DUMP – Ambientes Produtivos
Enigmas de C#: Disposable Structs
SQL Azure Federations na Pratica

Visual (Not) Basic
VISUAL (NOT) BASIC -Iterators

Comunidades
BizTalk Server – Princípios Básicos dos Mapas – Parte 2
Desenvolvimento em SharePoint 2010 – Parte 2

Silverlight & Model-View-ViewModel

Quinta-feira, Maio 26th, 2011

pic1

Existem várias formas diferentes de definir a camada de apresentação, pode-se seguir uma aproximação tradicional, na qual toda a responsabilidade da camada de apresentação se encontra na View ou então podemos seguir um pattern para prodecer à separação de responsabilidades da camada de apresentção.

A aproximação mais tradicional torna-se mais simples e criar permite rapidamente uma camada de apresentação. É ideal quando se trata de aplicações de pequena dimensão .

O problema é que não existem aplicações de pequena dimensão, algumas podem começar dessa forma, mas muito rapidamente crescem e transforma-se em uma dor de cabeça para qualquer equipa de manutenção, dando origem a mais uma “Black Box” passados alguns anos.

Para ajudar a solucionar esse tipo de problema recorrente, nasceram algumas patterns que nos permitem estruturar de uma melhor forma a camada de apresentação das aplicações, entre elas estão o MVC (Model-View-Controller), MPV (Model-View-Presenter) e o MVVM (Model-View-ViewModel) que é o tema de este post.

Como não podemos deixar de falar em Silverlight ou WPF quando o tema é MVVM, vou apresentar um tutorial no qual demonstro como implementar MVVM no Silverlight.

O MVVM pretende estabelecer uma separação clara de responsabilidades na camada de apresentação, a View apenas é responsável pela User Interface, o Model detém as regras de negócio (classes de negócio, acesso a dados, etc) e o ViewModel é o responsável de fornecer à View apenas os dados que ela necessita e é também o ViewModel quem tem a responsabilidade de reagir aos eventos  gerados pela View.

Uma das grandes vantagens na utilização de um pattern como este, é que permite alterar completamente a UI apresentada ao utilizador sem que se torne necessário alterar mais do que a View, ou então, num caso mais extremo, partilhar o Model e o ViewModel e criar dois Front-End diferentes, como Silverlight e Windows Phone 7.

Vamos então ao que interessa, criar uma Demo de uma aplicação de gestão de Clientes, que apresenta a lista  de clientes de uma empresa e também permite adicionar um novos clientes à lista actual.

Vamos criar um novo projecto do tipo Silverlight Application no VS2010

image

 

Seleccionar a check-box “Host the Silverlight application in a new Web site”

image

 

Adicionar duas novas referências ao projecto Silverlight

image

 

Adicionar as referências à página MainPage.xaml

<UserControl x:Class="Silverlight_MVVM_Demo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"             

    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">

    </Grid>
</UserControl>

 

Vamos definir a View

image

Agora em XAML

<UserControl x:Class="Silverlight_MVVM_Demo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="Gray" Width="800" Height="600">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--DataGrid Definition-->
        <sdk:DataGrid Height="300" Grid.Row="0" BorderThickness="1"/>

        <!--Data Input Definition-->
        <sdk:Label
            Grid.Row="1"
            Height="28"
            HorizontalAlignment="Left"
            Margin="10,10,0,0"
            VerticalAlignment="Top"
            Width="171"
            Content="Adicionar novo cliente"
            FontFamily="Verdana"
            FontSize="13.333"
            FontWeight="Bold" />
        <TextBlock
            HorizontalAlignment="Left"
            Margin="80,59,0,0"
            Grid.Row="1"
            TextWrapping="Wrap"
            Text="Nome"
            VerticalAlignment="Top"/>
        <TextBox
            HorizontalAlignment="Left"
            Margin="80,79,0,0"
            Grid.Row="1"
            TextWrapping="Wrap"
            VerticalAlignment="Top"
            Width="245"/>
        <TextBlock
            HorizontalAlignment="Left"
            Margin="80,120,0,0"
            Grid.Row="1"
            TextWrapping="Wrap"
            Text="NIF"
            VerticalAlignment="Top"/>
        <TextBox
            HorizontalAlignment="Left"
            Margin="80,140,0,136"
            Grid.Row="1"
            TextWrapping="Wrap"
            Width="245"
            d:LayoutOverrides="Height"/>
        <TextBlock
            HorizontalAlignment="Left"
            Margin="80,0,0,98"
            Grid.Row="1"
            TextWrapping="Wrap"
            Text="Telemóvel"
            VerticalAlignment="Bottom"/>
        <TextBox
            HorizontalAlignment="Left"
            Margin="80,0,0,70"
            Grid.Row="1"
            TextWrapping="Wrap"
            Width="245"
            VerticalAlignment="Bottom"/>
        <TextBlock
            Margin="0,0,229,98"
            Grid.Row="1"
            TextWrapping="Wrap"
            Text="Número de Cliente"
            VerticalAlignment="Bottom"
            HorizontalAlignment="Right"
            Width="111"/>
        <TextBox
            Margin="0,0,96,70"
            Grid.Row="1"
            TextWrapping="Wrap"
            VerticalAlignment="Bottom"
            HorizontalAlignment="Right"
            Width="245"/>
        <TextBlock
            Margin="0,120,321,0"
            Grid.Row="1"
            TextWrapping="Wrap"
            Text="Fax"
            VerticalAlignment="Top"
            HorizontalAlignment="Right"
            RenderTransformOrigin="-1.579,0.438"/>
        <TextBox
            Margin="0,140,96,136"
            Grid.Row="1"
            TextWrapping="Wrap"
            d:LayoutOverrides="Height"
            HorizontalAlignment="Right"
            Width="245"/>
        <TextBlock
            Margin="0,59,293,0"
            Grid.Row="1"
            TextWrapping="Wrap"
            Text="Telefone"
            VerticalAlignment="Top"
            HorizontalAlignment="Right"/>
        <TextBox
            Margin="0,79,96,0"
            Grid.Row="1"
            TextWrapping="Wrap"
            VerticalAlignment="Top"
            HorizontalAlignment="Right"
            Width="245"/>
        <Button
            Content="Adicionar"
            HorizontalAlignment="Right"
            Margin="0,0,8,8"
            Grid.Row="1"
            VerticalAlignment="Bottom"
            Width="75"/>
    </Grid>
</UserControl>

 

Criar a estrutura de directórios

image

 

De seguida adicionar ao directório Model uma nova classe com o nome Cliente.cs com a seguinte estrutura

namespace Silverlight_MVVM_Demo.Model
{
    public class Cliente
    {
        public string ClienteID { get; set; }
        public string Nome { get; set; }
        public string NIF { get; set; }
        public string Telefone { get; set; }
        public string Telemovel { get; set; }
        public string Fax { get; set; }

    }
}

Vamos adicionar duas classe base que implementam os Interfaces ICommand e INotifyPropertyChanged.

Classe RelayCommand

using System;
using System.Windows.Input;

namespace Silverlight_MVVM_Demo.ViewModel
{
    public class RelayCommand : ICommand
    {
        private Action<Object> _handler;
        public RelayCommand(Action<Object> handler)
        {
            _handler = handler;
        }

        private bool _isEnabled = true;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                if (value != _isEnabled)
                {
                    _isEnabled = value;
                    if (CanExecuteChanged != null)
                    {
                        CanExecuteChanged(this, EventArgs.Empty);
                    }
                }
            }
        }

        public bool CanExecute(object parameter)
        {
            return IsEnabled;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            _handler(parameter);
        }
    }
}

Se seguirmos uma abordagem simplista, podemos olhar para o ICommand como o interface que permite o ViewModel receber notificações de eventos da View.

 

Classe ViewModelBase

namespace Silverlight_MVVM_Demo.ViewModel
{
    using System.ComponentModel;
    /*TODOS OS VIEWMODEL HERDAM DESTA CLASSE*/
    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler  PropertyChanged;
        public void RaisePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

Vamos herdar todos os ViewModel da classe ViewModelBase para simplificar as notificações quando existem alterações nos conteúdos das propriedades, assim apenas vai ser necessário chamar o método RaisePropertyChanged(“NomeDaPropriedade”) para notificar o ViewModel e a View caso tal seja necessário.

 

De seguida criamos a classe de ViewModel

namespace Silverlight_MVVM_Demo.ViewModel
{
    using Model;
    using System.Collections.ObjectModel;

    public class MainPageViewModel : ViewModelBase
    {
        #region View Data Collection
        private ObservableCollection<Cliente> _ClientList;
        public ObservableCollection<Cliente> ClientList
        {
            get { return _ClientList; }
            set
            {
                _ClientList = value;
                /*Notificar alteração de conteúdo*/
                RaisePropertyChanged("ClientList");
            }
        }
        #endregion

        /*Propriedades utilizadas na View*/
        #region View Properties
        private string _ClientID;
        public string ClientID
        {
            get { return _ClientID; }
            set
            {
                _ClientID = value;
                /*Notificar alteração de conteúdo*/
                RaisePropertyChanged("ClientID");
            }
        }

        private string _ClientName;
        public string ClientName
        {
            get { return _ClientName; }
            set
            {
                _ClientName = value;
                /*Notificar alteração de conteúdo*/
                RaisePropertyChanged("ClientName");
            }
        }

        private string _ClientNIF;
        public string ClientNIF
        {
            get { return _ClientNIF; }
            set
            {
                _ClientNIF = value;
                /*Notificar alteração de conteúdo*/
                RaisePropertyChanged("ClientNIF");
            }
        }

        private string _ClientPhone;
        public string ClientPhone
        {
            get { return _ClientPhone; }
            set
            {
                _ClientPhone = value;
                /*Notificar alteração de conteúdo*/
                RaisePropertyChanged("ClientPhone");
            }
        }

        private string _ClientFax;
        public string ClientFax
        {
            get { return _ClientFax; }
            set
            {
                _ClientFax = value;
                /*Notificar alteração de conteúdo*/
                RaisePropertyChanged("ClientFax");
            }
        }

        private string _ClientCell;
        public string ClientCell
        {
            get { return _ClientCell; }
            set
            {
                _ClientCell = value;
                /*Notificar alteração de conteúdo*/
                RaisePropertyChanged("ClientCell");
            }
        }
        #endregion

        #region Commands
        public RelayCommand LoadClientData { get; set; }
        public RelayCommand SubmitForm { get; set; }
        #endregion

        public MainPageViewModel()
        {
            /*Comandos que o ViewModel vai reconhecer da View*/
            this.LoadClientData = new RelayCommand(MockClientList);
            this.SubmitForm = new RelayCommand(Submit);
        }

        /// <summary>
        /// Adiciona um novo cliente
        /// </summary>
        /// <param name="parameter"></param>
        protected void Submit(object parameter)
        {
            /*
             Como utilizamos as notificações quando
             é alterado o conteúdo de uma propriedade
             da View, já temos no ViewModel todos os
             dados.
             */
            var c = new Cliente
            {
                ClienteID = ClientID,
                Fax = ClientFax,
                NIF = ClientNIF,
                Nome = ClientName,
                Telefone = ClientPhone,
                Telemovel = ClientCell
            };

            ClientList.Add(c);

            ClientID = string.Empty;
            ClientFax = string.Empty;
            ClientCell = string.Empty;
            ClientName = string.Empty;
            ClientPhone = string.Empty;
            ClientNIF = string.Empty;
        }

        /// <summary>
        /// Dados iniciais da DataGrid
        /// </summary>
        /// <param name="parameter"></param>
        public void MockClientList(object parameter)
        {
            ClientList = new ObservableCollection<Cliente>();

            for (int i = 0; i < 3; i++)
            {
                var c = new Cliente{
                 ClienteID=i.ToString(),
                 Fax="123456789",
                 NIF="789456123",
                 Nome="Client "+i,
                 Telefone="5556623",
                 Telemovel="3237656511"
                };

                ClientList.Add(c);
            }
        }
    }
}

Agora ja temos definidas as três componentes do MVVM, apenas falta ligar a View com o ViewModel, e isso é conseguido através do Databinding, que o Silverlight nos proporciona para facilitar essa operação. Vamos então completar a página MainPage.xaml com os bindings.

<UserControl x:Class="Silverlight_MVVM_Demo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    xmlns:vm="clr-namespace:Silverlight_MVVM_Demo.ViewModel"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <!--DATACONTEXT DEFINITION-->
    <UserControl.DataContext>
        <!--Link entre o ViewModel e a View-->
        <vm:MainPageViewModel/>
    </UserControl.DataContext>

    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <!--Quando a página é carregada é executado o comando LoadClientData-->
            <i:InvokeCommandAction Command="{Binding LoadClientData}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>

    <Grid x:Name="LayoutRoot" Background="Gray" Width="800" Height="600">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--DataGrid Definition-->
        <sdk:DataGrid Height="300" Grid.Row="0" BorderThickness="1"/>

        <!--Data Input Definition-->
        <sdk:Label
            Grid.Row="1"
            Height="28"
            HorizontalAlignment="Left"
            Margin="10,10,0,0"
            VerticalAlignment="Top"
            Width="171"
            Content="Adicionar novo cliente"
            FontFamily="Verdana"
            FontSize="13.333"
            FontWeight="Bold" />
        <TextBlock
            HorizontalAlignment="Left"
            Margin="80,59,0,0"
            Grid.Row="1"
            TextWrapping="Wrap"
            Text="Nome"
            VerticalAlignment="Top"/>
        <TextBox
            Text="{Binding ClientName, Mode=TwoWay}"
            HorizontalAlignment="Left"
            Margin="80,79,0,0"
            Grid.Row="1"
            TextWrapping="Wrap"
            VerticalAlignment="Top"
            Width="245"/>
        <TextBlock
            HorizontalAlignment="Left"
            Margin="80,120,0,0"
            Grid.Row="1"
            TextWrapping="Wrap"
            Text="NIF"
            VerticalAlignment="Top"/>
        <TextBox
            Text="{Binding ClientNIF, Mode=TwoWay}"
            HorizontalAlignment="Left"
            Margin="80,140,0,136"
            Grid.Row="1"
            TextWrapping="Wrap"
            Width="245"
            d:LayoutOverrides="Height"/>
        <TextBlock
            HorizontalAlignment="Left"
            Margin="80,0,0,98"
            Grid.Row="1"
            TextWrapping="Wrap"
            Text="Telemóvel"
            VerticalAlignment="Bottom"/>
        <TextBox
            Text="{Binding ClientCell, Mode=TwoWay}"
            HorizontalAlignment="Left"
            Margin="80,0,0,70"
            Grid.Row="1"
            TextWrapping="Wrap"
            Width="245"
            VerticalAlignment="Bottom"/>
        <TextBlock
            Margin="0,0,229,98"
            Grid.Row="1"
            TextWrapping="Wrap"
            Text="Número de Cliente"
            VerticalAlignment="Bottom"
            HorizontalAlignment="Right"
            Width="111"/>
        <TextBox
            Text="{Binding ClientID, Mode=TwoWay}"
            Margin="0,0,96,70"
            Grid.Row="1"
            TextWrapping="Wrap"
            VerticalAlignment="Bottom"
            HorizontalAlignment="Right"
            Width="245"/>
        <TextBlock
            Margin="0,120,321,0"
            Grid.Row="1"
            TextWrapping="Wrap"
            Text="Fax"
            VerticalAlignment="Top"
            HorizontalAlignment="Right"
            RenderTransformOrigin="-1.579,0.438"/>
        <TextBox
            Text="{Binding ClientFax, Mode=TwoWay}"
            Margin="0,140,96,136"
            Grid.Row="1"
            TextWrapping="Wrap"
            d:LayoutOverrides="Height"
            HorizontalAlignment="Right"
            Width="245"/>
        <TextBlock
            Margin="0,59,293,0"
            Grid.Row="1"
            TextWrapping="Wrap"
            Text="Telefone"
            VerticalAlignment="Top"
            HorizontalAlignment="Right"/>
        <TextBox
            Text="{Binding ClientPhone, Mode=TwoWay}"
            Margin="0,79,96,0"
            Grid.Row="1"
            TextWrapping="Wrap"
            VerticalAlignment="Top"
            HorizontalAlignment="Right"
            Width="245"/>
        <Button
            Content="Adicionar"
            HorizontalAlignment="Right"
            Margin="0,0,8,8"
            Grid.Row="1"
            VerticalAlignment="Bottom"
            Width="75">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <!--Quando chamado o evento click, é executado o commando SubmitForm no ViewModel -->
                    <i:InvokeCommandAction Command="{Binding SubmitForm}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </Grid>
</UserControl>


E Finalmente temos a aplicação a funcionar com MVVM e nenhum código na View a não ser a definição do User Interface.

image

 

Solução VS2010 do projecto executado neste tutorial disponível aqui para download.

Referências:

http://www.silverlight.net/learn/videos/silverlight-4-videos/mvvm-introduction/

http://www.silverlight.net/learn/tutorials/silverlight-4/using-the-mvvm-pattern-in-silverlight-applications/

http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090016

Comunidade NetPonto na UTAD – Evento Presencial

Segunda-feira, Janeiro 31st, 2011

No dia 12/02/2011 a Comunidade NetPonto irá reunir-se em Vila Real pela 1ª vez, na Universidade de Trás-os-Montes e Alto Douro (UTAD). Para participar, efectue o registo de acordo com as instruções abaixo.

Agenda

13:45  – Recepção dos participantes

14:00 – Boas-vindas e apresentação da Comunidade NetPonto

14:10 – Desenvolvimento de Aplicações para Android em C# com o MonoDroidBruno Pires

15:40 – Integração Contínua com o HudsonBruno Lopes

17:10 – Coffee-break

17:40 – Desenvolvimento de Jogos em XNA para Windows Phone 7Virgílio Esteves e Andreas Vilela

19:10 – Painel de Discussão


Registo / Inscrição

Para participar, basta efectuar a inscrição através do site http://netponto-utad-fevereiro-2011.eventbrite.com/.
A entrada é gratuita.
Qualquer dúvida / esclarecimento, entre em contacto connosco.


Local

UTAD (Vila Real) – Engenharias I
Quinta de Prados
5001-801 Vila Real

Clique para ampliar o mapa.

Trajecto aconselhado desde Lisboa, Coimbra, Évora, Beja, Faro:
http://bit.ly/ehzMEE
Trajecto aconselhado desde o Porto:
http://bit.ly/fcgQIl
Trajecto aconselhado desde Portalegre, Castelo Branco, Guarda:
http://bit.ly/dHHt07

Sessões Técnicas Portugal GTUG

Quarta-feira, Novembro 10th, 2010

Google_GTUG_Pt

Nos dias 16 e 30 de Novembro vão-se realizar na TB Store duas sessões técnicas da Comunidade GTUG(Google Technical User Group) Portugal.

Na sessão de dia 30 de Novembro vou ter o prazer se estar presente na qualidade de orador com o tema “Como desenvolver aplicações Android e iOS com C#”.

 

Introdução:

Há pouco mais de um ano, a Novell colocou no mercado um produto, o MonoTouch.

Este produto permite aos developers com conhecimentos em .NET e C# reutilizar código e conhecimento bem como assegurar uma transição mais suave para a plataforma Apple iOS.

Dado o sucesso do produto no mercado, a Novell está a preparar uma proposta semelhante ao MonoTouch, mas desta vez dirigida aos developers da plataforma Android.

O MonoDroid encontra-se neste momento em Closed Beta Preview, no entanto vai ser possível demonstrar alguns dos detalhes e potencialidades do produto.

 

Podem efectuar o registo em http://portugalgtug-lisboa-2010-11-30.eventbrite.com/ e obter mais informações em http://portugal-gtug.blogspot.com/

Herança, Polimorfismo e Classes Abstractas – Quick Tips #2

Terça-feira, Julho 6th, 2010

Quando, a nível profissional trabalhamos em certas áreas de negócio, por vezes torna-se muito complexo implementar alguns dos conceitos básicos de POO (Programação Orientada a Objectos) que aprendemos.

Nestes casos é necessário fazer um esforço extra, abstrairmo-nos dos problemas de implementação das regras de negócio, dos sistemas existentes e desenvolver uma plataforma que, além de conciliar as regras de negócio e regras de arquitectura de software, tira partido das melhores funcionalidades oferecidas pela linguagem a ser utilizada.

É certamente o caminho para uma manutenção acessível e escalável, que vai garantir a longevidade da plataforma.

Herança e Polimorfismo são alguns dos conceitos mais importantes de POO, vou falar um pouco de cada um e apresentar uma pequena demonstração.

 

Herança

Por vezes as próprias regras de negócio estão agrupadas em famílias, temos que aproveitar esse factor a nosso favor e desenvolver uma estrutura do mesmo tipo por forma a que a arquitectura final seja consistente.

Recorrendo à herança entre classes podemos desenvolver uma estrutura de classes agrupadas por família, e que por sua vez têm informação organizada e transversal a toda a aplicação.

Vamos olhar para um exemplo real:

public class Angariacao
{
    public string Nome          { get; set; }
    public string Morada        { get; set; }
    public string EpocaBaixa    { get; set; }
    public string EpocaAlta     { get; set; }
    public string Enquadramento { get; set; }
}

public class CasaDeCampo : Angariacao
{
    public int    Capacidade    { get; set; }
    public string Tipologia     { get; set; }
}

public class HotelRural : Angariacao
{
    public string Actividades   { get; set; }
    public string Exterior      { get; set; }
    public string AreaSocial    { get; set; }
}

 

Como podemos verificar facilmente depois de analisar o código apresentado anteriormente, existe uma lógica para agrupar todas as propriedades partilhadas pelas classes CasaDeCampo e HotelRural.

A maioria das propriedades que cada uma das classes teria, estão agora na classe Angariação e essas propriedades vão ser partilhadas nas classes  CasaDeCampo e HotelRural através de herança.

Temos um grande número de vantagens ao utilizar este conceito de POO, uma delas é a fácil manutenção: caso se tenha que alterar/adicionar/remover uma propriedade na classe base, essa alteração é reflectida de forma automática em todas as classes que herdam da classe base.  Torna-se também mais rápido e eficiente adicionar novas classes que herdem da classe base, pois já existem nela implementadas muitas das funcionalidades básicas bem como as propriedades partilhadas que são transversais à família de classes.

 

Polimorfismo e Classes Abstractas

Polimorfismo significa “tomar várias formas”, quando utilizado em POO significa que uma assinatura de um método pode ter várias implementações diferentes.

Uma classe abstracta não pode ser instanciada, apenas define as propriedades e métodos que as classes filho que vão herdar.

Para exemplificar este conceito vamos recorrer às classes apresentadas no exemplo anterior e continuar a explorar o mesmo conceito:

//A classe passou a ser abstracta
public abstract class Angariacao
{
    public string Nome          { get; set; }
    public string Morada        { get; set; }
    public string EpocaBaixa    { get; set; }
    public string EpocaAlta     { get; set; }
    public string Enquadramento { get; set; }

    //Definição do método a ser implementado nas
    //classes que herdam de Angariacao
    public abstract void ImprimirTipoClasse();

}

public class CasaDeCampo : Angariacao
{
    public int    Capacidade    { get; set; }
    public string Tipologia     { get; set; }

    //Quando o método tem a assinatura abstract na classe base
    //é obrigatório implementar o override nas classes que herdam
    //da classe base
    public override void ImprimirTipoClasse()
    {
        Console.WriteLine(string.Format("Tipo: {0}", this.GetType()));
    }
}

public class HotelRural : Angariacao
{
    public string Actividades   { get; set; }
    public string Exterior      { get; set; }
    public string AreaSocial    { get; set; }

    //Quando o método tem a assinatura abstract na classe base
    //é obrigatório implementar o override nas classes que herdam
    //da classe base
    public override void ImprimirTipoClasse()
    {
        Console.WriteLine(string.Format("Tipo: {0}", this.GetType()));
    }
}

 

Neste momento temos definida a família angariação, que tem como base  a classe Angariação e filhos as classes CasaDeCampo e HotelRural.

A classe Angariação é abstract porque na lógica de negócio a implementar não existem objectos da classe base.

Como na classe base está declarado o método ImprimirTipoClasse com a assinatura abstract, a implementação de este método é obrigatória nas classes filho.

Para validar estes conceitos, criei um programa muito simples e que demonstra o potencial da Herança, Polimorfismo:

    class Program
    {
        static void Main(string[] args)
        {
            //lista de objectos da classe base
            var list = new List<Angariacao>();

            //adicionar à lista objectos que 
            //herdam da classe base
            list.Add(new CasaDeCampo());
            list.Add(new HotelRural());

            foreach (var item in list)
            {
                //Imprimir no ecrã o tipo de objecto
                //Demonstração final de Polimorfismo
                item.ImprimirTipoClasse();
            }

            Console.ReadKey();
        }
    }

Que resulta no seguinte ecrã quando se executa a aplicação:

heranca_e_polimorfismo

 

 

Para concluir, podemos verificar ao analisar a execução do programa que, embora a lista seja de objectos da classe base, podemos adicionar objectos que herdam da classe base, e quando invocamos o método ImprimirTipoClasse, o resultado é a execução do método que está definido classe filho.

Para criar um exemplo mais real, se a classe base tiver um método abstract que se chama AdicionarAngariacao, quando executado no programa da mesma forma que no exemplo acima demonstrado, iria ser adicionada uma Casa de Campo e um Hotel Rural ao sistema de acordo com as suas propriedades partilhadas e específicas, pois cada uma das classes filho implementa o método AdicionarAngariacao da forma mais conveniente.

ASP.NET Social Bookmarks

Quarta-feira, Janeiro 13th, 2010

SocialBookmarksO ASP.NET Social Bookmarks é um Web User Control que    permite partilhar informação com as mais variadas redes sociais.

Os utilizadores conseguem interagir de forma simples com o controlo, e para os programadores é um componente reutilizável, flexível e escalável.

O componente é implementado como qualquer outro controlo de ASP.NET, contém CSS, ícones, possui também de um método para executar a compressão de Url, bem como a utilização das API’s das redes sociais implementadas para permitir ao programador um processo simples e eficiente de  publicação de informação nas principais redes sociais.

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
    <link href="Stylesheet.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="SocialBookmarks" runat="server">
    <aspbook:Bookmarks ID="Bookmarks" runat="server"
        EnableViewState="False"
        ShowEmail="true" ShowTwitter="true" ShowFacebook="true"
        ShowFlickr="true" ShowPicasa="true"
        ShowGoogleBookmarks="true" ShowLinkedin="true"
        ShowMap="true" ShowFeeds="true"
        MyTitle="ASP.NET Social Bookmarks" ShowTitle="true"  />
    </form>
</body>
</html>

Além de ser simples e flexível, pode ser altamente customizado, possibilitando ao programador adicionar facilmente o acesso a novas redes sociais ou até novas funcionalidades.

As funcionalidades implementadas permitem publicar facilmente informação sem a necessidade de conhecer as API’s das redes sociais.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace AspNetSocialBookmarks
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Example();
        }

        public void Example()
        {
            Bookmarks.TweetToShare =
                    "Testing the new user control, ASP.NET Social Bookmarks";
            Bookmarks.TwitterUrlToShare = "http://www.blastersystems.com/blog";
            Bookmarks.TwitterUser = "brunoacpires";
            Bookmarks.TwitterTooltip = "Share on Twitter";
        }
    }
}

twitter

O ASP.NET Social Bookmarks Web User Control e o código fonte está disponível em http://socialbookmarks.codeplex.com/ sobre a licença LGPL.

Eventos e Delegates em .NET

Terça-feira, Novembro 24th, 2009

Este artigo tem como objectivo esclarecer o que é um delegate e um evento, bem como exemplificar a implementação e a sua utilização numa aplicação.

Delegates

Um delegate é um tipo de referência utilizado para encapsular um método com uma determinada assinatura.

Exemplo:


public delegate string DevolveStringDelegate();

Esta declaração de um delegate pode encapsular qualquer método que não tenha parâmetros de  entrada e devolva um objecto do tipo String.

 

Em exemplo de utilização de delegates

using System;
using System.Collections.Generic;
using System.Text;

namespace Delegates
{
    public class Program
    {
        //Declaração de um delegate que tem como assinatura 
        //uma variável do tipo String 
        delegate void testeDelegate(string s);

        static void Main(string[] args)
        {
            //texto que vai ser escrito na consola  
            string texto= "estou a ver um delegate a funcionar!";
            //Cria-se uma instância do delegate e no construtor passa-se 
            //como parâmetro o nome do método que se quer utilizar, neste  
            //caso o método é o metodoComAssinaturaString porque contém 
            //a mesma assinatura que o delegate, tem como parâmetro  
            //uma variável do tipo String e devolve void
            testeDelegate t = new testeDelegate(metodoComAssinaturaString);

            //invocação do método que o delegate está a referênciar 
            //caso esse método tenha parâmetros, estes são inseridos 
            //ao utilizar o método invoke do delegate 
            t.Invoke(texto);
        }

        public static void metodoComAssinaturaString(string texto)
        {
            Console.WriteLine(texto);
        }
    }
}

E ao executar o programa…

testeDelegate

 

Eventos

Agora que está esclarecido o que é um delegate e como se implementa, vamos utilizar esse conceito e avançar para a implementação de um evento.

Um evento é uma acção que é despoletada quando uma condição que está  estabelecida se torna verdadeira.

Diagrama_Eventos_e_Delegates

Seguindo o diagrama acima apresentado, vou dar um exemplo de um evento. Temos um calendário, como o google calendar (quem publica os eventos) por exemplo, que permite a inserção de uma reunião, depois configuramos o google calendar para nos enviar um e-mail a avisar da reunião (subscrever o evento), no entanto podemos não ter acesso ao e-mail na hora que está marcada a reunião, assim, configuramos o google calendar para nos enviar uma SMS para além do e-mail (subscrever o evento).

Assim, quando chega a hora da reunião recebemos o aviso por dois canais diferentes, email e SMS, e que contém a mesma informação (EventArgs) no entanto a fonte da informação é a mesma, o google calendar!

Vamos então demonstrar um exemplo prático

using System;
using System.Collections.Generic;
using System.Text;

namespace DelegatesAndEvents
{
    //classe que descreve a informação a ser publicada
    public class ProcessarInformacaoEventArgs : EventArgs
    {
        private int _progresso;

        public int progresso
        {
            get { return _progresso; }
            set { _progresso = value; }
        }

    }
}
using System;
using System.Collections.Generic;
using System.Text;

namespace DelegatesAndEvents
{
    //declaração do delegate que tem como parametro a 
    //classe ProcessarInformacaoEventArgs
    //que é onde vai ser guardada a informação que é 
    //enviada quando é disparado o evento
    public delegate void TickHandler(object sender,
        ProcessarInformacaoEventArgs p);

    //classe que publica o evento
    public class ProcessarInformacao
    {
        //declaração do evento que utiliza o 
        //delegate TickHandler
        public event TickHandler tick; 

        //Este método serve apenas de exemplo 
        //de processamento de informação
        public void ProcessarInfo()
        {
            long time = 100000000000;

            TimeSpan t = new TimeSpan(time);

            while (t.Ticks > 0)
            {
                t = t.Subtract(new TimeSpan(1000));
                long aux = time - t.Ticks;
                long res = (aux * 100) / time;

                //sempre que executa um ciclo, vai 
                //ser disparado um evento
                //que vai ser recebido por todas as 
                //classes que o subscreveram
                //e envia a informação processada 
                //por cada ciclo da estrutura
                //de decisão while
                OnTick((int)res);
            }
        }

        protected void OnTick(int p)
        {
            //chama o construtor com parametros da 
            //classe ProcessarInformacaoEventArgs
            //e invoca o evento com a informação que foi recebida
            ProcessarInformacaoEventArgs args = new ProcessarInformacaoEventArgs(p);
            tick(this,args);
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Text;

namespace DelegatesAndEvents
{
    //programa que subscreve o evento da classe ProcessarInformacao
    public class Program
    {
        static void Main(string[] args)
        {
            ProcessarInformacao p = new ProcessarInformacao();

            //Subscreve o evento
            p.tick += new TickHandler(p_tick);

            //Executar o processo que vai disparar o evento
            p.ProcessarInfo();
            Console.Read();
        }

        //Aqui é processada a informação enviada quando o evento é disparado
        static void p_tick(ProcessarInformacaoEventArgs p)
        {
            Console.WriteLine(p.progresso);
            Console.Clear();
        }
    }
}

 

Resultado da aplicação – Apresenta a percentagem de informação já processada.

testeEventos

Pode descarregar todos os projectos de este post aqui.

Demos desenvolvidas em VS2005.

Data Validator

Sábado, Outubro 31st, 2009

Biblioteca .NET de funções para executar a validação de números de identificação portugueses.

Este projecto tem como objectivo ajudar a optimizar o tempo que um programador utiliza a desenvolver código que é realmente importante para o projecto ao disponibilizar uma biblioteca de funções que permitem ao programador abstrair-se de tarefas que são repetitivas quando se desenvolve projectos em que é necessário executar validação da informação fornecida pelo utilizador.

Esta primeira versão permite:

- Validar o Nº de Bilhete de Identidade
- Validar o NIF (Número de Identificação Fiscal)
- Validar o NIB (Número de Identificação Bancária)
- Validar o IBAN (International Bank Account Number)
- Validar morada através dos serviços do CTT
- Obter morada através dos serviços do CTT

Envie as suas sugestões para bruno@blastersystems.com

Disponível para download no CodePlex:
http://datavalidator.codeplex.com

O operador Yield (C#)

Quarta-feira, Outubro 14th, 2009

O operador Yield decerto não dos mais utilizados no C#, no entanto pode em muitas situações simplificar o código produzido. Não é o operador de mais fácil compreensão que a linguagem C# disponibiliza ao programadores, no entanto é um operador extremamente útil em algumas situações.

Ele é utilizado num método para ajudar este a retornar uma instância do tipo IEnumerable ou IEnumerator.

Não pode ser utilizado num método anónimo, não pode também ser utilizado num bloco catch ou num bloco try que tenha mais do que uma cláusula catch.

 

Exemplo Prático com a utilização do operador yield :

using System;
using System.Collections;

namespace TesteYield
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (int numero in Exemplo1(5))
            {
                Console.WriteLine(numero);
            }
        }

        public static IEnumerable Exemplo1(int numero)
        {
            for (int i = 0; i < numero; i++)
            {
                yield return i;
            }

            yield break;
        }
    }
}

 

Exemplo Prático com a recorrendo a uma estrutura de dados:

using System;
using System.Collections;
using System.Collections.Generic;

namespace TesteYield
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (int numero in Exemplo1(5))
            {
                Console.WriteLine(numero);
            }
        }

        public static IEnumerable Exemplo1(int numero)
        {
            var res = new List<int>();

            for (int i = 0; i < numero; i++)
            {
                res.Add(i);
            }

            return res;
        }
    }
}

O resultado do programa será:

exemplo1

Quando é utilizado o yield return, não provoca o fim da execução do método, no caso do exemplo 1, o ciclo “for” vai incrementar a variável “i” e guardar o valor na variável do tipo IEnumerable ou IEnumerator.

Exemplo Prático nº2 – como criar facilmente um IEnumerable ou IEnumerator recorrendo ou yield:

using System;
using System.Collections;
using System.Collections.Generic;

namespace TesteYield
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (int numero in Exemplo2())
            {
                Console.WriteLine(numero);
            }
        }

        public static IEnumerable<int> Exemplo2()
        {
            yield return 0;
            yield return 1;
            yield return 2;
            yield return 3;
            yield return 4;

            yield break;
        }
    }
}

 

O resultado do programa será:

exemplo1

MonoTouch 1.0 Released

Quinta-feira, Setembro 17th, 2009

mt-green-box Depois de no início de Agosto de este ano a Novell oferecer a cerca de 2000 programadores a oportunidade de se juntarem aos testes do MonoTouch Beta, foi anunciado dia 14 de Setembro a versão final e comercial de esta nova framework para desenvolvimento de aplicações em C# para o iPhone.

O ponto mais positivo de esta framework, é que esta produz código nativo quando é executado o build da aplicação, estando assim de acordo com as normas  que a Apple obriga os programadores a seguir para que as aplicações criadas por estes possam ser incluídas na Apps Store da Apple.

O Mono utiliza o modelo de compilação just-in-time (JIT), onde o bytecode é traduzido para código máquina nativo em runtime, no entanto o compilador suporta um outro modelo de compilação, chamado ahead-of-time (AOT) que converte .NET Common Intermediate Language (CIL) para código nativo em tempo de compilação. Isto permite que aos programadores compilar as suas aplicações baseadas na Mono framework em aplicações nativas que não necessitam de uma  Virtual Machine ou qualquer outro componente em runtime para a aplicação ser executada com sucesso.

Esta framework inclui de compiladores, bibliotecas e ferramentas de integração com o iPhone SDK. Também inclui as bilbiotecas base do .NET Framework assim como um cross-compiler que pode ser utilizado para migrar aplicações e bibliotecas desenvolvidas em .NET para aplicações compatíveis com o iPhone e susceptíveis de serem publicadas na Apple Apps Store.

No entanto a Novell decidiu tornar esta framework num produto pago, e que pode ser adquirido na loja on-line do site oficial da Novell.

A empresa disponibiliza, no entanto uma versão trial do produto, que eu experimentei e da qual deixo aqui  uma demonstração.

Antes de mais, para utilizar o MonoTouch para desenvolver aplicações, são necessários alguns requisitos:

- Ter Apple Machintosh com um processador intel, OSX 10.5/6

- Instalar a Apple iPhone SDK 3.0 ou superior

- Ser um Apple iPhone Developer

- Instalar a última versão do Mono para OSX

- Instalar a última versão do MonoDevelop para OSX

 

Para esta demonstração desenvolvi um programa muito simples, este apenas tem um contador com o número de vezes que é pressionado um botão, no entanto o objectivo de esta demonstração concentra-se em mostrar como se pode desenvolver uma aplicação para iPhone recorrendo à MonoTouch framework.

 

Começamos por criar um novo projecto C# para iPhoneMd_hw_iphone8

 

De seguida construimos o interface, recorrendo para isso a uma ferramenta do Xcode, o Interface Builder

 InterfaceBuilder

E depois de criar a interface gráfica, vamos programar os eventos que a interface suporta, no exemplo apenas é necessário criar o evento TouchDown do botão “pressionar”monodevelop

 

Quando se faz o build do projecto, o MonoDevelop utiliza uma ferramenta que faz parte do iPhone SDK, o iPhone Simulator para testar a aplicação desenvolvida

IphoneSimulator

 

Está framework embora seja um produto comercial, oferece aos programadores da plataforma  .NET um novo mercado de trabalho bem como abre as portas a uma nova plataforma que se encontra em grande expansão.

 

Referências:

http://monotouch.net/

http://www.infoworld.com/d/developer-world/iphone-gets-net-app-development-194

http://arstechnica.com/open-source/news/2009/09/monotouch-drops-net-into-apples-walled-app-garden.ars

http://www.mobiletor.com/2009/09/15/novell-monotouch-1-0-sdk-for-iphone-app-developers/