Results 1 to 14 of 14

Thread: Delphi en "Feature Flag": best practices

  1. #1
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,582

    Delphi en "Feature Flag": best practices

    Hallo allemaal,

    Ik ben benieuwd naar hoe collega developers omgaan met onderstaand vraagstuk, maar laat ik bij het begin beginnen.

    Het bedrijf waar ik werk maakt software dat een code-base heeft dat meer dan 20 jaar oud is, ook hebben we wereldwijd tienduizenden klanten die het pakket 24/7 gebruiken.
    Zoals zo vaak brengt dit veel legacy (lees: spaghetti) code met zich mee, al zijn er ook veel latere stukken code dat netjes volledig object georiŽnteerd zijn.

    De werkwijze waarmee we nu globaal werken (we zijn met maar een heel klein team):
    • De "Product Owner" (PO) maakt feature request of bug aan en zet dit op naam van ťťn van de developers (dev)
    • De dev in kwestie pakt de laatste code uit master en creŽert een eigen (nieuwe) branche voor zijn taak.
    • Dev werkt aan zijn taak, test het en als hij tevreden is pushed hij zijn code en doet een pull request naar master, waarna de wijzigingen gemerged worden met master
    • Vervolgens gaat er een seintje naar de tester (QA), die de nieuwe implementatie (in master) vervolgens aan de tand voelt.
    • Wanneer de QA en PO vinden dat de taak goed volbracht is, krijgt de dev de opdracht om de wijzigingen te cherry picken (of pushen) naar de definitieve klantversie.

    Deze flow zou prima zijn in een ideale wereld, maar helaas leven we daar niet in, en met tienduizenden klanten (en dus ook verschillende instellingen en setups) kan het wel eens gebeuren dat er bij een bepaalde klant ineens iets niet meer werkt.
    Op dit moment is het zo dat er dan een hoge prioriteit taak wordt aangemaakt en dat (afhankelijk van de functie en of er wel of niet een work-around voor is) eventueel een oudere, nog wel correct werkende, versie wordt teruggezet (met het gevolg dat andere, nieuwe, functionaliteit niet meer aanwezig is).

    Nu wil management graag dat wij, in ons van spaghetti code vergeven product, iets van een "Feature Flag" (of "Feature Toggle") inbouwen die @runtime gezet kan worden (in een "Geheim" menu-scherm oid) door de supportafdeling.

    De meest "Simpele" (maar niet echt "Eenvoudige") manier zou zijn om dingen te doen als:
    Delphi Code:
    1. procedure BerekenPrijs(const AAantal: Integer; const AEenheidsPrijs): Currency;
    2. begin
    3.   if gTask1234 then // We moeten de nieuwe code gebruiken wanneer dit aan staat
    4.     Result := AAantal * AEenheidsPrijs
    5.   else
    6.     Result := Round(AAantal * AEenheidsPrijs); // Deze code is fout
    7. end;
    8.  
    9. procedure WeGaanRekenen;
    10. begin
    11.   WriteLn(BerekenPrijs(3, 1.46));
    12. end;
    Maar in de meeste gevallen is dat niet te doen, omdat je in een enkele method op meerdere plaatsen wijzigingen hebben die aan- of uitgezet moeten kunnen worden.
    Nog ingewikkelder wordt het als twee (of meer) collega's toevallig in dezelfde method zaken hebben aangepast (wellicht zelf in dezelfde stukken code).

    Je kunt er ook voor kiezen om het op method niveau te regelen, bijvoorbeeld:
    Delphi Code:
    1. procedure BerekenPrijs_1234(const AAantal: Integer; const AEenheidsPrijs): Currency;
    2. begin
    3.   Result := AAantal * AEenheidsPrijs;
    4. end;
    5.  
    6. procedure BerekenPrijs(const AAantal: Integer; const AEenheidsPrijs): Currency;
    7. begin
    8.   Result := Round(AAantal * AEenheidsPrijs); // Deze code is fout
    9. end;
    10.  
    11. procedure WeGaanRekenen;
    12. begin
    13.   if gTask1234 then // We moeten de nieuwe code gebruiken wanneer dit aan staat
    14.     WriteLn(BerekenPrijs_1234(3, 1.46))
    15.   else
    16.     WriteLn(BerekenPrijs(3, 1.46))
    17. end;
    Maar het gevolg hierbij is dat je complete methods moet gaan kopiŽren en dat je in alle aanroepen naar die methods het vlaggetje moet zetten.
    Bij beide oplossingen moet je tevens achteraf, als na enige tijd in het veld blijkt dat de nieuwe code goed is gebleken, alle oude verwijzingen (en vlaggetjes) weer moet verwijderen.

    Een derde idee dat ik had, maar dat is een beetje "Hacky" is om een "Frameworkje" te maken waarin ik nieuwe methods implementeer als hooks en pas als alles akkoord is bevonden de code definitief in het project hang.
    Afgezien van het "Hack"-dingetje is dan de vraag: hoe met de implementatie hiervan om te gaan zodra (bijvoorbeeld) de parameterlijst wijzigt?

    Was onze code-base nu helemaal volgens de (hedendaags) geldende regels geschreven, dan hadden we het geheel misschien nog kunnen automatiseren/vergemakkelijken door op object, method of unit niveau functionaliteit te laten schakelen, maar helaas moeten we het met de code (en resources) doen die we hebben; bij de oplossingen die ik kan bedenken blijven we zitten met een hoop extra werk (ook achteraf): ook onze QA moet bij iedere echte wijzigingen weer gaan testen.

    Mijn vraag is dus eigenlijk: hoe pakken jullie dit aan (indien je soortgelijke functionaliteit al hebben) of kun je meedenken en mij van wat ideeŽn voorzien?
    Om de handige Harry's voor te zijn: compiler directives kunnen we niet gebruiken, nieuwe code moet echt @runtime moeten worden aan- of uitgezet; support kan geen versies bouwen.

    Alvast bedankt voor het lezen en meedenken!

    Groet,

    Peter
    Last edited by VideoRipper; 18-Nov-21 at 15:10.
    TMemoryLeak.Create(Nil);

  2. #2
    Senior Member ErikB's Avatar
    Join Date
    Aug 2010
    Location
    Biddinghuizen
    Posts
    480
    een interessante vraag !

    even voor de beeldvorming: als je zo'n aanpassing doet zoals in het voorbeeld, dan lever je toch uiteindelijk als alles goedgekeurd is, een nieuwe versie uit ? Daar heb je dan toch niets meer met die oude "foute" code te maken??

    Nu wil management graag dat wij, in ons van spaghetti code vergeven product, iets van een "Feature Flag" (of "Feature Toggle") inbouwen die @runtime gezet kan worden (in een "Geheim" menu-scherm oid) door de supportafdeling.
    zou dat met een versienummer kunnen ?
    Code:
    if Versie > 1234 then ...
    het kan zijn dat ik de vraagstelling niet helemaal begrijp , natuurlijk ...
    Erik

  3. #3
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,582
    Nou, dat is niet helemaal wat ik bedoel.

    Een functie wordt aangepast omdat er een fout inzit of omdat deze uitgebreid moet worden.
    Na het fixen van deze bug en na alles uitvoerig getest te hebben doet alles het weer als verwacht... althans: zo lijkt het.

    Pas na twee weken, op zaterdagavond, krijgt support een klacht van een enkele klant dat de fix bij hem niet werkt (hoeft niet direct een "Harde" bug te zijn, het kan bijvoorbeeld ook liggen aan zijn exotische instellingen).
    Bug kan niet zo snal gefixt worden en, door een database update die bij de laatste release zat, kan de klant niet terug naar een vorige versie.

    Wij willen dus de nieuwe code tijdelijk uit kunnen zetten (met een vinkje) en weer terug kunnen naar de oude code, welke bij deze ene klant voorheen wel gewoon nog werkte.
    Het is dus niet afhankelijk van het versienummer en ook niet permanent: we willen de klant weer kunnen laten werken met het pakket, zonder een module uit te hoeven zetten (zodat de functionaliteit helemaal uitgeschakeld wordt).

    Na het weekend pakken we de bug dan weer op en kunnen het op een rustig tempo repareren en weer testen.
    Het kan ook gebruikt worden om nieuwe functionaliteit, bij een select aantal klanten, in het veld te testen, zonder dat andere klanten er weet van hebben: "Feature Flags".

    Pas als na enige tijd blijkt dat de code echt niet meer terugkomt in de meldingen, dan kunnen we de oude code definitief verwijderen.
    Last edited by VideoRipper; 18-Nov-21 at 17:37.
    TMemoryLeak.Create(Nil);

  4. #4
    Ik ben dol op feature flags! We gebruiken ze doorlopend!
    Ik heb bijvoorbeeld een langlopende feature die ik ontwikkel, in dit geval een tamelijk uitgebreide wizard die een gebruiker moet doorlopen bij een bepaalde bewerking op een bestelling. In de huidge flow bestaat die handeling al, maar doet het systeem wat automatische aannames en laat uiteindelijk een primitieve voorloper van mijn nieuwe wizard zien.

    Ergens in mijn code staat dus een actDieHandeling action. Die roept een method aan, en in die method staat:

    Delphi Code:
    1. if FeatureFlags.IsEnabled('MijnNieuweFeature') then
    2.   ToonMijnWizard
    3. else
    4.   DoeWatJeEerstDeed;

    Ik wil die redelijk makkelijk kunnen testen, maar bovendien wil ik niet ineens in een merge hell terechtkomen als hij definitief live gaat. Dus maak ik een feature flag, zet deze standaard uit, en schrijf m'n code. Telkens als er een stukje af is, met bijbehorende unit tests, kan ik dat pushen. Aan het gedrag in productie verandert het nog niets, want de feature staat uit, maar ik kan het wel al makkelijk (laten) testen, en ik weet tussentijds al dat er geen dingen stuk gaan door mijn aanpassingen. Gebeurt dat toch, dan moet dat haast zijn door het verkeerd uitlezen van de feature flag. Dat is heel zeldzaam, maar bovendien meestal makkelijk te vinden, omdat het in dat stadium maar een kleine aanpassing was (de eerste commit is nauwelijks meer dan bovenstaande if, met een stub-versie van ToonMijnWizard).

    In basis niet heel anders dan jij beschrijft.

    Dan qua uitvoering. Wij gebruiken al op vrij veel plekken Dependency Injection in onze code, maar dat is voor zoiets bepaald niet noodzakelijk. Je kan ook een globale instance maken. In onze container wordt het feature flag object geregistreerd als singleton per thread. Als je zelf een singleton feature flag object maakt, kan je die eventueel thread safe maken als dat relevant is. Je zal er toch voornamelijk uit lezen.

    Dan de waarden. Je moet die ergens vandaan halen, en de vraag is hoe vaak. Wij hebben een inifile met wat basis-instellingen, en een database-tabel met meer instellingen. De feature flags staan ook in deze laatste tabel. Het verschil is vooral dat bij ons de instellingen van allerlei types kunnen zijn (ook strings), terwijl feature flags altijd booleans zijn. Ook wordt de lijst met feature flags heel vaak opnieuw gelezen, zodat we direct een feature uit kunnen schakelen op alle clients, terwijl de overige instellingen alleen bij het opstarten worden gelezen. Details hangen natuurlijk af van wat je zelf wilt.

    Ik zou de feature flags wel een zinnige naam geven. Daar kan eventueel best een taaknummer in zitten, maar 'BedragenNietAfrondenNaarHeleEuros_t1234' vind ik persoonlijk duidelijker dan alleen 't1234'. Bovendien heb je als het goed is wel versiebeheer, en heb je dus in luttele tellen de commit gevonden waarin die if is toegevoegd, met daarin de auteur van de change, het moment, en in de commit message een taaknummer en uitleg. Toch?

    Het maakt niet zoveel uit of je die check nou in WeGaanRekenen of in BerekenPrijs zet. Het hangt er maar net van af op welke plek het zinnig is. Als BerekenPrijs altijd zus moet werken in de ene situatie en altijd zo in de andere, dan is het logisch om het daarin te zetten.

    Verder denk ik dat je gelijk hebt dat een feature flag niet lang zou moeten leven. Het is heel nuttig bij het ontwikkelen en uitrollen van een feature. Het zorgt ervoor dat je niet heel lang op je code moet zitten. Het zorgt ervoor dat je een soort tijdelijke patch kan doen voor een deel van je klanten, en het zorgt ervoor dat je een nieuwe feature juist tijdelijk _uit_ kan zetten zonder de hele applicatie opnieuw uit te moeten rollen. Zodra iets bewezen werkt en overal in gebruik is, kan je de feature flag en de oude code-paden gaan opruimen; zeer aanbevolen. En mocht het toch langer blijven bestaan, dan kan je 'm promoveren tot 'normale' instelling. Die kunnen technisch op dezelfde manier werken, natuurlijk. Zoveel verschil is er niet tussen config en feature flag.

    Het valt me op dat je voorbeeld uit losse procedures bestaat. Is dat in de echte applicatie ook zo? Alles losse procs, of eigenlijk methods in classes? Direct gebruik van specifieke classes, of gebruikmakend van baseclasses, factories, interfaces?

    Zelfs met losse procedures kan je dit overigens prima doen. Je simpele voorbeeld laat al zien dat dat kan. Je kan van gTask123 een global boolean maken, die je overal uit kan lezen. Het lezen daarvan is super snel, en je kan 'm zelfs makkelijk atomair updaten en het thread safe maken zonder al te veel moeite.

    Verschillen in parameters kan je meestal oplossen met een wrapper functie of met overloads, of optionele parameters met default waardes. Als je dit jaar nog opslag wil, beschrijf het dan als [url=https://en.wikipedia.org/wiki/Adapter_pattern[Adapter pattern[/url] of [url=https://en.wikipedia.org/wiki/Facade_pattern[/url].
    Is het verschil groter, dan moet de aanroepende code waarschijnlijk ook worden aangepast. Die valt dan uiteraard ook onder je feature flag.

    Voor je oplossing met function pointers geldt net zoiets als voor je boolean. Je kan bij het opstarten bepalen of je Bereken1 of Bereken2 gebruikt. In de aanroep is het super snel, en je kan die pointers zo vervangen (wellicht iets meer nodig om dat 100% thread safe te maken, maar vooral relevant als je veel threading gebruikt en tijdens het runnen wilt kunnen wisselen.
    Die varianten 1 en 2 verberg je liefst in het implementation deel van je unit, en je kent 1 ervan toe aan de wel zichtbare `Bereken`, die je overal kan gebruiken.
    Je kan dat hacky noemen, of je noemt het het Service Locator pattern.

    Of je code moet kopiŽren of niet hangt ook van je eigen smaak en ervaringen af. Ik zou liever iets meer kopiŽren, zodat het later ook makkelijker op te ruimen is, maar als het risico bestaat dat de twee varianten lang naast elkaar blijven bestaan, en/of dat andere developers ťťn van de twee varianten verder gaan aanpassen, terwijl ze eigenlijk beide zouden moeten aanpassen, dan kan het handiger zijn om iets fijnmaziger met je feature flag om te gaan en 'm op iets meer plaatsen te controleren. Zijn dat heel veel plaatsen, dan kan dat ook een teken zijn dat je code misschien anders gestructureerd moet worden, dat het nu een beetje spaghetti is... oh, dat zei je al

    Disclaimer: Onze codebase is ook zo'n 20 jaar oud, maar we hebben wel ons best gedaan om er geen spaghetti van te maken en het een beetje up to date te houden. Ook werken alle 5000 gebruikers bij hetzelfde bedrijf, waardoor het uitrollen van fixes meestal makkelijker is, en we niet echt verschillende versies voor verschillende klanten in het leven hoeven te houden.
    Last edited by GolezTrol; 18-Nov-21 at 21:51.
    1+1=b

  5. #5
    Ik gebruik(te) drie manieren om dit te regelen.

    - In een ini een variable met een parameter opnemen. ( Niet alle bedrijven laten het gebruik van een ini toe)
    - Als commandline switch programma.exe /feature1234
    - Een dummy bestand in de betreffende map plaatsen. If FileExist(dummy) then .....

    Voor alles is wel iets te zeggen en te maken, maar het genereerd wel veel extra werk, wat je dan weer goed moet commenten //feature 1234 18-11-21 wijziging bla bla bla

    Gr. Peter
    10.4.2, Delphi2010, of Lazarus 2.2.0

  6. #6
    Overigens, heel vervelend voor je Q&A-afdeling dat ze steeds opnieuw moeten testen. Dan moeten ze maar leren om unit tests te schrijven, en/of geautomatiseerde tests uitvoeren met een tool als SmartBear TestComplete.

    Om het wat dragelijker te maken kan je eventueel afspreken dat de programmeur op stroopwafels trakteert als de tester een fout vindt. )
    1+1=b

  7. #7
    kan me de tool niet meer herinneren die ze bij albumprinter gebruiken. Ze zijn er toen uitgebreid op ingegaan tijdens event in Amsterdam.

    Dat is een commerciele tool en het mooie was dat zij dat op afstand aan en uit konden zetten. Wie weet kan iemand hier die tool nog herinneren of zit er ook iemand van Albumprinter hier.

  8. #8
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,582
    Quote Originally Posted by GolezTrol View Post
    Ik ben dol op feature flags! We gebruiken ze doorlopend!
    Bedankt voor je uitgebreide betoog, @Jos!

    Ik ben voornamelijk benieuwd hoe het er globaal bij andere bedrijven aan toegaat, dus jouw verhaal is veelzeggend (ook wetende waar je werkt).

    Quote Originally Posted by Wok View Post
    Ik gebruik(te) drie manieren om dit te regelen.
    Thanks Peter

    Hoe functionaliteit uit/aan gezet kan worden kan op veel manieren; aangezien alles aan klantgebonden databases hangt, kunnen we het ook daar in kwijt, dus dat zou in ons geval dan een aardige manier kunnen zijn.

    Ik ben puur benieuwd naar de gangbare manier bij om (voornamelijk) bugfixes tijdelijk weer terug te kunnen draaien.
    Naast bugfixes kunnen het ook (kleine) aanpassingen zijn om bijvoorbeeld te kunnen voldoen aan nieuwe regelgeving.

    Veel nieuwe functionaliteit komt er niet echt bij: het product is al redelijk uitgekristalliseerd en dingen die nieuw zijn worden doorgaans via ons "Module"-framework aan- of uitgezet, wat eigenlijk niet veel meer is dan globale Boolean-vlaggetjes om eventueel bestaande flow aan te passen (maar deze functionaliteit is dan ook eigenlijk "Definitief" en mag altijd blijven bestaan).

    Quote Originally Posted by GolezTrol View Post
    Overigens, heel vervelend voor je Q&A-afdeling dat ze steeds opnieuw moeten testen.
    Helaas is de codebase niet overal fantastisch: veel (vieze) handen hebben er in de afgelopen 20 jaar aangezeten en de kwaliteit loopt echt van "Google-Koppie-peest", via puur procedureel tot heel abstract object georiŽnteerd.
    Ook zijn er enkele units, zonder gemeenschappelijke functionaliteit, van 40.000 regels groot en we hebben/krijgen er niet de tijd voor om veel (tegelijk) te refactoren.

    Unit-tests hebben we niet en met de huidige opzet is dat ook echt niet haalbaar.
    Het is ook niet een product dat nog een echt lang leven heeft: het staat nog niet op EOL en er is ook nog geen definitieve einddatum, maar mijn vermoeden is dat voor 2030 alle klanten zijn overgestapt op ons nieuwe (cloud-based) platform.
    Maar... in deze wereld weet je het maar nooit: we hebben nog steeds (veelal kleinere) klanten die met een hele oude versie (gemaakt met Delphi 5) werken, dus niets in onmogelijk.

    Quote Originally Posted by Benno View Post
    kan me de tool niet meer herinneren die ze bij albumprinter gebruiken.
    Helaas was ik daar niet bij, maar ik hoor graag de naam (en ervaringen) met een dergelijk stukje software.

    Bedankt Benno!
    TMemoryLeak.Create(Nil);

  9. #9
    Ik ga ook het liefst voor de vlag. En kopiŽren: ja! Ik wil de oude code niet stuk maken en elke wijziging is een mogelijkheid om het stuk te maken. Ik heb onlangs een behoorlijke snelheidsverbetering gemaakt in het framework van een vrij omvangrijk project. Dat heeft effect op tientallen schermen die allemaal gebruik maken van het framework. Sommige schermen hebben daar extra truuks mee uitgehaald en alles testen is meer werk dan live zetten en kijken waar het mis gaat. Dus rechtsboven staat er een vinkje "nieuwe functionaliteit" en de key-users hebben dat vinkje aan staan. Die hebben dus meteen al een veel snellere versie, maar soms werkt het even niet. Dan zetten ze het vinkje uit, krijgen weer de oude versie en kunnen door. Het vinkje gaat daarna weer aan en ik los het gevonden probleem op.

    In de loop der tijd is alles wel opgelost (denken we) en zetten we het vinkje voor iedereen aan. Ook hier geldt weer: als het toch niet werkt zet je het vinkje uit en doe je je ding even met de nieuwe versie. Zo komen we de laatste puntjes tegen en als iedereen blij is kan het vinkje weg. Omdat ik alles heb gekopieerd kan ik de oude code ook zonder twijfel verwijderen.
    Marcel

  10. #10
    Niet investeren in onderhoud omdat de software nog "maar" 10 jaar mee gaat is wel een beetje gek, vind ik. Net zoiets als geen olie meer peilen omdat je toch over een jaar of 4 een nieuwe auto wil. Maar goed, ik weet hoe dat gaat. Als de mindset er eenmaal is dat er wat nieuws komt, is er geen tijd en geld, en vaak ook geen motivatie meer om het oude te blijven poetsen.

    Bij ons was overigens ook een groot deel niet getest. We hadden (en hebben nog), heel veel code in datamodules, die direct queries uitvoeren en het resultaat gebruiken. Dat is lastig om te testen, omdat je een afhankelijkheid hebt naar een database, en zulke tests veel trager draaien, als je het al werkend krijgt.
    Maar we zijn er toch maar mee begonnen. Stukjes logica lostrekken uit die datamodules en die logica dan testen. Uiteindelijk is maar een fractie van de applicatie ge-unittest, maar dat zijn wel de nieuwe of recent aangepaste dingen.

    Dat is overigens wel lastig met een aparte Q&A afdeling. Die zal dat soort refactorings niet kunnen doen, en kan dus ook die unit tests niet schrijven. Als de developers zelf de code niet testbaar willen of kunnen maken, dan heeft dat weinig kans. Maar goed, dat staat los van het gebruik van feature flags.
    1+1=b

  11. #11
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,582
    Quote Originally Posted by Marcel View Post
    Ik ga ook het liefst voor de vlag. En kopiŽren: ja!
    Ik denk inderdaad dat vlaggetjes zetten en hele stukken code "Tijdelijk" kopiŽren inderdaad beter bij te houden is dan overal maar wat vlaggetjes tussen zetten in huidige code; zoiets zal het dan ook wel worden... als management uiteindelijk iets dergelijks zou willen (de pet staat hier ook dagelijks de andere kant op).

    Quote Originally Posted by GolezTrol View Post
    Niet investeren in onderhoud omdat de software nog "maar" 10 jaar mee gaat is wel een beetje gek, vind ik.
    Het zijn twee verschillende teams, dus ik doe puur het Delphi product; ik ben de enige hier in Nederland en dan hebben we nog twee contracters in het buitenland zitten die eraan werken. Delphi developers zijn maar moeilijk te vinden, lijkt het.
    Op dit moment (alhoewel, dit is al een paar jaar) is er een gigantische backlog, dus zaken als gefactoren gebeurt alleen als we er toch zijn en als het niet teveel tijd en moeite kost.

    Ik heb inmiddels een kleine proefklasse gebouwd om features bij te houden, met een formpje waarin je eventueel features uit en weer aan kunt zetten.
    Geen idee of we iets dergelijks ook zullen gaan gebruiken (de beroemde stand van de pet weer), maar anders ga ik eens bij een volgende taak kijken of het werkbaar is.
    Last edited by VideoRipper; 19-Nov-21 at 18:01.
    TMemoryLeak.Create(Nil);

  12. #12
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,274
    'T klink mij ook een beetje als "technical debt" management probleem in de oren. Ik gebruik geen feature flags, onze databaseloze applicaties en distributie lenen zich er niet voor (zelfs als er een geval zou zijn, zijn er meestal ook datastructuur veranderingen ).

  13. #13
    Quote Originally Posted by VideoRipper View Post
    Helaas was ik daar niet bij, maar ik hoor graag de naam (en ervaringen) met een dergelijk stukje software [voor GUI testing].
    Ik heb inmiddels uit betrouwbare bron begrepen dat dat Ranorex is. Dat heeft een IDE die de GUI van je desktop- of webapplicatie kan analyseren, en zo kan je test scripts opnemen. Je zou er geen code voor te hoeven schrijven, maar als dat toch moet (of als je dat toch wil), dan gebeurt dat in C# of VB.NET.
    Last edited by GolezTrol; 23-Nov-21 at 17:42.
    1+1=b

  14. #14
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,582
    Dedankt @Jos!
    TMemoryLeak.Create(Nil);

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •