|
|
Veamos cómo podemos usarlo en Python 3.2+
Implementemos una secuencia de Fibonacci y usemos lru_cache.
from functools import lru_cache
@lru_cache(maxsize=32)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
>>> print([fib(n) for n in range(10)])
# Output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
El argumento maxsize le dice a lru_cache cuántos valores de retorno recientes se almacenan en caché.
También podemos eliminar en caché fácilmente los valores de retorno usando:
fib.cache_clear()
Un método común para establecer límites de transacciones en Spring Framework es utilizar su gestión de transacciones impulsada por anotaciones y anotar métodos de servicio con la anotación @Transactional. Parece bastante simple, ¿verdad? Si y no. Aunque la gestión de transacciones impulsada por anotaciones de Spring Framework es fácil de configurar y usar, hay algunas cosas que debe recordar hacer:
Afortunadamente, es bastante fácil implementar una prueba que garantice qu
Sin más el test :
public class ServiceAnnotationTest {
private static final String PACKAGE_PATH_SEPARATOR = ".";
/*
* A string which is used to identify getter methods. All methods whose name contains the given string
* are considered as getter methods.
*/
private static final String GETTER_METHOD_NAME_ID = "get";
private static final String FILE_PATH_SEPARATOR = System.getProperty("file.separator");
/*
* The file path to the root folder of service package. If the absolute path to the service package
* is /users/foo/classes/com/bar/service and the classpath base directory is /users/foo/classes,
* the value of this constant must be /com/bar/service.
*/
private static final String SERVICE_BASE_PACKAGE_PATH = "/com/bar/service";
/*
* A string which is used to identify setter methods. All methods whose name contains the given string
* are considered as setter methods.
*/
private static final String SETTER_METHOD_NAME_ID = "set";
/*
* A string which is used to identify the test classes. All classes whose name contains the given string
* are considered as test classes.
*/
private static final String TEST_CLASS_FILENAME_ID = "Test";
private List<Class> serviceClasses;
/**
* Iterates through all the classes found under the service base package path (and its sub directories)
* and inserts all service classes to the serviceClasses array.
*
* @throws IOException
* @throws ClassNotFoundException
*/
@Before
public void findServiceClasses() throws IOException, ClassNotFoundException {
serviceClasses = new ArrayList<Class>();
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("classpath*:" + SERVICE_BASE_PACKAGE_PATH + "/**/*.class");
for (Resource resource : resources) {
if (isNotTestClass(resource)) {
String serviceClassCandidateNameWithPackage = parseClassNameWithPackage(resource);
ClassLoader classLoader = resolver.getClassLoader();
Class serviceClassCandidate = classLoader.loadClass(serviceClassCandidateNameWithPackage);
if (isNotInterface(serviceClassCandidate)) {
if (isNotException(serviceClassCandidate)) {
if (isNotEnum(serviceClassCandidate)) {
if (isNotAnonymousClass(serviceClassCandidate)) {
serviceClasses.add(serviceClassCandidate);
}
}
}
}
}
}
}
/**
* Checks if the resource given a as parameter is a test class. This method returns
* true if the resource is not a test class and false otherwise.
*
* @param resource
* @return
*/
private boolean isNotTestClass(Resource resource) {
return !resource.getFilename().contains(TEST_CLASS_FILENAME_ID);
}
/**
* Checks if the resource given as a parameter is an exception class. This method returns true
* if the class is not an exception class and false otherwise.
*
* @param exceptionCanditate
* @return
*/
private boolean isNotException(Class exceptionCanditate) {
return !Exception.class.isAssignableFrom(exceptionCanditate) &&
!RuntimeException.class.isAssignableFrom(exceptionCanditate) &&
!Throwable.class.isAssignableFrom(exceptionCanditate);
}
/**
* Parses a class name from the absolute path of the resource given as a parameter
* and returns the parsed class name. E.g. if the absolute path of the resource is
* /user/foo/classes/com/foo/Bar.class, this method returns com.foo.Bar.
*
* @param resource
* @return
* @throws IOException
*/
private String parseClassNameWithPackage(Resource resource) throws IOException {
String pathFromClasspathRoot = parsePathFromClassPathRoot(resource.getFile().getAbsolutePath());
String pathWithoutFilenameSuffix = parsePathWithoutFilenameSuffix(pathFromClasspathRoot);
return buildClassNameFromPath(pathWithoutFilenameSuffix);
}
/**
* Parses the path which starts from the classpath root directory by using the
* absolute path given as a parameter. Returns the parsed path.
* E.g. If the absolute path is /user/foo/classes/com/foo/Bar.class and the classpath
* root directory is /user/foo/classes/, com/foo/Bar.class is returned.
*
* @param absolutePath
* @return
*/
private String parsePathFromClassPathRoot(String absolutePath) {
int classpathRootIndex = absolutePath.indexOf(SERVICE_BASE_PACKAGE_PATH);
return absolutePath.substring(classpathRootIndex + 1);
}
/**
* Removes the file suffix from the path given as a parameter and returns new path
* without the suffix. E.g. If path is com/foo/Bar.class, com/foo/Bar is returned.
*
* @param path
* @return
*/
private String parsePathWithoutFilenameSuffix(String path) {
int prefixIndex = path.indexOf(PACKAGE_PATH_SEPARATOR);
return path.substring(0, prefixIndex);
}
/**
* Builds a class name with package information from a path given as a parameter and
* returns the class name with package information. e.g. If a path com/foo/Bar is given
* as a parameter, com.foo.Bar is returned.
*
* @param path
* @return
*/
private String buildClassNameFromPath(String path) {
return path.replace(FILE_PATH_SEPARATOR, PACKAGE_PATH_SEPARATOR);
}
/**
* Checks if the class given as an argument is an interface or not.
* Returns false if the class is not an interface and true otherwise.
*
* @param interfaceCanditate
* @return
*/
private boolean isNotInterface(Class interfaceCanditate) {
return !interfaceCanditate.isInterface();
}
/**
* Checks if the class given as an argument is an Enum or not.
* Returns false if the class is not Enum and true otherwise.
*
* @param enumCanditate
* @return
*/
private boolean isNotEnum(Class enumCanditate) {
return !enumCanditate.isEnum();
}
/**
* Checks if the class given as a parameter is an anonymous class.
* Returns true if the class is not an anonymous class and false otherwise.
*
* @param anonymousClassCanditate
* @return
*/
private boolean isNotAnonymousClass(Class anonymousClassCanditate) {
return !anonymousClassCanditate.isAnonymousClass();
}
/**
* Verifies that each method which is declared in a service class and which is not a
* getter or setter method is annotated with Transactional annotation. This test
* also ensures that the rollbackFor property of Transactional annotation specifies
* all checked exceptions which are thrown by the service method.
*/
@Test
public void eachServiceMethodHasTransactionalAnnotation() {
for (Class serviceClass : serviceClasses) {
Method[] serviceMethods = serviceClass.getMethods();
for (Method serviceMethod : serviceMethods) {
if (isMethodDeclaredInServiceClass(serviceMethod, serviceClass)) {
if (isNotGetterOrSetterMethod(serviceMethod)) {
boolean transactionalAnnotationFound = serviceMethod.isAnnotationPresent(Transactional.class);
assertTrue("Method " + serviceMethod.getName() + " of " + serviceClass.getName() + " class must be annotated with @Transactional annotation.", transactionalAnnotationFound);
if (transactionalAnnotationFound) {
if (methodThrowsCheckedExceptions(serviceMethod)) {
boolean rollbackPropertySetCorrectly = rollbackForPropertySetCorrectlyForTransactionalAnnotation(serviceMethod.getAnnotation(Transactional.class), serviceMethod.getExceptionTypes());
assertTrue("Method " + serviceMethod.getName() + "() of " + serviceClass.getName() + " class must set rollbackFor property of Transactional annotation correctly", rollbackPropertySetCorrectly);
}
}
}
}
}
}
}
/**
* Checks that the method given as a parameter is declared in a service class given as
* a parameter. Returns true if the method is declated in service class and false
* otherwise.
*
* @param method
* @param serviceClass
* @return
*/
private boolean isMethodDeclaredInServiceClass(Method method, Class serviceClass) {
return method.getDeclaringClass().equals(serviceClass);
}
/**
* Checks if the method given as parameter is a getter or setter method. Returns true
* if the method is a getter or setter method an false otherwise.
*
* @param method
* @return
*/
private boolean isNotGetterOrSetterMethod(Method method) {
return !method.getName().contains(SETTER_METHOD_NAME_ID) && !method.getName().contains(GETTER_METHOD_NAME_ID);
}
/**
* Checks if the method given as a parameter throws checked exceptions. Returns true
* if the method throws checked exceptions and false otherwise.
*
* @param method
* @return
*/
private boolean methodThrowsCheckedExceptions(Method method) {
return method.getExceptionTypes().length > 0;
}
/**
* Checks if the transactional annotation given as a parameter specifies all checked exceptions
* given as a parameter as a value of rollbackFor property. Returns true if all exceptions
* are specified and false otherwise.
*
* @param annotation
* @param thrownExceptions
* @return
*/
private boolean rollbackForPropertySetCorrectlyForTransactionalAnnotation(Annotation annotation, Class<?>[] thrownExceptions) {
boolean rollbackForSet = true;
if (annotation instanceof Transactional) {
Transactional transactional = (Transactional) annotation;
List<Class<? extends Throwable>> rollbackForClasses = Arrays.asList(transactional.rollbackFor());
for (Class<?> thrownException : thrownExceptions) {
if (!rollbackForClasses.contains(thrownException)) {
rollbackForSet = false;
break;
}
}
}
return rollbackForSet;
}
/**
* Verifies that each service class is annotated with @Service annotation.
*/
@Test
public void eachServiceClassIsAnnotatedWithServiceAnnotation() {
for (Class serviceClass : serviceClasses) {
assertTrue(serviceClass.getSimpleName() + " must be annotated with @Service annotation", serviceClass.isAnnotationPresent(Service.class));
}
}
}
Que diferencia tiene Unit y Nothing en Kotlin o en Scala?? Dado que kotlin se ha "inspirado" en muchas cosas de Scala. Por lo tanto creo que en este caso los 2 lenguajes son iguales. (En realidad no estoy tan seguro, comenten si tienen otra información)
Unit: Unit en Kotlin o Scala corresponde al void en Java y de C. Al igual que void, Unit es el tipo de retorno de cualquier función que no devuelva ningún valor significativo, y es opcional mencionar Unit como tipo de retorno. Pero a diferencia de void, Unit es una clase real (en kotlin) o object (en Scala) con una sola instancia.
Nothing: Nothing es un tipo en Kotlin que represente "un valor que nunca existe", eso significa simplemente "ningún valor en absoluto".
Nothing se puede usar como el tipo de retorno de una función que nunca devuelve la ejecución del código, como, en bucle para siempre o siempre arroja Exception. Java no tiene nada similar al tipo Nothing.
Veamos unos ejemplos donde debemos utilizar Nothing como tipo de retorno.
Supongamos que hay una función reportError() que siempre lanza una RuntimeException. En una aplicación real, este reportError() puede agregar algunos registros útiles adicionales antes de lanzar la excepción o arroja diferentes excepciones basadas en diferentes condiciones.
En java se implementaría :
throw new RuntimeException();
}
En Kotlin :
fun reportError(): Nothing {
throw RuntimeException()
}
En Scala :
def reportError(): Nothing {
throw RuntimeException()
}
Como vemos Nothing debe ser escrito explícitamente como el tipo de retorno; de lo contrario, el tipo de retorno seguirá siendo Unit.
¿Qué pasará si colocamos por error alguna linea de código después de llamar a este método reportError ()?
// Java
int i = 0;
void exampleOne() {
reportError(); // throws RuntimeException
i = 1; // This is unreachable code. But there is no warning.
}
En java no pasaría nada, pero pero en kotlin nos avisaría :
// Kotlin
var i = 0;
fun exampleOne() {
reportError(); // throws RuntimeException
i = 1; // We will get an 'Unreachable code' warning here.
}
En Kotlin tendríamos un warning.
Otra cuestión importante es que Nothing implementa o se puede hacer pasar por diferentes tipos, lo que permite que hagamos lo siguiente :
/** `???` can be used for marking methods that remain to be implemented.
* @throws NotImplementedError
*/
def ??? : Nothing = throw new NotImplementedError
Y luego utilizar ??? para marcar una función que nos falta implementar.
/**
* Filtra los elementos pares
*/
def filtrarPares(xs: List[Int]): List[Int] = ???
Y tiene más usos Nothing por ejemplo Nil que es la lista vacia es de tipo List[Nothing] dado que este tipo puede hacerse pasar por otros tipos.
Ojo que hay algunas diferencias entre Scala y Kotlin más que nada en los nulleables de kotlin pero la idea general es esta.
Y creo que estamos, si me olvide de algo, para eso están los comentarios!
begin
for i in (select constraint_name, table_name from user_constraints where table_name in ('tabla1', 'tabla2', 'tabla3')) LOOP
execute immediate 'alter table '||i.table_name||' disable constraint '||i.constraint_name||'';
end loop;
end;
/
Y para habilitarlas:
begin
for i in (select constraint_name, table_name from user_constraints where table_name in ('tabla1', 'tabla2', 'tabla3')) LOOP
execute immediate 'alter table '||i.table_name||' ENABLE constraint '||i.constraint_name||'';
end loop;
end;
/
Y Listo!
Existen muchas opciones pero es bueno ir por donde va la industria, es decir utilizar lo más usado. Claramente hoy en día se utiliza un framework backend + un framewor front.Comunicados por Apis Rest.
Por front podemos elegir : Angular, React o Vue , el mercado esta ahí.
Por back tenes muchas opciones: java - spring boot, solución super probada y te va andar muy bien.
dot net - dot net core con MVC, un poco más nuevo pero anda muy bien y se usa mucho.
Python: Django, viejito pero bueno,
Javascript con node y express.
Y si te interesa arriesgarte y optar por algo nuevo tenes Go, con Echo o otros frameworks.
En esta versión no tenemos grandes cambios a nivel de lenguaje. La lista final completa de características es:
Dejo link: https://jdk.java.net/15/
Y si la quieren descargar la versión libre :
respuesta = 42
Una ecuación en Haskell es una ecuación matemática: dice que el lado izquierdo y el lado derecho denotan el mismo valor.
El lado izquierdo debe ser un nombre al que le esté dando un valor. Por ejemplo :
x = 5 * y
No podemos escribir ecuaciones como lo hacemos en la matemática, por ejemplo esto esta mal :
2 * x = (3 * x) ** 2 - No se permite la reasignación en un FPL puro
Las ecuaciones no son asignaciones y una variable o nombre solo puede tener un valor. Puse variable o nombre dado que los nombres a menudo se denominan "variables", pero no varían. ¡Las variables son constantes!
n = 1
x = 3 * n
n = x -- Error: solo puede tener una definición de n
Una vez que le da un valor a un nombre, ¡nunca podrá cambiarlo! Esto es parte del significado de "puro" y "sin efectos secundarios"
¿Qué pasa con n = n + 1? En lenguajes imperativos, frecuentemente decimos n: = n + 1. Pero esto es una tarea, no una ecuación
En Haskell, es válido escribir n = n + 1. Pero Haskell lo intentará y fallará. Dado que tratará de resolver n con n de forma recursiva.
Pero como se puede vivir sin asignaciones? Pensemos en una declaración de asignación como si hiciera tres cosas:
En un lenguaje puramente funcional, nunca destruimos los viejos valores. Simplemente calculamos nuevos útiles. Si el valor anterior era realmente inútil, el recolector de basura reclamará su almacenamiento.
add = lambda x, y: x + y
print(add(3, 5))
# Output: 8
Podemos utilizar para indicar como ordenar nuestras listas :
a = [(1, 2), (4, 1), (9, 10), (13, -3)]
a.sort(key=lambda x: x[1])
print(a)
# Output: [(13, -3), (4, 1), (1, 2), (9, 10)]
Y podemos ordenar listas concurrentemente:
data = zip(list1, list2)
data = sorted(data)
list1, list2 = map(lambda t: list(t), zip(*data))
(b * b-4 * a * c) / 2 * a
y puede asignar estas expresiones a variables:
v = (b*b-4*a*c)/2*a
En Haskell, también puede hacer esto, y lo que es más: las expresiones son realmente todo lo que hay, no hay declaraciones.
Funciones: En Python, puede definir una función como
def hello(name):
return "Hello, "+name
En Haskell puedes escribir esto simplemente como:
hello name = "Hello, "++name
Tipos : C tiene tipos, por ejemplo:
int f (int x, int y) {
return x*y+x+y;
}
Haskell tiene tipos mucho más poderosos que C, y se definen en una linea diferente de la función :
f :: Int -> Int -> Int
f x y = x*y+x+y
Listas : En muchos lenguajes, p. Ej. Python, JavaScript, Ruby,… puedes crear listas como:
lst = ["A", "lista", "de", "cadenas"]
Haskell también usa esta sintaxis para listas.
Para unirse a listas, en Python puede escribir
lst = [1,2] + [3,4]
En Haskell esto sería muy similar:
lst = [1,2] ++ [3,4]
Funciones anónimas : En JavaScript puede definir funciones anónimas (funciones sin nombre) como:
var f = function (x, y) {return x * y + x + y};
En Haskell, estas funciones anónimas se denominan funciones lambda y en realidad son la base del lenguaje. Nuevamente, la sintaxis es muy compacta:
f = \x y -> x*y+x+y
\ representa el símbolo lambda.
Funciones de orden superior : Finalmente, en muchos lengujes, las funciones pueden operar sobre funciones. Por ejemplo, en Perl puede modificar los elementos en una lista usando:
map sub ($x){$x*2+1}, [1..10]
Haskell proporciona muchas de las llamadas funciones de orden superior y le permite definir las suyas propias.
map (\x -> x*2+1) [1..10]
SELECT sum(numbackends) FROM pg_stat_database;
Y Listo!! Con esta query se cuantas conexiones hay en mi base de datos.
|
Las corrutinas son similares a los generadores con algunas diferencias. Las principales diferencias son:
En primer lugar, revisemos el proceso de creación del generador. Podemos hacer generadores como este:
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
Luego lo usamos comúnmente en un bucle for como este:
for i in fib():
print(i)
Las corrutinas consumen valores que se le envían. Un ejemplo muy básico sería una alternativa grep en Python:
def grep(pattern):
print("Searching for", pattern)
while True:
line = (yield)
if pattern in line:
print(line)
yield en este caso no contiene ningún valor, sino que le proporcionamos valores externamente. Suministramos valores mediante el método .send(). Aquí hay un ejemplo:
search = grep('coroutine')
next(search)
# Output: Searching for coroutine
search.send("I love you")
search.send("Don't you love me?")
search.send("I love coroutines instead!")
# Output: I love coroutines instead!
Es necesario para iniciar la corrutina, correr next. Al igual que los generadores, las corrutinas no inician la función de inmediato. En su lugar, lo ejecutan en respuesta a los métodos __next __ () y .send (). Por lo tanto, debe ejecutar next () para que la ejecución avance a la expresión yield.
Podemos cerrar una corrutina llamando al método .close ():
search = grep('coroutine')
# ...
search.close()
Y listo!!
Dejo link: https://book.pythontips.com/en/latest/coroutines.html
Singleton es un patrón muy muy enseñado, y creo que es solo porque es fácil de implementar.
Pero este patrón nació en entornos no concurrentes y en procesos de desarrollo que no se utilizaba unit test. Por lo tanto, en ese entorno era bueno, pero el tiempo ha pasado y cada vez más todos los entornos son concurrentes y es imprescindible tener unit test en nuestro software. Lo que ha convertido al amigo Singleton en un Anti-Pattern.
Por que no deberíamos utilizar Singleton:
Si tienen más curiosidad dejo link: https://www.michaelsafyan.com/tech/design/patterns/singleton