Saturday, December 29, 2007
Instanciação dinâmica - VCL e VCL.NET
unit uCreateInstance;
interface
uses
Classes, SysUtils;
function CreateInstance(AClass: TClass): TObject; overload;
function CreateInstance(AClassName: string): TObject; overload;
implementation
function CreateInstance(AClass: TClass): TObject;
begin
{$IFDEF CLR}
Result := Activator.CreateInstance(AClass.ClassInfo); // .NET
{$ELSE}
Result := AClass.Create; // Win32
{$ENDIF}
end;
function CreateInstance(AClassName: string): TObject;
var
AClass: TClass;
begin
AClass := GetClass(AClassName);
if not Assigned(AClass) then
raise Exception.Create('A classe "' + AClassName + '" não está registrada.');
Result := CreateInstance(AClass);
end;
end.
Thursday, December 27, 2007
Wednesday, December 26, 2007
Quanto mais eu uso o C#...
Francamente. Um tanto de coisa na linguagem é feita para agradar os adoradores do C++ que não podem viver sem os operadores de incremento, ou para rivalizarem com o Java no quesito "quem consegue escrever código com menos linhas". O que, na prática, contribui pouco para o que realmente importa. EMO, clareza de código e facilidade de manutenção é muito, mas muito mais importante, do quê "quem escreve menos código para criar uma classe".
Veja só que beleza de código:
int i = 1;
i = i++;
i = i > 1 ? ++i : --i;
label1.Text = i.ToString();
Qual será o texto do label1????
.
.
.
Tem certeza???
.
.
.
Levou mais de 2 segundos para chegar ao resultado? Então tem algo errado com o código certo? Este tipo de aberração de código é que a linguagem, pela sua estrutura cheia de operadores "mágicos", permite escrever. Claro que a turma do C# vai me dizer "mas o cara que escreveu isto é um asshole!" ou "os operadores são poderosíssimos quando bem usados!". Tudo isto é verdade, claro, mas existem as linguagens que exigem ou reforçam boas práticas, e as que não o fazem. O C# é uma delas.
Mas fazer o quê. Para VS2005 acho melhor mesmo o Chrome!
Monday, December 24, 2007
So this is Christmas
Aí segue a história: Uma pena realmente, perder este monte de mentes a cada ano.
Thats too bad
Sunday, December 23, 2007
TIOBE Index
O Delphi está em 11a posição perdendo uma posição para o Ruby (não é novidade) e para o JavaScript (não que eu considere JavaScritp uma linguagem de fato! ). De qualquer forma o número "bom" disso é que o share do Delphi aumentou 0.10 no último ano. Pouco mas eu sinceramente esperava uma queda!
O IDE e a velha paleta
Engraçado é que não conheço sequer um desenvolvedor - desenvolvedor MESMO, não aqueles que só abrem o Delphi para estudar para certificação - que goste de paleta introduzida no BDS 2005 e continuada nas demais versões do Delphi. No Delphi Day online dia 7/12/2007 lembro-me de ter ouvido o Andreano Lanusse dizer mais ou menos "acostume-se com ela pois vai continuar assim!". O pessoal da CodeGear poderia rever isto aí na próxima versão. Pelo menos deveria poder deixá-la como o DDevExtensions faz e assim agradar os desenvolvedores que, assim como eu, preferem a IDE com a paleta antiga.
E preferir a paleta antiga não é "picuinha". A paleta antiga tem 2 vantagens importantes EMO:
1- Ocupa uma faixa estreita acima. Desta forma não torna minúscula a área disponível para quem ainda escreve CÓDIGO (CodeGear tem a ver com isto não? )
2- Permite ver os ícones dos componentes e escolhê-los sem ter que digitar seus nomes
A busca ao digitar é feita exclusivamente num Edit que pode ser colocado onde bem se desejar.
Monday, December 17, 2007
DataSnap.NET - Parte III
1) ASP.NET replacement of CodeGear's httpsrvr.dll
2) WinForms .NET replacement of CodeGear's Scktsrvr.exe
Ambos em C# (BDS 2006). Vou verificar e colocar para rodar em breve!
Obrigado Ondrej!
Saturday, December 15, 2007
Sunday, December 9, 2007
RemObjects & Pascal for VisualStudio
O primeiro RemObjects eu usei há muito, quando lançado. Hoje olho para ele com outros olhos, uma vez que a perspectiva de desenvolvimento corporativo e em multicamadas é, aparentemente, bem amplo. Não pude deixar de ver também o Chrome - Pascal para VS - e aí é que a coisa complica.... O Object Pascal é, de fato, adorado pelos seus usuários porquê nós de fato achamos que linhas de código como estas
static void Main(string[] args)
{
int i = 0;
i = i++;
}
diferentemente do que pensam os fanáticos por C++ e C# (o códito compila em ambos, com resultados diferentes!), nunca, nunca mesmo, irão contribuir para que o código fonte seja mais claro, que a qualidade do software seja mais garantida, que meu trabalho seja mais fácil ou mais bem feito, e que eu chegue mais cedo em casa! E ponto final.
A partir do momento que a RemObjects começa a transformar o ObjectPascal num híbrido eu, particularmente, começo a ficar desconfiado.
Quem quiser, tire a prova: Chrome Language Features
Vou até olhar mais profundamente, mas... com certeza tenho minhas restriçôes.
Friday, December 7, 2007
CodeGear Delphi Day - 7 Dezembro
Acho que já passou da hora deles abrirem o olho. Muita gente desenvolveu grandes sistemas multi-camadas em Delphi/Win32 ao longo de vários anos, principalmente com o surgimento do Midas/DataSnap. Agora não tem para onde correr. Se vai ter que jogar tudo fora e reescrever, porquê manter em Delphi? Porquê não ir para o VisualStudio?
Será que só eu que enxergo isto?
ATENÇÃO CODEGEAR: Passou da hora de ter um DataSnap.NET!!!! ACORDEM!!!
Tuesday, December 4, 2007
DataSnap.NET - Parte II: Aguardando o código
Continuando sobre o DataSnap.NET...
Escrevi para o TOndrej que mantém o excelente blog sobre programação & Delphi http://tondrej.blogspot.com solicitando o código que ele desenvolveu para criar servidores DataSnap.NET. Ele ficou de me enviar o código, em C# segundo está no blog. Assim que o tiver nas mãos vou dar uma bela fuçada! Seria um belo ponto de partida para um framework funcional. Apesar que... eu obviamente iria criar código em Delphi.NET, BDS 2006 ou RAD Studio 2007, pois o suporte a C# é mínimo.
Como NÃO programar um componente Trial/Shareware
Ultimamente tenho tido certa necessidade de “brincar” com os DCU’s de alguns componentes comerciais. “Brincar” aí significa disassemblá-los mesmo, e se possível alterar diretamente o DCU.
Isto pode ser necessário, por exemplo, quando você não possui o código fonte de um componente descontinuado pelo seu desenvolvedor, ou então quando é necessário ter certo nível de “engenharia reversa”.
Inevitavelmente me vem à cabeça uma outra possibilidade: quebrar algum mecanismo de proteção contra execução de componentes shareware, o que obviamente é ilegal e não recomendável. Um mecanismo comum de desenvolvedores de componentes shareware Delphi é checar se o IDE do Delphi está sendo executado. Se estiver, o componente executa normalmente. Caso contrário, a execução é abortada ou alguma nag screen é exibida.
A forma mais infantil de criar este mecanismo de proteção é criar uma função única de checagem e/ou verificação que retorna algum tipo de resultado, geralmente booleano. Quem desenvolve componentes em versões trial nunca deveria fazer isto a não ser que queria que seus DCU’s sejam quebrados até por crackers amadores.
Recentemente disassemblei um componente e encontrei um código deste tipo:
function CheckProtection: boolean;
var
Reg: TRegistry;
begin
result := False;
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
Reg.OpenKey('My Software Key', False);
if Reg.ValueExists('RegistryKey') then
Result := True;
finally
Reg.Free;
end;
end;
procedure TMyQuery.InternalPost;
begin
if not CheckProtection then
begin
ShowMessage(‘Versão Demo. Bla Bla Bla’);
Abort;
end;
// o código normal do componente “fucional” continua
inherited InternalPost;
end;
O código não é exatamente assim, claro. É só uma reconstrução resumida do que faz o componente, deduzido a partir da dissecação do seu DCU.
O mais engraçado aqui é que não importa o código da função CheckProtection, muito menos o código que é executado depois da chamada, caso ela retorne False. Se eu modificar 3 bytes no DCU, este código NUNCA será executado.
Disassemblando o DCU gerado para o código em Pascal acima teríamos algo do tipo:
function CheckProtection: Boolean;
55 PUSH EBP
8B EC MOV EBP,ESP
83 C4 F8 ADD ESP,-8
C6 45 FF 00 MOV BYTE PTR [EBP-1],$00
B2 01 MOV DL,$01
A1 00 00 00 00 MOV EAX,DWORD PTR [_Dn_TRegistry{0x102}]
E8 00 00 00 00 CALL TRegistry.Create{0x103}
89 45 F8 MOV DWORD PTR [EBP-8],EAX
BA 02 00 00 80 MOV EDX,$80000002
8B 45 F8 MOV EAX,DWORD PTR [EBP-8]
E8 00 00 00 00 CALL TRegistry.SetRootKey{0x104}
33 C0 XOR EAX,EAX
55 PUSH EBP
68 6E 00 00 00 PUSH CheckProtection{0x10D}+$0000006E
64 FF 30 PUSH DWORD PTR FS:[EAX]
64 89 20 MOV DWORD PTR FS:[EAX],ESP
33 C9 XOR ECX,ECX
BA 84 00 00 00 MOV EDX,CheckProtection{0x10D}+$00000084
8B 45 F8 MOV EAX,DWORD PTR [EBP-8]
E8 00 00 00 00 CALL TRegistry.OpenKey{0x105}
BA 9C 00 00 00 MOV EDX,CheckProtection{0x10D}+$0000009C
8B 45 F8 MOV EAX,DWORD PTR [EBP-8]
E8 00 00 00 00 CALL TRegistry.ValueExists{0x106}
84 C0 TEST AL,AL
74 04 JE +4; (0x5 )
C6 45 FF 01 MOV BYTE PTR [EBP-1],$01
33 C0 XOR EAX,EAX
5A POP EDX
59 POP ECX
59 POP ECX
64 89 10 MOV DWORD PTR FS:[EAX],EDX
68 75 00 00 00 PUSH CheckProtection{0x10D}+$00000075
8B 45 F8 MOV EAX,DWORD PTR [EBP-8]
E8 00 00 00 00 CALL TObject.Free{0xFE}
C3 RET NEAR
E9 00 00 00 00 JMP @HandleFinally{0xFF}
EB F0 JMP -16; (0x65)
8A 45 FF MOV AL,BYTE PTR [EBP-1]
59 POP ECX
59 POP ECX
5D POP EBP
C3 RET NEAR
FF FF ? EDI
FF FF ? EDI
0F 00 00 SLDT WORD PTR [EAX]
00 4D 79 ADD BYTE PTR [EBP+121],CL
20 53 6F AND BYTE PTR [EBX+111],DL
66 74 77 JE +119; (0x103)
61 POPA
72 65 JB +101; (0xF4)
20 4B 65 AND BYTE PTR [EBX+101],CL
79 00 JNS 0; (0x94)
FF FF ? EDI
FF FF ? EDI
0B 00 OR EAX,DWORD PTR [EAX]
00 00 ADD BYTE PTR [EAX],AL
52 PUSH EDX
65 67 69 73 74 72 79 4B 65 IMUL DWORD PTR GS:[BP+DI+116],$654B7972
79 00 JNS 0; (0xA )
end;
O código fonte em Pascal não é grande, mas o código assembly correspondente mete medo em qualquer um, certo? Talvez... Mas... Não importa o tamanho ou a complexidade do assembly da função CheckProtection. Se eu pegar as 2 primeiras linhas:
function CheckProtection: Boolean;
55 PUSH EBP
8B EC MOV EBP,ESP
E transformá-las em
function CheckProtection: Boolean;
B0 A1 MOV AL,$01
C3 RET NEAR
Teríamos exatamente o código que é gerado se eu tivesse uma função do tipo:
function CheckProtection: Boolean;
begin
Result := True;
Exit;
// o código a partir daqui nunca será executado
...
End;
Ou seja, não importa o que tenha após o EXIT! Ele nunca será executado e a função SEMPRE retornará TRUE. Se o desenvolvedor que trabalhou muitas horas para criar este componente basear seu mecanismo de proteção em algo ingênuo deste tipo... sorry, but... it is cracked!
Isto é só um exemplo do que é possível fazer com um DCU, e de como não se deve programar um mecanismo de proteção de versão de componente trial ou shareware!
Pode-se fazer outras coisas interessantes com uma DCUs, editando-a diretamente, tipo mudar o timestamp permitindo burlar o erro "A unit XPTO foi compilada com versão diferente da unit ABCD".
Monday, December 3, 2007
Firebird em Windows XP: Primeira conexão muito lenta
Assim como 90% dos Delpheiros também utilizo o Firebird em alguns sistemas - ainda na versão 1.5. Recentemente fui rodar um sistema que estava parado há tempos, e comecei a perceber que a primeira conexão levava minutos. Muitos minutos. Parecia até que travava o Windows XP.
Bem, depois de vasculhar a internet descobri o motivo: A extensão .GDB do arquivo de banco de dados e as interferências do System Restore (Restauração do Sistema) do Windows XP. Toda vez que um arquivo .GDB é acessado/modificado o "System Restore" automaticamente faz uma cópia do mesmo. Quando o arquivo tem poucos Megabytes isto pode ser imperceptível. Mas eu estava trabalhando com um BD de 800 Mb. Como resultado, a primeira conexão - via sistema ou via IBExpert - levava cerca de 5 minutos!
http://support.borland.com/kbshow.php?q=25953
Workaround:
1) Desabilite o System Restore do Windows XP - Não recomendável por razões óbvias
2) Modifique a extensão de seus arquivos Interbase/Firebird. Eu preferi usar esta. Padronizei então meus arquivos .GDB como sendo: Extensão .IB para os Interbase, e extensão .FDB para os arquivos Firebird. E voilá!
Monday, November 26, 2007
Filtros em TADODataSet
O filtro
(campo1 = valor1 OR campo1 = valor2) AND campo2 = 'ABCD'
simplesmente não funciona!!!
Não pode haver agrupamento de cláusulas usando o OR e posteriormente agrupando-as com outras cláusulas usando o AND. Teria que reescrever o filtro com:
(campo1 = valor1 AND campo2 = 'ABCD')
OR (campo1 = valor2 AND campo2 = 'ABCD')
Isto complica bastante a vida do desenvolvedor que, como eu, criou um "editor visual genérico" de filtros que se aplica a qualquer descendente do TDataSet.
Maneira rápida de fugir do problema: Utilize um ClientDataSet ligado num DataSetProvider, que por sua vez está ligado no ADODataSet (ou ADOQuery) original. E passe a usar o ClientDataSet no lugar do ADODataSet. O primeiro - e também o segundo - exemplo de filtro funciona perfeitamente no ClientDataSet!
Mais uma vez o ClientDataSet se mostrando superior ao ADO Recordset.
Sunday, November 25, 2007
Serialização de Objetos - Parte I
Quem trabalha com C# ou Java certamente irá encontrar em seu caminho a serialização de objetos, de forma mais ou menos rotineira. O interessante é que existem várias bibliotecas em Delphi que implementam métodos e classes para trabalhar com serialização, mas dificilmente encontramos código escrito utilizando este conceito. Uma destas bibliotecas era a Globus que foi depois incorporada pela gigante JEDI JVCL.
O conceito é simples: a partir de uma instância de uma classe qualquer – geralmente descendente de TPersistent – obtêm-se um XML que permita “reconstruir” esta instância mantendo-se todas as suas propriedades. Isto é conseguido fazendo extenso uso da RTTI (Run Time Type Information) para obter todas as propriedades Published da classe (somente as propriedades Published da classe geram informação de RTTI).
O processo de geração do XML que representará a classe é também simples: Percorre-se a lista de todas as propriedades Published da classe, convertendo cada property em um Tag correspondente, da forma:
<nome da propriedade>valor da propriedade</nome da propriedade>
Um TEdit por exemplo poderia ser representado pelo seguinte XML:
<TEdit>
<Left>27</Left>
<Top>59</Top>
<Width>121</Width>
<Height>21</Height>
<Tag>1</Tag>
<Visible>True</Visible>
</TEdit>
Atualmente venho utilizando a JVCL (classe TXMLSerializer) para serializar objetos. De fato, crei uma nova classe baseada na TXMLSerializer da JVCL, para ficar isolado de possíveis mudanças na JVCL - uma vez que da versão 2 para a 3 já ocorreram mudanças significativas, e não posso me dar ao luxo de reescrever código de produção sempre que a JVCL mudar.
O melhor de tudo é que migrei o TXMLSerializer para Delphi.NET (BDS 2006) - possuo um único código fonte para Win32 e .NET - e assim consigo serializar objetos entre aplicações Win32 e .NET, sem problemas, e sem precisar das monstruosidades dos parsers XML da MS, nem no ambiente Win32 nem no ambiente .NET.
Mais sobre este assunto depois!
Descobrindo se uma classe descende de uma outra
Criei uma pequena função que me permite dizer se uma classe é descendente de uma outra, utilizando o nome da classe ancestral.
Você pode se perguntar: "Mas qual o objetivo disso? Não é mais fácil usar o operador is?" Por exemplo:
if ActiveControl is TEdit then
TEdit(ActiveControl).SelectAll;
A resposta é: Depende! O operador is faz uma checagem de tipo dinâmica, mas requer que o TEdit seja conhecido em tempo de compilação e consequentemente requer que o código da classe TEdit esteja linkado no executável. O código acima só compila se a unit StdCtrls (onde está a declaração da classe TEdit) esteja na cláusula uses da unit.
Agora, imagine que você tenha um método onde inúmeras classes podem ser passadas como parâmetro e você não deseja - ou não possa - linkar todas as possíveis classes. Exemplo:
Procedure DoSomething(Instance: TPersistent);
Bem provavelmente você pode pensar: "Mas de quê me serve um método assim se desconheço a classe e não poderei usá-la diretamente?" A resposta é que bem provavelmente você irá utilizar a RTTI diretamente para obter e modificar as propriedades dos objetos referenciados por Instance, assim como faz o nosso conhecido Object Inspector.
Precisei utilizar esta função em algumas classes para saber, por exemplo, se um determinado DataSet era descendente direto do TCustomADODataSet padrão do Delphi, ou de um outro DataSet com linhagem totalmente diferente (TQuery, TSQLQuery), sem ter que linkar com as units ADODB, DBTables e SqlExpr, o que aumentaria consideravelmente o tamanho do meu executável.
Isso me permitiu criar classes de um framework que trabalhavam igualmente bem com ambos os DataSets, SEM QUE O CÓDIGO DE NENHUM DELES FOSSE LINKADO NO MEU EXECUTÁVEL FINAL.
O código é simples e por isto dispensei comentários. Simplesmente faço um loop onde comparo o nome da classe da instância passada como parâmetro com o nome da classe procurada. Se não for igual, passo para o ancestral imediatamente superior e refaço a comparação. Repito até que o resultado seja verdadeiro ou eu chegue ao topo da árvore da hierarquia do objeto.
function PertenceAClasse(const Instance: TObject; ParentClassName: string): boolean;
var
ParentClass: TClass;
ObjClassName,
TargetClassName: string;
begin
Result := False;
ObjClassName := UpperCase(Instance.ClassName);
TargetClassName := UpperCase(ParentClassName);
ParentClass := Instance.ClassType;
repeat
if ObjClassName = TargetClassName then
begin
Result := True;
break;
end;
ParentClass := ParentClass.ClassParent;
if ParentClass <> nil then
ObjClassName := UpperCase(ParentClass.ClassName);
until (ParentClass = nil);
end;
Wednesday, November 14, 2007
DataSnap.NET... Thats cool!
http://tondrej.blogspot.com/2004/10/datasnapnet.html
Really COOL guys!
Há exatos 2 anos venho batendo nesta tecla com o pessoal da CodeGear. Conversei inclusive com o Ramesh Theivendran na Borcon 2005 em SP. Imagine um servidor 100% .NET servindo clientes DataSnap, no matter what, ou seja, clientes Win32 ou .NET.
Imagine poder portar o servidor de aplicações para .NET e manter os clientes ainda em Win32? Migrar quando for mais conveniente?
Além de todo o horizonte que me abriria, iria matar os desenvolvedores VB e C# de inveja, é ou não é?
Porém... O post no blog é de 2004!!! E hoje, mais do que em 2004 EMHO, esta tecnologia seria bem vinda. Vou tentar contato com o autor para saber em que pé ficamos.
Ainda sobre a M$
Here we go Vista?
- Mood:
É muito muito chato, muito muito cheio de frescura visual que CANSA, e muito muito pouco produtivo. Depois de usá-lo por algum tempo me senti desiludido! Sinceramente! Senti igual quando tive que admitir que o ICQ estava morto, para glória do MSN Messenger, que até hoje não faz o que o ICQ fazia em 1998... Well, nesta área de TI parece que quase tudo novo piora um pouco o que já existia.
Fico impressionado como o XP alcançou rapidamente um nível de maturidade, para mim, excelente (não sou expert em segurança de SO!). Em mais de 2 anos que o uso não me lembro de ter "dado pau", travado, etc. Como plataforma para DESENVOLVIMENTO Windows, dificilmente será desbancado. Mas é isto. Resistirei enquanto puder!
E despistadamente alguns fabricantes de computadores/notebooks que vêm com Vista O&M instalado estÃo fazendo downgrade do SO... despistadamente para que a turma de Redmont não ouça...
Tuesday, November 13, 2007
Desenvolvimento Windows, futurologia & outras leituras de interesse.
Is Microsoft expanding the war?
Steve Trefethen
Giving Up on Microsoft
Jeff Atwood
Desktop Applications are Dead
Eugueny Kontsevoy
Desktop Applications are not dead!
Antonio Cangiano
E aí? Morreu ou não morreu?
Wednesday, November 7, 2007
Apresentação na Borcon 2007
Aí está o link para o dowload da minha apresentação na Borcon 2007 que teve o título acima.
Recebi alguns e-mails solicitando este material uma vez que o DVD que a Borland/CodeGear distribuiu no evento não continha nenhuma palestra.
Achei isto uma falha terrível da organização. O "evento" em si não termina no final do terceiro dia de apresentação. Todo mundo quer ver o material, inclusive consultar outras palestras que não puderam assistir ao vivo.
Download da palestra
Tuesday, November 6, 2007
SystemBuilder da Squadra
Bem... até hoje está lá no site deles para vender o SystemBuilder versão 3.x, para Delphi 5, 6 e 7. O demo que tem para download é 3.2. O software é protegido contra execução não autorizada, cópia, etc pelo HandProt, outra ferramenta da Squadra.
Um conhecido meu tem um sistema que se utilizou o System Builder para ser desenvolvido e me pediu para estudar a possibilidade de EVOLUÇÃO do sistema. Putz... que arapuca! Como a Squadra parou de desenvolver o SystemBuilder (não há versão para IDE superior ao Delphi 7), e também não tornou o fonte aberto (está aí uma boa idéia pessoal da Squadra!), não há como migrar o sistema para BDS 2006 por exemplo sem ter que reescrevê-lo.
Outra chatisse do SystemBuilder é sua proteção contra cópia. Se você tem um computador desktop e um notebook, prepare-se: Ou compre duas licenças ou use somente um deles. Nos idos de 1997 quando a Squadra vendia o SystemBuilder ainda vá lá. Mas hoje??
Resumo da ópera: Resolvi pegar os .dcu do SystemBuilder e, digamos, dissecá-los, para não dizer disassemblá-los!
Descobri duas coisas bem interessantes: O HandProt me pareceu bem escrito, com segurança redundante, proteção contra debugging, etc. Já o SystemBuilder... Só precisa de um patch de 6 bytes em 1 DCU e voilá! Não que eu tenha feito isto, certo?
Em breve vou detalhar como é feito isto.
Caros leitores, mais sobre Squadra, System Builder e Handprot aqui:
Borcon 2007
Algumas percepções minhas sobre a Borcon este ano:
- Da CodeGear: David I, Steve Shaughnessy (DBX) e o CEO Jim Douglas. Muito boas apresentações de todos eles. E muito bom ver o CEO vindo ao Brasil falar para a comunidade Delphi.
- Muito ECO IV, ASP.NET, DBExpress 4 e Blackfish, tudo do novo RAD Studio 2007.
- O novo DBExpress foi apresentado pelo arquiteto responsável pelo mesmo Steve Shaughnessy. A nova arquitetura do DBX me pareceu 10!
- Gostei muito do Blackfish, e acredito que desenvolvedores ASP.NET e Desktop que utilizam o Delphi vão gostar também. O deploy é muito simples e acredito que vai ser a "preferência" para este tipo de desenvolvedor. Ainda não sei dos detalhes de LICENÇAS ($) para deploy do Blackfish. Espero que a CodeGear não limite a sua utilização como fez com o Midas, quando foi lançado. Entre pagar pelo Blackfish ou usar o MySQL que já tem em 99% dos web hosts... qual será a opção?
- Fiquei muito pensativo sobre um gráfico que o Jim mostrou em sua apresentação, onde Delphi e C++ estão no lado do desenvolvimento "Desktop, small & middle-sized", deixando o Enterprise para o "managed code", C#, Java, etc. Levando por este lado a CodeGear quer nos dizer aplicações Win32 (e futuramente 64) acabaram no ambiente corporativo??? Até aí tudo bem... But... O RAD Studio 2007 é puro Delphi e C++. Aí pergunto: O preço do RAD Studio é compatível com ESTE MERCADO???
More comments later