Saturday 4 November 2017

Moving Gjennomsnittet Linq


IterateHelper virker overkill. Overbelastningen som ikke tar en indeks, slutter å gjøre mye mer ekstra arbeid (konvertere tilbakering til lambda som tar indeks, hold en telle som aldri blir brukt). Jeg forstår at det er gjenbruk, men det er en løsning for bare å bruke en forløp uansett, så det burde være effektivt. ndash Cameron MacFarland Dec 29 08 kl 23:20 Ive prøvde noen variasjoner på dette, og jeg fortsetter å gå tilbake til denne gutta løsningen. Igjen, dette er noen elses løsning. Men jeg har samlet koden i et lite bibliotek, og bruker det ganske regelmessig. Jeg kommer til å lime inn koden her, for den tilfeldige sjansen at hans nettsted (blogg) slutter å eksistere på et tidspunkt i fremtiden. (Det er ikke noe verre enn å se et innlegg som sier Her er det nøyaktige svaret du trenger, Klikk og Død URL.) Besvart 17. august 10 kl 14: 10Jeg dro nylig avoul av dette, og det tok meg en stund å finne ut hvorfor. Viser ut det faktum at jeg var å bygge opp spørringen min i deler ved hjelp av IEnumerable gjennomsnittlig 500k poster ble hentet (sakte) og gruppert i minnet. Endret den til å bruke IQueryable mens du bygde opp spørringen, ble gruppen utført på serveren, og jeg fikk bare et halvt dusin rader som jeg ventet. ndash Dave Downs 20. mai 10 kl 18:26 Jeg vil bare gjerne uttrykke hvor lett ditt svar leser. Jeg leste tre artikler på google før jeg fant din lettforståelige, super enkle forklaring på forskjellene. Takk 1 ndash Chev Jan 13 11 kl 17:24 En annen grunn til å foretrekke IEnumerable til IQueryable er at ikke alle LINQ-operasjoner støttes av alle LINQ-leverandører. Så lenge du vet hva du gjør, kan du bruke IQueryable til å presse så mye av spørringen til LINQ-leverandøren (LINQ2SQL, EF, NHibernate, MongoDB etc.). Men hvis du lar annen kode gjøre hva den vil med din IQueryable, vil du til slutt ende opp i trøbbel fordi noen klientkode et eller annet sted brukte en ikke-støttet operasjon. Jeg er enig med anbefalingen om ikke å frigjøre IQueryable s quotinto wildquot forbi depotet eller tilsvarende lag. ndash Avish 2. feb 14 kl 19:19 Det øverste svaret er bra, men det nevner ikke uttrykkstrær som forklarer hvordan de to grensesnittene er forskjellige. I utgangspunktet er det to identiske sett med LINQ-utvidelser. Hvor (), Sum (), Count (), FirstOrDefault (), etc har alle to versjoner: en som aksepterer funksjoner og en som aksepterer uttrykk. Den IEnumerable versjonen signaturen er: Hvor (FuncltCustomer, boolgt predikat) Den IQueryable versjon signaturen er: Hvor (ExpressionltFuncltCustomer, boolgtgt predikat) Youve sannsynligvis brukt begge de uten å innse det fordi begge er kalt med identisk syntaks: f. eks. Hvor (x gt x. City ltCitygt) virker på både IEnumerable og IQueryable Når du bruker Where () på en IEnumerable samling, sender kompilatoren en kompilert funksjon til Where () Når du bruker Where () på en IQueryable-samling, sender kompilatoren et uttrykk tre til Where (). Et uttrykkstreet er som refleksjonssystemet, men for kode. Kompilatoren konverterer koden til en datastruktur som beskriver hva koden din gjør i et format som er lett fordøyelig. Hvorfor bry deg med dette uttrykket treet jeg bare vil ha Hvor () å filtrere dataene mine. Hovedårsaken er at både EF - og Linq2SQL-ORMene kan konvertere ekspresjonstrær direkte inn i SQL, der koden din vil utføre mye raskere. Åh, det høres ut som en gratis ytelse, bør jeg bruke AsQueryable () overalt i det tilfellet. No IQueryable er bare nyttig hvis den underliggende dataleverandøren kan gjøre noe med det. Konvertering av noe som en vanlig liste til IQueryable gir deg ingen fordel. Begge vil gi deg utsatt utførelse, ja. Som det er foretrukket over det andre, avhenger det av hva din underliggende datakilde er. Å returnere en IEnumerable vil automatisk tvinge kjøretiden til å bruke LINQ til Objekter for å spørre samlingen din. Å returnere en IQueryable (som implementerer IEnumerable, forresten) gir den ekstra funksjonaliteten til å oversette spørringen til noe som kan fungere bedre på den underliggende kilden (LINQ til SQL, LINQ til XML, etc.). Ja, begge bruker utsatt kjøring. Lar illustrere forskjellen ved hjelp av SQL Server profiler. Når vi kjører følgende kode: I SQL Server profiler finner vi en kommando som er lik: Det tar omtrent 90 sekunder å kjøre den koden mot et WebLog-bord som har 1 million poster. Så er alle tabelloppføringer lastet inn i minnet som objekter, og deretter med hver. Hvor () blir det et annet filter i minnet mot disse objektene. Når vi bruker IQueryable i stedet for IEnumerable i eksemplet ovenfor (andre linje): I SQL Server profiler finner vi en kommando lik: Det tar omtrent fire sekunder å kjøre denne koden ved hjelp av IQueryable. IQueryable har en egenskap som kalles Expression som lagrer et treuttrykk som begynner å bli opprettet når vi brukte resultatet i vårt eksempel (som kalles utsatt utførelse), og til slutt blir dette uttrykket konvertert til en SQL-spørring for å kjøre på databasemotoren . svarte 8. juni kl 14:01 Generelt vil jeg anbefale følgende: Å returnere IQueryableltT hvis du vil aktivere utvikleren ved hjelp av metoden for å avgrense spørringen du returnerer før du kjører. Hvis du bare vil transportere et sett med Objekter for å oppsummere, ta bare IEnumerable. Tenk deg en IQueryable som den, det er en forespørsel om data (som du kan forfinne om du vil) En IEnumerable er et sett med objekter (som allerede er mottatt eller ble opprettet) over som du kan oppregne. besvart 11 apr 12 kl 13:09 quotCan oppgi, ikke quotcan IEnumerable. quot ndash Casey 12 februar 14 kl 18:23 Det er et blogginnlegg med kort kildekodeeksempel om hvordan misbruk av IEnumerableltTgt kan dramatisk påvirke LINQ-spørreskjema: Entity Framework : IQueryable vs IEnumerable. Hvis vi graver dypere og ser på kildene, kan vi se at det er åpenbart forskjellige utvidelsesmetoder for perfeksjon for IEnumerableltTgt: Den første returnerer tallrike iteratorer, og den andre skaper spørring gjennom spørringsleverandøren, spesifisert i IQueryable kilde. Det har vært mye sagt tidligere, men tilbake til røttene, på en mer teknisk måte: IEnumerable er en samling objekter i minnet som du kan oppregne - en minnesekvens som gjør det mulig å iterere gjennom (gjør det enkelt for innenfor foreach loop, men du kan bare gå med IEnumerator). De bor i minnet som det er. IQueryable er et uttrykkstreet som blir oversatt til noe annet på et tidspunkt med evne til å oppregne det endelige resultatet. Jeg antar at dette er det som forvirrer folk flest. De har tydeligvis forskjellige konnotasjoner. IQueryable representerer et uttrykkstreet (en forespørsel, rett og slett) som blir oversatt til noe annet av den underliggende spørrekundeleverandøren så snart utgivelses-APIer blir kalt, som LINQ-aggregatfunksjoner (Sum, Count, etc.) eller ToListArray, Dictionary. . Og IQueryable objekter kan også implementere IEnumerable. IEnumerableltTgt slik at hvis de representerer en forespørsel, kan resultatet av det spørsmålet bli iterert. Det betyr at IQueryable ikke trenger å være spørringer bare. Den rette sikt er at de er uttrykkstrær. Nå hvordan disse uttrykkene utføres og hva de blir til, er helt opp til såkalte spørringsleverandører (ekspresjonseksperter vi kan tenke på). I Entity Framework-verdenen (som er den mystiske underliggende datakildeleverandøren, eller spørringsleverandøren), blir IQueryable uttrykk oversatt til native T-SQL-spørringer. Nhibernate gjør lignende ting med dem. Du kan skrive din egen etter de begrepene som er ganske godt beskrevet i LINQ: Bygg en IQueryable Provider-kobling, for eksempel, og du vil kanskje ha en egendefinert spørringsgrensesnitt for produktleverandørens tjeneste. Så i utgangspunktet blir IQueryable objekter konstruert hele veien til vi eksplisitt slipper dem og forteller systemet å omskrive dem til SQL eller hva som helst og sende ned kjøringen for videre behandling. Som om å utsette utførelsen er det en LINQ-funksjon for å holde opp uttrykkstreet i minnet og sende det til utførelsen bare på forespørsel, når enkelte APIer kalles mot sekvensen (samme telle, toliste, etc.). Den riktige bruken av begge er avhengig av oppgavene du står overfor for det spesielle tilfellet. For det velkjente depotmønsteret velger jeg personlig å returnere IList. Det er IEnumerable over Lists (indeksere og lignende). Så det er mitt råd å bruke IQueryable bare innenfor repositorier og IEnumerable noe annet sted i koden. Ikke å si om testbarheten angår at IQueryable bryter ned og ødelegger separasjonen av bekymringsprinsippet. Hvis du returnerer et uttrykk fra repositorier, kan forbrukerne leke med persistenslaget som de ville ønske. Et lite tillegg til rotet :) (fra en diskusjon i kommentarene)) Ingen av dem er objekter i minnet, siden de ikke er ekte typer per se, de er markører av en type - hvis du vil gå så dypt. Men det er fornuftig (og det er derfor selv MSDN setter det på denne måten) å tenke på IEnumerables som minneinnsamlinger mens IQueryables er som uttrykkstrender. Poenget er at det IQueryable-grensesnittet arver det IEnumerable-grensesnittet, slik at hvis det representerer et søk, kan resultatene av det søket oppføres. Oppsummering forårsaker at uttrykkstreet knyttet til et IQueryable-objekt som skal utføres. Så, faktisk, kan du ikke ringe noen IEnumerable medlem uten å ha objektet i minnet. Det kommer inn der hvis du gjør det, uansett, hvis det ikke er tomt. IQueryables er bare spørringer, ikke dataene. svarte 5. juni kl 14:23 Kommentaren om at IEnumerables alltid er i minnet er ikke nødvendigvis sant. IQueryable-grensesnittet implementerer det IEnumerable grensesnittet. På grunn av dette kan du passere en rå IQueryable som representerer en LINQ-til-SQL-spørring rett inn i en visning som forventer en IEnumerable Du kan bli overrasket over å finne ut at datakonteksten din er utløpt, eller at du ender opp med å løse problemer med MARS ( flere aktive resultatsett). ndash Alexander Pritchard Jan 22 15 ved 20:13 så faktisk kan du virkelig ikke ringe noen IEnumerable medlem uten å ha objektet i minnet. Det kommer inn der hvis du gjør det, uansett, hvis det ikke er tomt. IQueryables er bare spørringer, ikke dataene. Men jeg ser virkelig poenget ditt. Jeg vil legge til en kommentar på dette. ndash Arman McHitarian 4 feb 15 kl 10:58 AlexanderPritchard ingen av dem er objekter i minnet, siden de ikke er egentlige typer per se, de er markører av en type - hvis du vil gå så dypt. Men det er fornuftig (og det er derfor selv MSDN sier det på denne måten) å tenke på IEnumerables som minneinnsamlinger mens IQueryables er som uttrykkstrender. Poenget er at det IQueryable-grensesnittet arver det IEnumerable-grensesnittet, slik at hvis det representerer et søk, kan resultatene av det søket oppføres. Oppsummering forårsaker at uttrykkstreet knyttet til et IQueryable-objekt som skal utføres. ndash Arman McHitarian 4 feb 15 kl 11:02 Jeg har nylig spilt inn i et problem med IEnumrable v. IQueryable. Algoritmen som ble brukt først utførte en IQueryable spørring for å oppnå et sett med resultater. Disse ble deretter overført til en forløpsløype, med gjenstandene som ble opprettet som en EF-klasse. Denne EF-klassen ble deretter brukt i fra-klausulen av en Linq til Entity-spørring, noe som resulterte i at resultatet skulle være IEnumerable. Jeg er ganske ny til EF og Linq for Entities, så det tok en stund å finne ut hva flaskehalsen var. Ved hjelp av MiniProfiling fant jeg spørringen og konverterte deretter alle de enkelte operasjonene til en enkelt IQueryable Linq for Entities-spørring. IEnumerable tok 15 sekunder og IQueryable tok 0,5 sekunder å utføre. Det var tre tabeller involvert, og etter å ha lest dette, tror jeg at den IEnumerable spørringen faktisk var å danne et tre bordkorsprodukt og filtrere resultatene. Prøv å bruke IQueryables som en regel av tommelen og profil arbeidet ditt for å gjøre endringene målbare. svaret 12. juli 12 klokka 20:39 var årsaken til at de IQueryable uttrykkene konverteres til en innfødt SQL i EF og utføres rett i DB mens IEnumerable-lister er i minnetobjekter. De hentes fra DB på et tidspunkt når du kaller aggregatfunksjoner som Count, Sum eller Any To. og operere i minnet etterpå. IQueryable s er også fast i minnet når du har ringt til en av disse APIene, men hvis ikke, kan du passere uttrykket opp i stabelen av lagene og leke med filtre til API-samtalen. Veldesignet DAL som et godt designet Repository vil løse denne typen problemer) ndash Arman McHitarian 5. juni 14 kl 15:29 Jeg vil gjerne avklare noen ting på grunn av tilsynelatende motstridende svar (det meste rundt IEnumerable). (1) IQueryable utvider det IEnumerable grensesnittet. (Du kan sende en IQueryable til noe som forventer IEnumerable uten feil.) (2) Både IQueryable og IEnumerable LINQ forsøker lat lasting når iterating over resultatsettet. (Merk at implementering kan sees i grensesnittutvidelsesmetoder for hver type.) Med andre ord, er IEnumerables ikke utelukkende i minnet. IQueryables blir ikke alltid utført på databasen. IEnumerable må laste ting inn i minnet (en gang hentet, muligens lat) fordi det ikke har noen abstrakt dataleverandør. IQueryables stole på en abstrakt leverandør (som LINQ-til-SQL), selv om dette også kan være leverandøren i minnet. (a) Hent liste over poster som IQueryable fra EF kontekst. (Ingen poster er i minnet.) (B) Send IQueryable til en visning hvis modell er IEnumerable. (Gyldig. IQueryable utvider IEnumerable.) (C) Iterer over og få tilgang til datasettene, poster, barnenheter og egenskaper fra visningen. (Kan føre til unntak) (1) IEnumerable forsøker lat lasting og datakonteksten din er utløpt. Unntak kastet fordi leverandøren ikke lenger er tilgjengelig. (2) Enhetsrammeenhetens proxy er aktivert (standard), og du forsøker å få tilgang til et relatert (virtuelt) objekt med en utgått datakontekst. Samme som (1). (3) Flere aktive resultatsett (MARS). Hvis du er iterating over IEnumerable i en foreach (var record i resultatset) blokkere og samtidig forsøke å få tilgang record. childEntity. childProperty. Du kan ende opp med MARS på grunn av lat lasting av både datasettet og relasjonsenheten. Dette vil føre til et unntak dersom det ikke er aktivert i tilkoblingsstrengen. Jeg har funnet ut at aktivering av MARS i forbindelsesstrengen virker utilsiktet. Jeg foreslår at du unngår MARS, med mindre det er godt forstått og eksplisitt ønsket. Utfør spørringen og lagre resultater ved å påkalle resultatListresultatSet. ToList () Dette synes å være den enkleste måten å sikre at enhetene dine er i minnet. I tilfeller der du får tilgang til tilknyttede enheter, kan du likevel kreve datakontekst. Enten det, eller du kan deaktivere entusiaster og eksplisitt inkludere tilknyttede enheter fra DbSet. Hovedforskjellen mellom IEnumerable og IQueryable handler om hvor filterlogikken utføres. En utfører på klientsiden (i minnet) og den andre kjøres på databasen. For eksempel kan vi vurdere et eksempel der vi har 10 000 poster for en bruker i vår database, og vi kan bare si ut 900 ut som er aktive brukere, så i dette tilfellet hvis vi bruker IEnumerable, laster den først alle 10 000 poster i minnet og gjelder deretter IsActive-filteret på det som til slutt returnerer de 900 aktive brukerne. På den annen side i samme tilfelle hvis vi bruker IQueryable, vil det direkte bruke IsActive-filteret på databasen, som direkte derfra, vil returnere de 900 aktive brukerne. besvart 9 mai 16 kl 12:03 så det er bra å bruke. i hvilket scenario. ndash Neo Jan 23 kl 9:08 Vi kan bruke begge på samme måte, og de er bare forskjellige i forestillingen. IQueryable utfører bare databasen på en effektiv måte. Det betyr at det skaper et helt utvalgsspørsmål og bare får de relaterte postene. For eksempel ønsker vi å ta de 10 beste kundene hvis navn starter med Nimal. I dette tilfellet vil det valgte spørsmålet bli generert som velg topp 10 fra Kunden der navnet Nimal. Men hvis vi brukte IEnumerable, ville spørringen være som å velge fra Kunden hvor navn som Nimal og topp ti vil bli filtrert på C-kodingsnivået (det får alle kundeoppføringene fra databasen og overfører dem til C). svarte Mar 25 16 kl 7:02 Når du bruker LINQ til Entities, er det viktig å forstå når du skal bruke IEnumerable og IQueryable. Hvis vi bruker IEnumerable, blir spørringen utført umiddelbart. Hvis vi bruker IQueryable, blir forespørselseksjonen utsatt til søknaden ber om opptellingen. Nå kan vi se hva som bør vurderes mens du bestemmer deg for å bruke IQueryable eller IEnumerable. Bruke IQueryable gir deg mulighet til å lage et komplekst LINQ-spørring ved å bruke flere setninger uten å utføre spørringen på databasenivå. Spørringen blir bare utført når den endelige LINQ-spørringen blir oppført. besvart 10. juli kl. 16:34 Både IQueryable og IEnumerable utsette kjøring. Forskjellen er om arbeidet er gjort i DB eller i minnet, ikke når det er gjort. ndash Servy 10. juli kl 16:45 Ditt svar 2017 Stack Exchange, Inc Personlig tror jeg at evnen til å innrømme og møte opp for dine feil er en verdifull bivirkning av å få erfaring og selvtillit som utvikler. Jeg kan også hjelpe deg med å komme ut av 8220Imposter Syndrome Jail8221 per se, men jeg kan si til yngre utviklere at du kan være mye mer sanguine om feilene du gjør i din tekniske beslutningstaking når du kommer over å tenke at du må bevise din verdt for alle rundt deg hele tiden. Dette innlegget kan bare være navleblikk, men I8217d satser på noe her inne som det vil gjelde for de fleste utviklere før eller senere. I8217ve hadde noen av disse feilene gniddd i ansiktet denne uka så dette har vært i tankene mine. For noen år siden hadde jeg sagt at min største feil var en mangel på å gi tilstrekkelig dokumentasjon og eksempelbruk. I dag legger jeg gjerne Marten. StructureMap. eller Storyteller-dokumentasjon mot nesten alle OSS-prosjekter, så jeg vil fortsette å være skyldig over de tidligere synder. Don8217t Fly Solo på store ting Jeg synes it8217s er perfekt mulig å jobbe selv på små, selvforsynte biblioteker. Hvis du prøver å gjøre noe stort skjønt, trenger du hjelp fra andre folk. Ideelt sett trenger you8217ll faktisk koding og testing, men i det minste trenger du tilbakemeldinger og har ideer fra andre folk. Hvis du har lyst til å se prosjektet tiltrekke deg betydelig bruk, vil du definitivt ha andre folk som også er investert i å se at prosjektet lykkes. Jeg kan hjelpe deg mye her med hensyn til hvordan du oppnår hele 8220buildet en levende OSS community8221 ting. Annet enn Marten, har I8217ve aldri vært veldig vellykket på å hjelpe til med å vokse et fellesskap rundt noen av verktøyene I8217ve bygget. FubuMVC hadde et godt samfunn i begynnelsen, men jeg tilskriver det mye mer til Chad Myers og Josh Arnold enn hva jeg gjorde på den tiden. Tenk at tiden er lineær Hver gang jeg lager en StructureMap-utgave, føler jeg meg som 8220that8217s det, I8217m endelig ferdig med denne tingen, og jeg kan gå videre til andre ting nå.8221 Jeg trodde at 3.0-utgivelsen skulle løse det verste permanent av StructureMap8217s strukturelle og ytelsesfeil. Så kom ASP Core, CoreCLR, og et ønske om å øke hastigheten på vår programstartstrappingstid, så kom StructureMap 4.0 8212, og denne gangen var jeg virkelig ferdig, takk. Bortsett fra at jeg varn8217t. Brukere fant nye feil fra brukstilfeller som I8217d aldri vurdert (og wouldn8217t bruker allikevel, men jeg går ned). Corey Kaylor og jeg endte opp med å gjøre noen ytelsesoptimeringer til StructureMap sent i fjor som unclogged noen problemer med StructureMap i kombinasjon med noen av verktøyene vi bruker. Bare denne mandag tilbrakte jeg 3-4 timer med å se utestående feil og trekke forespørsler for å skyve ut en ny utgave. Mitt poeng her er å adoptere tankegangen at aktiviteten din på et OSS-prosjekt er syklisk, ikke lineært. Programvaresystemer, rammer eller biblioteker blir aldri fullført, bare forlatt. Dette har vært min eneste største feil, og it8217 er virkelig et problem av perspektiv. Vær realistisk om brukerne støttes I8217ve hadde problemer fra tid til annen på StructureMap når jeg ble løst, følelsen av at jeg var for tilbakestående med brukerens spørsmål og problemer med en blanding av skyld og frustrasjon. Jeg tror det eneste virkelige svaret er å bare være realistisk om hvor fort du kan komme deg rundt for å takle brukerproblemer og kutte deg litt slakk. Din familie, din arbeidsplass, og du må være en høyere prioritet enn noen på internett. Bygningsfunksjoner for tidlig I de tidlige dagene med Agile-utviklingen snakket vi litt om 8220pull8221 mot 8220push8221 tilnærminger til prosjektets omfang. I 8220push8221-stilen prøver du å planlegge forut for tiden hvilke funksjoner og infrastruktur du trenger og bygge det ut tidlig. I en 8220pull8221-stil forsinker du å introdusere ny infrastruktur eller funksjoner til det er et demonstrert behov for det. Min konsekvente erfaring i løpet av det siste tiåret har vært at funksjonene jeg bygde i reaksjon på et bestemt behov for et pågående prosjekt på jobben, har vært mye mer vellykket enn ideer jeg stakk inn i mitt OSS-prosjekt fordi det hørtes kult på den tiden. Dogfooding Prøv å ikke sette noe der ute for forbruk av andre hvis du har brukt det selv i realistiske situasjoner. Jeg hoppet sannsynligvis pistolen på Storyteller 4.0-utgivelsen, og I8217ll må trykke en ny utgave neste uke for brukervennlighet og et par feil. Alt dette stresset kunne ha blitt unngått hvis I8217d bare brukte alfa8217ene i flere av mine egne prosjekter før du klipper nuget. På den annen side, noen ganger det du trenger mest, er tilbakemelding fra andre folk. Jeg lurer på om jeg gjorde en feil ved å legge til hendelsesinnkjøpsfunksjonaliteten i Marten. Prosjektet jeg hadde i tankene som ville ha brukt det på jobb, har blitt avbrutt på ubestemt tid, og I8217m egentlig ikke egentlig dogfooding det selv. Heldigvis har mange andre folk brukt det i realistiske scenarier, og I8217m er nesten helt avhengig av dem for å finne problemer eller foreslå forbedringer eller API-endringer. Jeg tror at funksjonaliteten vil forbedre mye raskere hvis jeg var den som forfedrer det, men det skjer ikke snart. Utilstrekkelig gjennomgang av trekkforespørsler Jeg prøver å feire på siden av å ta i trekkforespørsler før heller enn senere, og det fører ofte til problemer i veien. På en måte er det vanskeligere å behandle kode fra noen andre for nye funksjoner fordi du ikke er så investert i å se deg gjennom implikasjonene og potensielle gotchas. Jeg ser en trekkforespørsel som kommer med tilstrekkelige tester, og jeg pleier å ta den inn. Det har vært flere ganger da jeg ville ha vært bedre i å stoppe og tenke på hvordan det passer inn i resten av prosjektet. Jeg vet ikke hva det eksakte svaret er her. For strenge krav til trekkforespørsler, og du vil ikke få noen. For lite tilsyn fører til at du støtter noen andre8217s kode. Overreach og Hubris Jeg hater å si at du ikke bør jage OSS-drømmene dine, men jeg tror du må være forsiktig så du ikke overregerer eller tar opp et oppdrag umulig. Å ta min spektakulære flamout med FubuMVC-prosjektet som et eksempel, tror jeg personlig gjorde disse feilene: Å være altfor stor. En helt alternativ webutvikling og service buss rammeverk med sine egne konsepter av modularitet langt utenfor mainstream var bare aldri kommer til å fly. Jeg tror du er mer sannsynlig å lykkes ved å være en del av et eksisterende økosystem i stedet for å prøve å skape et helt nytt økosystem. Jeg antar at I8217m sier at det bare kommer til å være veldig mange DHH8217 eller John Resig8217s. Bygg infrastruktur som wasn8217t direkte relatert til kjernen i prosjektet. FubuMVC på slutten inkluderte sin egen prosjekt templating motor, sin egen statiske fil middleware, en Saml2 leverandør, og ulike andre evner som jeg kunne ha trukket av hyllen i stedet for å bygge meg selv. Alle de tilleggsutstyrene representerte en enorm mulighetskostnad for meg selv. Bare flat ut bygge for mye ting i stedet for å fokusere på å forbedre kjernen i prosjektet. Mens dette er en fungerende demonstrasjon på boksen min, er det en veldig tidlig konseptuell tilnærming for gjennomgang av andre folk i min butikk. I8217d elsker å ha tilbakemelding på denne tingen. Jeg brukte ganske mye tid på vårt Salt Lake City-kontor i forrige uke og snakket med våre QA-folk om testautomatisering generelt og hvor Selen gjør eller ikke passer inn i vår (ønsket) tilnærming. Utviklerne i butikken min bruker Selen ganske mye i dag i vår Storyteller-godkjenningssuite med blandede resultater, men nå ønsker våre QA-folk å automatisere noen av deres manuelle testpakker og sparker dekkene på Selen. Som en oppfølging til disse diskusjonene, viser dette innlegget det svært tidlige konseptet for hvordan vi kan bruke Selen-funksjonalitet innenfor Storyteller-spesifikasjonene for deres og din tilbakemelding. Hele koden er i Storyteller8217s 4.1 grenen. Demo-spesifikasjon Let8217s starter veldig grovt. Let8217s sier at du har en nettside som har en tagg med en slags brukerbeskjedestekst that8217s er skjult først. Dessuten sier let8217s at du har to knapper på skjermen med teksten 8220Show8221 og 8220Hide.8221. En Storyteller-spesifikasjon for atferden kan se slik ut: og HTML-resultatene vil se slik ut: 3 sekunders kjøretid er for det meste inne opprettelsen og lanseringen av en Chrome-nettleserversjon. Mer om dette senere. For å implementere denne spesifikasjonen trenger vi to ting, Fiksjonsklasser som implementerer ønsket språk og de faktiske spesifikasjonsdataene i en markdown-fil som vises i neste avsnitt. I dette eksemplet vil det være et nytt 8220Storyteller. Selenium8221 bibliotek som danner grunnlaget for å integrere Selen i Storyteller-spesifikasjoner med en felles 8220ScreenFixture 8221-baseklasse for Fixture8217s som er målrettet med Selen. Etter det ser SampleFixture-klassen som brukes i beskrivelsen ovenfor, ut som dette: Hvis du redigerte spesifikasjonene i Storyteller8217s-spesifikasjonsredigering. you8217ll har en rullegardinboks som opplister elementene etter navn hvor som helst hvor du må spesifisere et element som dette: Til slutt legger den foreslåtte Storyteller. Selenium-pakken informasjon til ytelsesloggingen for hvor lenge en nettside skal lastes. Dette er tiden i henhold til WebDriver og shouldn8217t brukes til detaljert ytelsesoptimalisering, men it8217 er fortsatt et nyttig nummer for å forstå ytelsesproblemer under Storyteller-spesifikasjonens henrettelser. Se linjen 8220Navigationsimple. htm8221 nedenfor: Hva ser den faktiske spesifikasjonen ut Hvis du forfattere spesifikasjonen ovenfor i brukergrensesnittet Storyteller, får you8217d denne markdown-filen: Men hvis du skriver beskrivelsen for hånd direkte i markdown-filen, kan forenkle det til dette: We8217 prøver veldig hardt med Storyteller 4 for å gjøre spesifikasjoner enklere å skrive for ikke-utviklere, og det du ser ovenfor er et produkt av den innsatsen. Hvorfor Storyteller Selen i stedet for bare Selen Hvorfor vil du bruke Storyteller og Selen sammen i stedet for bare Selen i seg selv Et par grunner: There8217s mye mer skjer i effektive automatiserte tester i tillegg til å kjøre nettlesere (konfigurering av systemdata, kontrollsystemdata , starterstopping av systemet under test). Storyteller gir seg mye mer funksjonalitet enn Selen i seg selv. It8217s er svært verdifull til å uttrykke automatiserte tester på et høyere nivå språk med noe som Storyteller eller Agurk i stedet for å gå helt ned til skjermelementer og andre implementeringsdetaljer. Jeg sier dette delvis for å gjøre beskrivelsene mer menneskelige lesbare, men også for å avkoble ekspresjonen av testen fra de underliggende implementeringsdetaljer. Du vil gjøre dette slik at testene dine lettere kan ta imot strukturelle endringer på nettsidene. Hvis you8217ve aldri har jobbet med storskala automatisert testing mot en nettleser, må du virkelig være oppmerksom på at slike tester kan være veldig sprø i møte med endringer i brukergrensesnittet. Storyteller gir mye ekstra instrumentering og ytelseslogging som kan være svært nyttig for feilsøking eller ytelsesproblemer. Jeg hater å kaste denne ut der, men Storyteller8217s konfigurerbar retrykkfunksjon i kontinuerlig integrering er veldig nyttig for testpakker med oodles av asynkron oppførsel som du kjører ofte inn i moderne webapplikasjoner Fordi noen vil spørre, eller en F-entusiast vil uunngåelig kaste dette der ute, ja, det er også Canopy som bryter en fin DSL rundt Selen og gir litt stabilisering. I8217m ikke nedbrytende Canopy i det minste, men alt jeg sa om bruk av rå Seleni gjelder også for å bruke Canopy av seg selv. For å være litt mer øye-poky om det, var en av de første suksesshistoriene til Storyteller 3 i å erstatte en dårlig instabil testpakke som brukte Canopy naivt. Storyteller er et langt løpeprosjekt for å forberede menneskelige lesbare, kjørbare spesifikasjoner for prosjekter. Den nye 4.0-versjonen er ment å gjøre Storyteller enklere å bruke og konsumere for ikke-tekniske folk, og for å forbedre developer8217s evne til å feilsøke spesifikasjonsfeil. Etter ca 5 måneders innsats kunne jeg endelig kutte 4,0 Nugets for Storyteller i morges og de nyeste dokumentasjonsoppdateringene. Hvis du er helt ny til Storyteller, sjekk ut vår startside eller denne webcasten. Hvis du kommer fra Storyteller 3.0, vet du bare at du må først konvertere dine spesifikasjoner til det nye 4.0-formatet. Storyteller Fixture API hadde ingen brytende endringer, men oppstartstrinnene er litt annerledes for å imøtekomme dotnet CLI. Du kan se hele listen over endringer her. eller de store høydepunktene i denne utgivelsen er: CoreCLR Support Storyteller 4.0 kan brukes på enten 4.6 prosjekter eller prosjekter som retter seg mot CoreCLR. Fra nå er Storyteller nå et kryssplattformverktøy. Du kan lese mer om mine erfaringer som migrerer Storyteller til CoreCLR her. Embraces dotnet CLI. Jeg elsker den nye dotnet cli og ønsker at we8217d hadde det for mange år siden. Det er en ny 8220dotnet storyteller8221 CLI-utvidelsespakke som tar plass til det gamle ST. exe-konsollverktøyet i 3.0 som skal være enklere å konfigurere for nye brukere. Markdown Everywhere Storyteller 4.0 endret spesifikasjonsformatet til et Markdown plus-format. lagt til en ny evne til å designe og generere Fixture8217s med markdown. og du kan gjerne bruke markdown-tekst som prosa innenfor spesifikasjoner for å forbedre din evne til å kommunisere intensjoner i Storyteller-spesifikasjoner. Stepthrough-modus. Integrasjonstester kan være svært vanskelig å feilsøke når de feiler. To ease the load, Storyteller 4.0 adds the new Stepthrough mode that allows you manually walk through all the steps of a Storyteller specification so you can examine the current state of the system under test as an aid in troubleshooting. Asynchronous Grammars . It8217s increasingly an async-first kind of world, so Storyteller follows suit to make it easier for you to test asynchronous code . Performance Assertions . Storyteller already tracks some performance data about your system as specifications run, so why not extend that to applying assertions about expected performance that can fail specifications on your continuous integration builds Other Things Coming Soon(ish) A helper library for using Storyteller with ASP Core applications with some help from Alba. I8217m hoping to recreate some of the type of diagnostics integration we have today with Storyteller and our FubuMVC applications at work for our newer ASP Core projects. A separate package of Selenium helpers for Storyteller An extension specifically for testing relational database code A 4.1 release with the features I didn8217t get around to in 4.0) How is Storyteller Different than Gherkin Tools First off, can we just pretend for a minute that GherkinCucumber tools like SpecFlow may not be the absolute last word for automating human readable, executable specifications By this point, I think most folks associate any kind of acceptance test driven development or truly business facing Behavioral Driven Development with the Gherkin approach 8212 and it8217s been undeniably successful. Storyteller on the other hand, was much more influenced by Fitnesse and could accurately be described as a much improved evolution of the old FIT model . SpecFlow is the obvious comparison for Storyteller and by far the most commonly used tool in the space. The bottom line for me with Storyteller vs. SpecFlow is that I think that Storyteller is far more robust technically in how you can approach the automated testing aspect of the workflow. SpecFlow might do the businesstesting to development workflow a little better (but I8217d dispute that one too with the release of Storyteller 4.0), but Storyteller has much, much more functionality for instrumenting, troubleshooting, and enforcing performance requirements of your specifications. I strongly believe that Storyteller allows you to tackle much more complex automated testing scenarios than other options. Here is a more detailed list about how Storyteller differs from SpecFlow: Storyteller is FOSS. So on one hand, you don8217t have to purchase any kind of license to use it, but you8217ll be dependent upon the Storyteller community for support. Instead of parsing human written text and trying to correlate that to the right calls in the code, Storyteller specifications are mostly captured as the input and expected output. Storyteller specifications are then 8220projected8221 into human readable HTML displays. Storyteller is much more table centric than Gherkin with quite a bit of functionality for set-based assertions and test data input. Storyteller has a much more formal mechanism for governing the lifecycle of your system under test with the specification harness rather than depending on an application being available through other means. I believe that this makes Storyteller much more effective at development time as you cycle through code changes when you work through specifications. Storyteller does not enforce the 8220GivenWhenThen8221 verbiage in your specifications and you have much more freedom to construct the specification language to your preferences. Storyteller has a user interface for editing specifications and executing specifications interactively (all React. js based now). The 4.0 version makes it much easier to edit the specification files directly, but the tool is still helpful for execution and troubleshooting. We do not yet have direct Visual Studio integration like SpecFlow (and I8217m somewhat happy to let them have that one)), but we will develop a dotnet test adapter for Storyteller when the dust settles on the VS2017csproj churn. Storyteller has a lot of functionality for instrumenting your specifications that8217s been indispensable for troubleshooting specification failures and even performance problems. The built in performance tracking has consistently been one of our most popular features since it was introduced in 3.0. When I was at Codemash this year, Matthew Groves was kind enough to let me do a podcast with him on Marten for the Cross Cutting Concerns podcast. Check it out . I8217m flying out to our main office next week and one of the big things on my agenda is talking over our practices around databases in our software projects. This blog post is just me getting my thoughts and talking points together beforehand. There are two general themes here, how I8217d do things in a perfect world and how to make things better within the constraints of the organization and software architecture that have now. I8217ve been a big proponent of Agile development processes and practices going back to the early days of Extreme Programming (before Scrum came along and ruined everything about the way that Scrappy ruined Scooby Doo cartoons for me as a child). If I8217m working in an Agile way, I want: Strong project and testing automation as feedback cycles that run against all changes to the system Some kind of easy traceability from a built or deployed system to exactly the version of the code and its dependencies. preferably automated through your source control processes Technologies, tools, and frameworks that provide high reversibility to ease the cost of doing evolutionary software design. From the get go, relational databases have been one of the biggest challenges in the usage of Agile software practices. They8217re laborious to use in automated testing, often expensive in time or money to install or deploy, the change management is a bit harder because you can8217t just replace the existing database objects the way we can with other code, and I absolutely think it8217s reduces reversibility in your system architecture compared to other options. That being said, there are some practices and processes I think you should adopt so that your Agile development process doesn8217t crash and burn when a relational database is involved. Keep Business Logic out of the Database, Period. I8217m strongly against having any business logic tightly coupled to the underlying database. but not everyone feels the same way. For one reason, stored procedure languages (tSQL, PLSQL, etc.) are very limited in their constructs and tooling compared to the languages we use in our application code (basically anything else). Mostly though, I avoid coupling business logic to the database because having to test through the database is almost inevitably more expensive both in developer effort and test run times than it would be otherwise. Some folks will suggest that you might want to change out your database later, but to be honest, the only time I8217ve ever done that in real life is when we moved from RavenDb to Marten where it had little impact on the existing structure of the code. In practice this means that I try to: Eschew usage of stored procedures. Yes, I think there are still some valid reasons to use sprocs, but I think that they are a 8220guilty until proven innocent8221 choice in almost any scenario Pull business logic away from the database persistence altogether whenever possible. I think I8217ll be going back over some of my old designing for testability blog posts from the CodebetterALT days to try to explain to our teams that 8220wrap the database in an interface and mock it8221 isn8217t always the best solution in every case for testability Favor persistence tools that invert the control between the business logic and the database over tooling like Active Record that creates a tight coupling to the database. What this means is that instead of having business logic code directly reading and writing to the database, something else (Dapper if we can, EF if we absolutely have to) is responsible for loading and persisting application state back and forth between the domain in code and the underlying database. The point is to be able to completely test your business logic in complete isolation from the database. I would make exceptions for use cases where using the database engine to do set based logic in a stored procedure is a more efficient way to solve the problem, but I haven8217t been involved in systems like that for a long time. Database per DeveloperTesterEnvironment My very strong preference and recommendation is to have each developer, tester, and automated testing environment using a completely separate database. The key reason is to isolate each thread of team activity to avoid simultaneous operations or database changes from interfering with each other. Sharing the database makes automated testing much less effective because you often get false negatives or false positives from database activity going on somewhere else at the same time 8212 and yes, this really does happen and I8217ve got the scars to prove it. Additionally, it8217s really important for automated testing to be able to tightly control the inputs to a test. While there are some techniques you can use to do this in a shared database (multi-tenancy usage, randomized data), it8217s far easier mechanically to just have an isolated database that you can easily control. Lastly, I really like being able to look through the state of the database after a failed test. That8217s certainly possible with a shared database, but it8217s much easier in my opinion to look through an isolated database where it8217s much more obvious how your code and tests changed the database state. I should say that I8217m concerned here with logical separation between different threads of activity. If you do that with truly separate databases or separate schemas in the same database, it serves the same goal. 8220The8221 Database vs. Application Persistence There are two basic development paradigms to how we think about databases as part of a software system: The database is the system and any other code is just a conduit to get data back and forth from the database and its consumers The database is merely the state persistence subsystem of the application I strongly prefer and recommend the 2nd way of looking at that, and act accordingly. That8217s a admittedly a major shift in thinking from traditional software development or database centric teams. In practice, this generally means that I very strongly favor the concept of an application database that is only accessed by one application and can be considered to be just part of the application. In this case, I would opt to have all of the database DDL scripts and migrations in the source control repository for the application. This has a lot of benefits for development teams: It makes it dirt simple to correlate the database schema changes to the rest of the application code because they8217re all versioned together Automated testing is easier within continuous integration builds becomes easier because you know exactly what scripts to apply to the database before running the tests No need for elaborate cascading builds in your continuous integration setup because it8217s just all together In contrast, a shared database that8217s accessed by multiple applications is a lot more potential friction. The version tracking between the two moving parts is harder to understand and it harms your ability to do effective automated testing. Moreover, it8217s wretchedly nasty to allow lots of different applications to float on top of the same database in what I call the 8220pond scum anti-pattern8221 because it inevitably causes nasty coupling issues that will almost result in regression bugs due to it being so much harder to understand how changes in the database will ripple out to the applications sharing the database. A much, much younger version of myself walked into a meeting and asked our 8220operational data store8221 folks to add a column to a single view and got screamed at for 30 minutes straight on why that was going to be impossible and do you know how much work it8217s going to be to test everything that uses that view young man Assuming that you absolutely have to continue to use a shared database like my shop does, I8217d at least try to ameliorate that by: Make damn sure that all changes to that shared database schema are captured in source control somewhere so that you have a chance at effective change tracking Having a continuous integration build for the shared database that runs some level of regression tests and then subsequently cascades to all of the applications that touch that database being automatically updated and tested against the latest version of the shared database. I8217m expecting some screaming when I recommend that in the office next week-) At the least, have some mechanism for standing up a local copy of the up to date database schema with any necessary baseline data on demand for isolated testing Some way to know when I8217m running or testing the dependent applications exactly what version of the database schema repository I8217m currently using. Git submodules Distribute the DB via Nuget Finally do something useful with Docker, distribute the DB as a versioned Docker image, and brag about that to any developer we meet The key here is that I want automated builds constantly running as feedback mechanisms to know when and what database changes potentially break (or fix too) one of our applications. Because of some bad experiences in the past, I8217m hesitant to use cascading builds between separate repositories, but it8217s definitely warranted in this case until we can get the big central database split up. At the end of the day, I still think that the shared database architecture is a huge anti-pattern that most shops should try to avoid and I8217d certainly like to see us start moving away from that model more and more. Document Databases over Relational Databases I8217ve definitely put my money where my mouth is on this (RavenDb early on, and now Marten ). In my mind, evolutionary or incremental software design is much easier with document databases for a couple reasons: Far fewer changes in the application code result in database schema changes It8217s much less work to keep the application and database in sync because the storage just reflects the application model Less work in the application code to transform the database storage to structures that are more appropriate for the business logic. I. e. relational databases really aren8217t great when your domain model is logically hierarchical rather than flat It8217s a lot less work to tear down and set up known test input states in document databases. With a relational database you frequently end up having to deal with extraneous data you don8217t really care about just to satisfy relational integrity concerns. Likewise, tearing down relational database state takes more care and thought than it does with a document database. I would still opt to use a relational database for reporting or if there8217s a lot of set based logic in your application. For simpler CRUD applications, I think you8217re fine with just about any model and I don8217t object to relational databases in those cases either. It sounds trivial, but it does help tremendously if your relational database tables are configured to use cascading deletes when you8217re trying to set a database into a known state for tests. Team Organization My strong preference is to have a completely self-contained team that has the ability and authority to make any and all changes to their application database, and that8217s most definitely been valid in my experience. Have the database managed and owned separately from the development team is a frequent source of friction and definitely a major hit to your reversibility that forces you to do more potentially wrong, upfront design work. It8217s much worse when that separate team does not share your priorities or simply works on a very different release schedule. I think it8217s far better for a team to own their database 8212 or at the very worst, have someone who is allowed to touch the database in the team room and team standup8217s. If I had full control over an organization, I would not have a separate database team. Keeping developers and database folks on separate team makes your team have to spend more time on inter-team coordination, takes away from the team8217s flexibility in deciding what they can deliver, and almost inevitably causes a bottleneck constraint for projects. Even worse in my mind is when neither the developers nor the database team really understand how their work impacts the other team. Even if we say that we have a matrix organization. I want the project teams to have primacy over functional teams. To go farther, I8217d opt to make functional teams (developers, testers, DBA8217s) be virtual teams solely for the purpose of skill acquisition, knowledge sharing, and career growth. My early work experience was being an engineer within large petrochemical project teams, and the project team dominant matrix organization worked a helluva lot better than it did at my next job in enterprise IT that focused more on functional teams. As an architect now rather than a front line programmer, I constantly worry about not being able to feel the 8220pain8221 that my decisions and shared libraries cause developers because that pain is an important feedback mechanism to improve the usability of our shared infrastructure or application architecture. Likewise, I worry that having a separate database team creates a situation where they8217re not very aware of the impact of their decisions on developers or vice versa. One of the very important lessons I was taught as an engineer was that it was very important to understand how other engineering disciplines work and what they needed so that we could work better with them. Now though, I do work in a shop that has historically centralized the control of the database in a centralized database team. To mitigate the problems that naturally arise from this organizational model, we8217re trying to have much more bilateral conversations with that team. If we can get away with this, I8217d really like to see members of that team spend more time in the project team rooms. I8217d also love it if we could steal a page from my original engineering job (Bechtel ) and suggest some temporary rotations between the database and developer teams to better appreciate how the other half of that relationship works and what their needs are. I just uploaded Marten 1.3.0 to Nuget (but note that Nuget has had issues today with the index updating being delayed). This release is mostly bugfixes, but there8217s some new functionality, and significant improvements to performance on document updates and bulk inserts. You can see the entire list of changes here with some highlights below. Thanks to Phillip Haydon There8217s a slew of new documentation on our website about Postgresql for Sql Server folks . What8217s New It wasn8217t a huge release for new features, but these were added: What8217s Next The next release is going to be Marten 2.0 because we need to make a handful of breaking API changes (don8217t worry, it8217s very unlikely that most users would hit this). The big ticket item is a lot more work to reduce memory allocations throughout Marten. The other, not-in-the-slightest-bit-sexy change is to standardize and streamline Marten8217s facilities for database change tracking with the hope that this work will make it far easier to start adding new features again. Years ago when I was in college and staying at my grandparent8217s farm, my uncle rousted me up well after midnight because he could see headlights in our pasture. We went to check it out to make sure no one was trying to steal cattle (it8217s very rare, but does happen) and found one of my grandparent8217s neighbors completely stuck in a fence row and drunkenly trying to get himself out. I don8217t remember the exact 8220conversation,8221 but his vocabulary was pretty well a single four letter expletive used as noun, verb, adjective, and adverb and the encounter went pretty quickly from potentially scary to comical. Likewise, when OSS maintainers deploy the phrase 8220I take pull requests,8221 they mean a slew of very different things depending on the scenario or other party. In order of positive to negative, here are the real meanings behind that phrase if you hear it from me: I think that would be a useful idea to implement and perfectly suitable for a newcomer to the codebase. Go for it. I like that idea, but I don8217t have the bandwidth to do that right now, would you be willing to take that on I don8217t think that idea is valuable and I wouldn8217t do it if it were just me, but if you don8217t mind doing that, I8217ll take it in. You8217re being way too demanding, and I8217m losing my patience with you. Since you8217re clearly a jerk, I8217m expecting this to make you go away if you have to do anything for yourself. My shop has started to slowly transition from FubuMVC to ASP Core (w and wo MVC) in our web applications. Instead of going full blown Don Quixote and writing my own alternative web framework like I did in 2009, I8217m trying to embrace the mainstream concentrate on tactical additions where I think that makes sense. I8217ve been playing around with a small new project called Alba that seeks to make it easier to write integration tests against HTTP endpoints in ASP Core applications by adapting the 8220Scenario8221 testing mechanism from FubuMVC. I8217ve pushed up an alpha Nuget (1.0.0-alpha-28) if you8217d like to kick the tires on it. Right now it8217s very early, but we8217re going to try to use it at work for a small trial ASP Core project that just started. I8217m also curious to see if anybody is interested in possibly helping out with either coding or just flat out testing it against your own application. A Quick Example First, let8217s say we have a minimal MVC controller like this one: With that in place, I can use Alba to write a test that exercises that HTTP endpoint from end to end like this: A couple points to note here: The easiest way to tell Alba how to bootstrap your ASP application is to just pass your Startup type of your application to the SystemUnderTest. ForStartupltTgt() method shown above in the constructor function of that test fixture class. Alba is smart enough to set up the hosting content path to the base directory of your application project. To make that concrete, say your application is at 8220srcMyApp8221 and you have a testing project called 8220srcMyApp. Testing8221 and you use the standard idiom using the same name for both the directory and the assembly name. In this case, Alba is able to interrogate your MyApp. Startup type, deduce that the 8220parallel8221 folder should be 8220MyApp. Testing,8221 and automatically set the hosting content path to 8220srcMyApp8221 if that folder exists. This can of course be overridden. When the Scenario() method is called, it internally builds up a new HttpContext to represent the request, calls the lambda passed into Scenario() to configure that HttpContext object and register any declarative assertions against the expected response, and executes the request using the raw 8220RequestDelegate8221 of your ASP Core application. There is no need to be running Kestrel or any other HTTP server to use Alba 8212 but it doesn8217t hurt anything if Kestrel is running in side of your application. The Scenario() method returns a small object that exposes the HttpContext of the request and a helper object to more easily interrogate the http response body for possible further assertions. Where would this fit in Alba itself isn8217t a test runner, just a library that can be used within a testing harness like xUnit or Storyteller to drive an ASP Core application. One of the things I8217m trying to accomplish this quarter at work is to try to come up with some suggestions for how developers should decide which testing approach to take in common scenarios. Right now I8217m worried that our automated testing frequently veers off into these two non-ideal extremes: Excessive mocking in unit tests where the test does very little to ascertain whether or not the code in question would actually work in the real system End to end tests using Selenium or Project White to drive business and persistence logic by manipulating the actual web application interface. These tests tend to be much more cumbersome to write and laborious to maintain as the user interface changes (especially when the developers don8217t run the tests locally before committing code changes). Alba is meant to live in the middle ground between these two extremes and give our teams an effective way to test directly against HTTP endpoints. These Scenario() tests originally came about in FubuMVC because of how aggressive we were being in moving cross cutting concerns like validation and transaction management to fubu8217s equivalent to middleware. Unit testing an HTTP endpoint action was very simple, but you really needed to exercise the entire Russian Doll of attached middleware to adequately test any given endpoint. How is this different than Microsoft. AspNetCore. TestHost While I8217ve been very critical of Microsoft8217s lack of attention to testability in some their development tools, let me give the ASP team some credit here for their TestHost library that comes out of the box. Some of you are going to be perfectly content with TestHost, but Alba already comes with much more functionality for common set up and verifications against HTTP requests. I think Alba can provide a great deal of value to the ecosystem even with an existing solution from Microsoft. I did use a bit of code that I borrowed from an ASPNet repository that was in turn copypasted from the TestHost repository. It8217s quite possible that Alba ends up using TestHost underneath the covers. TLDR 8211 I8217m getting burned out supporting StructureMap, but it8217s still very heavily used and I8217m really hoping to recruit some new blood to eventually take the project over from me. I8217ve been mulling over whether or not I want to continue development of StructureMap. At this point, I feel like the 3.0 and 4.0 releases dealt with all the major structural and performance problems that I could think of. If you ask me what I8217d like to be do to improve one of my other OSS projects I could bend your ear for hours, but with StructureMap I8217ve got nothing in mind. The project is still very widely used (1.5M downloads from Nuget) and I don8217t mean to just drop it by any means, but I8217m wondering if anybody (hopefully plural) would like to take ownership over StructureMap and actually keep it advancing I feel like the code is pretty clean, the test coverage is solid, and there8217s even close to comprehensive documentation already published online. Why I8217ve lost enthusiasm: I8217ve worked on StructureMap since 2003 I8217m mentally exhausted trying to stay on top of the user questions and problems that come rolling in and I8217m starting to resent the obligation to try to help users unwind far out usages of the tool and dozens of disparate application frameworks. There8217s a consistent and vocal backlash against IoC containers in my Twitter feeds. To some degree, I think their experiences are just very different than my own and I don8217t recognize the problems they describe in my own usage, but it still dampens enthusiasm. I8217ve got several other projects going that I8217m frankly more passionate about right now (Marten. Storyteller. a couple others) Microsoft has a small, built in IoC container as part of ASP Core that I suspect will eventually wipe out all the myriad OSS IoC containers. I can point to plenty advantages of StructureMap over what8217s built in, but most users probably wouldn8217t really notice At this point, with every application framework or service bus, folks are putting their IoC container behind an abstraction of some kind that tends to reduce StructureMap and other tools into the least common denominator functionality, so what8217s the point of trying to do anything new if it8217s gonna be thrown away behind a lame wrapping abstraction The ASP Core compatibility has been a massive headache for me with StructureMap and I8217m dreading the kinds of support questions that I expect to roll in from users developing with ASP Core. More on this one later. EDIT 15: We8217re still hiring for Salt Lake City or Phoenix. I can probably sell a strong remote candidate in the U. S. but I can8217t get away with remote folks in Europe (sorry). We8217re (Extend Health. part of Willis Towers Watson ) doing a little bit of reorganization with our software architecture team and how it fits within the company. As part of that, we8217re looking to grow the team with open slots in our main Salt Lake City office and our new Phoenix office. We might be able to add more remote folks later (I8217m in Austin, and another member is in Las Vegas), but right now we8217re looking for someone to be local. Who we8217re looking for Let me say upfront that I have a very conflicted relationship with the term 8220software architect.8221 I8217ve been a member of the dreaded, centralized architect team where we mostly just got in the way and I8217ve had to work around plenty of architecture team8217s 8220advice.8221 This time around, I want our new architecture team to be consistently considered to be an asset to our development teams while taking care of the strategic technical goals within our enterprise architecture. More than anything, the architecture team needs to be the kind of folks that our development teams want to work with and can depend on for useful advice and help. We8217re not going to be landing huge upfront specifications and there won8217t be much UML-spewing going on. You will definitely be hands on inside the code and it8217s likely you8217ll get to work on OSS projects as part of your role (check out my GitHub profile to get an idea of the kinds of work we8217ve done over the years). You8217re going to need to have deep software development experience and been in roles of responsibility on software teams before. You8217re going to need to have strong communication skills because one of your primary duties is to help and mentor other developers. A good candidate should be thoughtful, always on the lookout for better approaches or technologies, and able to take on all new technical challenges. It8217s not absolutely required, but a healthy GitHub or other OSS profile would be a big plus. The point there is just to look for folks that actually enjoy software development. You8217ll notice that I8217m not writing up a huge bullet list of required technical acronyms. I8217m more worried about the breadth and depth of your experience than an exact fit with whatever tools we happen to be using at the moment. That being said, we8217re mostly using on the server side (but with a heavy bias toward OSS tools) and various Javascript tools in the clients with a strong preference for React. jsRedux in newer development. We do a lot of web development, quite a bit of distributed messaging work, and some desktop tools used internally. Along the way you8217ll see systems that use document databases, event sourcing, CQRS, and reactive programming. I can safely promise you that our development challenges are considerably more interesting than the average shop. Post navigasjon

No comments:

Post a Comment