We leren & delen

ACA Group Blog

Lees meer over onze inzichten en meningen over diverse onderwerpen, nuttige inzichten en advies van onze experts.

Uitgelicht

20 JAN. 2023
Kickstart je volgende project met een kant-en-klare webapplicatie-architectuur
Kickstart je volgende project met een kant-en-klare webapplicatie-architectuur
Leestijd 6 min

Het starten van een nieuw webproject kan een ontmoedigende taak zijn met veel verschillende onderdelen om rekening mee te houden en te configureren. Voor ontwikkelaars kan het zeker handig zijn om toegang te hebben tot een startpunt voor het bouwen van webapps, met alle benodigde bestanden en configuraties al ingesteld. Het bespaart niet alleen veel tijd en moeite in vergelijking met wanneer je alles vanaf nul moet opbouwen, het verhoogt ook de productiviteit en maakt klanten blij omdat ze veel sneller tastbare resultaten kunnen zien. Bij ACA Group doen we veel van dergelijke implementaties en de volgende vereisten zijn gemeenschappelijk voor de meeste webapplicatieprojecten: Een geweldige gebruikerservaring: een snelle, responsieve en vlotte frontend die flexibel genoeg is om elk soort gebruikersinteractie te implementeren Betrouwbare en performante verwerking: een solide database en backend oplossing die gemakkelijk uitbreidbaar, testbaar, onderhoudbaar en begrijpbaar is voor elke ingenieur Gebruikersauthenticatie en -beveiliging: een robuuste en volwassen authenticatieserver die ook SSO en gebruikersfederatie heeft en integreert met veel verschillende providers Eenvoudige en veilige implementatie: toch eenvoudig te ontwikkelen zonder al te veel overhead Ons antwoord op deze terugkerende eisen is een flexibele softwarebasis die out of the box werkt. Met een paar regels in de terminal kun je een nieuw project opstarten dat alle bovenstaande functionaliteiten in een basistoestand heeft, wachtend om uitgebreid en uitgebouwd te worden. De figuur hieronder illustreert de basis van de architectuur die we vaak gebruiken voor kleine en middelgrote webapplicaties, en de verschillende services die een rol spelen. Natuurlijk zijn er nog andere componenten in het spel, maar die worden vaker per geval geïmplementeerd. Backend Laten we beginnen met het brein van de webapplicatie - de backend. Voor ons Python-team is het niet meer dan logisch om deze taal te gebruiken om de ruggengraat van de applicatie te bouwen. FastAPI biedt veel flexibiliteit in termen van hoe je bedrijfslogica en ontwerppatronen implementeert. Het is ook een van de best presterende backend-oplossingen die je kunt kiezen in Python; het heeft geweldige documentatie en wordt ondersteund door een solide community. Een populaire keuze voor projecten met data-analyse, machine learning of AI, een Python backend maakt het gemakkelijker om geavanceerde technologieën dichter bij de gebruiker te brengen. Frontend Voor het ontwerpen van de gebruikerservaring - of de frontend - geven we de voorkeur aan Angular , een volwassen en goed onderzocht JavaScript-framework dat overal in de industrie wordt gebruikt. Het is ontworpen om eenvoudig interactieve webapplicaties van één pagina te maken die in elke moderne webbrowser kunnen draaien. Angular heeft ook een gevestigde reputatie op het gebied van goede prestaties en schaalbaarheid, waardoor het risico op schaalbaarheidsproblemen bij grotere projecten afneemt. Een ander voordeel is dat Angular gestructureerd is en veel lijkt op backend code, waardoor het makkelijker te begrijpen is voor niet-frontend ontwikkelaars. Database en opslag Voor gegevensopslag is PostgreSQL een veelgebruikt en betrouwbaar databasemanagementsysteem (DBMS) dat zeer geschikt is voor verschillende toepassingen, waaronder webontwikkeling. Het staat bekend om zijn prestaties, vooral als het gaat om het verwerken van grote hoeveelheden gegevens. Het kan complexe query's efficiënt verwerken en heeft de reputatie goed te kunnen schalen naarmate de grootte van de database toeneemt. Het is ook rijk aan functies en heeft verschillende opties voor indexering en query optimalisatie. Beveiliging en verificatie Onze beveiligde authenticatieserver is gebouwd op Keycloak , een volwassen IAM-oplossing die organisaties helpt hun applicaties en diensten te beveiligen. Het is niet alleen open-source, maar ook gesponsord door 's werelds leider op het gebied van open source voor bedrijven, RedHat. Het biedt een enkel toegangspunt voor gebruikers om zichzelf te authenticeren en toegang te autoriseren tot verschillende bronnen; en het ondersteunt een breed scala aan authenticatiemechanismen, zoals gebruikersnaam en wachtwoord, twee-factor authenticatie en social login. Infrastructuur Het volgende stukje van de puzzel is NGinx , dat al het inkomende verkeer orkestreert en verdeelt over de services. Het is een krachtige en flexibele webserver en reverse proxy die vaak wordt gebruikt om inkomende klantverzoeken veilig en met hoge prestaties af te handelen. Het staat bekend om zijn vermogen om een groot aantal gelijktijdige verbindingen af te handelen met een laag gebruik van bronnen, en is vooral efficiënt bij het serveren van statische inhoud zoals afbeeldingen, CSS en JavaScript-bestanden. Nginx kan verzoeken van clients doorsturen naar een of meer services, waarbij het verkeer eenvoudig naar de juiste component van de webapplicatie wordt geleid en de belasting over meerdere servers of services wordt verdeeld, zelfs als ze dezelfde rol vervullen. Dit betekent ook dat alle verschillende services uitsluitend via NGinx communiceren met SSL/TLS protocollen, waardoor al het verkeer wordt versleuteld en gevoelige gegevens worden beveiligd. Implementatie Tot slot vergemakkelijkt Docker de implementatie en ontwikkeling. Door de verschillende onderdelen van de app te containeriseren, zoals de backend of de database, wordt het veel eenvoudiger om de app op verschillende hostingomgevingen te implementeren. Dit is vooral belangrijk als klanten verschillende eisen hebben op het gebied van hostingmachines, infrastructuur, enzovoort. Met Docker kunnen de services van de app op een gestandaardiseerde manier worden verpakt en vervolgens consistent worden ingezet in verschillende omgevingen. Docker heeft ook voordelen voor het beheren van de app in productie. Door componenten in containers te plaatsen, kun je eenvoudig op- of afschalen, updates en rollbacks uitrollen en de gezondheid van de app bewaken. Dit kan helpen om de betrouwbaarheid en onderhoudbaarheid van de app te verbeteren. Voor ontwikkelaars maakt Docker het ook makkelijker om de app in verschillende omgevingen te testen, samen te werken met teamleden en taken zoals het bouwen, testen en uitrollen van de app te automatiseren. Kickstart een nieuw project 👊 Het doel van deze architectuur is om een startpunt te bieden voor het bouwen van een webapplicatie met alle benodigde componenten al geconfigureerd. We hebben het verpakt in een sjabloon dat alles bevat wat je nodig hebt om te beginnen, zodat je niet vanaf nul een startarchitectuur hoeft te bouwen. In plaats daarvan kunt u de sjabloon gebruiken als basis en deze vervolgens aanpassen aan uw specifieke behoeften. Om deze template te gebruiken, hebben we gekozen voor een tool genaamd Cookiecutter. Het hoeft maar één keer geïnstalleerd te worden door de persoon die de initiële repository opzet om een nieuw project te maken op basis van een sjabloon van de bovenstaande architectuur. Als onderdeel van dit proces worden een paar waarden gevraagd om het sjabloon aan te passen, zoals de naam van het project, het e-mailadres van de beheerder, welke functies je wilt inschakelen, enzovoort. Zodra je Cookiecutter hebt gebruikt om de projectmap aan te maken, bevat deze alles wat je nodig hebt om de webapplicatie te bouwen en uit te voeren. Om met de app aan de slag te gaan, kun je een eenvoudig Docker-commando uitvoeren en de webapplicatie is in een mum van tijd klaar voor gebruik. Dit maakt live ontwikkeling op elk deel van de applicatie mogelijk met hot reload, en maakt de implementatie zo eenvoudig als een paar klikken. Conclusie Al met al kan een kant-en-klare webapplicatie-architectuur zoals beschreven in deze blog een waardevol hulpmiddel zijn om tijd en moeite te besparen op elk nieuw project. Door een solide basis te bieden voor het bouwen van een webapplicatie, kan het teams helpen om snel een MVP op te starten, zonder vanaf nul te hoeven beginnen. De combinatie van de bovenstaande technologieën bespaart niet alleen tijd en moeite, maar geeft je ook het vertrouwen dat je app goed is uitgerust voor een breed scala aan behoeften.

