Talking Code & Product with Benedikt Deicke
Brian Casel : [00:00:00] Hey, it's Open Threads. It's my podcast. I'm Brian Casel. Welcome to it. Back on the show today is Benedikt Deicke. He is the co-founder of Userlist. You've heard Benedikt a couple episodes back where we talked about product and starting off a new SaaS company and deciding what to build. Well, as the technical co-founder in Userlist, Benedikt and I, really geeked out in this second half on code and software frameworks and deciding on which tools to use. We talked about frontend, we talked about backend, API driven development, test driven development, or not test driven development, but talking in depth about test coverage in SaaS and software. So I think it was a fun opportunity to really geek out on the code side of things.
I find it interesting, you know, there are [00:01:00] so many SaaS, podcasts out there but most of them talk about the marketing side of SaaS, which of course is important. Or they talk about, the story of building a SaaS company or, you know, there are some like development and software development, podcasts out there, but they're not really talking about the business of SaaS.
I think in this episode, Benedikt and I, had a really good chat talking about the technical considerations as they apply to a SaaS business. So I think you'll really enjoy it. As always, today's show is brought to you by ZipMessage. That's the tool for async video messaging and audio, and screen and text. You can mix it up. That's what most people do with ZipMessage. I'll tell you a thing or two about that later in the show. But for now, let's talk to Benedikt about code.
Benedikt Deicke: Yeah. I mean that's maybe that, yeah, let's maybe take a step back and be upfront about this. Like Userlist is a Rails application in the backend, but it doesn't have any Vue logic, [00:03:00] any styling whatsoever. It's basically just an adjacent API and then it's a frontend code base in Ember.js. That's, that's actually a separate repository that just talks to the backend.
And there are pros and cons to doing it like this. Again we-
Brian Casel : I did wanna ask you about that. So, Okay. So, is like a headless like Rails API?
Benedikt Deicke: Yeah. Yes, exactly. it is just an API with a few small exceptions, but for the most part it's just the API. It's just shuffling data around. And the frontend is its own, its own code base has its own test suite has all the styling, all the UI. So it's literally two separate code bases. And that also kind of explains why we, we are working on stuff separately some of the time because it's actually what it is. Like it's not, there's no connection other than the API.
And a ton of uh, Tailwind CSS, that, That's our stack that builds ZipMessage. Like, is that separation for you? Like, is that how you, you built most of your projects before Userlist?
Benedikt Deicke: It was definitely a setup that I was familiar with from my previous product that I've built. So it didn't really question it in that sense. I feel like these days the pendulum has swung a little bit in the other direction. These days it's more like, let's build like just arrays code base that does the really tame stuff using Turbo and stuff like that.
Brian Casel : Mm-hmm.
Where does Ember.js fit? Like I've, I've heard so much about it, but I really know nothing about how it works. Like how does Ember compare [00:05:00] to, like, Vue or React or, or that sort of stuff? Is it like lighter weight? Like what is, what is it?
Benedikt Deicke: It's more like heavier weight React or Vue I guess
Brian Casel : Interesting.
Benedikt Deicke: To me, Ember.js is basically the Rails of the frontend where it's basically the battery included frontend framework, similar to Rails is like the backend framework that brings everything. Yeah, and it's been around for like, it kind of grew out of Rails as well, in a way.
A lot of core arrays people eventually went off and built Ember. Well maybe not a lot, but a couple. To me it had like a similar feeling of like, when I first was using Ember.Js, I had a similar similar feeling to when first using rails where it magically just worked.
And I, I love it that way, but I often wonder like, what are we missing out on now with things like Ember.Js or what, you know, whatever other sort of frontend tools or workflows. Cuz you know, you have this advantage of having, you know, a whole career as a developer. like technical, like sort of like in the trenches on this stuff. And I feel like I've dipped in and out of development and in the last few years just much heavier building these products. But like, I don't have all those years of experience having played around with different approaches, you know so I'm always sort of like curious, like..
So like you find like with, with Ember and, and having this like, separated like frontend, it's, it's actually more efficient, not from a user perspective, but I mean, for you guys like shipping speed and maintaining the app, like it's a pretty, pretty [00:08:00] solid setup you feel?
Benedikt Deicke: So again, like I chose this because I was familiar with it, so yeah, it, it, it felt like an easy choice in hindsight I don't think we got all of the benefits from like splitting this off from the get go. Like it definitely made stuff harder than it needed to be. And I feel like only these days where we are like getting more ambitious in terms of what we wanna do on the frontend and what, like, in terms of interactivity and how things feel and how things react.
Brian Casel : -cause it's like someday we're gonna need to build it
Benedikt Deicke: dunno, to drag and drop and like, like someday we are going to need that flexibility on like that reactiveness, I guess it's, it's the trump.
And it's now, it's now actually on the road map. we're actually going to build it at some point. It was supposed to be the next big thing we work on. Maybe there's something in between, but we'll see that's the process we're, we're trying to figure out right now. But I feel like. Those five years, maybe it was a waste of, well not necessarily a waste, but maybe it slowed us down [00:10:00] more than it benefited us. I'm not saying that I regret the decision because in parts, like it makes things super convenient, but in other parts it makes it harder than just like playing out HTML from the rays from the rays backend. So it's always, I, I don't know..
Brian Casel : it does seem like, like it's a, a good long term choice. I mean, we're not gonna like, rebuild anything anytime soon. But like, we're starting to think about a mobile app for ZipMessage. Like a dedicated iOS and Android app. And for that we'd probably start to move toward like, alright, we have our API and then the, the mobile app talks to it, right?
So that's something that might come sometime next year.
Brian Casel : Hey, sorry to interrupt. Can we hop on a call today and have a meeting about that thing that you're working on? Ugh. I know, right? Another Zoom call. Really. Here's a better idea. Replace your next meeting with an asynchronous conversation using ZipMessage. It's the video [00:11:00] messaging tool that lets you share a link with anyone to have a threaded async conversation all on one page.
Record, send and receive messages on video, screen share, audio messages, or text. Your customers, clients and freelancers don't need to download or install anything in order to reply to your ZipMessages. They just click your link and record their response. Reserve your own link, like ZipMessage.com/your name and share your intake page with anyone or embed it on your own website.
Automatic transcriptions, Zapier integration, reusable message templates, and more. ZipMessage is made for the way that you communicate asynchronously with your team and your customers. Go to ZipMessage.com and use it for free as long as you want with unlimited messages and responses. And for listeners of this podcast, mention Open Threads and get 50% off your first two months on our premium plan.
Okay, back to the [00:12:00] show.
You know, before we wrap up, I did want to touch on something cuz we just really went deep on this over at ZipMessage is testing, you know, writing automated tests. I know it's something you're, you're very experienced in and this is where, all right, I'm just gonna talk about like the, the challenge that we just had with it, and this is so much about my inexperience in writing and, and using tests in software development. Again, a few years back, a few attempts ago with SaaS, we had no tests and I experienced the pain of having like zero test coverage, right?
So then when I got into ProcessKit and then in ZipMessage, I went way the other way. Like we need a hundred percent test coverage on every single thing we ever build. Right? And it helped, but I what I'm literally just learning recently now is, so I, I just spent so much effort and me and my [00:13:00] team on writing feature tests, inter creation tests, you know which are clearly like the slowest to run the, the most brittle, they fail the most in different environments.
And we, we've built up hundreds and hundreds of these feature tests. And I think that we ended up like way too heavy on the feature test side and too light on like unit tests and request tests and things like that. And so that's one of the things that I'm learning now is, is we should have been, we should have kept the test coverage up the whole way through, but much more on the unit test side than the feature request side.
So I'm, I'm curious, like, what can you speak to in terms of your approach to having a well tested application and what is your approach to actually writing tests for every new feature? Do you do like test driven development where you're writing the test first? Do you do it afterward? What types of tests?
How, how does it all kind of fit together for you?
Benedikt Deicke: Yeah. So I feel like, oh, I, I wanna address the, the feature tests a little bit. I feel like [00:14:00] if you're not writing any tests, start by writing feature tests, because they test a lot of things in one go. Like you write one test and they test almost all of it. Or even all of it.
Brian Casel : And, and that was the thinking. Like if we have a good feature test written, then we just, then we mostly know. Most of what's happening under the hood is working cuz the test passed.
Benedikt Deicke: Yeah, Yeah exactly. So that's, that's totally the right approach in my books.
Brian Casel : And, and for, for anyone listening who is, who is not familiar with this, just a, a quick thing like by feature test we mean like literally writing a, like an automated test that like kind of clicks through a browser experience. A user like clicking this button and then they should see this and then they go onto this page and this should happen. And confirm that this element is on the page and then it passes, right?
Benedikt Deicke: Yeah. So it's very high level and therefore it tests the entire thing because it's literally acting like a user. The downside is it's super slow. And it can be super brittle if you're not super careful because you change the label of the button [00:15:00] and suddenly the test doesn't work anymore.
Because once you click on the save button and not on the next step button or whatever. In our application, I think we even lacking a little bit of the feature tests because at this stage we don't have automated tests that do the full stack, like from the browser through our API to the database, because it's separate code bases that is a lot harder than it maybe should be.
So we are testing the frontend in isolation and the backend in isolation at this stage. So on the frontend, that means we are doing tests for like kind of unit tests for individual components. So wanna make sure that we have a dropdown. If we click it, it shows a menu, and then if you hit the arrow key, it moves to the next item and stuff like that.
So we test these things in isolation, and then we have kind of like feature tests where we test, like you go to signup page, you enter your name and your email address [00:16:00] and your password and click next, you get a confirmation and there's an API call to the backend that creates that user. So we, we test those parts on the frontend and then on the backend we do a lot of. We do a lot of, I, I personally do a lot of unit tests because I feel like it's the easiest way to test business logic because they're just like checking that a few small components are working correctly an isolated fashion. And then on top of that we do a little bit of request backs where, where we like, Okay, if I make a get request to this resource, I should get this list back. And it doesn't include users that belong to a different account or stuff like that.
So we do, in a way it's a little bit like feature testing, but again, it's not like the full stack, it's just the API. But most of our tests are unit tests.
Brian Casel : Are you writing as you implement the feature?
Benedikt Deicke: Depends a little bit. I'm not doing test [00:17:00] driven development these days because I feel like test driven development is great if you know what you're building.
But a lot of times we have a rough idea of what we want. But-
Brian Casel : It takes shape, like after it's in the browser.
Benedikt Deicke: -it's, it takes a while until you actually know what you're building and you actually know how it's supposed to behave. So what usually happens is that we build something rough then a test for it, and then in the process of adding tests to it, figure out where it's actually broken
Brian Casel : Mm-hmm.
Benedikt Deicke: So it's a lot of like doing an experiment, having a thesis of what we, what we would like to do, and then playing around with it either in the browser or using the arrays console and development by just like hooking stuff up. And once we are fairly certain that it's got the correct behavior, we start adding tests for like all the edge cases and. Yeah, as you write a test, you usually come up with like crazy ideas how to break this
And [00:18:00] uh, more often than not, you actually break it and learn about things you haven't considered before. And then we adjust to code again and it's a little bit of back and forth.
Brian Casel : This is, again, it's one of those things where like we just literally went through a whole two weeks of my developer and I like going through our whole test suite, literally removing a lot of feature tests that were just too redundant. Adding a lot of headache to our, to running our tests, making them like less useful.
And then parallel, like running the tests in parallel. And then now like, like now going forward, like our policy, me and my developers is to focus much more on the unit test side. And it, I guess from a workflow standpoint, cuz we used to always build features and then write the feature tests as the final step in the shipping process, right?
Like we would, or one of the final steps, like we would build the feature manually, test it, and then make sure we write a bunch of feature, mostly feature tests to make sure it's all working. And that's sort of, that workflow can work when you're using feature tests. But I feel like with unit tests, [00:19:00] you wanna be writing those as you the methods and the service objects and the workers and stuff like that. Like, otherwise you're, it's hard to like go back and find all those pieces to, to write tests for.
Benedikt Deicke: Yeah. It happens really close to each other, like yeah, at some point at the same time. But I again, rarely do the test first and then write a code afterwards. It's more like development together and sort of.. I feel like what's nice about, getting the unit tests really solid is like that's, in my books, that's the place where the serious problems arise,
Like in terms of if you get the business logic wrong, in our case, we might be sending the wrong email to the wrong user or stuff like that, or sending too much emails or stuff like that. So we always try to get that part nailed down as much as possible. And then, like if the UI shows the slightly wrong state, or maybe the page doesn't [00:20:00] load in the ui, that's less of a problem. Like, sure it's not great, but it's also not, it's not causing any mae to one of our customer's customers and like upsetting them about our customer and stuff like that so.
Brian Casel : A hundred percent. And we have I, you know, I put like a, an important tag, like the word important on probably 20% of our tests. You know, cuz this is like a really important part of the app that gets used every single day, you know? So I use the important tag -
Benedikt Deicke: Yeah. And you don't, you don't wanna break the core, right,
Brian Casel : Yeah, yeah. Like the things that are like, like signing up for an account and sending a, a message and, and you know, that sort of stuff are like, If we're gonna, like, we, we routinely run a hundred percent of our tests, but if we wanna just make sure that the most important stuff we're working, then we'll run the important ones.
Right. And then same thing with Stripe, which is our billing system. You know, any test that interacts with Stripe, we, we put a Stripe tag on it so that like, [00:21:00] again, like anything billing related, we, we wanna make sure that we're not gonna double charge someone or that we're handling, like, handling like plan downgrades and upgrades correctly and stuff like that. So it's always a tricky process.
Benedikt Deicke: Yep.
Brian Casel : Benedict, this is, this is awesome. I. I love getting the chance to like geek out with someone on, on the tech side of, SaaS. I, I do feel like there are, you know, there there's a lot of like, podcasts that are like just for developers just talking code, but that's just, that's not necessarily like about SaaS.
And then there's a lot of SaaS podcasts that are mostly talking about marketing. They're not really talking about the actual product. So I'm glad we, we have you know, these couple of episodes here to to talk a little product. So, feels good.
Benedikt Deicke: Yeah. I feel like there's a, there's room for a technical SaaS podcast or something like that.
Brian Casel : There should be. Yeah. Yeah, yeah, hopefully, we'll, we'll do this again. I'll keep keeping tabs on Userlist. I love what you guys are doing. I think, I think [00:22:00] it's really exciting. I, I really feel like you guys are starting to really hit your stride terms of building some really interesting things. We'll, be waiting for the visual workflow builder. should, should come any day now right?
Benedikt Deicke: Hopefully soon. Yeah, like, I mean, both me and our friend, we're both excited about getting to this, but looking at customer feedback, there might be something else that's more requested than this, so maybe it makes sense to do this. This other thing first,
Brian Casel : And, and folks, if you have not, you know, tried Userlist really, I, I do recommend giving it a look, especially just from a design standpoint. If you're just gonna like, look at the website and the interface you know, you and Jane have, have done a really fantastic job with it. It's, it's pretty impressive.
Benedikt Deicke: Thank you. Well, the, the design is a hundred percent on Jane. I'm just making sure I build it the way she wants it.
Brian Casel : Hey, I mean, the, the styling, sure. But like, you know, I, I strongly believe that the design of software happens at, you know, front to back. You know, I, I, I literally [00:23:00] think of, of designing from database models to how, how it interacts with the user. So I think you guys are doing an awesome job.
Benedikt Deicke: That's true. Thank you.
Brian Casel : Good stuff. All right. Thanks Benedikt.
Benedikt Deicke: Yep. Thanks.
Brian Casel : Well, that wraps up today's Open Thread. Hey, tell me what you think. I'm on Twitter @casjam, and right after that, head over to iTunes and give this show a five star review. Really helps it reach more folks like us. I appreciate it. Talk to you next week.