Skip to main content

Sincpro framework to use DDD, Clean architecture, Hexagonal architecture

Project description

Sincpro Framework (Application layer framework)

The main goal of this framework is create a proxy and facade component/entity, using a pattern bus components that wraps all the application layer, allowing to the developer import all the business logic ready to be executed in any context

Main features:

  • Allow to inject dependencies provided by the user
  • Allow to inject error handler at the top level
  • Execute the business logic in a bus component only providing the DTO(Data transfer object)
  • Allow to execute decoupled (use case, feature , business logic)
    • using the component Feature
  • Allow to execute several use cases based on abstraction called ApplicationService
    • This one contains the feature bus and the developer will be able to execute the use case in any context

Example usage

Init the framework

This framework provide a command bus that will provide to the developer register use cases

  • Feature -> This component will be used to execute decoupled business logic
  • ApplicationService -> This component has injected the feature bus and the developer will be able to execute the registered Feature
# Import the framework
from sincpro_framework import (
  UseFramework, 
  ApplicationService, 
  DataTransferObject,
  Feature as _Feature
)

# Define exceptions this is optional but is a good practice
class GlobalError(Exception): pass
class AppServiceError(Exception): pass
class FeatureError(Exception): pass


# Some dependencies as function
def call_print(algo):
    print(f"Calling from closure {algo}")


def global_error_handler(error):
    """
    Global layer to handle an error
    This function will catch all the exceptions that were
    raised 
    """
    if isinstance(error, GlobalError):
        print("ERROR HANDLEADO")
    else:
        raise Exception("ERROR NO HANDLEADO")


    
def app_error_handler(error):
    """
    We add a handler for `application service` errors
    """
    if isinstance(error, AppServiceError):
        print("APPLICATION HANDLER ERROR")
        raise GlobalError("ERROR DESEDE APPLICATION")
    else:
        raise Exception("ERROR NO HANDLEADO")


def feat_error_handler(error):
    """
    
    """
    if isinstance(error, FeatureError):
        print("FEATURE HANDLER ERROR")
        raise AppServiceError("ERROR DESEDE FEATURE")
    else:
        raise Exception("ERROR NO HANDLEADO")


framework_sp = UseFramework()
# You can add as many dependencies as you want
# Also need to provide a name to the dependency, so in the context of the framework 
# you will be able to call the injedted dependency
framework_sp.add_dependency("andres", call_print)
framework_sp.add_global_error_handler(global_error_handler)
framework_sp.add_app_service_error_handler(app_error_handler)
framework_sp.add_feature_error_handler(feat_error_handler)

# -------------------------------------------- #
# Buena practica en caso de querer tipar las injecciones de dependiencias
# se sugiere crear una clase `Feature` o `ApplicationService` que hereden de las abtracciones
# por ejemplo estamos importando `Feature` original pero como `_Feature` para no confundir
from typing import TypeAlias
class Feature(_Feature, ABC):
    andres: TypeAlias = call_print
    
# de esta forma el IDE o editor nos ayudara a ver los tipos de las injecciones de dependencias
# Recordar utilizar la clase Feature de este modulo en lugar de `sincpro_framework.Feature` ya que este contiene 
# los tipos de las injecciones de dependencias y normalmente este contiene toda la configuracion 
    

once you initialize the bus, you will be able to import the framework in your application layer

this framework should be used in the application layer

pattern to import the framework follow the next snippet

# Path file: src.apps.siat_api
# Application layer main entry: __init__.py
# import the initialized framework
from src.apps.some_application.infrastructure.sp_framework import (
    ApplicationService,
    DataTransferObject,
    Feature,
    framework_sp,
)

# the `use_case` represent the application layer inside of it
# you should find all the `Feature` and `ApplicationService`
from .use_case import *

# Require to export to be consumed for the infrastructure layer or the more external layer
__all__ = [
    "use_case",
    "framework_sp",
    "Feature",
    "DataTransferObject",
    "ApplicationService",
]



# then import the framework_sp from any another consumer

Once you have the framework imported you will be able to register the use cases(Features or ServiceApplication)

from src.apps.some_application import framework_sp

# -------------------------------------------- #
#  Feature
# -------------------------------------------- #

@dataclass(kw_only=True)
class CommandRegisterServiceConfiguration(DataTransferObject):
    comm: str


@dataclass(kw_only=True)
class ResponseRegisterServiceConfiguration(DataTransferObject):
    comm: str


@framework_sp.feature(CommandRegisterServiceConfiguration)
class RegisterServiceConfiguration(Feature):
    def execute(
        self, dto: CommandRegisterServiceConfiguration
    ) -> ResponseRegisterServiceConfiguration:
        raise FeatureError("EError de feature")
        return ResponseRegisterServiceConfiguration(comm=dto.comm)

# -------------------------------------------- #
#  Application service
# -------------------------------------------- #
@dataclass(kw_only=True)
class CommandRegisterServiceConfiguration2(DataTransferObject):
    comm: str


@dataclass(kw_only=True)
class ResponseRegisterServiceConfiguration(DataTransferObject):
    comm: str


@framework_sp.app_service(CommandRegisterServiceConfiguration2)
class RegisterServiceConfiguration(ApplicationService):
    def execute(
        self, dto: CommandRegisterServiceConfiguration2
    ) -> ResponseRegisterServiceConfiguration:
        self.andres("Hello") # -> Dependency injected by the user
        self.feature_bus.execute(CommandRegisterServiceConfiguration(comm="Hello")) #-> Decoupled feature
        raise AppServiceError("Testing Global error")
        return ResponseRegisterServiceConfiguration(comm=dto.comm)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sincpro_framework-1.0.1.tar.gz (8.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sincpro_framework-1.0.1-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

File details

Details for the file sincpro_framework-1.0.1.tar.gz.

File metadata

  • Download URL: sincpro_framework-1.0.1.tar.gz
  • Upload date:
  • Size: 8.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.6 Linux/6.8.0-45-generic

File hashes

Hashes for sincpro_framework-1.0.1.tar.gz
Algorithm Hash digest
SHA256 200e20f2698789b26ac69aa3b36f578480e14c6a3c5de68c04e95a19ff372928
MD5 94cf14d2dd7175b2ebaf3fba8a9f0f05
BLAKE2b-256 2bca1b0504902a216188d890cb6770d234cee744397e4e824c2e9cddba434ff1

See more details on using hashes here.

File details

Details for the file sincpro_framework-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: sincpro_framework-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 9.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.6 Linux/6.8.0-45-generic

File hashes

Hashes for sincpro_framework-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d26ca35b857d44184887568c460e138551dbf7b6854655ea583827c19cb83ee6
MD5 509d29678214980f9c9364864dc145ac
BLAKE2b-256 9d931809882493124ef40607926f0f8b0aea601698b41d5f00601047e4245fe0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page