Crudo? Uff! un monton.
Por ejemplo, esto:
Código SQL
[-]SELECT * ;
FROM tastrade!customer ;
WHERE customer.country = "Canada" ;
INTO ARRAY aMyArray
Se hace en foxpro (copia los resultados en un array). No asi:
Código PHP:
cmd.text = "SELECT * ;" +
"FROM tastrade!customer ;"
"WHERE customer.country = \"Canada\" ;"
"INTO ARRAY aMyArray";
cmd.execute()
for row in rows:
//Copiar el array...
Cuando trabajaba con fox, no sabia que existían problemas con los lenguajes OO y el acceso a bases de datos (el "impedance mismatch"). Tampoco habian injecciones sql, porque el sql se escribia directo, no armando cadenas.
Ahora, lo mas cercano seria algo como LINQ:
Código SQL
[-]
from p in db.Purchases
where p.Customer.Address.State == "WA" || p.Customer == null
where p.PurchaseItems.Sum (pi => pi.SaleAmount) > 1000
select p
Lo cual es genial. El compilador te ayuda
con errores cuando cambia una tabla o campo (de nombre o tipo). Y automaticamente genera el sql de acuerdo a la BD. O si no es una BD? Pues tambien:
http://code.msdn.microsoft.com/101-L...mples-3fb9811b
Código PHP:
public void Linq6()
{
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var numsPlusOne =
from n in numbers
select n + 1;
Console.WriteLine("Numbers + 1:");
foreach (var i in numsPlusOne)
{
Console.WriteLine(i);
}
}
Asi que el como ejecutar consultas es un primer problema. Luego viene el problema de como hacerlo de forma asincronica/paralela. Con canales de GO, el comando await en .NET es un gran avance.
Luego viene otro problema, que mostre levemente con el codigo de fox. El como pasar datos a las estructuras (hacer binding). Con fox era muy facil incluso linkear a variables, copiar a cursores en memoria y cosas por el estilo. Con LINQ es masomenos igual de bueno, pero no identico. Ya que fox tenia el motor integrado, no se pierde ni la abilidad ni la velocidad al procesar localmente los datos.
Lo mas cercano? Creo que python tiene
http://pandas.pydata.org/pandas-docs/stable/10min.html (pero diverge mucho...). Asi que este paso es el del procesamiento local.
Cuando mencione que el manejo de Bases de datos es crudo, realmente estaba pensando en "datos" en general.
Asi que corremos la consulta de clientes y obtenemos un conjunto de datos. Esta en un dataset o un diccionario. No es lo mismo a que si estuviera en una tabla de datos local...
Luego esta el problema en si de binding, validacion, procesamiento/transformacion.
Pensemos en el binding. Delphi es genial con su TDataSet, pero eso tambien es una muy pobre opcion (en mi epoca de fox, uno no sabia que el binding era problematico!). La mejor idea actual es la
programacion reactiva... porque resuelve el problema de los eventos.
El uso de eventos (los tipicos OnClick) se vuelven muy complicados con el tiempo, y enredados de verificar, testear y entender. Son codigo espaguetti. Y en el momento que se le meten cosas asincronicas? Sin ayuda del lenguaje/librerias es imposible de manejar...
Un ejemplo:
http://swannodette.github.io/2013/07...ial-processes/
https://github.com/ReactiveCocoa/ReactiveCocoa
Y la validacion y definición de campos. Un ejemplo de como podría ser,
de cuenta de python/django:
Código PHP:
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
Y un
formulario se hace asi:
Código PHP:
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField()
sender = forms.EmailField()
cc_myself = forms.BooleanField(required=False)
Y es de notar: 1) No hay nada de GUI ahi. Y sin embargo, es un formulario funcional. Es 100% testeable, 100% multiplataforma, 100% no visual.
Ahora resumiendo (porque como notan, me toca jalar de multiples lenguajes y entornos) como se veria un lenguaje para que fuera como en foxpro, pero moderno?:
P.D: La sintaxis y todo es un invento, aun no tengo nada en concreto.
Código PHP:
#Asumiendo que sqlite esta integrado
uses:
db, sqlite3, mysql
Record Invoice:
ref:Str
customer:Customer
subTotal:Money
total:Money
date:Date = Date.now
class Invoices(Table)
record = Invoice
indexBy = [record.ref] #Define los indices
#Antes de guardar
def Invoices.willAppend(old, new:Customer):Err
if new.customer is None:
return Err('Customer is empty', new)
#Automaticamente se actualiza si cambian los records y procesa la suma
#Una implementacion http://docs.espressologic.com/docs/tutorial
def Invoices.total():Money
sumTotal = sum(self.items.total)
return react(self.records, sumTotal)
db = MySql('localhost'..)
db.register(Invoices)
i=Invoices()
i.append(ref=1, customer=c, date=Date(2000,02,01), subTotal=10, total=20)
#Como en linq, los query se pueden guardar y componer
query = select x in db.Invoices if customer==c
query = query if total > 0
for x in query:
print x
#Que consulta tan lenta!
async datos = query.execute()
#No hay callbacks
#A proposito, recuerdan el bind?
#Funcionando sobre el subconjunto de datos
print datos.total().value
#Y como en fox, puedo jalar los datos a un engine local:
dbLocal = sqlite3(':memory')
dbLocal.import(datos)
#ahora consulto los datos locales:
query = select x in dbLocal.Invoices if customer==c