3. var zero = 0;
var numbers = new[] {1, 2, 3, 4};
numbers.Select(x => x / zero).ToList();
Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero.
at Test.Application.<>c__DisplayClass3.<Main>b__2(Int32 x) in F:Visual Studio
ProjectsScalaVsCsProgram.cs:line 21
at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Test.Application.Main() in F:Visual Studio ProjectsScalaVsCsProgram.cs:line 21
wat
4. Scala
C#
def upperCase(args: Array[String]) {
val res = for (a <- args) yield a.toUpperCase
println("Arguments: " + res.mkString)
}
…
upperCase(Array ("a", "b", "c"))
public static void UpperCase(string[] args) {
var res = from arg in args select arg.ToUpperInvariant();
Console.Out.WriteLine("Arguments: {0}", String.Join("", res));
}
…
UpperCase(new []{"a", "b", "c"});
5. Scala
C#
def upperCase(args: Array[String]) {
val res = for (a <- args) yield a.toUpperCase
println("Arguments: " + res.mkString)
}
…
upperCase(Array ("a", "b", "c"))
public static IEnumerable<string> UpperCaseYield(string[] args) {
foreach (var arg in args) {
yield return arg.ToUpperInvariant();
}
}
6. object implicits {
implicit def arrayWrapper[A : ClassTag](x: Array[A]) =
new {
def sort(p: (A, A) => Boolean) = {
util.Sorting.stableSort(x, p); x
}
}
}
import implicits._
…
Scala
val numbers = Array(2, 3, 1, 4)
numbers.sort((x: Int, y: Int) => x < y))
7. C#
public static class implicits {
public static IList<T> MySort<T>(this IList<T> list, Func<T, T, int> func)
where T : class {
var temp = list.ToArray();
Array.Sort(temp, (x, y) => func(x, y));
return temp;
}
}
var objects = new[] {"a", "b", "c"};
objects.MySort(String.CompareOrdinal);
9. Automatic Resource Management
Scala, a través de librerías
C#, magia en el compilador
Debatible
Madurez
dynamic
async / await
Código nativo
Xamarin
10. JVM
Scala
CLR
C# tiene bastantes cosas, aunque a veces la
sintaxis no es la mejor
F#
“Scala feels closer to Java than F# to C#”
Java-----C#-------Scala-------------------F#
11. let zero = 0
let numbers = [| 1; 2; 3 |]
Seq.map(fun x -> x / zero) numbers |> Seq.length
System.DivideByZeroException: Attempted to divide by zero.
at FSI_0002.it@7-1.Invoke(Int32 x) <- wat
at Microsoft.FSharp.Collections.IEnumerator.map@116.DoMoveNext(b& )
at Microsoft.FSharp.Collections.IEnumerator.MapEnumerator`1.System-Collections-IEnumerator-
MoveNext()
at Microsoft.FSharp.Collections.SeqModule.Length[T](IEnumerable`1 source)
at <StartupCode$FSI_0002>.$FSI_0002.main@()
at main@dm()
Stopped due to error
12. Una breve introducción a la industria de tarjetas de crédito
Por qué el proyecto vale la pena
Visión funcional de la aplicación
13. MasterCard, VISA, American Express
Esquema descentralizado de
cobertura mundial
Iniciativas para nuevos negocios,
control de fraude
Chip & PIN (EMV), “Verified By Visa”,
etc.
PCI Council
PCI DSS
Data Security Standard
Aplicable a ambientes productivos
PA DSS
Aplicable a aplicaciones de pagos
14.
15. Estándares de seguridad para proteger información
sensible de tarjetas y prevenir fraude
Obligatorios para proveedores de servicio, comercios, etc.
Apuntan a impedir el acceso pero también a desvalorizar la información
16.
17. Nº de tarjeta, tracks, PIN, en claro,
“por todos lados”
CRM, contabilidad, facturación, etc.
etc.
Sistemas no preparados para cumplir
con la norma PCI DSS
Enorme costo de adaptación
La norma en sí es cara y difícil de
cumplir
18. El estándar tiene más de 260 requisitos individuales,
afectando desde políticas de RRHH hasta el control de
qué servicios se ejecutan en cada computadora dentro
del “ambiente de tarjetas PCI”
Análisis GAP: 2 meses
Proyecto PCI: 7 meses
Certificación / ajustes: 2 meses
~2 millones U$S
+
200.000 – 500.000+ U$S / año
en auditorías
19. Cada módulo de software que deba certificarse tiene un sobrecosto enorme por los
requisitos técnicos.
Documentación
Detalles de logging, seguridad, estándares
Evidencia de procesos de desarrollo seguro, etc.
Criptografía -> gestión de claves
20.
21. PCI aplica sólo a “sistemas que
almacenan, procesan o transmiten el nº
de tarjeta”
La forma más fácil de “certificar PCI”
entonces es evitar almacenar, procesar
o transmitir el nº de tarjeta
SecureTX es PA-DSS, el resto queda
fuera de la norma
22. Estrategia de reducción del alcance a
través de tokenización
def tokenize(card:String): String
5588 3201 2345 6789
->
1000 0000 4365 6789
Desarrollo de middleware tokenizador
“Secure TX”
24. “Tokenizer”
es un servicio web aparte
“SecureTX switch”
es la aplicación que estamos
discutiendo
“Authorizer / switch”
podría ser un procesador de pagos
cualquiera
El esquema de la derecha es minimal,
se dan escenarios más complejos
Transaction
storage
Authorizer /
switch
SecureTX
switch
SecureTX
tokenizer
Encrypted card
storage
TX
1
2
34
5
26. Akka
Librería y runtime para desarrollar
aplicaciones para la JVM
Altamente concurrentes
Distribuidas
Con tolerancia a fallas
Orientadas a eventos asincrónicos
Modelo de actores
Cada actor tiene un mailbox de eventos:
mensajes que procesa secuencialmente
Modelo de ejecución simplificado, fácil
de entender y evitar problemas típicos
de concurrencia
Modelo de supervisión para tolerancia a
fallas
Meta-actores (p.e. para distribución de
carga)
27. Librería para integración de mensajes
“Todos con todos” de canales x
formatos
Canales: JMS, Archivos, HTTP, … …
Formatos: Largo fijo, CSV, XML, JSON,
etc.
Muy configurable mediante Spring
Rutas, endpoints, etc.
EAI patterns en código o XML
Akka – Camel integra ambas librerías
29. TCP, HSM – Akka.IO 2.2 en Scala
Precisamos full-duplex asincrónico, y Camel es one-way o request-reply
Binario + ISO8583 o “ASCII largo fijo” configurable
Tokenizer, PaymentProcessor, Management
Camel
En principio:
Tokenizer por HTTP4
PaymentProcessor, Management por JMS
Pero parte de la gracia de Camel es que esto es muy configurable
30. class Tokenizer extends Actor with Producer with akka.actor.ActorLogging {
val config = SwApp.appConfigContext.getBean(self.path.name).asInstanceOf[TokenizerBean]
val contextHeader = "TOKENIZER_CONTEXT"
val cardIdResource = "cardid"
val cardNumberResource = "cardnumber"
def endpointUri: String = s"http4://${config.host}:${config.port}"
override def transformOutgoingMessage(msg: Any) = msg match {
case TokenizeRequest(cardNumber, senderContext) => CreateCamelMessage(cardIdResource, cardNumber, senderContext)
case OpenCardRequest(token, senderContext) => CreateCamelMessage(cardNumberResource, token, senderContext)
}
private def CreateCamelMessage(resource:String, data:String, senderContext:Any) = {
val headers = Map(
Exchange.HTTP_URI -> s"$endpointUri/$resource/$data",
Exchange.HTTP_METHOD -> "GET",
contextHeader -> senderContext
)
CamelMessage("", headers)
}
override def transformResponse(msg: Any) = msg match {
case msg: CamelMessage => msg.headerAs[String](Exchange.HTTP_URI) match {
case Success(cardId) if cardId.contains(cardIdResource) => TokenizeResponse(msg.bodyAs[String], msg.headers(contextHeader))
case Success(cardNumber) if cardNumber.contains(cardNumberResource) => OpenCardResponse(msg.bodyAs[String], msg.headers(contextHeader))
case Success(other) => log.error("Unexpected response {} from Tokenizer", other)
case Failure(e) => log.error(e, "Error received from Tokenizer")
}
case akka.actor.Status.Failure(e) => log.error(e, "Error received from Tokenizer")
}
}
31. 2200 LOC Scala
promedio 100 por archivo
1000 LOC Java (HSM)
promedio 145 por archivo
.jar 300 kb
lib 22 mb
“If I have seen further it is by standing on the shoulders of giants”
32. akka-testkit
ScalaTest
TeamCity no sabe ejecutar tests de
Scala
http://youtrack.jetbrains.com/issue/TW-
29678
33. JMeter
En condiciones preliminares e
imperfectas
Ambiente local + Oracle de desarrollo
Flujo simplificado
“Enviando” las transacciones a log por
Camel (sin JMS)
Todo con la misma tarjeta
~100 tps
34. A través del “ManagementReceiver”
podemos dinámicamente configurar,
bajar, reiniciar canales.
Trivial de hacer con Akka
Metrics de @coda
Además enviamos status a través del
"ManagementSender"