Lees verder
We leren & delen

ACA Group Blog

Lees meer over onze inzichten en meningen over diverse onderwerpen, nuttige inzichten en advies van onze experts.

Uitgelicht

20 JAN. 2023
Kickstart je volgende project met een kant-en-klare webapplicatie-architectuur
Kickstart je volgende project met een kant-en-klare webapplicatie-architectuur
Leestijd 6 min

Het starten van een nieuw webproject kan een ontmoedigende taak zijn met veel verschillende onderdelen om rekening mee te houden en te configureren. Voor ontwikkelaars kan het zeker handig zijn om toegang te hebben tot een startpunt voor het bouwen van webapps, met alle benodigde bestanden en configuraties al ingesteld. Het bespaart niet alleen veel tijd en moeite in vergelijking met wanneer je alles vanaf nul moet opbouwen, het verhoogt ook de productiviteit en maakt klanten blij omdat ze veel sneller tastbare resultaten kunnen zien. Bij ACA Group doen we veel van dergelijke implementaties en de volgende vereisten zijn gemeenschappelijk voor de meeste webapplicatieprojecten: Een geweldige gebruikerservaring: een snelle, responsieve en vlotte frontend die flexibel genoeg is om elk soort gebruikersinteractie te implementeren Betrouwbare en performante verwerking: een solide database en backend oplossing die gemakkelijk uitbreidbaar, testbaar, onderhoudbaar en begrijpbaar is voor elke ingenieur Gebruikersauthenticatie en -beveiliging: een robuuste en volwassen authenticatieserver die ook SSO en gebruikersfederatie heeft en integreert met veel verschillende providers Eenvoudige en veilige implementatie: toch eenvoudig te ontwikkelen zonder al te veel overhead Ons antwoord op deze terugkerende eisen is een flexibele softwarebasis die out of the box werkt. Met een paar regels in de terminal kun je een nieuw project opstarten dat alle bovenstaande functionaliteiten in een basistoestand heeft, wachtend om uitgebreid en uitgebouwd te worden. De figuur hieronder illustreert de basis van de architectuur die we vaak gebruiken voor kleine en middelgrote webapplicaties, en de verschillende services die een rol spelen. Natuurlijk zijn er nog andere componenten in het spel, maar die worden vaker per geval geïmplementeerd. Backend Laten we beginnen met het brein van de webapplicatie - de backend. Voor ons Python-team is het niet meer dan logisch om deze taal te gebruiken om de ruggengraat van de applicatie te bouwen. FastAPI biedt veel flexibiliteit in termen van hoe je bedrijfslogica en ontwerppatronen implementeert. Het is ook een van de best presterende backend-oplossingen die je kunt kiezen in Python; het heeft geweldige documentatie en wordt ondersteund door een solide community. Een populaire keuze voor projecten met data-analyse, machine learning of AI, een Python backend maakt het gemakkelijker om geavanceerde technologieën dichter bij de gebruiker te brengen. Frontend Voor het ontwerpen van de gebruikerservaring - of de frontend - geven we de voorkeur aan Angular , een volwassen en goed onderzocht JavaScript-framework dat overal in de industrie wordt gebruikt. Het is ontworpen om eenvoudig interactieve webapplicaties van één pagina te maken die in elke moderne webbrowser kunnen draaien. Angular heeft ook een gevestigde reputatie op het gebied van goede prestaties en schaalbaarheid, waardoor het risico op schaalbaarheidsproblemen bij grotere projecten afneemt. Een ander voordeel is dat Angular gestructureerd is en veel lijkt op backend code, waardoor het makkelijker te begrijpen is voor niet-frontend ontwikkelaars. Database en opslag Voor gegevensopslag is PostgreSQL een veelgebruikt en betrouwbaar databasemanagementsysteem (DBMS) dat zeer geschikt is voor verschillende toepassingen, waaronder webontwikkeling. Het staat bekend om zijn prestaties, vooral als het gaat om het verwerken van grote hoeveelheden gegevens. Het kan complexe query's efficiënt verwerken en heeft de reputatie goed te kunnen schalen naarmate de grootte van de database toeneemt. Het is ook rijk aan functies en heeft verschillende opties voor indexering en query optimalisatie. Beveiliging en verificatie Onze beveiligde authenticatieserver is gebouwd op Keycloak , een volwassen IAM-oplossing die organisaties helpt hun applicaties en diensten te beveiligen. Het is niet alleen open-source, maar ook gesponsord door 's werelds leider op het gebied van open source voor bedrijven, RedHat. Het biedt een enkel toegangspunt voor gebruikers om zichzelf te authenticeren en toegang te autoriseren tot verschillende bronnen; en het ondersteunt een breed scala aan authenticatiemechanismen, zoals gebruikersnaam en wachtwoord, twee-factor authenticatie en social login. Infrastructuur Het volgende stukje van de puzzel is NGinx , dat al het inkomende verkeer orkestreert en verdeelt over de services. Het is een krachtige en flexibele webserver en reverse proxy die vaak wordt gebruikt om inkomende klantverzoeken veilig en met hoge prestaties af te handelen. Het staat bekend om zijn vermogen om een groot aantal gelijktijdige verbindingen af te handelen met een laag gebruik van bronnen, en is vooral efficiënt bij het serveren van statische inhoud zoals afbeeldingen, CSS en JavaScript-bestanden. Nginx kan verzoeken van clients doorsturen naar een of meer services, waarbij het verkeer eenvoudig naar de juiste component van de webapplicatie wordt geleid en de belasting over meerdere servers of services wordt verdeeld, zelfs als ze dezelfde rol vervullen. Dit betekent ook dat alle verschillende services uitsluitend via NGinx communiceren met SSL/TLS protocollen, waardoor al het verkeer wordt versleuteld en gevoelige gegevens worden beveiligd. Implementatie Tot slot vergemakkelijkt Docker de implementatie en ontwikkeling. Door de verschillende onderdelen van de app te containeriseren, zoals de backend of de database, wordt het veel eenvoudiger om de app op verschillende hostingomgevingen te implementeren. Dit is vooral belangrijk als klanten verschillende eisen hebben op het gebied van hostingmachines, infrastructuur, enzovoort. Met Docker kunnen de services van de app op een gestandaardiseerde manier worden verpakt en vervolgens consistent worden ingezet in verschillende omgevingen. Docker heeft ook voordelen voor het beheren van de app in productie. Door componenten in containers te plaatsen, kun je eenvoudig op- of afschalen, updates en rollbacks uitrollen en de gezondheid van de app bewaken. Dit kan helpen om de betrouwbaarheid en onderhoudbaarheid van de app te verbeteren. Voor ontwikkelaars maakt Docker het ook makkelijker om de app in verschillende omgevingen te testen, samen te werken met teamleden en taken zoals het bouwen, testen en uitrollen van de app te automatiseren. Kickstart een nieuw project 👊 Het doel van deze architectuur is om een startpunt te bieden voor het bouwen van een webapplicatie met alle benodigde componenten al geconfigureerd. We hebben het verpakt in een sjabloon dat alles bevat wat je nodig hebt om te beginnen, zodat je niet vanaf nul een startarchitectuur hoeft te bouwen. In plaats daarvan kunt u de sjabloon gebruiken als basis en deze vervolgens aanpassen aan uw specifieke behoeften. Om deze template te gebruiken, hebben we gekozen voor een tool genaamd Cookiecutter. Het hoeft maar één keer geïnstalleerd te worden door de persoon die de initiële repository opzet om een nieuw project te maken op basis van een sjabloon van de bovenstaande architectuur. Als onderdeel van dit proces worden een paar waarden gevraagd om het sjabloon aan te passen, zoals de naam van het project, het e-mailadres van de beheerder, welke functies je wilt inschakelen, enzovoort. Zodra je Cookiecutter hebt gebruikt om de projectmap aan te maken, bevat deze alles wat je nodig hebt om de webapplicatie te bouwen en uit te voeren. Om met de app aan de slag te gaan, kun je een eenvoudig Docker-commando uitvoeren en de webapplicatie is in een mum van tijd klaar voor gebruik. Dit maakt live ontwikkeling op elk deel van de applicatie mogelijk met hot reload, en maakt de implementatie zo eenvoudig als een paar klikken. Conclusie Al met al kan een kant-en-klare webapplicatie-architectuur zoals beschreven in deze blog een waardevol hulpmiddel zijn om tijd en moeite te besparen op elk nieuw project. Door een solide basis te bieden voor het bouwen van een webapplicatie, kan het teams helpen om snel een MVP op te starten, zonder vanaf nul te hoeven beginnen. De combinatie van de bovenstaande technologieën bespaart niet alleen tijd en moeite, maar geeft je ook het vertrouwen dat je app goed is uitgerust voor een breed scala aan behoeften.

