Hum... Fiquei pensando em algumas coisas após ter terminado o tutorial (se é que é um tutorial :P) ...
Uma das coisas é colocar o "assincronismo" na parte "Model" da coisa.
Pensando bem, se é a tela do Android (por exemplo) que trava por causa da resposta do serviço, por que diabos tenho que colocar o "assincronismo" no lado do serviço?
Eu poderia resolver com alguma coisa assim, no lado da View:
this.startLoading();
this.callAsync(presenter.callLogin, (returned: Object) throws Exception -> {
this.finishLoading();
if (object is User) {
...
} else if (object is Error) {
...
}
});
E colocar o Model e o Presenter síncronos.
E por que pensei nisso? Por causa que nem todas as aplicações pedem coisas assíncronas (por exemplo, um serviço de API que, na teoria, ao receber uma requisição, não seria necessário executar o serviço assíncrono).
Mas, se em todo o caso, os serviços (Models) são assíncronos (seja por que foi pensado assim, ou esteja utilizando uma biblioteca assíncrona) e você estiver precisando usar em alguma coisa síncrona, dependendo da linguagem, é possível fazer algo assim:
public function onRequest(request: Request, response: Response) {
...
presenter.callLogin();
this.wait();
if (this.user != null) {
...
} else if (this.error != null) {
...
}
...
}
public function onLogin(user: User) {
this.user = user;
this.notify();
...
}
public function onLoginFail(error: Error) {
this.error = error;
this.notify();
...
}
Tomara que, desta vez, eu tenha acertado! :P
Até mais!
Mostrando postagens com marcador Arquitetura. Mostrar todas as postagens
Mostrando postagens com marcador Arquitetura. Mostrar todas as postagens
segunda-feira, 19 de novembro de 2018
sexta-feira, 16 de novembro de 2018
Isso é MVP (Model-View-Presenter)? Terceira (e acho que última) parte - Presenter
Como muita gente viu, eu arrumei a parte dois (realmente, fazer as coisas com pressa dá nisso...).
Vamos a última parte (eu acho), a implementação da classe Presenter.
Esta classe tem como característica juntar a parte View (da segunda parte deste artigo) com a Model (da primeira parte deste mesmo).
Então temos:
//Classe de Presenter que implementa a delegação do Modelo (ILoginModelDelegate) e da View (ILoginViewDelegate)
public class LoginPresenter implements ILoginModelDelegate, ILoginViewDelegate {
//Propriedades privadas
private property model: ILoginModel;
private property view: ILoginView;
//Construtor da classe
public constructor(view: ILoginView) {
//Cria o model através de uma Fábrica (Factory)
model = Factory::instance.getModel(ILoginModel.class);
model.delegate = this;
view.delegate = this;
}
//Função de login
private function login() {
model.login(view.username, view.password);
}
@implementation
public function onLoginSuccess(user: User) {
view.onLogin(user);
}
@implementation
public function onLoginError(error: Error) {
view.onLoginFail(error);
}
@implementation
public function callLogin() {
login();
}
}
E, assim, temos a junção de tudo. Por exemplo, se fosse uma "página web":
public class LoginPageView: Page, ILoginView, OnClickListener {
private property presenter: LoginPresenter;
private property @UI okButton: UIButton;
...
public constructor() {
...
presenter = new LoginPresenter(this);
okButton.setOnClickListener(this);
...
}
...
@implementation
public function OnClick(sender: UIObject) {
presenter.callLogin();
}
....
}
Se fosse uma "Activity do Android":
public class LoginActivity: Activity, ILoginView, OnClickListener {
private property presenter: LoginPresenter;
private property okButton: Button;
...
@override
public function onCreate(savedInstanceState: Bundle) {
...
presenter = new LoginPresenter(this);
okButton.setOnClickListener(this);
...
}
...
@implementation
public function OnClick(sender: View) {
...
presenter.callLogin();
...
}
....
}
Vamos a última parte (eu acho), a implementação da classe Presenter.
Esta classe tem como característica juntar a parte View (da segunda parte deste artigo) com a Model (da primeira parte deste mesmo).
Então temos:
//Classe de Presenter que implementa a delegação do Modelo (ILoginModelDelegate) e da View (ILoginViewDelegate)
public class LoginPresenter implements ILoginModelDelegate, ILoginViewDelegate {
//Propriedades privadas
private property model: ILoginModel;
private property view: ILoginView;
//Construtor da classe
public constructor(view: ILoginView) {
//Cria o model através de uma Fábrica (Factory)
model = Factory::instance.getModel(ILoginModel.class);
model.delegate = this;
view.delegate = this;
}
//Função de login
private function login() {
model.login(view.username, view.password);
}
@implementation
public function onLoginSuccess(user: User) {
view.onLogin(user);
}
@implementation
public function onLoginError(error: Error) {
view.onLoginFail(error);
}
@implementation
public function callLogin() {
login();
}
}
E, assim, temos a junção de tudo. Por exemplo, se fosse uma "página web":
public class LoginPageView: Page, ILoginView, OnClickListener {
private property presenter: LoginPresenter;
private property @UI okButton: UIButton;
...
public constructor() {
...
presenter = new LoginPresenter(this);
okButton.setOnClickListener(this);
...
}
...
@implementation
public function OnClick(sender: UIObject) {
presenter.callLogin();
}
....
}
Se fosse uma "Activity do Android":
public class LoginActivity: Activity, ILoginView, OnClickListener {
private property presenter: LoginPresenter;
private property okButton: Button;
...
@override
public function onCreate(savedInstanceState: Bundle) {
...
presenter = new LoginPresenter(this);
okButton.setOnClickListener(this);
...
}
...
@implementation
public function OnClick(sender: View) {
...
presenter.callLogin();
...
}
....
}
Ou se fosse um "serviço JSON":
public class LoginJSONView: JSON, ILoginView {
private property presenter: LoginPresenter;
...
public constructor {
...
presenter = new LoginPresenter(this);
...
}
...
@override
public onPost(request: Request, response: Response) {
...
presenter.callLogin();
...
}
....
}
public class LoginJSONView: JSON, ILoginView {
private property presenter: LoginPresenter;
...
public constructor {
...
presenter = new LoginPresenter(this);
...
}
...
@override
public onPost(request: Request, response: Response) {
...
presenter.callLogin();
...
}
....
}
Acho que é isso... Se eu esquecer de alguma coisa, depois eu arrumo. (errar é humano, ainda mais depois dos 40... :P )
Até mais!
quarta-feira, 31 de outubro de 2018
Isso é MVP (Model-View-Presenter)? Segunda parte - View
Bem, tenho que corrigir uma coisa anteriormente: o método "login" esta síncrono, seria melhor se ele fosse assincrono, ou usando callbacks:
public function login(username: string, password: string, callback: function(user: User?, error: Error)) {
}
ou usando métodos de delegação de uma interface (que será implementada na classe de Presenter):
public interface ILoginModelDelegate {
public function onLoginSuccess(user: User);
public function onLoginError(error: Error);
}
Beleza, agora podemos continuar! (se eu não me lembrar de nada até lá...)
Se para Model, a gente fez uma interface para ela (para facilitar a mudança da origem de dados -- seja serviços REST, SOAP ou banco de dados), a gente faz a mesma coisa para a View.
Por que? -- você deve perguntar...
Pelo mesmo motivo: desacoplamento, ou seja, para que a nossa "tela" possa mudar de HTML para um serviço que retorna json ou para outro que retorna XML:
public interface ILoginView {
public property (readonly) username: string;
public property (readonly) password: string;
public function onLogin(user: User);
public function onLoginFail(error: Error);
}
public class LoginPageView: Page, ILoginView {
public property (readonly) username: string {
return txtUserName.text;
}
...
}
public class LoginRestView: Rest, ILoginView {
public property (readonly) username: string {
return request.getParameter("username");
}
...
}
Legal, né?
Bem, acho que é isso... Na próxima fica faltando só a Presenter. :)
Até mais!
public function login(username: string, password: string, callback: function(user: User?, error: Error)) {
}
ou usando métodos de delegação de uma interface (que será implementada na classe de Presenter):
public interface ILoginModelDelegate {
public function onLoginSuccess(user: User);
public function onLoginError(error: Error);
}
Beleza, agora podemos continuar! (se eu não me lembrar de nada até lá...)
Se para Model, a gente fez uma interface para ela (para facilitar a mudança da origem de dados -- seja serviços REST, SOAP ou banco de dados), a gente faz a mesma coisa para a View.
Por que? -- você deve perguntar...
Pelo mesmo motivo: desacoplamento, ou seja, para que a nossa "tela" possa mudar de HTML para um serviço que retorna json ou para outro que retorna XML:
public interface ILoginView {
public property (readonly) username: string;
public property (readonly) password: string;
public function onLogin(user: User);
public function onLoginFail(error: Error);
}
public class LoginPageView: Page, ILoginView {
public property (readonly) username: string {
return txtUserName.text;
}
...
}
public class LoginRestView: Rest, ILoginView {
public property (readonly) username: string {
return request.getParameter("username");
}
...
}
Legal, né?
Bem, acho que é isso... Na próxima fica faltando só a Presenter. :)
Até mais!
quarta-feira, 24 de outubro de 2018
Isso é MVP (Model-View-Presenter)? Primeira parte - Model
Sabe aquele tipo de cara que aprende somente na prática? Então, este sou eu (por isso, eu não tenho certeza se isso é MVP).
MVP é uma sigla para Model-View-Presenter (modelo, visão e apresentação), que é um tipo de modelo de arquitetura de software, como o MVC.
Como este, seguimos o padrão de separar o "negócio" (regras, cálculos, verificações, dados, etc.), o "M" da sigla, da tela (bem, tela é tela :P), o "V" da sigla.
Se separamos, existe alguém que junta, certo? Sim, e este "juntador" é representado pela letra "P" (o Presenter).
Bem, melhor que explicar, vamos a codificação (programador entende melhor "programando"). Primeiramente, vamos entender as classes de modelo:
public interface IUserModel {
//Função que verifica se o usuário é válido.
//@param username string que contém o nome do usuário (obrigatório)
//@param password string que contém a senha do usuário (obrigatório)
//@return se os valores foram válidos, retorna um objeto da classe User, com as informações do usuário, caso o contrário, retorna null
public function login(username: string, password: string): User?;
}
//Implementação da interface IUserModel que usa banco de dados
public class UserDatabaseModel: IUserModel {
@implementation
public function login(username: string, password: string): User? {
...
}
}
Por que temos uma interface em modelo? Por causa da teoria de "baixo acoplamento", e por que podemos, em vez de usar uma classe que conecta em banco de dados, usar uma classe que conecta em serviços REST, por exemplo:
//Implementação da interface IUserModel que usa serviços REST
public class UserRESTServiceModel: IUserModel {
@implementation
public function login(username: string, password: string): User? {
...
}
}
E, assim, utilizar um serviço ou outro, só mudando a instância:
public property model: IUserModel = new UserDatabaseModel();
Acho que a primeira parte esta concluída, na próxima, veremos a "V" de view (não de vingança). :)
Até mais!
MVP é uma sigla para Model-View-Presenter (modelo, visão e apresentação), que é um tipo de modelo de arquitetura de software, como o MVC.
Como este, seguimos o padrão de separar o "negócio" (regras, cálculos, verificações, dados, etc.), o "M" da sigla, da tela (bem, tela é tela :P), o "V" da sigla.
Se separamos, existe alguém que junta, certo? Sim, e este "juntador" é representado pela letra "P" (o Presenter).
Bem, melhor que explicar, vamos a codificação (programador entende melhor "programando"). Primeiramente, vamos entender as classes de modelo:
public interface IUserModel {
//Função que verifica se o usuário é válido.
//@param username string que contém o nome do usuário (obrigatório)
//@param password string que contém a senha do usuário (obrigatório)
//@return se os valores foram válidos, retorna um objeto da classe User, com as informações do usuário, caso o contrário, retorna null
public function login(username: string, password: string): User?;
}
//Implementação da interface IUserModel que usa banco de dados
public class UserDatabaseModel: IUserModel {
@implementation
public function login(username: string, password: string): User? {
...
}
}
Por que temos uma interface em modelo? Por causa da teoria de "baixo acoplamento", e por que podemos, em vez de usar uma classe que conecta em banco de dados, usar uma classe que conecta em serviços REST, por exemplo:
//Implementação da interface IUserModel que usa serviços REST
public class UserRESTServiceModel: IUserModel {
@implementation
public function login(username: string, password: string): User? {
...
}
}
Na hora de usar essas, em vez de instanciar um objeto da própria classe:
public property model: UserRESTServiceModel = new UserRESTServiceModel();
Podemos instanciar um objeto da interface:
public property model: IUserModel = new UserRESTServiceModel();
E, assim, utilizar um serviço ou outro, só mudando a instância:
public property model: IUserModel = new UserDatabaseModel();
Acho que a primeira parte esta concluída, na próxima, veremos a "V" de view (não de vingança). :)
Até mais!
quinta-feira, 16 de novembro de 2017
Orientação à Objetos: Simples ou Complexo?
Será que programar orientado à objetos é tão fácil quanto se pensa?
Por exemplo, vamos ver a classe Properties da API oficial do Java:
Você acha que isso faz sentido? Que isso esta correto?
Pois bem, então tente fazer a seguinte instrução:
Properties prop = new Properties();
prop.put("numero", 1);
prop.put("texto", "um");
System.out.println("O valor da propriedade numero é: "
+ prop.getProperty("numero"));
System.out.println("O valor da propriedade texto é: "
+ prop.getProperty("texto"));
Por que diabos eu consigo recuperar a propriedade "texto" e não consigo fazer o mesmo com o "numero"?
Outro exemplo (agora com a classe Stack):
Stack<String> stack = new Stack<String>();
stack.push("a");
stack.push("b");
stack.push("c");
System.out.println("Pilha: " + stack);
stack.remove(0);
System.out.println("Pilha: " + stack);
É meio estranho eu conseguir remover o primeiro item de uma pilha, não? :P
Coisas a se pensar...
Até mais!
domingo, 3 de março de 2013
Como decidir as tecnologias de um projeto de software?
Só para avisar: não sou nenhum especialista e nem um guru (guru e não Gugu), mas ai vão umas dicas de alguém que tem alguma experiência na área de informática:
1) Se sua equipe estiver montada, saiba antes da experiência e "das vontades" de cada um;
2) Pesquise as tecnologias que você pensa em usar, antes de utiliza-las (pode ser bobo, mas é realmente uma dica :) );
3) Se você não sabe ou não tem certeza do que utilizar, pense sempre no mais simples;
4) Quanto mais complexo uma tecnologia é, pior será a velocidade de desenvolvimento (vá por mim, querer se mostrar que é o "bão", pode acabar bem "mar" :P );
5) Comunique as suas decisões para a equipe ("surpresas" que não são presentes ou comemorações, podem ser tão perigosas quanto "bombas");
6) Nunca se "empolgue" com uma tecnologia, no nosso meio, na maioria das vezes, a razão vem antes do coração (ficou meio brega, para não falar outra coisa... :P );
7) Em uma decisão arquitetural, planeje antes de executar (sempre);
8) Se tiver tempo, faça provas de conceito com as tecnologias que você não sabe ou que são novas;
9) Se conseguir, verifique o projeto como um todo antes de decidir quais tecnologias utilizar;
10) Se possível, pergunte antes para alguém que tenha mais experiência na tecnologia que você. Perguntar não deveria ofender a pessoa e nem você (como meu pai diz: "Perguntar não é burrice, burrice é deixar de perguntar!" :P );
Obs.: Sabe que estou percebendo: que ando colocando carinhas ( :P ) demais nos meus textos.
Até mais!
quarta-feira, 26 de setembro de 2012
Planejamento e Construção
De tempos em tempos, eu acho que confundo "falta de planejamento" com "metodologia ágil"...
Por várias vezes, me peguei pensando:
"Para que planejar/explicar/escrever estas coisas no quadro, vamos é trabalhar!" (neste caso, o sinônimo de trabalhar é "programar")
"Para que criar uma arquitetura? O sistema é simples!" (seria simples, se o sistema não fosse distribuído, não tivesse que manter as informações no mainframe e que um dos requisitos não funcionais seria a performance...)
"O escopo desta história esta fechado." (na verdade, deu o maior sono na reunião de planejamento...)
"Hum... Acho que poderiamos fazer isso um pouco diferente..." (uma pequena observação nesta frase: em 90% dos casos, vá por mim: é melhor não fazer "diferente")
"Acho que o cliente vai gostar dessa modificação!" (nesta, pelo menos uns 80% dos clientes não vão gostar das modificações que você faz, principalmente por não consulta-los antes...)
"Poderiamos discutir isso mais tarde..." (no final, não discutimos nada :( )
"Para que planejar testes (unitários/regressivos/funcionais/exploratórios), eu sempre faço as coisas direito!" (essa é pura prepotência minha, afinal sou humano e como umano, herro -- pelo menos, um humano normal erra :) )
"Vamos cortar os testes para dar mais tempo de implementar" (tá, e a qualidade, ó!)
"Vou deixar esse prá lá, que este é fácil de alterar" (é, se não tivesse que alterar o pedaço em 1000 linhas de código que você copiou e colou por toda parte...)
"Vou deixar esse prá lá, que este vai tomar tempo" (acabei de perceber que frases que começam com "Vou deixar..." são bem perigosas... :P )
Preciso parar de pensar que um projeto de informática é só codificação. Ele é muito mais do que código: é um conjunto de conhecimentos e idéias (e de sonhos, talvez :) ) de várias pessoas que participam direta ou indiretamente de minha equipe.
Só uma observação ao meus "leitores": Também não menospreze a codificação, pois esta ainda é a "realização" de tal "sonho/idéia/conhecimento". :P
Continuo errando e aprendendo...
Até mais!
Marcadores:
Analista de Sistemas,
Arquitetura,
Comportamento,
Desenvolvimento,
Opinião
quarta-feira, 30 de maio de 2012
A Árvore e o Balanço no Desenvolvimento de Software
Alguém já viu a imagem acima?
Pois é, faz uns 10 anos atrás que vi esta imagem e parece que a gente nunca aprende...
Quando me falam de um projeto novo, já fico pensando em customizações do sistema, em efeitos visuais (ter drag n'drop, menu rotativo, fade in, fade out, etc.) ou em tecnologias novas... Mas, que se formos pensar, são coisas que, no final, não são prioritárias ou agregam pouco ou nenhum valor para a aplicação ou o usuário final.
Acho que, algumas vezes, precisamos focar no que é realmente necessário para o nosso cliente. Esta certo que fazer algo realmente bonito é muito legal, mas o importante, na minha singela opinião, é que a aplicação que construimos tem que ser algo mais que bonito, tem que ser algo útil para ele.
De que me adianta um sistema que faz relatórios 3D na tela, se no final o que a pessoa precisa é de uma simples listagem dos produtos mais vendidos?
"Quanto mais simples, melhor..." -- já me dizia um professor meu na faculdade.
É, errando e aprendendo... ;)
Até mais!
Marcadores:
Analista de Sistemas,
Arquitetura,
Práticas,
Profissional,
Projetos
sexta-feira, 9 de setembro de 2011
10 dicas para ser um bom arquiteto de sistemas
As dicas que peguei com os caras de arquitetura, durante estes anos:
1) Saber que você SEMPRE terá que estudar novas metodologias/tecnologias que SEMPRE aparecem todo ANO (ou seja, enfia a sua cara no livro, meu filho...). :P
2) Saber que você NÃO sabe tudo.
3) Saber que você TEM que saber tudo.
4) Ter paciência e calma por que, por mais que você seja uma pessoa precavida, SEMPRE as coisas tendem a dar errado.
5) Utilizar SEMPRE a regrinha do Mais ou Menos 7. (Que regra é essa? Sei lá, vou ter que estudar... :P)
6) Saber que você SEMPRE terá problemas com ambiente (seja de desenvolvimento, testes, homologação, implantação, etc.).
7) Se possivel, utilizar SEMPRE as tecnologias que você conhece.
8) NUNCA criar uma arquitetura mirabolante para validar o login e a senha de um usuário. (Hã? Acho que esta eu vou entender quando for arquiteto...)
9) SEMPRE dar suas opiniões, para que depois você possa falar: "Eu não avisei?" :P
10) Ser SIMPLES (sim, das duas maneiras que você entendeu).
Será que eu consigo seguir estas dicas? :D
Até mais!
1) Saber que você SEMPRE terá que estudar novas metodologias/tecnologias que SEMPRE aparecem todo ANO (ou seja, enfia a sua cara no livro, meu filho...). :P
2) Saber que você NÃO sabe tudo.
3) Saber que você TEM que saber tudo.
4) Ter paciência e calma por que, por mais que você seja uma pessoa precavida, SEMPRE as coisas tendem a dar errado.
5) Utilizar SEMPRE a regrinha do Mais ou Menos 7. (Que regra é essa? Sei lá, vou ter que estudar... :P)
6) Saber que você SEMPRE terá problemas com ambiente (seja de desenvolvimento, testes, homologação, implantação, etc.).
7) Se possivel, utilizar SEMPRE as tecnologias que você conhece.
8) NUNCA criar uma arquitetura mirabolante para validar o login e a senha de um usuário. (Hã? Acho que esta eu vou entender quando for arquiteto...)
9) SEMPRE dar suas opiniões, para que depois você possa falar: "Eu não avisei?" :P
10) Ser SIMPLES (sim, das duas maneiras que você entendeu).
Será que eu consigo seguir estas dicas? :D
Até mais!
terça-feira, 15 de março de 2011
Arquitetura de Software: Quando usar a agregação e quando usar a herança?
Uma vez, eu falei da diferença de agregação, composição e herança.
Agora, vou tentar falar de quando se pode usar um ou outro. Parece fácil diferenciar, mas é muito mais complexo do que se imagina...
Por que eu digo isso?
Porque a própria API do Java SE contém erros de herança/agregação.
Verdade? Como assim?
Vejamos a classe Stack do pacote java.util:
public class Stack<T> extends Vector<T>{
....
public boolean empty() {
...
}
public T peek() {
...
}
public T pop() {
...
}
public T push(T item) {
...
}
public int search(Object o) {
...
}
}
Hum... Ela herda da classe Vector e os métodos parecem corretos para uma classe que representa uma pilha...
Mas existem alguns problemas...
E você me pergunta: Como assim??? Quais???
Vejamos, como Stack herda de Vector, os métodos que a classe Vector possui também existem na classe Stack, gerando o seguinte problema:
Se, em um Vector, eu posso remover um item de qualquer posição do vetor através do método remove(int i), e posso colocar o item em qualquer lugar através do método add(int i, E item), então eu posso fazer o mesmo em um Stack (pilha):
Stack<String> pilha = new Stack<String>();
pilha.push("Primeiro");
pilha.push("Segundo");
pilha.remove(0); //Remove o primeiro item colocado em uma pilha? Não deveria ser sempre o último colocado?
pilha.add(0,"Terceiro"); //Colocando o item abaixo do topo de uma pilha (???)
E isso não esta errado? Por definição, uma pilha deveria somente colocar ou retirar itens do topo? (pelo menos, eu acho que seria o esperado...)
Neste caso, parece que seria melhor usar uma agregação:
public class Stack<T> {
private Vector<T> v;
public Stack() {
v = new Vector<T>();
}
public boolean empty() {
return v.isEmpty();
}
public T peek() {
return v.lastElement();
}
public T pop() {
T t = peek();
v.remove(t);
return t;
}
public T push(T item) {
v.add(item);
return item;
}
public int search(Object o) {
return v.indexOf(o);
}
}
Assim, um Stack (pilha) não seria um Vector (vetor), a classe somente utilizaria um objeto Vector. (o que parece "certo"...)
Para usar herança, é preciso realmente saber se uma classe tem as mesmas caracteristicas de outra (por exemplo: Carro herda de Veiculo por que um Carro também é um Veiculo).
De resto, se você não tiver certeza, ou não souber, vale a dica: é uma agregação. :)
É díficil... mas se não fosse, não seria Orientação á Objetos. :P
Até, espero que isso ajude alguém!
Obs.: Esta dica é de um professor meu! Valeu! :)
Agora, vou tentar falar de quando se pode usar um ou outro. Parece fácil diferenciar, mas é muito mais complexo do que se imagina...
Por que eu digo isso?
Porque a própria API do Java SE contém erros de herança/agregação.
Verdade? Como assim?
Vejamos a classe Stack do pacote java.util:
public class Stack<T> extends Vector<T>{
....
public boolean empty() {
...
}
public T peek() {
...
}
public T pop() {
...
}
public T push(T item) {
...
}
public int search(Object o) {
...
}
}
Hum... Ela herda da classe Vector e os métodos parecem corretos para uma classe que representa uma pilha...
Mas existem alguns problemas...
E você me pergunta: Como assim??? Quais???
Vejamos, como Stack herda de Vector, os métodos que a classe Vector possui também existem na classe Stack, gerando o seguinte problema:
Se, em um Vector, eu posso remover um item de qualquer posição do vetor através do método remove(int i), e posso colocar o item em qualquer lugar através do método add(int i, E item), então eu posso fazer o mesmo em um Stack (pilha):
Stack<String> pilha = new Stack<String>();
pilha.push("Primeiro");
pilha.push("Segundo");
pilha.remove(0); //Remove o primeiro item colocado em uma pilha? Não deveria ser sempre o último colocado?
pilha.add(0,"Terceiro"); //Colocando o item abaixo do topo de uma pilha (???)
E isso não esta errado? Por definição, uma pilha deveria somente colocar ou retirar itens do topo? (pelo menos, eu acho que seria o esperado...)
Neste caso, parece que seria melhor usar uma agregação:
public class Stack<T> {
private Vector<T> v;
public Stack() {
v = new Vector<T>();
}
public boolean empty() {
return v.isEmpty();
}
public T peek() {
return v.lastElement();
}
public T pop() {
T t = peek();
v.remove(t);
return t;
}
public T push(T item) {
v.add(item);
return item;
}
public int search(Object o) {
return v.indexOf(o);
}
}
Assim, um Stack (pilha) não seria um Vector (vetor), a classe somente utilizaria um objeto Vector. (o que parece "certo"...)
Para usar herança, é preciso realmente saber se uma classe tem as mesmas caracteristicas de outra (por exemplo: Carro herda de Veiculo por que um Carro também é um Veiculo).
De resto, se você não tiver certeza, ou não souber, vale a dica: é uma agregação. :)
É díficil... mas se não fosse, não seria Orientação á Objetos. :P
Até, espero que isso ajude alguém!
Obs.: Esta dica é de um professor meu! Valeu! :)
sexta-feira, 11 de março de 2011
Arquitetura de Software: Qual a diferença entre agregação, composição e herança?
Sempre me fiz esta pergunta... Então, vamos lá! :)
As diferenças são:
Agregação é a utilização de uma classe por outra através de um vínculo comum, onde a classe utilizada (agregado) faz "sentido" sem a classe que a utiliza (agregador). Um exemplo são as classes do tipo Carro e Roda (Um carro possue rodas, mas as rodas existem sem o carro).
class Carro {
private Roda[] rodas;
}
class Roda {
}
Composição é uma agregação mais "forte", onde o agregado não faz sentido sem o agregador. Um exemplo clássico, são classes do tipo Pedido e ItemPedido (Um pedido possue itens de pedido e o item de pedido não existe sem um pedido).
class Pedido {
private ItemPedido[] itens;
}
class ItemPedido {
//O código abaixo é só de exemplo, mas nem sempre em uma composição deve ser colocado assim.
private Pedido pedido;
}
Herança é quando uma classe possue todas as características de uma outra classe, a classe que possue as caracteristicas comuns é chamada de base ou de pai e a classe que "herda" estas caracteristicas é chamada de filha. Um exemplo são classes do tipo Animal e Mamifero (pois um mamífero é um animal, mas nem todo animal é mamífero):
class Animal {
}
class Mamifero extends Animal {
}
É isso ai... Pareceu até que estou escrevendo uma apostila :P
Até!
As diferenças são:
Agregação é a utilização de uma classe por outra através de um vínculo comum, onde a classe utilizada (agregado) faz "sentido" sem a classe que a utiliza (agregador). Um exemplo são as classes do tipo Carro e Roda (Um carro possue rodas, mas as rodas existem sem o carro).
class Carro {
private Roda[] rodas;
}
class Roda {
}
Composição é uma agregação mais "forte", onde o agregado não faz sentido sem o agregador. Um exemplo clássico, são classes do tipo Pedido e ItemPedido (Um pedido possue itens de pedido e o item de pedido não existe sem um pedido).
class Pedido {
private ItemPedido[] itens;
}
class ItemPedido {
//O código abaixo é só de exemplo, mas nem sempre em uma composição deve ser colocado assim.
private Pedido pedido;
}
Herança é quando uma classe possue todas as características de uma outra classe, a classe que possue as caracteristicas comuns é chamada de base ou de pai e a classe que "herda" estas caracteristicas é chamada de filha. Um exemplo são classes do tipo Animal e Mamifero (pois um mamífero é um animal, mas nem todo animal é mamífero):
class Animal {
}
class Mamifero extends Animal {
}
É isso ai... Pareceu até que estou escrevendo uma apostila :P
Até!
Assinar:
Postagens (Atom)




