Creating your own race to a programming finish line with a hidden gem in mirai, the lowdown on using Generative AI for data visualization with more than a few surprises, and going from start to finish with a Shiny app created under the BDD mindset.
Episode Links
Supporting the show
Episode Links
- This week's curator: Sam Parmar - @[email protected] (Mastodon) & @parmsam_ (X/Twitter)
- Aaaaand… they’re off!
- Generative AI for Data Visualisation
- Behavior-Driven Development in R Shiny: A Step-By-Step Example
- Entire issue available at rweekly.org/2025-W42
Supporting the show
- Use the contact page at https://serve.podhome.fm/custompage/r-weekly-highlights/contact to send us your feedback
- R-Weekly Highlights on the Podcastindex.org - You can send a boost into the show directly in the Podcast Index. First, top-up with Alby, and then head over to the R-Weekly Highlights podcast entry on the index.
- A new way to think about value: https://value4value.info
- Get in touch with us on social media
- Eric Nantz: @[email protected] (Mastodon), @rpodcast.bsky.social (BlueSky) and @theRcast (X/Twitter)
- Mike Thomas: @[email protected] (Mastodon), @mike-thomas.bsky.social (BlueSky), and @mike_ketchbrook (X/Twitter)
- Warriors of Light - Final Fantasy - Darangen - https://ocremix.org/remix/OCR01339
- Honky Town - Super Mario RPG: Legend of the Seven Stars - Wiesty, XPRTNovice - https://ocremix.org/remix/OCR03535
[00:00:03]
Eric Nantz:
Hello, friends. We are back with episode 213 of the Our Week Who Howlads podcast. And thanks for being patient with us. We were off last week. I'll get to why in a little bit. But if you're tuning in for the first time, this this is the usually weekly show where we talk about the excellent highlights and other resources that have been shared on this week's our weekly issue at ourweekly.0rg. My name is Eric Nance, and I'm glad you joined us from wherever you are around the world. And at least he's back at this time, hopefully, not as rusty as I am. My awesome cohost, Mike Thomas, is with me as always. Hi, Mike. How are you doing?
[00:00:38] Mike Thomas:
Doing pretty well. We had a a big nor'easter yesterday that wiped out power, but we are back up and running today and ready to record.
[00:00:46] Eric Nantz:
Well, happy to hear you are safe at least after that one. I had a good good little, time off. The kids had the fall break from school. We're not to put that back in my day hat on, but back in my day, we didn't get things like fall breaks. It was only spring break, and that was it. So these kids don't know how good they have it. So it was truly put on a lot of miles going up to the friendly confines of Michigan again and caught my first ever Detroit Red Wings game in person, which, didn't quite go so well that night, but them's the breaks. I guess that shouldn't go to the games anymore because they won the next two handily. So what what kind of stuff? Gonna try again. We'll try again. If they make the playoffs, I can't resist. I gotta go again.
Small sample size. Yeah. Yeah. We have an end of of one so far. So, anyway, playoffs, let's cross our fingers. We're still early, but we'll see what happens. But we can guarantee at least we got some awesome highlights to discuss today, and this week's issue was curated by Sam Parmer. And as always, he had tremendous help from our fellow Rwicky team members and contributors like all of you around the world with your poll requests and other wonderful suggestions. So we're gonna speed right into the first highlight and that's, I guess, an intentional pun here because we're gonna look at ways you can speed up assessing different results with one of the packages as getting a lot of attention in the world of asynchronous programming in the our ecosystem.
We are talking about the Mirai package in this first highlight, authored by Charlie Gao who recently joined Posit as an engineer and he has made tremendous progress, making Mirai a first class citizen for almost all things asynchronous across many different workflows in the R ecosystem. And sure enough, there are some hidden gems in there that aren't even as obvious right off the tin. But one of our fellow curators of our we definitely took notice and he's gonna discuss that in our first highlight here. And so this is coming from our longtime curator Jonathan Caro and on his microblog he talks about a neat little exploration, on one of these hidden functions in MirrorEye.
And in particular, what motivated this is he was looking at the latest post from, another, site called Thinking Machines Lab, and it had an interesting header image about how the LLM annotated what looked like a sentence, but in certain parts of the sentence, it had the scores associated by the LOM to put that various word to complete that sentence. And so if you look at the the link in your in your computer after this, you'll see that a few of the words in this sentence have like a threshold next to it of the probability of it being chosen.
So that got him thinking that, you know, there are some times where you might have multiple avenues to get to a solution. You don't necessarily know which one's going to pan out or which one might be quote unquote best. So as he was looking at Mirai, in some additional research, he noticed this little gem called race underscore Mirai in one of its functions, which lets you evaluate with one or more Mirai objects running them at the same time, and then the, the output of that function will return whenever the fastest one completes no matter which one it is. So that's interesting. The the example in the documentation has some little sleep calls so you know which one's gonna finish first.
But you thought that was kind of intriguing because there are a lot of times in the world of data science when you might have multiple op, multiple possibilities to accomplish a task and you don't necessarily know which one's gonna be better. So often you'll do benchmarking and do one at a time to kind of see how they go, but you know what? Why not run them all at once? So it is a classic computer science problem as well as he notes in the blog, and he thought a good way to test this might be to implement three different methods of sorting in r. And this is a little moment for me because I just usually take the default for the sort function, but there are different methods for sorting. We got the quick method, the radix method, and the shell method. Those are all documented in the help page for sort, but he thought it might be interesting to spin up some Mirai daemons for each of these. So he did three of them.
And then to be able to quickly have some helper functions or Mirai objects to run these different sort algorithms with a vector of numbers, in this case, a pretty small vector nonetheless. But he timed that out, and sure enough, the method of sorting called quick was the winner in this very first test. Again, not many ends in this case, but he wanted to prove it out after the mirror I call by just running a simple benchmark from the bench package. Then sure enough in those results, the quick method is the winner there. So that was great and all but that was only for you know up to a thousand numbers there why not bump it up a little bit more let's do a little bigger here shall we so he does that to now about looks like 5,000,000 numbers instead so once you have that what's the fastest here again using Mirai's race Mirai function this time the winner is the Radix method I actually don't know radix does in this case, but that's where the help functions for and sure enough he thought okay sanity check time. Let's run this in benchmark once again and sure enough the fastest is radix but he did notice that and this is a common thing in a lot of things asynchronous processing or HPC computing.
When you use multiple cores or multiple systems there is a bit of overhead when you hand off different, like, data types, data structures, or other parameters in these processes. So sometimes that can be a big deal. Not so much here, but it is something worth as a caveat to note in case you're doing this with a larger set of information. So that means that this race mirror eye is indeed working. It's getting that fastest one out first and that return object so you can use your imagination like he did at the end of the post and do a simple wrapper function, calls a race sort, which does this entire process of spinning up the Mirai daemons, the three different Mirai objects, and then tack caching those results in an object and then be able to inspect what it did there. So there are there's pretty interesting ways you could do this.
You may have some caveats to deal with if you do, say, more than three of these. I don't know. We haven't he hasn't really exhausted. We looked at that yet, but I think for some quick benchmarking, this is a pretty neat, neat opportunity to leverage MirrorEye in a novel use case. So it looks like you did get some, a lot of comments on this on Mastodon after he posted this. So a lot of people are interested in trying this out, I think. And I think I'm gonna add this in my Mirai expirations down the road. So great way to race to that finish line without really knowing which race car is gonna get into that finish line first. So pretty cool little hidden gem in Mirai, and I'm always curious to see more what I could do with that package.
[00:08:40] Mike Thomas:
I'd really appreciated sort of the simple approach to demonstrating this race mirror eye function, because I think he he did a great job sort of explaining the art of the possibilities. And as you mentioned, Eric, setting it up with, the the paper from the Thinking Machines Lab, with the LLM kind of thought process and how it determines what words it's going to include in a sentence. And then even the the reference to the Tuftee book as well, seeing with with fresh eyes where he has kind of this very interesting graphical sentence out there. And his approach here to demonstrating what RayseMirai does, you know, reminds me a lot of, like, the bench package can do with that benchmark function. And I'm not sure sort of what additional insights you get by leveraging MirrorEye to accomplish that where you are kind of benchmarking, you know, the same process that you're running three different ways, on different,
[00:09:41] Eric Nantz:
cores of your computer. Right? Essentially. Right. Right. As opposed to for that matter. It could be no Right. Cluster or anything. Yep.
[00:09:49] Mike Thomas:
That's a very good point. Right. As opposed to, I think, what the bench package tries to do or some of those other ones would be, you know, running it on the same, you know, either single thread or or multiple threads, that same process, multiple times one after the other. So I think that's there may be certainly some interesting use cases where you would want to kind of execute these things all simultaneously and compare the times and obviously get out whichever one ran quickest. I could think of a lot of opportunities here to to do this, to try to improve data pipelines or things like that, and, you know, run different, data wrangling pipelines.
There's a lot of discussion in the comments here that I think, you know, the audience may find interesting. And the most of the com most of the conversation here in the comments of the blog post are around particular use cases, you know, timeouts, cancellations, things like that. So that may help to frame this up a little bit more conceptually. But I think this this, race function is is really, really cool, and I'm excited to see how the MirrorEye package, you know, continues to grow and gain some steam in the ecosystem.
[00:10:58] Eric Nantz:
Yeah. I know Charlie's not slowing down anytime soon. I had a chance to catch up with him a bit of Positconf, and he's got a lot of a lot of big ideas to make this, you know, even more supercharged for for new use cases. So, yeah, if it's not in your async toolbox already, yeah, definitely have a look at Mirai for your async needs. And next, speaking of comparing different ways to get to a result, we, you know, it's twenty twenty five. There are always gonna be some form of an AI type of post and and a highlight, and we have another one, but it's, definitely interesting use case that is coming up a lot more these days on how you can use AI to help accomplish some data analysis needs. And in this particular highlight, we're gonna look at what are some of the common, you know, services that we can use for GenAI generation of LMS in the context of data visualization, which as always can have a lot of different avenues you can pursue here.
And so this post is coming from a long time contributor to our weekly, Nicole O'Rini, who has a great, blog post once again. And and by the way, Nicole Nicola, your quartal site is fantastic. It was hugely helpful for me when I was migrating my shiny dev series site to to quartal. So certainly thank you for sharing your your journey in that migration. But I digress. We're back to Jane AI here. She thought it'd be an interesting exercise to look at one of the things that she does routinely, which is visualization often with the tiny Tuesday data sets that are released every week. And she wondered, you know, I've been doing a lot of this on my own. Wonder how the different Gen AI, you know, model providers are stacking up to a realm of data visualization.
Now there are a lot of ways you can approach this and one might think, well, why don't we take like a classical data set like the MT cars or IRIS or even more recently the penguins data set. She thought, you know what? For this exercise, let's go a little under the radar here. Let's look at some tidy Tuesday datasets that don't necessarily get a lot of press or a lot of examples, if you will, in the online resources that these models are trained on. So she decided to use two different datasets for this, and we'll go through these each one by one here. But the first one is for weather forecasting data.
And instead of looking at the entire dataset, she tried to subset these a bit so that it would not break any, like, context limits when you upload these as part of your prompt for the AI models. So with this, she was she subsetted it to the city of Syracuse in 2021 to look at the predicted forecast for the different days of that year, and she asked the l o m to look at doing a visualization of the forecasted temperature versus the observed temperature. Pretty logical comparison and she even includes in the post what she would do in this situation if it was her hand generating the visualizations and as always they look fantastic. Great use of the best practices for visualization.
So what were the contenders for benchmarking in these, AI models here? The four contenders are chat g b t, Claude by anthropic, copilot, and lastly, Gemini, which has been getting a little more attention because it does have a free tier that I think a lot of people are leveraging at the moment. So she threw a prompt in here, which wasn't a a huge prompt by any means, but it it was to paraphrase here create the relationship or chart for the relationship between forecasted temperature and observed temperature. She mentions that one of the columns explains over the forecast for high or low temperatures which is important when you think about how to organize this, and that she had a very generic sentence at the end. The generated image should follow data visualization best practices.
There are a lot of best practices, so how did this stack up? Well, from the case of the weather forecasting, chat g p t did a halfway decent job and again you'll want to look at the post on your computer or phone when you after listening to this episode. It's a basic scatter plot with the bet with the predictive line with different colors for each of the high or low temperature, you know, points on the graph. But it did some things that were kind of odd such as guessing this the units being Celsius instead of Fahrenheit. It even has a 100 degrees Celsius as for the limit on the axis. Yeah. That you might be melting at that point if I had my mess correct in my head. So the l and then quite get that nuance.
Didn't quite do the best color choice for the high and low temperatures for accessibility reasons, and it was a static plot, which again in some cases might be good, but, you know, it's like interactivity in the age of web based formats and shiny apps. Things get pretty interesting when you look at the different models. Claude basically built an entire React app out of this. Wow, so it was interactive but a little bit excessive probably, and it did like two things not just the plot but then kind of an analysis of the predictability.
And so if you don't know react, good luck debugging that if someone went wrong. But, it did some interesting choices nonetheless. Copilot did okay. You know, it's got an interactive type of chart, with the scatterplot of, again, the two color choices for the different higher low temperature. It did have some nice air checking in the code apparently, but it didn't actually generate the chart when it returned out. She had to expand the chart as part of the objects that were those, being returned. Not as obvious if you're new to this. So that's that was a little weird because you could get the Python code but it had to hit the button calling see my thinking.
While the LMS do this when X tries to hide a lot behind the scenes, so she had to dig the dig the thing the thing out. Last but not least is Gemini, which had an interactive chart with, again, some suspect color choices for the high and low. But being interactive, she could both see the data table and the plot. But, you know, not too bad. Not too bad at all. So I think in this case, Jim and I seem to do pretty well here. But again, each of these, in my opinion, have their benefits and trade offs. But that wasn't the only dataset she looked at, Mike. Looks like she's got another set here looking at CEO departures data. How did the Gen AI models do with this?
[00:18:29] Mike Thomas:
And I think it's involuntary, non health related CEO departures data, where you're looking at the relationship between fiscal year and CEO dismissal rate. So I think for anybody who's familiar with data visualization, when you hear that one of your axes or or variables is going to be a year or some sort of a date, right, that leads us to probably thinking about, line charts, right, for that particular trend analysis. So ChatGPT produced a line chart, and it produced, you know, some accompanying text sort of explaining what it did.
Fairly basic chart doesn't necessarily follow the best data visualization practices like, you know, rotated access labels. It did plot the rate rather than the absolute count given, which was probably, more appropriate for, the dataset that was being used and the, the visual that was produced. So not too bad. Claude unable to produce a visualization. It said that the air the air message that Claude returned was that the text was 2413% larger than allowed. So I think we exceeded the context window and the data was just too big to upload. Copilot said pretty much the exact same thing. Gemini has a nice big context window and produced a small interactive chart, with some accompanying explanation about what it, produced. And again, Eric, similar to the prior dataset, it seems like there's a lot of consistency in the design choices that, these LLMs make when you ask them to produce data visualization. So the the the line chart sort of conceptually from a formatting standpoint looks very similar to the weather forecast data.
And Gemini was also smart enough to plot, the rate instead of the absolute count in terms of CEO dismissals by year. So I can, you know, summarize some of the final thoughts that Nicola had as well. I think she's kind of rank ordering these these AI tools with Gemini being at the top with, you know, sort of good overall comparable performance across the the two datasets and the prompts that she provided. Obviously, charts are are not perfect by any means, but they do allow interactive, data exploration and don't necessarily over complicate things.
ChatGPT, I think was was kind of next in terms of overall utility. You know, very comparable across the two different datasets, very similar. Charts look kind of a little amateurish ish and not quite as good as what Gemini was able to produce. Claude was good for for small datasets but over engineered things way too much. And I can definitely, assimilate with that. I asked a very simple question of a modeling question, financial modeling question the other day to Claude, and it just built me a React app.
[00:21:31] Eric Nantz:
Wow.
[00:21:32] Mike Thomas:
That I did not ask for necessarily need. It was awesome, but went way above and beyond. And Nicola says it it'll do that unless you prompt it not to. So that's something that I have to, think about and and consider is actually telling it not to go above and beyond, which I hadn't thought of. And then Copilot seemed to be kind of the the lowest end of the totem pole here, sort of poor overall. Initially, produced some code to create a chart, but not at the chart itself. And unless you actually click that see my thinking button and unable to work with larger data, I've had similar experiences with Copilot. I don't really understand Copilot because the Microsoft, you know, marketing posts I see lately say that, you know, sitting behind Copilot now is the latest version of ChatGPT or the latest version of of Claude. So I think that there's some integration there. I don't want anybody I feel like if I speak ill of Copilot, somebody from Microsoft is gonna knock on my door two seconds later. So I'm gonna end it there, but I really appreciate it. Yeah. Data visualization isn't something that I've thrown at LLMs too often, and I think Nicole did a great job of, sort of providing us with a couple of use cases across a couple of datasets and and taking a look at benchmarking the results that came back from the different tools that are out there. So very interesting and a reason for me to probably dig into Gemini more than I have to this point.
[00:23:02] Eric Nantz:
Yeah. You and me both. It's been I've heard a lot about it. Just haven't really dived into it. And another thing that'll be interesting to compare as you recall with us at at Positconf a month ago, we did see in one of the keynotes, Joe Chang, unveil the Databot plug in to Positron, which helps you leverage the LOMs to help analyze datasets, and it can produce visualization. So I'm interested to see what Databot's gonna do with a prompt similar to one Nikola has put in here. That might be, an interesting comparison because I know they've done a lot of tuning, as Joe has mentioned, to make sure it doesn't do anything too crazy and it sticks to the confines of the particular data you're looking at. But I think that would be an interesting comparison too.
I still do not do a lot of the agentic side of this other than my, as I mentioned a couple episodes ago, my 4AM escapade, the creative quick shiny after my presentation, which actually was helped because of the shiny context with with that agent encoding. Not like this. I think this if I just did like a well, apparently, if I did quad, I would have had to react that. That would have made no sense in my in my presentation. So good thing I didn't do that. But this is this is some interesting stuff, and the jury's still out to just how far you can take it with such a subjectively, you know, subjectively creative, you know, visualization because there are a lot of choices you have to make as a human that we take for granted that these elements are. Once they get good at this, yeah, then we might get into Skynet territory, but we're we're not quite there yet.
And last in our highlights today, we're gonna revisit a topic that's definitely gotten a lot of attention, especially in the shiny community. And I would say almost the past year, we see multiple, you know, top notch developers and practitioners speak about the benefits and the awesome ways you can supercharge your development with a paradigm called behavior driven development or BDD for short. In fact, I was rewatching some of the PasaConf recordings and there was a great presentation about BDD in the context of building a shiny dashboard. But one of the things that we've been featuring in previous episodes of our weekly highlights is kind of the nuts and bolts of how this works in the context of a shiny application.
And the contributor at the forefront of this has been Jacob Sobolewski, who I believe is an engineer at at Absalon, who has been doing multiple posts. And I do mean multiple on his blog about the different niches inside BDD and other test, you know, development strategies. And we've we've covered them. I know at least a handful of them in previous episodes. But when he comes with us today is probably the best place to start for this. So it's kind of interesting that this didn't come first, but this was the culmination not too dissimilar to what Veera did in our last episode with the shiny side of l o m series.
Now if you've heard about BDD and you're like, what's in it for me? But what does this actually look like in practice? This post is for you. Because Jacob in this post, in a very comprehensive way, takes you from literally nothing. You've got an idea for an app, but you have nothing yet. And how BDD can help construct the inner workings of this application in ways that, at least I can speak for myself, I did not expect at all. And the overall framing of this is going from the outside in. And let's elaborate what that really means. Instead of whipping out your your favorite template snippet of like your app UI and app server functions, you're starting from scratch with writing specifications.
Now not just specifications on like a plain text document, but actually specifications within test stat. What the heck do I mean by this? Well, if you got your test stat structure all booted up in your application structure, you can then do within this a test script like he calls, and let me phrase the context of this. He is building an application that's a simple kind of user form with a few different fields. And then when that feed those fields are quote, unquote submitted, it's going to some storage system for another app or another process that consume. Quite common in the world of Shiny. You're assembling user inputs. You're taking those. You're sending them somewhere.
So he starts literally from the basics of this specification around the idea of the data submission process. And in this code that he has in the blog post, you have two different approaches to this. But one, within test that you have a function called describe, and this is where you can put, like, the overall subject of that specification, and then the function it about what quote unquote that specification is supposed to accomplish. This is where it gets interesting. He has three functions that look as if I'm writing them in plain language, given no content, pipe that to when I submit entry with all required fields, pipe that, then there are entries.
I really had to take a double take on this for a little bit. It was like, where did those come from? The test that, you know, just go crazy on me? No. These functions don't exist yet. That's the paradigm here that does take a little bit getting used to. Use plain language to create functions. Actually don't have anything in it yet, and we're starting from the specification. So of course that's not gonna work on its own. Right? It's not supposed to work on yet because we don't have flush anything out yet. So that's where you start building the actual test infrastructure to fill in the blanks a little bit on these functions, like given no content. What does that actually mean? Well, now in this next part of the post, he does put in some ideas of what this means.
So in the case of given no content, you're creating whatever the storage mechanism is going to be. You're going to create what's called a driver to put things into that storage and then returning the context object associated with it. Again, nothing's been built for that part yet either. Those innards are still not fleshed out yet, but he's doing this for each of those steps in the specification, fleshing out those functions kind of in a step by step fashion. So again, that's the point. They don't exist yet, but it's framing your mind. Now again, this is why I'm interpreting it. Maybe I'm getting this totally wrong.
It's framing your mind for what you need to complete in order to satisfy this specification. So you can kind of start doing this bit by bit. So then you think, okay. Well, I got those inner parts of that specification function not fleshed out yet. How do we actually do this? So this is where things get interesting and I learned something new just even in the in the weeds a little bit. You can also extend certain objects from shiny test two, which he's gonna use in this example. The app driver r six object is what Shiny test two uses to, you know, do the manipulation in your app, like setting inputs or returning stuff.
You can extend the existing class, and he's got a little utility function in there called fill required fields and has, you know, the placeholders for those different inputs, then he's able to put those in. And again, the key part is it's hiding implementation details still, even though he got the the bones of this driver function, there's still some things that need to be fleshed out. And then it only then does he get to actually starting to write work on the app itself. So we went from like the very bare bones specification to the inner workings of those specifications and now to the app itself and things are still kind of abstract, but then it's like, okay, now we got the app scaffolding. How do we implement like the storage mechanism?
Now he brings an r six class into the picture, but it didn't start this way. That's the key. It did not start this way. And then he goes through the different specifications fleshing out what the driver will do to satisfy these different specifications. Absolutely fascinating. And, again, there we would need probably another hour to really dive in the nuts and bolts of this. But the nice thing here is that this has examples that you can draw upon for, again, a very basic app, and that's his his call to action at the end here. Try this out once. I think he realizes that when we look at this on the surface, it may be difficult to grok until you actually get into the weeds of it.
But as you get into the weeds of this, he does have links to those previous posts that I mentioned about whether it's the cadence of BDD all the way into the nuts and bolts of unit testing versus acceptance testing and a lot of the things that he started with in this series. But now this is kind of like that flowchart of where things fit in that big picture. I admit I'm in a case where I've started a big app about a year ago, so I can't, like, retrofit it per se. But when I get a new app in my in my shop, I'm definitely gonna try this out if it's basic enough because I don't know. Still, the jury's still out on huge apps and how this will work, but it definitely got me thinking a bit. So the the shiny developer in me thinks that this might be worth a test drive of a smaller app. But, Mike, what do you think about the BDD workflow here?
[00:33:40] Mike Thomas:
I like it. I feel very seen or called out by Jacob, in the try this yourself section where he goes, you don't have excuses anymore. Here's your playbook. He has given us a playbook multiple times. And this is probably, as you mentioned, Eric, the best end to end simple simplified use case, for leveraging this particular frame framework, this BDD framework. And there's a lot of great benefits to it. You you're really starting again from the outside in with these high level things that you're trying to accomplish and and writing those down. It almost feels Bayesian in a way. And and you're starting with a very simple implementation that forces you or really encourages you to write your unit tests at the the same time, and put those out before you actually get to writing the Shiny code itself. Very, probably, object oriented programming comes in here in a lot of different ways, I imagine, not just in some of the examples, but I think it it sort of makes sense to use an OOP approach when you're using the speed ed, throw another few more acronyms out there, type of framework.
And it it certainly makes a lot of sense. I see the reason behind doing it. And, you know, I really like the approach that he's he's laid out here for us in this particular example. So Jacob really just has this four step process where he he recommends us to try to get started if you don't want to, you know, sort of copy exactly what he did in this blog post, you know, with this, again, you know, cucumber and and Gherkin methodology for writing sort of in plain English, things that you're trying to accomplish. So these four steps are, you know, write one acceptance test describing user value, and it it has to fail. Build just enough infrastructure to run it, which also must fail, and then develop the and implement the simplest solution that passes to to make it pass, and then refactor when your tests provide safety, once those tests are in place to keep it passing, which makes a whole lot of sense. It's obviously sort of not the workflow that I'm sure most of us shiny developers started out in our career doing. Maybe you did.
But for me, it was, hey, how can I write my code to to make my app do cool stuff as quickly as possible as opposed to build the safety nets around it first, or think about it sort of from a high level first? And I think we all know in our gut that we should have gone the opposite way, and Jacob has provided us now with ample resources to help hold our hand when we decide to to go that opposite way in that sort of more safeguarded approach. So this is, again, not his first blog post in this series, and probably the one that lays it out as obviously for me as possible. So I'd really encourage anyone in the shiny community out there to to take a look at this. If this is new concepts to you, I I think this will really hit home, this particular blog
[00:36:52] Eric Nantz:
post. Yeah. This is going into my running list of different expirations to challenge myself in my dev workflow. And behind the scenes, I've been doing some things to eventually, you know, within hopefully a few months, resurrect the shiny dev series. And I think something like this is right to evaluate even if it's just myself initially. But, I I think it's like you said, there's no excuse now. So I I I definitely have some projects coming up that I think could be a good test case for this, and especially since I'm beefing up some of the other open source work I do, I think this could be a great companion. Maybe some of the shiny state stuff I do better down the road. So who knows how far I can take it. But, you and your learning journey of our can take it your your learning journey in all sorts of directions of our weekly. We've got not just these highlights. We've got so many of our great updates. There's great showcases in the world of data science, new packages, great tutorials, and whatnot.
Again, we could blab around for three more hours about the content in each of these issues, but we can't do that today. So we'll leave you with, of course, the link to get all this information is at rweekly.0rg, the the latest issue right on the front page, as well as the archive of issues too if you want to catch up on what you missed. And also, we love to hear from you and the audience as well. One of the best ways to help out the project is via a poll request, and you can do that with, like, a new blog post link, a new package link. Just send us a pull request on GitHub. It's all marked down all the time. Markdown is awesome. Markdown is king. I write our markdown, markdown, all the markdowns out there, different flavors. I love them all.
But we also love hearing from you directly too. You can get in touch with us via the contact page in the episode show notes. You can also get a hold of us on social media. I am at blue sky [email protected]. Also, I'm Massimo with @rpodcastatpodcastindexonsocial, and I'm on LinkedIn. Just search my name. You'll find me there causing all sorts of chaos. Mike, where can listeners find you? On blue sky at mike dash thomas dot b s k y dot social
[00:39:12] Mike Thomas:
or on LinkedIn in if you search Ketchbrooke Analytics, k e t c h b r o o k, you can see what I'm up to. Alright. Well, that will do it. I'll put a stamp on episode 213.
[00:39:22] Eric Nantz:
No more fall breaks at least until the holiday season, I guess. But we should be back hopefully with another edition of our weekly highlights next week.
Hello, friends. We are back with episode 213 of the Our Week Who Howlads podcast. And thanks for being patient with us. We were off last week. I'll get to why in a little bit. But if you're tuning in for the first time, this this is the usually weekly show where we talk about the excellent highlights and other resources that have been shared on this week's our weekly issue at ourweekly.0rg. My name is Eric Nance, and I'm glad you joined us from wherever you are around the world. And at least he's back at this time, hopefully, not as rusty as I am. My awesome cohost, Mike Thomas, is with me as always. Hi, Mike. How are you doing?
[00:00:38] Mike Thomas:
Doing pretty well. We had a a big nor'easter yesterday that wiped out power, but we are back up and running today and ready to record.
[00:00:46] Eric Nantz:
Well, happy to hear you are safe at least after that one. I had a good good little, time off. The kids had the fall break from school. We're not to put that back in my day hat on, but back in my day, we didn't get things like fall breaks. It was only spring break, and that was it. So these kids don't know how good they have it. So it was truly put on a lot of miles going up to the friendly confines of Michigan again and caught my first ever Detroit Red Wings game in person, which, didn't quite go so well that night, but them's the breaks. I guess that shouldn't go to the games anymore because they won the next two handily. So what what kind of stuff? Gonna try again. We'll try again. If they make the playoffs, I can't resist. I gotta go again.
Small sample size. Yeah. Yeah. We have an end of of one so far. So, anyway, playoffs, let's cross our fingers. We're still early, but we'll see what happens. But we can guarantee at least we got some awesome highlights to discuss today, and this week's issue was curated by Sam Parmer. And as always, he had tremendous help from our fellow Rwicky team members and contributors like all of you around the world with your poll requests and other wonderful suggestions. So we're gonna speed right into the first highlight and that's, I guess, an intentional pun here because we're gonna look at ways you can speed up assessing different results with one of the packages as getting a lot of attention in the world of asynchronous programming in the our ecosystem.
We are talking about the Mirai package in this first highlight, authored by Charlie Gao who recently joined Posit as an engineer and he has made tremendous progress, making Mirai a first class citizen for almost all things asynchronous across many different workflows in the R ecosystem. And sure enough, there are some hidden gems in there that aren't even as obvious right off the tin. But one of our fellow curators of our we definitely took notice and he's gonna discuss that in our first highlight here. And so this is coming from our longtime curator Jonathan Caro and on his microblog he talks about a neat little exploration, on one of these hidden functions in MirrorEye.
And in particular, what motivated this is he was looking at the latest post from, another, site called Thinking Machines Lab, and it had an interesting header image about how the LLM annotated what looked like a sentence, but in certain parts of the sentence, it had the scores associated by the LOM to put that various word to complete that sentence. And so if you look at the the link in your in your computer after this, you'll see that a few of the words in this sentence have like a threshold next to it of the probability of it being chosen.
So that got him thinking that, you know, there are some times where you might have multiple avenues to get to a solution. You don't necessarily know which one's going to pan out or which one might be quote unquote best. So as he was looking at Mirai, in some additional research, he noticed this little gem called race underscore Mirai in one of its functions, which lets you evaluate with one or more Mirai objects running them at the same time, and then the, the output of that function will return whenever the fastest one completes no matter which one it is. So that's interesting. The the example in the documentation has some little sleep calls so you know which one's gonna finish first.
But you thought that was kind of intriguing because there are a lot of times in the world of data science when you might have multiple op, multiple possibilities to accomplish a task and you don't necessarily know which one's gonna be better. So often you'll do benchmarking and do one at a time to kind of see how they go, but you know what? Why not run them all at once? So it is a classic computer science problem as well as he notes in the blog, and he thought a good way to test this might be to implement three different methods of sorting in r. And this is a little moment for me because I just usually take the default for the sort function, but there are different methods for sorting. We got the quick method, the radix method, and the shell method. Those are all documented in the help page for sort, but he thought it might be interesting to spin up some Mirai daemons for each of these. So he did three of them.
And then to be able to quickly have some helper functions or Mirai objects to run these different sort algorithms with a vector of numbers, in this case, a pretty small vector nonetheless. But he timed that out, and sure enough, the method of sorting called quick was the winner in this very first test. Again, not many ends in this case, but he wanted to prove it out after the mirror I call by just running a simple benchmark from the bench package. Then sure enough in those results, the quick method is the winner there. So that was great and all but that was only for you know up to a thousand numbers there why not bump it up a little bit more let's do a little bigger here shall we so he does that to now about looks like 5,000,000 numbers instead so once you have that what's the fastest here again using Mirai's race Mirai function this time the winner is the Radix method I actually don't know radix does in this case, but that's where the help functions for and sure enough he thought okay sanity check time. Let's run this in benchmark once again and sure enough the fastest is radix but he did notice that and this is a common thing in a lot of things asynchronous processing or HPC computing.
When you use multiple cores or multiple systems there is a bit of overhead when you hand off different, like, data types, data structures, or other parameters in these processes. So sometimes that can be a big deal. Not so much here, but it is something worth as a caveat to note in case you're doing this with a larger set of information. So that means that this race mirror eye is indeed working. It's getting that fastest one out first and that return object so you can use your imagination like he did at the end of the post and do a simple wrapper function, calls a race sort, which does this entire process of spinning up the Mirai daemons, the three different Mirai objects, and then tack caching those results in an object and then be able to inspect what it did there. So there are there's pretty interesting ways you could do this.
You may have some caveats to deal with if you do, say, more than three of these. I don't know. We haven't he hasn't really exhausted. We looked at that yet, but I think for some quick benchmarking, this is a pretty neat, neat opportunity to leverage MirrorEye in a novel use case. So it looks like you did get some, a lot of comments on this on Mastodon after he posted this. So a lot of people are interested in trying this out, I think. And I think I'm gonna add this in my Mirai expirations down the road. So great way to race to that finish line without really knowing which race car is gonna get into that finish line first. So pretty cool little hidden gem in Mirai, and I'm always curious to see more what I could do with that package.
[00:08:40] Mike Thomas:
I'd really appreciated sort of the simple approach to demonstrating this race mirror eye function, because I think he he did a great job sort of explaining the art of the possibilities. And as you mentioned, Eric, setting it up with, the the paper from the Thinking Machines Lab, with the LLM kind of thought process and how it determines what words it's going to include in a sentence. And then even the the reference to the Tuftee book as well, seeing with with fresh eyes where he has kind of this very interesting graphical sentence out there. And his approach here to demonstrating what RayseMirai does, you know, reminds me a lot of, like, the bench package can do with that benchmark function. And I'm not sure sort of what additional insights you get by leveraging MirrorEye to accomplish that where you are kind of benchmarking, you know, the same process that you're running three different ways, on different,
[00:09:41] Eric Nantz:
cores of your computer. Right? Essentially. Right. Right. As opposed to for that matter. It could be no Right. Cluster or anything. Yep.
[00:09:49] Mike Thomas:
That's a very good point. Right. As opposed to, I think, what the bench package tries to do or some of those other ones would be, you know, running it on the same, you know, either single thread or or multiple threads, that same process, multiple times one after the other. So I think that's there may be certainly some interesting use cases where you would want to kind of execute these things all simultaneously and compare the times and obviously get out whichever one ran quickest. I could think of a lot of opportunities here to to do this, to try to improve data pipelines or things like that, and, you know, run different, data wrangling pipelines.
There's a lot of discussion in the comments here that I think, you know, the audience may find interesting. And the most of the com most of the conversation here in the comments of the blog post are around particular use cases, you know, timeouts, cancellations, things like that. So that may help to frame this up a little bit more conceptually. But I think this this, race function is is really, really cool, and I'm excited to see how the MirrorEye package, you know, continues to grow and gain some steam in the ecosystem.
[00:10:58] Eric Nantz:
Yeah. I know Charlie's not slowing down anytime soon. I had a chance to catch up with him a bit of Positconf, and he's got a lot of a lot of big ideas to make this, you know, even more supercharged for for new use cases. So, yeah, if it's not in your async toolbox already, yeah, definitely have a look at Mirai for your async needs. And next, speaking of comparing different ways to get to a result, we, you know, it's twenty twenty five. There are always gonna be some form of an AI type of post and and a highlight, and we have another one, but it's, definitely interesting use case that is coming up a lot more these days on how you can use AI to help accomplish some data analysis needs. And in this particular highlight, we're gonna look at what are some of the common, you know, services that we can use for GenAI generation of LMS in the context of data visualization, which as always can have a lot of different avenues you can pursue here.
And so this post is coming from a long time contributor to our weekly, Nicole O'Rini, who has a great, blog post once again. And and by the way, Nicole Nicola, your quartal site is fantastic. It was hugely helpful for me when I was migrating my shiny dev series site to to quartal. So certainly thank you for sharing your your journey in that migration. But I digress. We're back to Jane AI here. She thought it'd be an interesting exercise to look at one of the things that she does routinely, which is visualization often with the tiny Tuesday data sets that are released every week. And she wondered, you know, I've been doing a lot of this on my own. Wonder how the different Gen AI, you know, model providers are stacking up to a realm of data visualization.
Now there are a lot of ways you can approach this and one might think, well, why don't we take like a classical data set like the MT cars or IRIS or even more recently the penguins data set. She thought, you know what? For this exercise, let's go a little under the radar here. Let's look at some tidy Tuesday datasets that don't necessarily get a lot of press or a lot of examples, if you will, in the online resources that these models are trained on. So she decided to use two different datasets for this, and we'll go through these each one by one here. But the first one is for weather forecasting data.
And instead of looking at the entire dataset, she tried to subset these a bit so that it would not break any, like, context limits when you upload these as part of your prompt for the AI models. So with this, she was she subsetted it to the city of Syracuse in 2021 to look at the predicted forecast for the different days of that year, and she asked the l o m to look at doing a visualization of the forecasted temperature versus the observed temperature. Pretty logical comparison and she even includes in the post what she would do in this situation if it was her hand generating the visualizations and as always they look fantastic. Great use of the best practices for visualization.
So what were the contenders for benchmarking in these, AI models here? The four contenders are chat g b t, Claude by anthropic, copilot, and lastly, Gemini, which has been getting a little more attention because it does have a free tier that I think a lot of people are leveraging at the moment. So she threw a prompt in here, which wasn't a a huge prompt by any means, but it it was to paraphrase here create the relationship or chart for the relationship between forecasted temperature and observed temperature. She mentions that one of the columns explains over the forecast for high or low temperatures which is important when you think about how to organize this, and that she had a very generic sentence at the end. The generated image should follow data visualization best practices.
There are a lot of best practices, so how did this stack up? Well, from the case of the weather forecasting, chat g p t did a halfway decent job and again you'll want to look at the post on your computer or phone when you after listening to this episode. It's a basic scatter plot with the bet with the predictive line with different colors for each of the high or low temperature, you know, points on the graph. But it did some things that were kind of odd such as guessing this the units being Celsius instead of Fahrenheit. It even has a 100 degrees Celsius as for the limit on the axis. Yeah. That you might be melting at that point if I had my mess correct in my head. So the l and then quite get that nuance.
Didn't quite do the best color choice for the high and low temperatures for accessibility reasons, and it was a static plot, which again in some cases might be good, but, you know, it's like interactivity in the age of web based formats and shiny apps. Things get pretty interesting when you look at the different models. Claude basically built an entire React app out of this. Wow, so it was interactive but a little bit excessive probably, and it did like two things not just the plot but then kind of an analysis of the predictability.
And so if you don't know react, good luck debugging that if someone went wrong. But, it did some interesting choices nonetheless. Copilot did okay. You know, it's got an interactive type of chart, with the scatterplot of, again, the two color choices for the different higher low temperature. It did have some nice air checking in the code apparently, but it didn't actually generate the chart when it returned out. She had to expand the chart as part of the objects that were those, being returned. Not as obvious if you're new to this. So that's that was a little weird because you could get the Python code but it had to hit the button calling see my thinking.
While the LMS do this when X tries to hide a lot behind the scenes, so she had to dig the dig the thing the thing out. Last but not least is Gemini, which had an interactive chart with, again, some suspect color choices for the high and low. But being interactive, she could both see the data table and the plot. But, you know, not too bad. Not too bad at all. So I think in this case, Jim and I seem to do pretty well here. But again, each of these, in my opinion, have their benefits and trade offs. But that wasn't the only dataset she looked at, Mike. Looks like she's got another set here looking at CEO departures data. How did the Gen AI models do with this?
[00:18:29] Mike Thomas:
And I think it's involuntary, non health related CEO departures data, where you're looking at the relationship between fiscal year and CEO dismissal rate. So I think for anybody who's familiar with data visualization, when you hear that one of your axes or or variables is going to be a year or some sort of a date, right, that leads us to probably thinking about, line charts, right, for that particular trend analysis. So ChatGPT produced a line chart, and it produced, you know, some accompanying text sort of explaining what it did.
Fairly basic chart doesn't necessarily follow the best data visualization practices like, you know, rotated access labels. It did plot the rate rather than the absolute count given, which was probably, more appropriate for, the dataset that was being used and the, the visual that was produced. So not too bad. Claude unable to produce a visualization. It said that the air the air message that Claude returned was that the text was 2413% larger than allowed. So I think we exceeded the context window and the data was just too big to upload. Copilot said pretty much the exact same thing. Gemini has a nice big context window and produced a small interactive chart, with some accompanying explanation about what it, produced. And again, Eric, similar to the prior dataset, it seems like there's a lot of consistency in the design choices that, these LLMs make when you ask them to produce data visualization. So the the the line chart sort of conceptually from a formatting standpoint looks very similar to the weather forecast data.
And Gemini was also smart enough to plot, the rate instead of the absolute count in terms of CEO dismissals by year. So I can, you know, summarize some of the final thoughts that Nicola had as well. I think she's kind of rank ordering these these AI tools with Gemini being at the top with, you know, sort of good overall comparable performance across the the two datasets and the prompts that she provided. Obviously, charts are are not perfect by any means, but they do allow interactive, data exploration and don't necessarily over complicate things.
ChatGPT, I think was was kind of next in terms of overall utility. You know, very comparable across the two different datasets, very similar. Charts look kind of a little amateurish ish and not quite as good as what Gemini was able to produce. Claude was good for for small datasets but over engineered things way too much. And I can definitely, assimilate with that. I asked a very simple question of a modeling question, financial modeling question the other day to Claude, and it just built me a React app.
[00:21:31] Eric Nantz:
Wow.
[00:21:32] Mike Thomas:
That I did not ask for necessarily need. It was awesome, but went way above and beyond. And Nicola says it it'll do that unless you prompt it not to. So that's something that I have to, think about and and consider is actually telling it not to go above and beyond, which I hadn't thought of. And then Copilot seemed to be kind of the the lowest end of the totem pole here, sort of poor overall. Initially, produced some code to create a chart, but not at the chart itself. And unless you actually click that see my thinking button and unable to work with larger data, I've had similar experiences with Copilot. I don't really understand Copilot because the Microsoft, you know, marketing posts I see lately say that, you know, sitting behind Copilot now is the latest version of ChatGPT or the latest version of of Claude. So I think that there's some integration there. I don't want anybody I feel like if I speak ill of Copilot, somebody from Microsoft is gonna knock on my door two seconds later. So I'm gonna end it there, but I really appreciate it. Yeah. Data visualization isn't something that I've thrown at LLMs too often, and I think Nicole did a great job of, sort of providing us with a couple of use cases across a couple of datasets and and taking a look at benchmarking the results that came back from the different tools that are out there. So very interesting and a reason for me to probably dig into Gemini more than I have to this point.
[00:23:02] Eric Nantz:
Yeah. You and me both. It's been I've heard a lot about it. Just haven't really dived into it. And another thing that'll be interesting to compare as you recall with us at at Positconf a month ago, we did see in one of the keynotes, Joe Chang, unveil the Databot plug in to Positron, which helps you leverage the LOMs to help analyze datasets, and it can produce visualization. So I'm interested to see what Databot's gonna do with a prompt similar to one Nikola has put in here. That might be, an interesting comparison because I know they've done a lot of tuning, as Joe has mentioned, to make sure it doesn't do anything too crazy and it sticks to the confines of the particular data you're looking at. But I think that would be an interesting comparison too.
I still do not do a lot of the agentic side of this other than my, as I mentioned a couple episodes ago, my 4AM escapade, the creative quick shiny after my presentation, which actually was helped because of the shiny context with with that agent encoding. Not like this. I think this if I just did like a well, apparently, if I did quad, I would have had to react that. That would have made no sense in my in my presentation. So good thing I didn't do that. But this is this is some interesting stuff, and the jury's still out to just how far you can take it with such a subjectively, you know, subjectively creative, you know, visualization because there are a lot of choices you have to make as a human that we take for granted that these elements are. Once they get good at this, yeah, then we might get into Skynet territory, but we're we're not quite there yet.
And last in our highlights today, we're gonna revisit a topic that's definitely gotten a lot of attention, especially in the shiny community. And I would say almost the past year, we see multiple, you know, top notch developers and practitioners speak about the benefits and the awesome ways you can supercharge your development with a paradigm called behavior driven development or BDD for short. In fact, I was rewatching some of the PasaConf recordings and there was a great presentation about BDD in the context of building a shiny dashboard. But one of the things that we've been featuring in previous episodes of our weekly highlights is kind of the nuts and bolts of how this works in the context of a shiny application.
And the contributor at the forefront of this has been Jacob Sobolewski, who I believe is an engineer at at Absalon, who has been doing multiple posts. And I do mean multiple on his blog about the different niches inside BDD and other test, you know, development strategies. And we've we've covered them. I know at least a handful of them in previous episodes. But when he comes with us today is probably the best place to start for this. So it's kind of interesting that this didn't come first, but this was the culmination not too dissimilar to what Veera did in our last episode with the shiny side of l o m series.
Now if you've heard about BDD and you're like, what's in it for me? But what does this actually look like in practice? This post is for you. Because Jacob in this post, in a very comprehensive way, takes you from literally nothing. You've got an idea for an app, but you have nothing yet. And how BDD can help construct the inner workings of this application in ways that, at least I can speak for myself, I did not expect at all. And the overall framing of this is going from the outside in. And let's elaborate what that really means. Instead of whipping out your your favorite template snippet of like your app UI and app server functions, you're starting from scratch with writing specifications.
Now not just specifications on like a plain text document, but actually specifications within test stat. What the heck do I mean by this? Well, if you got your test stat structure all booted up in your application structure, you can then do within this a test script like he calls, and let me phrase the context of this. He is building an application that's a simple kind of user form with a few different fields. And then when that feed those fields are quote, unquote submitted, it's going to some storage system for another app or another process that consume. Quite common in the world of Shiny. You're assembling user inputs. You're taking those. You're sending them somewhere.
So he starts literally from the basics of this specification around the idea of the data submission process. And in this code that he has in the blog post, you have two different approaches to this. But one, within test that you have a function called describe, and this is where you can put, like, the overall subject of that specification, and then the function it about what quote unquote that specification is supposed to accomplish. This is where it gets interesting. He has three functions that look as if I'm writing them in plain language, given no content, pipe that to when I submit entry with all required fields, pipe that, then there are entries.
I really had to take a double take on this for a little bit. It was like, where did those come from? The test that, you know, just go crazy on me? No. These functions don't exist yet. That's the paradigm here that does take a little bit getting used to. Use plain language to create functions. Actually don't have anything in it yet, and we're starting from the specification. So of course that's not gonna work on its own. Right? It's not supposed to work on yet because we don't have flush anything out yet. So that's where you start building the actual test infrastructure to fill in the blanks a little bit on these functions, like given no content. What does that actually mean? Well, now in this next part of the post, he does put in some ideas of what this means.
So in the case of given no content, you're creating whatever the storage mechanism is going to be. You're going to create what's called a driver to put things into that storage and then returning the context object associated with it. Again, nothing's been built for that part yet either. Those innards are still not fleshed out yet, but he's doing this for each of those steps in the specification, fleshing out those functions kind of in a step by step fashion. So again, that's the point. They don't exist yet, but it's framing your mind. Now again, this is why I'm interpreting it. Maybe I'm getting this totally wrong.
It's framing your mind for what you need to complete in order to satisfy this specification. So you can kind of start doing this bit by bit. So then you think, okay. Well, I got those inner parts of that specification function not fleshed out yet. How do we actually do this? So this is where things get interesting and I learned something new just even in the in the weeds a little bit. You can also extend certain objects from shiny test two, which he's gonna use in this example. The app driver r six object is what Shiny test two uses to, you know, do the manipulation in your app, like setting inputs or returning stuff.
You can extend the existing class, and he's got a little utility function in there called fill required fields and has, you know, the placeholders for those different inputs, then he's able to put those in. And again, the key part is it's hiding implementation details still, even though he got the the bones of this driver function, there's still some things that need to be fleshed out. And then it only then does he get to actually starting to write work on the app itself. So we went from like the very bare bones specification to the inner workings of those specifications and now to the app itself and things are still kind of abstract, but then it's like, okay, now we got the app scaffolding. How do we implement like the storage mechanism?
Now he brings an r six class into the picture, but it didn't start this way. That's the key. It did not start this way. And then he goes through the different specifications fleshing out what the driver will do to satisfy these different specifications. Absolutely fascinating. And, again, there we would need probably another hour to really dive in the nuts and bolts of this. But the nice thing here is that this has examples that you can draw upon for, again, a very basic app, and that's his his call to action at the end here. Try this out once. I think he realizes that when we look at this on the surface, it may be difficult to grok until you actually get into the weeds of it.
But as you get into the weeds of this, he does have links to those previous posts that I mentioned about whether it's the cadence of BDD all the way into the nuts and bolts of unit testing versus acceptance testing and a lot of the things that he started with in this series. But now this is kind of like that flowchart of where things fit in that big picture. I admit I'm in a case where I've started a big app about a year ago, so I can't, like, retrofit it per se. But when I get a new app in my in my shop, I'm definitely gonna try this out if it's basic enough because I don't know. Still, the jury's still out on huge apps and how this will work, but it definitely got me thinking a bit. So the the shiny developer in me thinks that this might be worth a test drive of a smaller app. But, Mike, what do you think about the BDD workflow here?
[00:33:40] Mike Thomas:
I like it. I feel very seen or called out by Jacob, in the try this yourself section where he goes, you don't have excuses anymore. Here's your playbook. He has given us a playbook multiple times. And this is probably, as you mentioned, Eric, the best end to end simple simplified use case, for leveraging this particular frame framework, this BDD framework. And there's a lot of great benefits to it. You you're really starting again from the outside in with these high level things that you're trying to accomplish and and writing those down. It almost feels Bayesian in a way. And and you're starting with a very simple implementation that forces you or really encourages you to write your unit tests at the the same time, and put those out before you actually get to writing the Shiny code itself. Very, probably, object oriented programming comes in here in a lot of different ways, I imagine, not just in some of the examples, but I think it it sort of makes sense to use an OOP approach when you're using the speed ed, throw another few more acronyms out there, type of framework.
And it it certainly makes a lot of sense. I see the reason behind doing it. And, you know, I really like the approach that he's he's laid out here for us in this particular example. So Jacob really just has this four step process where he he recommends us to try to get started if you don't want to, you know, sort of copy exactly what he did in this blog post, you know, with this, again, you know, cucumber and and Gherkin methodology for writing sort of in plain English, things that you're trying to accomplish. So these four steps are, you know, write one acceptance test describing user value, and it it has to fail. Build just enough infrastructure to run it, which also must fail, and then develop the and implement the simplest solution that passes to to make it pass, and then refactor when your tests provide safety, once those tests are in place to keep it passing, which makes a whole lot of sense. It's obviously sort of not the workflow that I'm sure most of us shiny developers started out in our career doing. Maybe you did.
But for me, it was, hey, how can I write my code to to make my app do cool stuff as quickly as possible as opposed to build the safety nets around it first, or think about it sort of from a high level first? And I think we all know in our gut that we should have gone the opposite way, and Jacob has provided us now with ample resources to help hold our hand when we decide to to go that opposite way in that sort of more safeguarded approach. So this is, again, not his first blog post in this series, and probably the one that lays it out as obviously for me as possible. So I'd really encourage anyone in the shiny community out there to to take a look at this. If this is new concepts to you, I I think this will really hit home, this particular blog
[00:36:52] Eric Nantz:
post. Yeah. This is going into my running list of different expirations to challenge myself in my dev workflow. And behind the scenes, I've been doing some things to eventually, you know, within hopefully a few months, resurrect the shiny dev series. And I think something like this is right to evaluate even if it's just myself initially. But, I I think it's like you said, there's no excuse now. So I I I definitely have some projects coming up that I think could be a good test case for this, and especially since I'm beefing up some of the other open source work I do, I think this could be a great companion. Maybe some of the shiny state stuff I do better down the road. So who knows how far I can take it. But, you and your learning journey of our can take it your your learning journey in all sorts of directions of our weekly. We've got not just these highlights. We've got so many of our great updates. There's great showcases in the world of data science, new packages, great tutorials, and whatnot.
Again, we could blab around for three more hours about the content in each of these issues, but we can't do that today. So we'll leave you with, of course, the link to get all this information is at rweekly.0rg, the the latest issue right on the front page, as well as the archive of issues too if you want to catch up on what you missed. And also, we love to hear from you and the audience as well. One of the best ways to help out the project is via a poll request, and you can do that with, like, a new blog post link, a new package link. Just send us a pull request on GitHub. It's all marked down all the time. Markdown is awesome. Markdown is king. I write our markdown, markdown, all the markdowns out there, different flavors. I love them all.
But we also love hearing from you directly too. You can get in touch with us via the contact page in the episode show notes. You can also get a hold of us on social media. I am at blue sky [email protected]. Also, I'm Massimo with @rpodcastatpodcastindexonsocial, and I'm on LinkedIn. Just search my name. You'll find me there causing all sorts of chaos. Mike, where can listeners find you? On blue sky at mike dash thomas dot b s k y dot social
[00:39:12] Mike Thomas:
or on LinkedIn in if you search Ketchbrooke Analytics, k e t c h b r o o k, you can see what I'm up to. Alright. Well, that will do it. I'll put a stamp on episode 213.
[00:39:22] Eric Nantz:
No more fall breaks at least until the holiday season, I guess. But we should be back hopefully with another edition of our weekly highlights next week.
Episode Wrapup