Lees verder

Alle blogs

Leestijd 12 min
10 FEB. 2023

In softwareontwikkeling zijn datatransformatie en het genereren van gegevens uit andere gegevens veelvoorkomende taken. Alle programmeertalen pakken dit op een andere manier aan, elk met hun eigen troeven en minpunten. Afhankelijk van het probleem, zijn sommige manieren meer aangewezen dan andere. In deze blog ontdek je eenvoudige maar toch krachtige methodes om gegevens te genereren en te transformeren in Python. Voordat we een complexer geval bespreken, beginnen we met een basisvoorbeeld. Stel je voor dat we een paar winkels hebben en elke winkel heeft zijn eigen database met items die zijn toegevoegd door werknemers. Sommige velden zijn optioneel, wat betekent dat werknemers niet altijd alles invullen. Naarmate we groeien, kan het moeilijk worden om een duidelijk overzicht te krijgen van alle items in onze winkels. Daarom ontwikkelen we een Python-script dat de verschillende items uit de databases van onze winkels verzamelt in één enkele database. from stores import store_1 , store_2 , store_3 # In de hele code worden typehints gebruikt. items_1 : Generator [ Item , Geen , Geen ] = store_1 . get_items ( ) items_2 : Generator [ Item , Geen , Geen ] = store_2 . get_items ( ) items_3 : Generator [ Item , Geen , Geen ] = store_3 . get_items ( ) Generatoren store_1.get_items() retourneert een generator van items. Generators zullen een belangrijke rol spelen in deze blogpost. Met generatoren kunnen we een complexe keten van transformaties opzetten over enorme hoeveelheden gegevens zonder dat we zonder geheugen komen te zitten, terwijl onze code beknopt en schoon blijft. Als je nog niet bekend bent met Python: def a_generator ( ) : for something in some_iterable : # do logic yield something Twee dingen zijn hier belangrijk. Ten eerste, het aanroepen van een generator zal geen data teruggeven; het zal een iterator teruggeven. Ten tweede worden waarden op verzoek geproduceerd. Een meer diepgaande uitleg kan hier worden gevonden. Syntax Er zijn twee manieren om generatoren te maken. De eerste lijkt op een normale Python functie, maar heeft een yield statement in plaats van een return statement. De andere is beknopter, maar kan snel ingewikkeld worden als de logica complexer wordt. Het heet de Python generator expressie syntaxis en wordt voornamelijk gebruikt voor eenvoudigere generatoren. # Basis generator syntax def generate_until ( n : int ) - Generator [ int , None , None ] : while i n ; yield i i += 1 # Generator expressie syntax gen_until_5 : Generator [ int , None , None ] = ( i for i in range ( 5 ) ) Code Om het eenvoudig te houden, voeren we het script aan het eind van de dag één keer uit, zodat we een complete database hebben met alle items uit alle winkels. uit stores importeer store_1 , store_2 , store_3 uit database importeer all_items # In de hele code worden typehints gebruikt. items_1 : Generator [ Item , Geen , Geen ] = store_1 . get_items ( ) items_2 : Generator [ Item , Geen , Geen ] = store_2 . get_items ( ) items_3 : Generator [ Item , Geen , Geen ] = store_3 . get_items ( ) # Laten we aannemen dat onze `add_or_update()` functie generators accepteert. # Als een item al bestaat, wordt het bijgewerkt, anders wordt het toegevoegd aan de database. # We kunnen ze gewoon een voor een toevoegen, zoals hier. all_items . add_or_update ( items_1 ) all_items . add_or_update ( items_2 ) all_items . add_or_update ( items_3 ) # De database bevat nu alle nieuwste items van alle winkels. Voor dit gebruik is dit prima. Maar als de complexiteit groeit en er meer winkels worden toegevoegd, kan het snel onoverzichtelijk worden. Gelukkig heeft Python geweldige ingebouwde tools om onze code te vereenvoudigen. Itertools Eén module in Python heet itertools. Volgens de Python-documenten " standaardiseert de module een kernset van snelle, geheugenefficiënte hulpmiddelen die op zichzelf of in combinatie nuttig zijn. Samen vormen ze een "iterator algebra", waardoor het mogelijk wordt om gespecialiseerde tools beknopt en efficiënt in pure Python te bouwen. " Een geweldige functie is itertools.chain() . Deze wordt gebruikt om meerdere iterables aan elkaar te 'ketenen' alsof ze één zijn. We kunnen het gebruiken om onze generatoren aan elkaar te koppelen. uit stores importeer store_1 , store_2 , store_3 uit database importeer all_items uit itertools importeer chain # Typehints worden door de hele code gebruikt. items_1 : Generator [ Item , None , None ] = store_1 . get_items ( ) items_2 : Generator [ Item , None , None ] = store_2 . get_items ( ) items_3 : Generator [ Item , Geen , Geen ] = store_3 . get_items ( ) # Met itertools.chain kunnen we de generators samenvoegen tot één. # Chain zelf is ook een generatorfunctie, dus er wordt nog geen data gegenereerd. items : Generator [ Item , None , None ] = chain ( items_1 , items_2 , items_3 ) all_items . add_or_update ( items ) # - hier worden gegevens gegenereerd # De database bevat nu alle nieuwste items van alle winkels . Genertator functies Laten we nu aannemen dat ons item een tupel is met vijf velden: naam, merk, leverancier, kosten en het aantal stuks in de winkel. Het heeft de volgende signatuur: tuple[str,str,str,int,int]. Als we de totale waarde van de artikelen in de winkel willen, hoeven we alleen maar het aantal artikelen met de kosten te vermenigvuldigen. # zowel ontvangt als retourneert een generator def calc_total_val ( items : Generator ) - Generator : for item in items : # geef de eerste 3 artikelen en het product van de laatste 2 geef *item [ : 3 ] , item [ 3 ] *item [ 4 ] # we kunnen dit ook schrijven als een generator expressie omdat het zo eenvoudig is ( ( *item [ : 3 ] , item [ 3 ] *item [ 4 ] ) for item in items ) Nu ziet het er zo uit: tuple[str, str, str, int]. Maar we willen het uitvoeren als JSON. Daarvoor kunnen we gewoon een generator maken die een woordenboek teruggeeft en daar json.dumps() op aanroepen. Laten we aannemen dat we een iterator van dicts kunnen doorgeven aan de add_or_update() functie en dat deze automatisch json.dumps() aanroept. # zowel ontvangt als retourneert een generator def as_dict_item ( items : Generator ) - Generator : for item in items : yield { "name" : item [ 0 ] , "brand" : item [ 1 ] , "supplier" : item [ 2 ] , "total_value" : item [ 3 ] , } Nu we meer logica hebben, laten we eens kijken hoe we die kunnen samenvoegen. Een geweldig ding over generatoren is hoe duidelijk en beknopt het is om ze te gebruiken. We kunnen een functie maken voor elke processtap en de gegevens er doorheen laten lopen. from stores import store_1 , store_2 , store_3 from database import all_items from itertools import chain def calc_total_val ( items ) : for item in items : yield *item [ : 3 ] , item [ 3 ] *item [ 4 ] def as_item_dict ( items ) : for item in items : yield { " name" : item [ 0 ] , " brand" : item [ 1 ] , " supplier" : item [ 2 ] , " total_value" : item [ 3 ] , } items_1 = store_1 . get_items ( ) items_2 = store_2 . get_items ( ) items_3 = store_3 . get_items ( ) items = chain ( items_1 , items_2 , items_3 ) # - maak één grote iterable items = calc_total_val ( items ) # - bereken de totale waarde items = as_item_dict ( items ) # - transformeer het in een dict all_items . add_or_update ( items ) # - hier worden de gegevens gegenereerd # De database bevat nu alle nieuwste items van alle winkels Om de stappen die we hebben genomen te laten zien, heb ik alles opgesplitst. Er zijn nog een paar dingen die verbeterd kunnen worden. Kijk eens naar de functie calc_total_val(). Dit is een perfect voorbeeld van een situatie waarin een generatoruitdrukking kan worden gebruikt. from stores import store_1 , store_2 , store_3 from database import all_items from itertools import chain def as_item_dict ( items ) : for item in items : yield { " naam" : item [ 0 ] , " merk" : item [ 1 ] , " leverancier" : item [ 2 ] , " totaal_waarde" : item [ 3 ] , } items_1 = store_1 . get_items ( ) items_2 = store_2 . get_items ( ) items_3 = store_3 . get_items ( ) items = keten ( items_1 , items_2 , items_3 ) items = ( ( *item [ : 3 ] , item [ 3 ] *item [ 4 ] ) voor item in items ) items = as_item_dict ( items ) all_items . add_or_update ( items ) Om het nog netter te maken, kunnen we al onze functies in een aparte module plaatsen. Op deze manier bevat ons hoofdbestand alleen de stappen die de gegevens doorlopen. Als we beschrijvende namen gebruiken voor onze generatoren, kunnen we meteen zien wat de code zal doen. Nu hebben we dus een pijplijn voor de gegevens gemaakt. Hoewel dit slechts een eenvoudig voorbeeld is, kan het ook worden gebruikt voor meer gecompliceerde workflows. Gegevensproducten Alles wat we in het bovenstaande voorbeeld hebben gedaan, kan eenvoudig worden toegepast op een Data Product. Als je niet bekend bent met gegevensproducten, is hier een geweldige tekst over gegevensmazen . Stel je voor dat we een gegevensproduct hebben dat gegevens samenvoegt. Het heeft meerdere ingangen met verschillende soorten gegevens. Elk van die ingangen moet worden gefilterd, getransformeerd en opgeschoond voordat we ze kunnen samenvoegen tot één uitvoer. De klant vereist dat de uitvoer een enkel JSON-bestand is dat wordt opgeslagen in een S3-bucket. De bestaande infrastructuur staat slechts 500 Mb RAM toe voor de containers. Laten we nu alle gegevens laden, wat transformaties doen, alles samenvoegen en het in een JSON-bestand parsen. from input_ports import port_1 , port_2 from output_ports import S3_port from json import dumps data_port_1 : Generator = port_1 . get_data ( ) data_port_2 : Generator = port_2 . get_data ( ) output = [ ] voor rij in data_port_1 : # doe hier wat transformatie of filtering output . append ( rij ) voor rij in data_port_2 : # doe hier wat transformatie of filtering output . append ( rij ) S3_port . save ( dumps ( output )) Hoewel dit een uitstekende oplossing lijkt die het werk doet en eenvoudig te begrijpen is, crasht onze container plotseling door een OutOfMemory-fout. Na wat lokaal testen op onze machine, zien we dat het een 834Mb bestand heeft geproduceerd dat niet kan werken met slechts 500 MB RAM voor de container. Het probleem met de bovenstaande code is dat we alles eerst in een lijst bewaren, zodat alles in het geheugen wordt opgeslagen. Oplossing Laten we het nog eens proberen. Voor S3 kunnen we MultipartUpload gebruiken. Dit betekent dat we niet het hele bestand in het geheugen hoeven te bewaren. En natuurlijk moeten we onze lijsten vervangen door generatoren. from input_ports import port_1 , port_2 from output_ports import S3_port from itertools import chain from json import dumps data_port_1 : Generator = port_1 . get_data ( ) data_port_2 : Generator = port_2 . get_data ( ) def port_1_transformer ( data : Generator ) : voor rij in data : # doe hier wat transformatie of filtering opbrengst rij def port_2_transformer ( data : Generator ) : voor rij in data : # doe hier wat transformatie of filtering opbrengst rij output = chain ( port_1_transformer ( data_port_1 ) , port_2_transformer ( data_port_2 ) ) voor deel in output : S3_port . save_part ( dumps ( part )) Omdat we nu maar één onderdeel tegelijk in het geheugen hebben, gebruikt dit veel minder geheugen dan de eerdere oplossing met bijna geen extra werk. Echter, het sturen van een postverzoek naar S3 voor elk item kan een beetje veel zijn. Vooral als we 300.000 items hebben. Maar er is nog een probleem ... De 'part size' moet tussen de 5MiB en 5GiB zijn. Om dit op te lossen, kunnen we meerdere onderdelen groeperen voordat we ze parseren. Maar als we er teveel groeperen, bereiken we opnieuw de geheugenlimiet. De grootte van de chunk moet daarom afhangen van hoe groot de individuele delen van je data zijn. Laten we, om dit te demonstreren, een grootte van 1.000 gebruiken. Hoe groter de chunkgrootte, hoe meer geheugen er wordt gebruikt, maar hoe minder verzoeken aan S3. We geven er dus de voorkeur aan dat onze chunks zo groot mogelijk zijn zonder dat het geheugen opraakt. from input_ports import port_1 , port_2 from output_ports import S3_port from itertools import chain from json import dumps data_port_1 : Generator = port_1 . get_data ( ) data_port_2 : Generator = port_2 . get_data ( ) def makebatch ( iterable , len ) : for first in iterable : yield chain ( [ first ] , islice ( iterable , len - 1 ) ) def port_1_transformer ( data : Generator ) : for row in data : # do some transformation or filtering here yield row def port_2_transformer ( data : Generator ) : for row in data : # do some transformation or filtering here yield row output = chain ( port_1_transformer ( data_port_1 ) , port_2_transformer ( data_port_2 ) ) for chunk in makebatch ( output , 1000 ) : S3_port . save_part ( dumps ( chunk ) ) Dit is alles wat er hoeft te gebeuren. Het is genoeg om grote hoeveelheden gegevens te transformeren en op te slaan in een S3-bucket, zelfs als de bronnen schaars zijn. Bonus Als je berekeningen rekenintensief zijn, is het eenvoudig om ze parallel uit te voeren. Met slechts een paar extra regels kunnen we onze transformers op meerdere cores laten draaien. from multiprocessing . pool import Pool met Pool ( 4 ) als pool : # imap_unordered kan ook worden gebruikt als de volgorde niet belangrijk is data_1 = pool . imap ( port_1_transformer , data_port_1 , chunksize=500 ) data_2 = pool . imap ( port_2_transformer , data_port_2 , chunksize=500 ) uitvoer = keten ( data_1 , data_2 ) Het beste hieraan? We hoeven verder niets te veranderen omdat imap kan worden geïtereerd om resultaten te krijgen, net als elke andere generator. Laten we nu alles bij elkaar gooien. Dit is alles wat we nodig hebben voor rekenintensieve transformaties, over grote hoeveelheden gegevens, met gebruik van meerdere cores. from input_ports import port_1 , port_2 from output_ports import S3_port from itertools import chain from json import dumps from multiprocessing . pool import Pool data_port_1 : Generator = port_1 . get_data ( ) data_port_2 : Generator = port_2 . get_data ( ) def makebatch ( iterable , len ) : for first in iterable : yield chain ( [ first ] , islice ( iterable , len - 1 ) ) def port_1_transformer ( data : Generator ) : for row in data : # do some transformation or filtering here yield row def port_2_transformer ( data : Generator ) : for row in data : # do some transformation or filtering here yield row with Pool ( 4 ) as pool : # imap_unordered could also be used if the order is not important data_1 = pool . imap ( port_1_transformer , data_port_1 , chunksize=500 ) data_2 = pool . imap ( port_2_transformer , data_port_2 , chunksize=500 ) uitvoer = keten ( data_1 , data_2 ) voor chunk in makebatch ( uitvoer , 1000 ) : S3_port . save_part ( dumps ( chunk ) ) Conclusie Generatoren worden vaak verkeerd begrepen door nieuwe ontwikkelaars, maar ze kunnen een uitstekend hulpmiddel zijn. Of het nu gaat om een eenvoudige transformatie of iets geavanceerder zoals een gegevensproduct, Python is een goede keuze vanwege het gebruiksgemak en de overvloed aan tools die beschikbaar zijn in de standaardbibliotheek.

Lees verder
Hoe kies je tussen Python en NodeJS?
Leestijd 5 min
16 MEI 2022

Python en NodeJS zijn allebei geweldige oplossingen voor het bouwen van moderne webapplicaties. Maar welke van de twee moet je gebruiken? In deze blog leggen we hun belangrijkste kenmerken uit, zodat je kunt kiezen wat het beste is voor jouw project en team. In een eerdere blog hebben we al uitgelegd wat het verschil is tussen front-end en back-end frameworks. Vanuit het perspectief van een ontwikkelaar en architect wordt de logica van een programma gedeeld tussen front-end en back-end . Op die manier wordt de verantwoordelijkheid goed verdeeld, terwijl ontwikkeling, ondersteuning op lange termijn en het toevoegen van nieuwe functies aan de applicatie eenvoudiger en beter onderhoudbaar worden. Het stimuleert een goede samenwerking tussen de teamleden die aan het project werken. Als je ooit een grote applicatie hebt ontwikkeld met gewoon JavaScript of jQuery en AJAX, dan is er een inherente rommeligheid die gepaard gaat met een dergelijke schaal in die context. Het gebruik van front-end frameworks houdt je code gestructureerd en schoon aan de front-end kant en versnelt de ontwikkeling van je applicatie , aangezien je bekend bent met het framework dat je gebruikt. Aangezien React of VueJS, of elk ander front-end framework, een RESTful API nodig heeft om mee te communiceren om een webapplicatie dynamisch en gepersonaliseerd te maken, is het creëren van de back-end API met iets als FastAPI of Flask als je Python-verslaafd bent, of NodeJS als je een JavaScript-fan bent, een geweldige manier om die scheiding van zorgen te benaderen waar we het in onze andere blog over hebben gehad. Python of NodeJS? De server-kant of back-end van een applicatie is de ruggengraat van het project en de client-kant is ervan afhankelijk. Hoe mooi, performant en responsief je frontend ook is, de applicatie zal plat op zijn gezicht vallen zonder een robuuste backend om het overeind te houden. Dit leidt tot de onvermijdelijke keuze voor elke architect om te kiezen tussen de twee titanen van de back-end technologie - NodeJS vs Python. Kiezen tussen deze twee kan een ontmoedigende taak zijn, vooral als je niet weet voor welke specifieke scenario's ze geschikt zijn. Afhankelijk van de omvang van het project en het team dat je hebt, is het kiezen van de "ideale" back-endtechnologie misschien niet essentieel. Kies gewoon wat ideaal is voor je ontwikkelteam dat samenwerking, onderhoudbaarheid, codekwaliteit en snelheid van ontwikkeling bevordert. Als je een geweldig Python-team hebt, maak dan gebruik van hun vaardigheden door ze de backend te laten bouwen in combinatie met een front-end framework of een templating engine (zoals Jinja2) als de frontend eenvoudig genoeg is. Als je echter een team van geweldige full stack ontwikkelaars hebt, maak dan gebruik van hun ervaring en kennis van JavaScript en zorg voor een uniforme code stack met NodeJS. Als je nog steeds beide opties overweegt en wilt kiezen wat het beste is voor jouw project, dan vind je hieronder een lijst met dingen waar zowel Python als NodeJS goed in zijn. De sterke punten van Python Python is een beproefde programmeertaal die al heel lang bestaat. Het is de laatste jaren sterk geoptimaliseerd en biedt nu zeer goede prestaties. Inherente codehelderheid zorgt voor een gemakkelijk te onderhouden codebase en vergemakkelijkt de samenwerking tussen teamleden. Debuggen is eenvoudiger dan in JavaScript, wat de productiviteit verder bevordert. Het heeft tonnen bestaande bibliotheken, integraties en goed geschreven documentatie om back-end functionaliteit aan te vullen zonder het wiel opnieuw uit te vinden. Python is DE programmeertaal voor Big Data, Machine Learning, AI en veel op onderzoek gebaseerde of wetenschappelijke verwerkingstaken die moeilijker te implementeren zouden zijn met JS. Sommige back-end oplossingen zoals FastAPI worden geleverd met cloud-native oplossingen zoals Jina. De sterke punten van NodeJS Een unified stack project is meestal een goed idee als je ervaren ontwikkelaars hebt in de stack waar je je op richt. Een webapplicatie met alleen Python heeft nadelen en schaalt niet goed zonder veel handgemaakte optimalisaties. Dus als je voor één stack gaat, is een JavaScript frontend framework + NodeJS de betere keuze. Hoewel de onderhoudbaarheid van code een probleem kan zijn voor grootschalige projecten, kunnen kleinere projecten of proof-of-concepts sneller worden ontwikkeld dan met Python. Het is inherent event-driven en heeft een non-blocking I/O model waardoor het een ideale optie is voor het ontwikkelen van data-streaming real-time applicaties zoals messaging applicaties of snelle e-commerce websites. NodeJS gaat sierlijker om met invoer- en uitvoerstromen dan Python en is geweldig in het weergeven van en reageren op gegevensstromen. Wanneer je te maken hebt met veel gebruikersinteracties en "snelle" of bijna onmiddellijke reacties van de UI wenselijk zijn, is NodeJS een betere keuze dan Python. Conclusie Python biedt een geweldige oplossing voor back-end diensten, gebouwd op een volwassen programmeertaal. Het gebruiken als een full-stack, Python-only oplossing met templating is echter beperkend. Python inzetten via bijvoorbeeld FastAPI of Flask als backend webserver en combineren met een frontend framework, zoals React JS of Vue JS, is een zeer goede optie voor het bouwen van een moderne webapplicatie. Het wordt geleverd met alle benodigde tools voor het bouwen van geweldige applicaties die gebruik moeten maken van machine learning, AI, data-analyse en is over het algemeen een geweldige keuze als je rekening moet houden met complexe bedrijfsregels die worden toegepast op back-end logica. NodeJS is ook fantastisch en wordt met de dag beter. Het gebruikt een event-driven, non-blocking I/O-model waardoor het een ideale optie is voor het ontwikkelen van data-intensieve real-time toepassingen. Over het algemeen biedt het betere prestaties en snelheid dan op Python gebaseerde apps, maar het implementeren van complexe bedrijfslogica is moeilijker dan in Python. Het is een ideale oplossing voor het ontwikkelen van messaging- of chattoepassingen, of elk soort datastreamingtoepassing. Het is ook geweldig voor e-commerce apps en websites die afhankelijk zijn van de snelheid van het verwerken van gebruikersverzoeken en het reageren op een "snelle" manier.

Lees verder
Leestijd 3 min
30 JUN. 2021

Waarom is Python een van de snelst groeiende programmeertalen ter wereld? En waarom hebben wij Python gekozen als een van onze programmeertalen? Om die vragen te beantwoorden, zullen een aantal van onze experts op dit gebied je door ons verhaal leiden in de volgende blogposts in deze serie: Waarom we (ook) voor Python hebben gekozen Hoe bedrijven Python gebruiken in de echte wereld Waarom Python zo populair is in innovatie De juiste oplossing op het juiste moment De traditie en het hart van ACA Group liggen in klantgerichtheid en innovatie. Daarom beperken we ons niet tot één programmeertaal of één specifieke technologie of oplossing. We onderzoeken de markt, experimenteren met nieuwe technologieën en zoeken altijd naar de best mogelijke oplossing voor onze huidige en toekomstige klanten. Dit is precies de reden waarom we Python hebben gekozen als een van onze programmeertalen. Maar voordat we ons richten op het "waarom Python?", laten we beginnen met het hoe. Hoe is het allemaal begonnen voor Python? Snelst groeiende programmeertaal ter wereld Python is eigenlijk begonnen als een hobbyproject van Guido Van Rossum. Tijdens een lange vakantievakantie in december 1989 begon Guido met het ontwikkelen van een ABC-achtige taal die kon praten met het OS en geschikt zou zijn om snel OS-hulpprogramma's voor Amoeba te ontwikkelen. Hij noemde zijn ontluikende project Python , geïnspireerd op het Monty Python's Flying Circus televisieprogramma. (Bron: Computer - Guido van Rossum: De beginjaren van Python https://www.computer.org/csdl/magazine/co/2015/02/mco2015020007/13rRUy3gmYB) Flash forward naar 2021: Guido's hobbyproject heeft een ongelooflijke groei doorgemaakt en is uitgegroeid tot een wereldberoemde programmeertaal. En je hoeft mij niet op mijn woord te geloven, talrijke onderzoeken tonen het aan: Python is echt de snelst groeiende programmeertaal ter wereld met meer dan zes miljoen ontwikkelaars . Kijk maar eens naar een van deze populaire en bekende gegevenslinks: RedMonk-rating , Github , Stack Overflow , PYPYL-index , Slashdata en TIOBE-index . Waarom is Python zo populair? Hier gaan we: de aanwijzing waar jullie waarschijnlijk allemaal op hebben gewacht. "Waarom is Python zo populair en waarom heeft ACA Python gekozen als een van de programmeertalen?". Eenvoud en doeltreffendheid Python is ontworpen om een zeer leesbare taal te zijn en die eenvoud is een van de belangrijkste redenen waarom het zo populair is. Python is een krachtige en elegante taal die duidelijk en consistent wil zijn met een eenvoudige syntaxis. Dit betekent dat het zeer toegankelijk is voor beginners en dat het een relatief overzichtelijke visuele lay-out heeft. Omdat het geschreven is in en gelezen kan worden als alledaags Engels (zonder leestekens), is Python snel uitgegroeid tot een van de makkelijkste programmeertalen om te leren. En last but not least, deze eenvoud en consistentie maakt het ook zeer effectief voor programmeurs om te gebruiken, en dus kostenefficiënter om applicaties mee te bouwen. Gemeenschap bibliotheken Met de Python-gemeenschap aan je zijde sta je er nooit alleen voor. Er zijn veel grote en actieve gemeenschappen over de hele wereld die veel ondersteuning bieden. Het feit dat Python zo wijdverspreid is over verschillende industrieën, bedrijven en mensen, betekent dat er een enorm aantal ontwikkelaars met de taal werkt. Zo'n grote gemeenschap die blijft groeien, resulteert in veel ondersteuningsmateriaal, betrouwbaarheid en vertrouwen. Ontwikkelaars kunnen niet alleen vertrouwen op de community, maar ook op een uitstekende en uitgebreide lijst van bibliotheken. Deze bibliotheken en frameworks zijn een ongelooflijke bron van informatie en besparen tijd in projecten . Dit maakt zowel de bibliotheken als Python nog populairder. Veelzijdigheid en flexibiliteit Een van de dingen die ontwikkelaars geweldig vinden aan deze programmeertaal is het feit dat het kan worden gebruikt in een verscheidenheid aan projecten en in meerdere industrieën, waaronder data science, machine learning, blockchain en nog veel meer. Met andere woorden, Python beperkt je niet tot een bepaalde toepassing. Python is niet gemaakt om een specifieke behoefte te beantwoorden, dus het wordt niet gedreven door specifieke templates of API's, wat zowel vrijheid als geschiktheid voor snelle ontwikkeling mogelijk maakt. Dit zijn de belangrijkste en bekendste redenen achter het succes van Python. Maar hoe zit het met de mogelijke nadelen, de bruikbaarheid en de relatie met innovatie? Wil je meer weten over Python? Als je Python al een beetje kent, dan weet je dat we vandaag slechts een tipje van de sluier hebben opgelicht. Geen zorgen! Onze volgende twee blogposts worden binnenkort gelanceerd en onthullen: Waar je rekening mee moet houden als je Python kiest of ermee begint Waar en hoe bedrijven over de hele wereld Python tegenwoordig gebruiken Waarom Python een van de meest gewilde vaardigheden in datawetenschap is Waarom Python zo populair is in innovatie Blijf op de hoogte!

Lees verder