Podcasts about value objects

  • 13PODCASTS
  • 16EPISODES
  • 51mAVG DURATION
  • ?INFREQUENT EPISODES
  • Mar 13, 2025LATEST

POPULARITY

20172018201920202021202220232024


Best podcasts about value objects

Latest podcast episodes about value objects

Laravel News Podcast
Svelte starters, document conversion, and Playwright

Laravel News Podcast

Play Episode Listen Later Mar 13, 2025 55:27


Jake and Michael discuss all the latest Laravel releases, tutorials, and happenings in the community.This episode is sponsored PropelAuth - make authentication your advantage - and CodeRabbit - cut code review time and bugs in half with AI-driven, contextual feedback.Show linksTemporary Context Scope in Laravel 12.1 Livewire 3.6 Released Laravel MongoDB 5.2 Released: Support for Laravel 12, Laravel Scout, Vector Search, and more Laravel 12 Svelte Starter Kit Flux 2.0 Livewire UI Kit Artisan Benchmark GraphemeLaravel Auto CRUD Seamless Document Conversion in Laravel With Docswap Control Hardware Components in Laravel with Pinout Access Management in Filament With the Shield Plugin Dagger Components: A Powerful Alternative to Laravel Blade Components Laravel Playwright - Start testing with Playwright quickly In-depth guide on documenting API requests with Scramble Athens Laravel meetup (waitlist)TutorialsIn-depth guide on documenting API requests with ScramblePerformance and Value Objects in Laravel AccessorsStreamline Your Laravel Models with Stringable AttributesResource Response Customization in Laravel APIsCatch Unintended HTTP Requests in Laravel TestsCustom Key Sorting in Laravel CollectionsEnsuring Secure URLs in Laravel ApplicationsCleaner Queue Chains with Laravel's Enum IntegrationSimplified HTTP Response Mocking in Laravel TestsWorking with Flash Session Data in LaravelHandling Exceptions with Laravel's rescue Helper

No Compromises
Taking liberties with value objects

No Compromises

Play Episode Listen Later Nov 23, 2024 12:23 Transcription Available


Programmers love geeking out and creating specialized terms and vocabulary. Well I can do that too. In today's episode, we talk about "value objects", put our own special definition on it, and discuss when we might use these in a Laravel project.(00:00) - What I mean by "value object" (03:00) - Nicer to do in newer PHP versions (04:00) - Main use case for value objects (05:30) - Use them for everything then? (09:00) - A second reason to use a value object (10:45) - Silly bit Sign up for our newsletter and get short, practical Laravel tips delivered fresh to your inbox.

The Bike Shed
386: Value Objects Revisited: The `Tally` Edition

The Bike Shed

Play Episode Listen Later May 31, 2023 41:08


If you're in the market for bicycle shorts, Joël's got you. Stephanie just returned from RubyKaigi in Japan and shares details of her trip. Recently at thoughtbot, there have been conversations around an interesting data modeling exercise. Joël and Stephanie discuss the following: Value Objects vs. Hashes Doing Math on Compound Numbers Monoids and Folding Naming Concepts in Code This episode is brought to you by Airbrake (https://airbrake.io/?utm_campaign=Q3_2022%3A%20Bike%20Shed%20Podcast%20Ad&utm_source=Bike%20Shed&utm_medium=website). Visit Frictionless error monitoring and performance insight for your app stack. Ruby Kaigi (https://rubykaigi.org/2023/) Google Translate Lens (https://lens.google/) Video on city parks (https://www.youtube.com/watch?v=qnyikrFlGdU) Enumerable#tally (https://ruby-doc.org/3.2.2/Enumerable.html#method-i-tally) Hash#merge (https://ruby-doc.org/3.2.2/Hash.html#method-i-merge) Monoids (https://blog.ploeh.dk/2017/10/06/monoids/) Enumerable#all? (https://ruby-doc.org/3.2.2/Enumerable.html#method-i-all-3F) Value of specialized vocabulary (https://www.bikeshed.fm/356) Gist with Joël's code solution (https://gist.github.com/JoelQ/3056a0a6e8b5488faa5caeef630cd702) Transcript: STEPHANIE: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Stephanie Minn. JOËL: And I'm Joël Quenneville. And together, we're here to share a little bit of what we've learned along the way. STEPHANIE: So, Joël, what's new in your world? JOËL: I've made an unusual purchase this week. I went out and bought a pair of bicycle shorts. And, for those who are not aware, these are special shorts that have padding built into them. Typically, they're, like, skin-tight, but I got, I guess, what are called mountain biking shorts. So, they kind of look more like the cut of a normal short. But they've got this, like, built-in padding for biking. STEPHANIE: So. Just to confirm, you did get these shorts for biking purposes, right? JOËL: Yes. I purchased these shorts for biking purposes. STEPHANIE: Okay. [laughs] JOËL: And I got these because I was talking to a friend about this and mentioning that this was, like, probably the most ambitious cycling thing I've ever done in my life. And they recommended if you have not done bike shorts, you really should get them. They make a big difference. STEPHANIE: Wow. Okay, I have two thoughts here. First of all, you prefaced this saying that this was an unusual purchase. So I thought maybe that you bought these bike shorts for some other purpose. [laughs] But I am excited to talk about this because I've also been curious about trying bike shorts. I bike a lot in Chicago in the summer, and I've been doing, like, longer rides on the Lakefront trail. And one of my goals, actually, this summer is to do a bikepacking trip. But I have not been super comfortable on longer rides. And I was just thinking that this might be something really helpful to make them a little more enjoyable. JOËL: So, is the kind of biking that you're doing closer to what might be considered commuting? STEPHANIE: Yeah, mostly commuting. But also, just, like, going on long rides on the weekends, in addition to this, hopefully, forthcoming bikepacking trip up to a state park. So not too long, maybe, like, 60 miles, but definitely long enough to start getting a little uncomfy on your seat. JOËL: Yeah, is 60 miles, like, in one day? STEPHANIE: Yeah, exactly. JOËL: That's a lot. Yeah, the friend who recommended biking shorts to me told me that pretty much anything over maybe 10 miles is worth getting shorts. STEPHANIE: Wow, okay. I clearly have been suffering [laughs] for way too long, then. Tell me more about your cycling trip. JOËL: So this is a bikes plus beer trip. Basically, I plotted a bunch of breweries in Belgium on a map and constructed an itinerary that could hit a bunch of them while keeping fairly short rides between towns. And the goal is to do maybe 30-35 miles in a day. And so I'll be going probably, like, cycling in the morning, and then exploring and drinking in the afternoon and evening. STEPHANIE: That sounds amazing. That's really cool to do a little bit of a tour of the area and then also traveling by bike. JOËL: Yeah, I'm excited because other modes of transport really just give you the origin and the destination, whereas cycling, you kind of get all of the in-between places. You get a much better feel for the area that you're in. And you can make all these unexpected stops if you want. You can make detours. So I feel like you get the sort of being in the moment, being in the place effect that you would have as a pedestrian but with a much longer reign. STEPHANIE: Yeah, absolutely. That's exactly what I was going to say. I love cycling. And there's something really special about being able to be present in your surroundings and seeing people on the street or a cool building as you're going. But also going at a speed where it feels very fun and very freeing to just be cycling through a town and making stops when you want to, and traveling greater distances than you could be able to on foot. JOËL: So I just received these bike shorts yesterday in the mail. So today, at the end of the day, I'm going out for a bike ride, and I'm going to see if they perform as advertised. STEPHANIE: That's exciting. Keep us posted [laughs] on if you end up liking them or not. JOËL: Yeah, yeah. The next episode or two, I'll have to report bike shorts; yay or nay? STEPHANIE: Yeah, The Bike Shed will now become bike gear reviews. JOËL: The name will actually line up, then with what the people googling, it might think it actually is. Stephanie, what's new in your world? STEPHANIE: Speaking of vacation, I just got back from a two-and-a-half-week trip myself. I mentioned on the podcast a couple of episodes ago, I think, that I was traveling to Japan for RubyKaigi, an international Ruby Conference over in Japan. And then I spent another week in Taiwan, just on my own time. So, yeah, I had a really big, long trip, and it was really great. It was my first time going abroad in a really long time. It was my first time being somewhere where I didn't speak the language. So, in Japan...I don't speak any Japanese. And it was both challenging and also, like, not too bad. I found my way around through a lot of gesturing and smiling, and nodding. [laughs] And, hopefully, people were able to understand what I was trying to communicate. Also, pointing at menus, I highly recommend going to places that have pictures of the food, and then you can just point when you want to order. [laughs] JOËL: So, did you find that English was not particularly useful then in Japan as a tourist? STEPHANIE: Yeah, I would say so. The next thing was that most signs were translated. So we ended up taking public transportation a lot. And that was quite easy to navigate, especially since I have kind of navigated subways in other cities before, and reading the signs is no problem. But when you're trying to communicate with locals, that was a little harder. JOËL: Did you use any, like, apps on your phone or anything like that to help navigate kind of the different language? STEPHANIE: Yeah, the Google Translate Lens app. I can't remember exactly what it is. But this was my first time really using it. And I was really impressed by how it was able to translate things that you're using your camera to take pictures of, or just, like, having your camera view. I did feel a little silly, like, holding my phone up to everything and trying [laughs]...so I could understand what I was reading. But for menus that did not have pictures, that was my backup strategy. [laughs] JOËL: Did you ever have to have your phone translate something and then just show your phone to someone else? STEPHANIE: No, I didn't have to go that far. Though I do think that it has a feature where you can have someone speak into the phone, and it will translate that into your native language. And then you respond by speaking into it and then playing the sound for them, which, you know, I bet really works in a pinch. But I think that required a little more investment into the interaction [laughs] with the other person than I was ready for. Like I said, the gesturing served me quite well. JOËL: I got the experience of being on the other side of that a while back. So, here in Boston, I was just walking down the street, and someone stopped me and just holds up their phone. And they've typed something in Chinese on there. And they hit a button, and it comes in English. STEPHANIE: [laughs] JOËL: And they're asking for directions. And I think I typed a sentence back on their phone in English, and then they hit the translate button and got it back in Chinese. We went back and forth a few times. And eventually, I think he got what he wanted, and we went our separate ways. And I was kind of amazed that this whole interaction happened. STEPHANIE: Yeah, that's really cool. JOËL: Yeah, kudos to that person for having the courage to stop someone on the street when you don't speak their language. STEPHANIE: Yeah, absolutely. I think even when I was struggling to communicate with someone because of the language barrier, I could tell from their gesturing in return that we were, like, willing to help each other out. And that, like, there was still an ability to find some kind of connection, even though, you know, we didn't completely understand each other. And that was definitely one thing that I really enjoyed was being in a place with, you know, people different from me and having that exposure. It's been a really long time since I've got to experience that, and that was really valuable. JOËL: So, other than the conference, what would you say are some highlights of the trip for you, maybe one from Japan and one from Taiwan? STEPHANIE: So one of my favorite things about being in Tokyo was all the green space that was around. I ended up walking a lot just to explore the neighborhoods. And I always just stumbled across a local park or even a shrine that had really great nature around it, a lot of big trees. You know, some, like, water features, maybe like a pond, and a lot of really fun plants that I got to learn about. And, yeah, that was really nice, especially in such a dense urban area, like, coming across green space to just sit for a little while. And it was such a nice relief from the density and busyness of a big city. That was just one thing that I was really impressed by being in Japan. JOËL: That's really cool. I think that really speaks to the quality of their urban planning. I know that the stereotype of Tokyo that I have in my mind is that it's, like, you know, ultra-modern, ultra-urban, you know, it's the largest city in the world. So the idea that they've taken the time to set up all these little parks everywhere is really endearing. Particularly, I think the idea of smaller parks at the neighborhood level where you don't need, you know, something massive like, let's say, New York's Central Park, which is, you know, really cool. But having just a little green space in your neighborhood where you can, like, stop by, I think it's a wonderful upgrade to local people's quality of life. I was recently listening to a video on YouTube from a city planning channel talking about just all the thinking that goes behind city parks, and having them at different scales, and how that impacts the residents of different areas. So it's really cool to hear that Tokyo has done a great job with that. STEPHANIE: Yeah, absolutely. I think part of the joy of just stumbling upon it was that you know, even when I wasn't seeking it out, it would just come along during my walks. And, yeah, it really was very refreshing. JOËL: What about Taiwan? STEPHANIE: So, in Taiwan, what I really enjoyed about it it's a bit of a smaller island. And so you can actually get to a lot of places within a few days. And a lot of folks take day trips out to the coast from Taipei. And I was able to do a two-day trip to another county that had some hot springs, and I got to enjoy an outdoor hot springs in the rain. And that was really nice because it was, like, surrounded by trees. And it happened to be raining that morning, but, you know, we were all kind of already getting wet, so it didn't really matter. And it was just, like, this really serene and gorgeous experience being able to enjoy that. And I think that was another place where I was in a very urban area, and then being able to escape a little bit was really nice. JOËL: That sounds like a magical moment. Have you visited hot springs before, or was this your first time going to a hot spring? STEPHANIE: I have been to a few in the U.S. before. I like to take road trips to national parks. And there are some really great hot springs in the U.S. as well. And so this was kind of something that I really wanted to do somewhere else just to experience it elsewhere. And, yeah, I'm really glad to have checked that off my bucket list. JOËL: That's really cool. I've never been to a hot spring, and it sounds like a fun thing to do. So it's on my kind of greater bucket list. It's maybe not a top-five thing to do, but definitely, something I want to do one day. STEPHANIE: Cool. Love it. That was vacation talk from Joël and Stephanie. [laughs] MID-ROLL AD: Debugging errors can be a developer's worst nightmare...but it doesn't have to be. Airbrake is an award-winning error monitoring, performance, and deployment tracking tool created by developers for developers that can actually help cut your debugging time in half. So why do developers love Airbrake? It has all of the information that web developers need to monitor their application - including error management, performance insights, and deploy tracking! Airbrake's debugging tool catches all of your project errors, intelligently groups them, and points you to the issue in the code so you can quickly fix the bug before customers are impacted. In addition to stellar error monitoring, Airbrake's lightweight APM helps developers to track the performance and availability of their application through metrics like HTTP requests, response times, error occurrences, and user satisfaction. Finally, Airbrake Deploy Tracking helps developers track trends, fix bad deploys, and improve code quality. Since 2008, Airbrake has been a staple in the Ruby community and has grown to cover all major programming languages. Airbrake seamlessly integrates with your favorite apps to include modern features like single sign-on and SDK-based installation. From testing to production, Airbrake notifiers have your back. Your time is valuable, so why waste it combing through logs, waiting for user reports, or retrofitting other tools to monitor your application? You literally have nothing to lose. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today! JOËL: So recently at thoughtbot, we've been having conversations around this really interesting data modeling exercise, where let's say this is a company, and you want to purchase T-shirts for everyone at the company. You have already some T-shirts on hand because you've done this kind of thing before in a couple of different warehouses. And you need to know how many new T-shirts you need to order in order to have enough for everyone. So as long as you keep things simple, the math is pretty easy because you sum the number of people at your company, and then you sum the number of shirts across all of your warehouses, and that gives you the T-shirts that you need, the T-shirts that you have. You get the difference between those two numbers, and that tells you how many new T-shirts you need to order. Where things get more complicated is once you start introducing T-shirt sizes, and that's where the fun data modeling comes in. If everyone at your company has a T-shirt size that they want and then at your warehouses, you store...the object that represents a warehouse stores a hash of sizes and how many of each size you have. Now, how do you do all this, like, summing across things? And it's not really just a single number that you want. Now you need to know how many small, mediums, and larges. And, sometimes, you've got a hash. Sometimes you've got just symbols on a user, and you've got a sum across hashes. Maybe do some differences across hashes. And it gets kind of tricky to work with. So that's sort of the problem as it's initially presented. And we've been having a really interesting conversation around different ways to try to solve it in a way that's really kind of clean and nice. STEPHANIE: Yeah, that's interesting because what you described sounds like the first iteration of solving the problem is, oh, the warehouse stores this information as a hash. So maybe I will create a new hash for the counts of T-shirt sizes that I need and then do the comparison on those two hashes. It sounds like maybe there was some unwieldiness or maybe even some duplicated code there. Is that what you think you all were trying to solve by modeling this differently? JOËL: I think we kind of quickly hit some limitations with hashes. One thing that is fun before we start trying to combine a bunch of hashes is that some of the data exists as a hash on the warehouses. But to get the T-shirts that we need, all we have are an array of users and a size on all of them. And we can use this fun method from Enumerable called Tally to give us a kind of Tally hash that is just a mapping of size, two counts of that size in the array. And so that's a really fun method. You don't get to bring it out that often in Ruby. And it's nice because that hash format happens to match the same format as the hashes stored on the warehouse objects. STEPHANIE: Right. So now you're comparing apples to apples. But it sounds like maybe this hash representation does hold some kind of significance. JOËL: Yeah. I guess, for me, I tend to see anytime you're doing fancier operations on a hash more than just reading in and out; it probably wants to be some kind of value object. And, in this case, we kind of want to do math on hashes. I think the equation is kind of still the same thing. We're trying to get the difference between the two, between the want versus have, but you can't just subtract one hash from another directly. There's some things that you can do with the hash merge method that allows you to pass a custom block and do some things there. But we're going to have to do this sort of repeatedly. And now we're kind of leaking some of that knowledge a little bit. So it feels like something where you might want to actually name this concept and make it an object of its own that can then have its own kinds of domain operations as methods on it. STEPHANIE: Yeah, I like that a lot. Because even just as I was thinking about it when you are storing data like that in just a hash, what do you call it? Like, what do you name it? I think I've seen things like that named, like, T-shirt data, or, like, warehouse data, or warehouse T-shirt counts, or T-shirt counts. You know, that is when it starts to diverge, and you end up maybe seeing the same, like, data represented, but it being named different things in different parts of the code. And I, in experience, have found that very painful. JOËL: Yeah, because I guess you could have, like, T-shirts on hand from your warehouse; that's one hash. But the hash generated from the users might get called something like user preferences. And if you're reading through that code and you see a hash, and you're like, okay, do these two hashes that I'm looking at, maybe in a test, just kind of coincidentally have the same keys? Or are these kind of fundamentally the same thing? Or is the idea of, like, T-shirts on hand like a stock different from, like, a preference? And do they represent different things that just happen to be similar in this particular scenario? STEPHANIE: Right. And especially if then there are methods where you're passing that data structure that really represents the same thing. But you're passing it as arguments, and then, suddenly, one variable name, user preferences, or user T-shirt preferences becomes, you know, T-shirt count. That has been really confusing for me before. JOËL: One thing that does get, I think, clunky very quickly is that you have all of these warehouse objects that have that hash of, like, stock on hand on them. And what you really want is a kind of aggregate object that tells you not what's the stock on hand for one warehouse but across all warehouses. So you've got to go through, I guess, that array of warehouses and somehow kind of aggregate all of those hashes together. And because they're already tallies, you can't just do Enumerable Tally on it anymore. You've got to find some way to combine them together, and that gets tricky really quickly. STEPHANIE: Right. I can see they're starting to be, like, nested loops, especially if you're just working with primitives. JOËL: I think some initial implementations that we saw ended up doing either, like, some kind of reduce block or eachwithobject, or something like that, which are, I think, fine solutions here. But what lives inside of those blocks is what gets complicated. And I don't know about you, but I feel like if I'm reading through some code and then all of a sudden I see a reduce block, and it's, like, ten lines of logic with maybe some, like, nested things, like, maybe some nested loops or some conditions inside of it, that's kind of intimidating. Reduce is not a super easy method to wrap your head around, especially when the block has got a lot of logic. STEPHANIE: Yeah, that's a really good point. It definitely gives me pause. And I have to, like, you know, commit to reading the method in its entirety to fully understand [laughs] what's going on. JOËL: Sometimes, like, really pause and, like, annotate with comments and all this stuff. STEPHANIE: So, what did you end up thinking about in terms of solving that problem of aggregating the sums of all the different T-shirt sizes for each warehouse? JOËL: So I think, for me, oftentimes, it's easier to make the problem a little bit smaller, solve that smaller problem, and then try to kind of scale up back up again and particularly when you're dealing with something like reducing or aggregating a large collection. Like, forget about dealing with a collection. Just how could I combine two items of this type? So if I had two of these hashes. And forget about fitting it for an array. But if I have two of these hashes, how could I combine them together? And you could do this with hash merge. I wanted to do things a little bit more encapsulated. And because I also knew that we're building some more logic around these, I actually wrote a custom object. I called it a tally, maybe inspired by that Enumerable method, and implemented an operator plus on this tally object. So a tally object can plus another tally object. And the response from that is you get a third tally object that's gone through all of the keys and summed them together. So it's kind of an aggregate sum. STEPHANIE: This is a cool example of a method that's a verb also representing a noun to name the return value, right? So the Tally method on Enumerable returns a hash, which we have been talking about for a while as, like, a data structure that's, you know, perfectly fine, but maybe we can leverage turning it into like you said, a value object to give it more meaning or to make it easier to work with. And it seems like the naming part just kind of fell into your lap. JOËL: Yeah, tally is interesting in that it is both a noun and a verb in English. I'm not sure what the grammatical term for that kind of word is. STEPHANIE: So, once you extracted this new class out, what insights or observations did you have about this problem? JOËL: What becomes really cool about this is that once you have a way of combining two objects together, reduce is a way to just kind of scale that up to an arbitrary number. And so, just like you can sum an array of numbers by reducing plus over the array. Because I have plus on my tally object, I can reduce plus operator over an array of tally objects. And they all just kind of sum together in a single tally that's the combination of all of them. So this is really cool. What used to be an intimidating reduce block, the intimidating logic gets moved into a plus method, which I think is much more approachable. Because I can go in the context of an object and say, okay, I've got this tally object, and I'm trying to add it to another tally object. And we're just going one key at a time, adding them together. Simple enough. And then in the place where we're reducing, all we're saying is list of tallies reduce plus. And I know that pattern already because I do it with integers to sum them together. And so now I've just got this really simple one-line in the scary part. And the actual complex logic is much more approachable. STEPHANIE: That is very cool. I found it really interesting that this came about because we were trying to do math on these two hashes. So it seems like, you know, a tally because it represents a score or, like, a number. Like, we were able to implement those plus operators and get to a simple solution because we're working with numbers. JOËL: Yeah, I think it might be fair to describe it as maybe a compound number is the term that I use. I don't know if that's mathematically correct. Oftentimes, when you're dealing with things that represent a number or something that's represented numerically but that might have more than one number involved in it. But you still want to do math with this kind of compound, multi-number value anyway. And one example that you might have is, let's say, a point in 2D space. You have an X coordinate and a Y coordinate. And you can do math on points. In fact, there's a whole field of math to deal with that kind of thing. That's an important thing that you have to do. You might want to be able to add or subtract points. You might want to do certain types of multiplication on them. And so just because something has more than one number associated to it doesn't mean that it can't be used for math. In fact, oftentimes, that's where the fancier math does come into play. But when we treat them as primitives, and we just have, let's say, our XY pair was a hash, or, like, a two-element array, then we lose the ability to do math nicely. If we create, let's say, a point class that has an X and Y, and then we define plus, we define minus, we define scalar and vector multiplication, things like that, now we can do all those operations. And we can treat it like math, even though it's not just a simple integer anymore. STEPHANIE: Yeah, I like that a lot because we do end up working with data, you know, maybe even from our database. But then, inevitably, we want to, like, learn something about it. And so I was thinking about how frequently I use GROUP BY in MySQL queries and how, oftentimes, I care about counts, or, like, number of records. And perhaps this is why we see, like, the hash primitive used so frequently in codebases that then become pretty complicated once we're trying to, like I mentioned, like, learn something about it or, like, compare things or whatever logic that we need to do. And transforming them into objects that then know how to do math on themselves [laughs] is very cool. JOËL: Hashes are interesting because they're pretty much just basic data structures. And I think, very often, they're sort of pre-objects. They're things that want to eventually become objects. And, oftentimes, what I find is that hashes get passed around a system. And various other classes or subsystems all have bits of logic that act on the hash because the hash can't own that. And so you end up with the logic around the concept of whatever the hash represents kind of scattered and maybe duplicated across three or four places in the application. And then, all of a sudden, if you give that a name, if you create a class for it, you can pull all of that logic into one place. And, all of a sudden, it probably cleans up all of the surrounding places because now they don't have to care about the implementation of exactly what operating on the hash is. But, also, it means that these operations generally have, like, nice domain names. And, in the case of a complex number, you might even have that represented through math operations, like, plus or minus. And that allows your code to read really nicely. STEPHANIE: Right. Which gets me thinking about how I mentioned, like, tally as a noun, and, you know, you implemented your custom class. But do you think there's any value in the idea of a tally being specifically like a hash-like thing with a number as the value for each key, like, that existing as a more general class for people to use? JOËL: Oh, that's interesting. So, in my personal implementation, I hard-coded values for small, medium, and large because those were the T-shirt sizes from the example. But you're talking about some sort of generic tally object that maybe would be a gem or something like that that people could use that represents counts of arbitrary things or multiple counts of arbitrary things that might then implement some common math operators so that you could add or subtract them. STEPHANIE: Yeah, exactly. Because I was just thinking, you know, like I mentioned, I often represent that when I count number of records in my database. Or even I can recall a problem that I encountered previously where I had to figure out the number of orders for an e-commerce store based on the location. And I held that in a hash data structure, but really, it's a tally. [laughs] And so, yeah, I think that maybe we've kind of stumbled across a very useful representation of very common problems. JOËL: Yeah, I can see there being use for a generic version of this. Maybe that's your chance to go out and create some open source, or maybe this already exists. We should maybe research that first. STEPHANIE: Yeah, if any one of our listeners know, [laughs] send us an email. JOËL: So something that was really interesting to me about all of these changes, introducing the value object, cleaning up the reduce, all that stuff, is that, in the end, once the...there was this object that represented the sort of aggregate compound value, the tally, then the equation stayed the same. And I can just slot in those variables as before. Whereas previously, when we switch from just a single count to this, like, we need to take into account sizes that, like, broke the initial implementation of the code. So it's funny how you sort of go from a simple implementation and then a new requirement, which breaks it. But then just changing the hash to be an object all of a sudden made the original code, which didn't really need to change; it just worked again. STEPHANIE: Hmm. That's really interesting because it makes me think about how maybe the primitives were perfectly fine, you know, in the first set of requirements, and not until, like, an additional complexity or something new emerged that we needed to reach for an object that could support the change. JOËL: Yeah. And I think I'd argue that if you're doing just raw T-shirt count, an integer is probably the right value to use there. But if you're doing counts broken out by T-shirt size, then having an object that's a single thing that responds to plus and minus so that you can use it in the same equation where you're saying sum up all of these things from the warehouse, and then do a difference with the T-shirts that we need that becomes really nice. STEPHANIE: Do you think there was some value in going through the hash implementation first, though, and then arriving at using a more custom object? I'm curious, kind of, like, what that journey was like. JOËL: It's hard to say. I would say maybe yes. But I could also see someone who's done this a lot, who's built the sort of heuristics, the instincts around this could immediately be like, oh, wait, we're trying to sum hashes here. Clearly, these need to be objects. Clearly, what we need is something that implements a plus operator that we can reduce. STEPHANIE: Yeah, I like that a lot. Because part of, you know, knowing what to reach for is having seen it enough times and seeing patterns, right? JOËL: This reminds me of a particular pattern that comes from the world of functional programming. It has a kind of scary-sounding name. It's monoid, not monad, monoid. And the idea in the context of Ruby is it's some kind of object that implements a plus method. So two of these objects can combine each other. And typically, you also have some sort of empty version of this object or some sort of, like, zero value. And there's a few rules that go around, like, kind of how this object has to behave. Like, you can't just put any implementation you want in that plus method. Certain requirements that have to be met for it to be considered, like, a valid plus method in this pattern. But if you do meet those requirements, then arrays of this type of object are just inherently reducible because you can just reduce plus over them. And so I think anytime you're trying to aggregate some sort of unwieldy data structure, that's probably a useful pattern to have because, you know, wait, as long as I have a way to combine two items together and potentially some way to generate an empty state, I can aggregate this whole list. STEPHANIE: I'm curious, does that also apply to non-numerical values? JOËL: Yes, any kind of aggregation combination, whatever. So maybe what you're doing is you're combining strings together. STEPHANIE: Got it. JOËL: String concatenation is a form of combination. And so you could be reducing some kind of concatenation over an array of strings, and you end up with one aggregate string that's the combination of all of them. Sometimes, though, you're not just taking values and putting them next to each other so that what you have is kind of all of them at the same time. You might instead do some kind of comparison. An example here might be Boolean values. You might say the way that I'm sort of, quote, unquote, "aggregating" two values, two Boolean values is with the operator AND. And so you have two Boolean values, and you get a new sort of combo value out of them, that is, are both of these values true? STEPHANIE: Whoa, that's blowing my mind right now. Because I had never thought of the, like, AND operator on Booleans, essentially aggregating them into a single true or false value. [laughs] JOËL: It's kind of weird, right? But I guess we do the same thing with numbers. One plus one doesn't give us 11 unless you're writing JavaScript. STEPHANIE: [laughs] JOËL: You know, we get a new number too, that is some sort of, like, combination of the two. So, similarly, it kind of makes sense that two Booleans might combine to create a new sort of third Boolean value. Where it gets really interesting, though, is that once you have this sort of combination, if you try to reduce AND over an array of Booleans, what you effectively have created is Ruby's Enumerable all method that checks to say, are all values in this array true? STEPHANIE: Interesting. But really, the way that's implemented is just, like, a definition of what aggregate means for Booleans, right? JOËL: Right. But it's taking that idea of aggregating two values and scaling it up to an array of many values. So we know Boolean AND. Another way to think about it is, are both of these values true? Is the question it's trying to answer. And then we're scaling that out to say, is both of these values true for everything? So are all of these values true? Because we're going from two to many. STEPHANIE: Cool. So maybe the takeaway for some of our listeners could be, like, next time they find themselves having to deal with a collection or an Enumerable and, you know, using a reduce or, like, trying to break it down to compare two of those elements first, and figuring out how they want that interaction to work. Does that sound right? JOËL: Yeah, absolutely. Once you have a way to combine two elements together, if you want to scale it up to n elements, you just plug it into reduce, and it does the rest of the work for you. My big takeaways from this exercise were one: the value of creating custom objects. Wrapping primitives like hashes in an object and adding a few domain methods on them made such a difference in my final implementation. Secondly, I think it's what you're saying, this whole thing about breaking down complex reduce problems by figuring out how to combine two items and then just using reduce to scale it to an array. And then, finally, I think this is a point that we've mentioned on this podcast before, the value of specific vocabulary - being able to name things and patterns. And so knowing some of the details of this monoid pattern and having a name for it means that now I start seeing it in places. And so the moment I see, oh, wait, we're aggregating values; we're combining two values together and then doing this in a reduce, immediately, my mind goes, wait, that feels like monoid. And then, I can explore that with my custom object to try to make the code better. STEPHANIE: Yeah. And even if you don't remember the monoid part specifically, the idea of Tally, like, that is something that I think is really cool and really applicable to a lot of codebases. JOËL: So, for those who are interested in more practically what this code looks like, I've put this all in a Gist, and I'll link to it in the show notes. This was a really fun exercise for me because I used sort of two development techniques to help sort of build this out. One, I went with a kind of literate programming approach, where I had just a Ruby file and would have put in some big comment blocks talking about what the setup was, what I was trying to do, and then describing how I'd like to use the code, and then try to write code that made that happen. And then, for the actual objects that I was using under the hood, I used TDD to test drive and build them out. So you've got all of that in the Gist. We've got the tests and that sort of literate programming script that almost reads like a mini blog post, except it's executable Ruby. So, if you're curious to see about that, the link is in the show notes. STEPHANIE: That's a very cool format. I'm excited to take a look. On that note, shall we wrap up? JOËL: Let's wrap up. STEPHANIE: Show notes for this episode can be found at bikeshed.fm. JOËL: This show has been produced and edited by Mandy Moore. STEPHANIE: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes. It really helps other folks find the show. JOËL: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed, or you can reach me @joelquen on Twitter. STEPHANIE: Or reach both of us at hosts@bikeshed.fm via email. JOËL: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeee!!!!!!! ANNOUNCER: This podcast is brought to you by thoughtbot, your expert strategy, design, development, and product management partner. We bring digital products from idea to success and teach you how because we care. Learn more at thoughtbot.com.

The Bike Shed
367: Value Objects

The Bike Shed

Play Episode Listen Later Jan 17, 2023 34:00


Joël's been traveling. Stephanie's working on professional development. She's also keeping up a little bit more with Ruby news and community news in general and saw that Ruby 3.2 introduced a new class called data to its core library for the use case of creating simple value objects. This episode is brought to you by Airbrake (https://airbrake.io/?utm_campaign=Q3_2022%3A%20Bike%20Shed%20Podcast%20Ad&utm_source=Bike%20Shed&utm_medium=website). Visit Frictionless error monitoring and performance insight for your app stack. Maggie Appleton's Tools for Thought (https://maggieappleton.com/tools-for-thought) Episode on note-taking with Amanda Beiner (https://www.bikeshed.fm/357) Obsidian (https://obsidian.md/) Zettelkasten (https://zettelkasten.de/posts/overview/) Evergreen notes (https://notes.andymatuschak.org/Evergreen_notes) New Data class (https://ruby-doc.org/3.2.0/Data.html) Joël's article on value objects (https://thoughtbot.com/blog/value-object-semantics-in-ruby) Episode on specialized vocabulary (https://www.bikeshed.fm/356) Primitive Obsession (https://wiki.c2.com/?PrimitiveObsession) Transcript: AD: thoughtbot is thrilled to announce our own incubator launching this year. If you are a non-technical founding team with a business idea that involves a web or mobile app, we encourage you to apply for our eight-week program. We'll help you move forward with confidence in your team, your product vision, and a roadmap for getting you there. Learn more and apply at tbot.io/incubator. STEPHANIE: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Stephanie Minn. JOËL: And I'm Joël Quenneville. And together, we're here to share a little bit of what we've learned along the way. STEPHANIE: So, Joël, what's new in your world? JOËL: I've been traveling for the past few weeks in Europe. I just recently got back to the U.S. and have just gotten used to drinking American-style drip coffee again after having espresso every day for a few weeks. And it's been an adjustment. STEPHANIE: I bet. I think that it's such a downgrade compared to European espresso. I remember when I was in Italy, I also would really enjoy espresso every day at a local cafe and just be like sitting outside drinking it. And it was very delightful. JOËL: They're very different experiences. I have to say I do enjoy just holding a hot mug and sort of sipping on it for a long time. It's also a lot weaker. You wouldn't want to do a full hot mug of espresso. That would just be way too intense. But yeah, I think both experiences are enjoyable. They're just different. STEPHANIE: Yeah. So, that first day with your measly drip coffee and your jet lag, how are you doing on your first day back at work? JOËL: I did pretty good. I think part of the fun of coming back to the U.S. from Europe is that the jet lag makes me a very productive morning person for a week. Normally, I'm a little bit more of an evening person. So I get to get a bit of an alter ego for a week, and that helps me to transition back into work. STEPHANIE: Nice. JOËL: So you've also been on break and have started work again. How are you feeling productivity-wise, kicking off the New Year? STEPHANIE: I'm actually unbooked this week and the last week too. So I'm not working on client projects, but I am having a lot of time to work on just professional development. And usually, during this downtime, I also like to reassess just how I'm working, and lately, what that has meant for me is changing my note-taking process. And I'm really excited to share this with you because I know that you have talked about this on the show before, I think in a previous episode with a guest, Amanda Beiner. And I listened to that episode, and I was really inspired because I was feeling like I didn't have a note-taking system that worked super well for me. But you all talked about some tools you used and some, I guess, philosophies around note-taking that like I said, I was really inspired by. And so I hopped on board the Obsidian train. And I'm really excited to share with you my experience with it. So I really like it because I previously was taking notes in my editor under the impression that, oh, like, everything is in one place. It'll be like a seamless transition from code to note-taking. And I was already writing in Markdown. But I actually didn't like it that much because I found it kind of distracting to have code things kind of around. And if I was navigating files or something, something work or code-related might come up, and that ended up being a bit distracting for me. But I know that that works really well for some people; a coworker of ours, Aji, I know that he takes his notes in Vim and has a really fancy setup for that. And so I thought maybe that's what I wanted, but it turns out that what I wanted was actually more of a boundary between code and notes. And so, I was assessing different note-taking and knowledge management software. And I have been really enjoying Obsidian because it also has quite a bit of community support. So I've installed a few plugins for just quality-of-life features like snippets which I had in my editor, and now I get to have in Obsidian. I also installed things like Natural Language Dates. So for my running to-do list, I can just do a shortcut for today, and it'll autofill today's date, which, I don't know, because for me, [laughs] that is just a little bit less mental work that I have to do to remember the date. And yeah, I've been really liking it. I haven't even fully explored backlinking, and that connectivity aspect, which I know is a core feature, but it's been working well for me so far. JOËL: That's really exciting. I love notes and note-taking and the ways that we can use those to make our lives better as developers and as human beings. Do you have a particular system or way you've approached that? Because I know for me, I probably looked at Obsidian for six months before I kind of had the courage to download it because I didn't want to go into it and not have a way to organize things. I was like; I don't want to just throw random notes in here. I want to have a system. That might just be me. But did you just kind of jump into it and see, like, oh, a system will emerge? Did you have a particular philosophy going in? How are you approaching taking notes there? STEPHANIE: That's definitely a you thing because I've definitely had the opposite experience [laughs] where I'm just like, oh, I've downloaded this thing. I'm going to start typing notes and see what happens. I have never really had a good organizational system, which I think is fine for me. I was really leaning on pen and paper notes for a while, and I still have a certain use case for them. Because I find that when I'm in meetings or one-on-ones and taking notes, I don't actually like to have my hands on the keyboard because of distractions. Like I mentioned earlier, it's really easy for me to, like, oh, accidentally Command-Tab and open Slack and be like, oh, someone posted something new in Slack; let me go read this. And I'm not giving the meeting or the person I'm talking to my full attention, and I really didn't like that. So I still do pen and paper for things where I want to make sure that I'm not getting distracted. And then, I will transfer any gems from those notes to Obsidian if I find that they are worth putting in a place where I do have a little bit more discoverability and eventually maybe kind of adding on to my process of using those backlinks and connecting thoughts like that. So, so far, it's truly just a list of separate little pages of notes, and yeah, we'll see how it goes. I'm curious what your system for organizing is or if you have kind of figured out something that works well for you. JOËL: So my approach focuses very heavily on the backlinks. It's loosely inspired by two similar systems of organization called Zettelkasten and evergreen notes. The idea is that you create notes that are ideas. Typically, the title is like a thesis statement, and you keep them very short, focused on a single thing. And if you have a more complex idea, it probably breaks down into two or three, and then you link them to each other as makes sense. So you create a web of these atomic ideas that are highly interconnected with each other. And then later on, because I use this a lot for either creating content in the future or to help refine my thinking on various software topics, so later on, I can go through and maybe connect three or four things I didn't realize connected together. Or if I'm writing an article or a talk, maybe find three or four of these ideas that I generated at very different moments, but now they're connected. And I can make an article or a talk out of them. So that's sort of the purpose that I use them for and how I've organized things for myself. STEPHANIE: I think that's a really interesting topic because while I was assessing different software for note-taking and, like I said, knowledge management, I discovered this blog post by Maggie Appleton that was super interesting because she is talking about the term tools of thought which a lot of these different software kind of leveraged in their marketing copy as like, oh, this software will be like the key to evolving your thinking and help you expand making connections, like you mentioned, in ways that you weren't able to before. And was very obviously trying to upsell you on this product, and she -- JOËL: It's over the top. STEPHANIE: A little bit, a little bit. So in this article, I liked that she took a critical lens to that idea and rooted her article in history and gave examples of a bunch of different things in human history that also evolved the ways humans were able to express their thoughts and solve problems. And so some of the ones that she listed were like storytelling and oral tradition. Literally, the written language obviously [laughs] empowered humans to be able to communicate and think in ways that we never were before but also drawings, and maps, and spreadsheets. So I thought that was really cool because she was basically saying that tools of thought don't need to be digital, and people claiming that these software, you know, are the new way to think or whatever, it's like, the way we're thinking now, but we also have this long history of using and developing different things that helped us communicate with each other and think about stuff. JOËL: I think that's something that appealed to me when I was looking at some of these note-taking systems. Zettelkasten, in particular, predates digital technology. The original system was built on note cards, and the digital stuff just made it a little bit easier. But I think also when I was reading about these ideas of keeping ideas small and linking them together, I realized that's already kind of how I tend to organize information when I just hold it in my brain or even when I try to do something like a tweet thread on Twitter where I'll try to break it up. It might be a larger, more complex idea, but each tweet, I try to get it to kind of stand on its own to make it easier to retweet and all that. And so it becomes a chain of related ideas that maybe build up to something, but each idea stands on its own. And that's kind of how in these systems notes end up working. And they're in a way that you can kind of remix them with each other. So it's not just a linear chain like you would have on Twitter. STEPHANIE: Yeah, I remember you all in that episode about note-taking with Amanda talked about the value of having an atomic piece of information in every note that you write. And since then, I've been trying to do that more because, especially when I was doing pen and paper, I would just write very loose, messy thoughts down. And I would just think that maybe I would come back to them one day and try to figure out, like, oh, what did I say here, and can I apply it to something? But it's kind of like doing any kind of refactoring or whatever. It's like, in that moment, you have the most context about what you just wrote down or created. And so I've been a little more intentional about trying to take that thought to its logical end, and then hopefully, it will provide value later. What you were saying about the connectivity I also wanted to kind of touch on a little bit further because I've realized that for me, a lot of the connection-making happens during times where I'm not very actively trying to think, or reflect, or do a lot of deep work, if you will. Because lately, I've been having a lot of revelations in the shower, or while I'm trying to fall asleep, or just other kinds of meditative activity. And I'm just coming to terms with that's just how my brain works. And doing those kinds of activities has value for me because it's like something is clearly going on in my brain. And I definitely want to just honor that's how it works for me. JOËL: I had a great conversation recently with another colleague about the gift of boredom and how that can impact our work and what we think about, and our creativity. That was really great. Sometimes it's important to give ourselves a little bit more blank space in our lives. And counter-intuitively, it can make us more productive, even though we're not scheduling ourselves to be productive. STEPHANIE: Yes, I wholeheartedly agree with that. I think a lot about the feeling of boredom, and for me, that is like the middle of summer break when you're still in school and you just had no obligations whatsoever. And you could just do whatever you wanted and could just laze around and be bored. But letting your mind wander during those times is something I really miss. And sometimes, when I do experience that feeling, I get a little bit anxious. I'm like, oh, I could be doing something else. There's whatever endless list of chores or things that are, quote, unquote, "productive." But yeah, I really like how you mentioned that there is value in that experience, and it can feel really indulgent, but that can be good too. MID-ROLL AD: Debugging errors can be a developer's worst nightmare...but it doesn't have to be. Airbrake is an award-winning error monitoring, performance, and deployment tracking tool created by developers for developers that can actually help cut your debugging time in half. So why do developers love Airbrake? It has all of the information that web developers need to monitor their application - including error management, performance insights, and deploy tracking! Airbrake's debugging tool catches all of your project errors, intelligently groups them, and points you to the issue in the code so you can quickly fix the bug before customers are impacted. In addition to stellar error monitoring, Airbrake's lightweight APM helps developers to track the performance and availability of their application through metrics like HTTP requests, response times, error occurrences, and user satisfaction. Finally, Airbrake Deploy Tracking helps developers track trends, fix bad deploys, and improve code quality. Since 2008, Airbrake has been a staple in the Ruby community and has grown to cover all major programming languages. Airbrake seamlessly integrates with your favorite apps to include modern features like single sign-on and SDK-based installation. From testing to production, Airbrake notifiers have your back. Your time is valuable, so why waste it combing through logs, waiting for user reports, or retrofitting other tools to monitor your application? You literally have nothing to lose. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today! JOËL: So you mentioned recently that you've had a lot of revelations or new ideas that have come upon you or that you've been able to dig into a little bit more. Is there one you'd like to share with the audience? STEPHANIE: Yeah. So during this downtime that I've had not working on client work, I have been able to keep up a little bit more with Ruby news or just community news in general. And in, I think, an edition of Ruby Weekly, I saw that Ruby 3.2 introduced this new class called data to its core library for the use case of creating simple value objects. And I was really excited about this new feature because I remembered that you had written a thoughtbot blog post about value objects back in the summer that I had reviewed. That was an opportunity that I could make a connection between something happening in recent news with some thoughts that I had about this topic a few months ago. But basically, this new class can be used over something like a struct to create objects that are immutable in their values, which is a big improvement if you are trying to follow value objects semantics. JOËL: So, I have not played around with the new data class. How is it different from the existing struct that we have in Ruby? STEPHANIE: So I think I might actually answer that first by saying how they're similar, which is that they are both vehicles for holding pieces of data. So we've, in the past, been able to use a struct to very cheaply and easily create a new class that has attributes. But one pitfall of using a struct when you're trying to implement something like a value object is that structs also came with writer methods for all of its members. And so you could change the value of a member, and that it kind of inherently goes against the semantics of a value object because, ideally, they're immutable. And so, with the data class, it doesn't offer writer methods essentially. And I think that it freezes the instance as well in the constructor. And so even if you tried to add writer methods, you would eventually get an error. JOËL: That's really convenient. I think that may be an area where I've been a little bit frustrated with structs in the past, which is that they can be modified. They basically get treated as if they're hashes with a slightly nicer syntax to interact with them. And I want slightly harder boundaries around the data. Particularly when I'm using them as value objects, I generally don't want people to modify them because that might lead to some weird bugs in the code where you've got a, I don't know, something represents a time value or a date value or something, and you're trying to do math on it. And instead of giving you a new time or date, value just modifies the first one. And so now your start date is in the past or something because you happen to subtract a time from it to do a calculation. And you can't assign it to a variable anywhere. STEPHANIE: Yeah, for sure. Another kind of pitfall I remember noticing about structs were that the struct class includes the enumerable module, which makes a struct kind of like a collection. Whereas if you are using it for a value object, that's maybe not what you want. So there was a bit of discourse about whether or not the data class should inherit from struct. And I think they landed on it not inheriting because then you can draw a line in the sand and have that stricter enforcement of saying like, this is what a data as value object should be, and this is what it should not be. So I found that pretty valuable too. JOËL: I think I've heard people talk about sort of two classes of problems that are typically solved with a struct; one is something like a value object where you probably don't want it to be writable. You probably don't want it to be enumerable. And it sounds like data now takes on that role very nicely. The other category of problem is that you have just a hash, and you're trying to incrementally migrate it over to some nicer objects in some kind of domain. And struct actually gives you this really nice intermediate phase where it still mostly behaves like a hash if you needed to, but it also behaves like an object. And it can help you incrementally transition away from just a giant hash into something that's a little bit more programmatic. STEPHANIE: Yeah, that's a really good point. I think struct will still be a very viable option for that second category that you described. But having this new data class could be a good middle ground before you extract something into its own class because it better encapsulates the idea of a value object. And one thing that I remember was really interesting about the article that you wrote was that sometimes people forget to implement certain methods when they're writing their own custom value objects. And these come a bit more out of the box with data and just provide a bit more like...what's the word I'm looking for? I'm looking for...you know when you're bowling, and you have those bumpers, I guess? [laughs] JOËL: Uh-huh. STEPHANIE: They provide just like safeguards, I guess, for following semantics around value objects that I thought was really important because it's creating an artifact for this concept that didn't exist. JOËL: And to recap for the audience here, the difference is in how objects are compared for equality. So value objects, if they have the same internal value, even if they're separate objects in memory, should be considered equal. That's how numbers work. That's how hashes work. Generally, primitives in Ruby behave this way. And structs behave that way, and the new data class, it sounds, also behaves that way. Whereas regular objects that you would make they compare based off of the identity of the object, not its value. So if you create two user instances, not ActiveRecord, but you could create a user class, you create two instances in memory. They both have the same attributes. They will be considered not equal to each other because they're not the same instance in memory, and that's fine for something more complex. But when you're dealing with value objects, it's important that two objects that represent the same thing, like a particular time for a unit of measure or something like that, if they have the same internal value, they must be the same. STEPHANIE: Right. So prior to the introduction of this class, that wasn't really enforced or codified anywhere. It was something that if you knew what a value object was, you could apply that concept to your code and make sure that the code you wrote was semantically aligned with this concept. And what was kind of exciting to me about the addition of this to the core class library in Ruby is that someone could discover this without having to know what a value object is like more formally. They might be able to see the use of a data class and be like, oh, let me look this up in the official Ruby docs. And then they could learn like, okay, here's what that means, and here's some rules for this concept in a way that, like I mentioned earlier, felt very implicit to me prior. So that, I don't know, was a really exciting new development in my eyes. JOËL: One of the first episodes that you and I recorded together was about the value of specific vocabulary. And I think part of what the Ruby team has done here is they've taken an implicit concept and given it a name. It's extracted, and it has a name now. And if you use it now, it's because you're doing this data thing, this value object thing. And now there's a documentation page. You can Google it. You can find it rather than just be wondering like, oh, why did someone use a struct in this way and not realize there are some implicit semantics that are different? Or wondering why did the override double equals on this custom class? STEPHANIE: Yeah, exactly. I think that the introduction of this class also provides a solution for something that you mentioned in that blog post, which was the idea of testing value objects. Because previously, when you did have to make sure that you implemented methods, those comparison methods to align with the concept of a value object, it was very easy to forget or just not know. And so you provided a potential solution of testing value objects via an RSpec shared example. And I remember thinking like, ooh, that was a really hot topic because we had also been debating about shared examples in general. But yeah, I was just thinking that now that it's part of the core library, I think, in some ways, that eliminates the need to test something that is using a data class anyway because we can rely a little bit more on that dependency. JOËL: Right? It's the built-in behavior now. Do you have any fun uses for value objects recently? STEPHANIE: I have not necessarily had to implement my own recently. But I do think that the next time I work with one or the next time I think that I might want to have something like a value object it will be a lot easier. And I'm just excited to play around with this and see how it will help solve any problem that might come up. So, Joël, do you have any ideas about when you might reach for a data object? JOËL: A lot of situations, I think, when you see the primitive obsession smell are a great use case for value objects, or maybe we should call them data objects now, now that this is part of Ruby's vocabulary. I think I often tend to; preemptively sounds bad, but a lot of times, I will try to be careful. Anytime I'm doing anything with raw numbers, magic strings, things like that, I'll try to encapsulate them into some sort of struct. Or even if it's like a pair of numbers, it always goes together, maybe a latitude and longitude. Now, those are a pair. Do I want to just be passing around a two-element array all the time or a hash that would probably make a very nice data object? If I have a unit of measure, some number that represents not just the abstract concept of three but specifically three miles or three minutes, then I might reach for something like a data class. STEPHANIE: Yeah, I think that's also true if you're doing any kind of arithmetic or, in general, trying to compare anything about two of the same things. That might be a good indicator as well that you could use something richer, like a value object, to make some of that code more readable, and you get some of those convenient methods for doing those comparisons. JOËL: Have you ever written code where you just have like some number in the code, and there's a comment afterwards that's like minutes or miles or something like that, just giving you the unit as a comment afterwards? STEPHANIE: Oh yeah. I've definitely seen some of that code. And yeah, I mean, now that you mentioned it, that's a great use case for what we're talking about, and it's definitely a code smell. JOËL: It can often be nice as you make these more domain concepts; maybe they start as a data object, but then they might grow with their own custom methods. And maybe you extend data the same way you could extend a struct, or maybe you create a custom class to the point where the user...whoever calls that object, doesn't really need to know or care about the particular unit, just like when you have duration value. If you have a duration object, you can do the math you want. You can do all the operations and don't have to know whether it is in milliseconds, or seconds, or minutes because it knows that internally and keeps all of the math straight as opposed to just holding on to what I've done before, which is you have some really big number somewhere. You have start is, or length is equal to some big number and then comment milliseconds. And then, hopefully, whoever does math on that number later remembers to do the division by 1,000 or whatever they need. STEPHANIE: I've certainly worked on code where we've tolerated those magic numbers for probably longer than we should have because maybe we did have the shared understanding that that value represents minutes or milliseconds or whatever, and that was just part of the domain knowledge. But you're right, like when you see them, and without a very clear label, all of that stuff is implied and is really not very friendly for someone coming along in the future. As well as, like you mentioned earlier, if you have to do math on it later to convert it to something else, that is also a red flag that you could use some kind of abstraction or something to represent this concept at a higher level but also be extensible to different forms, so a duration to represent different amounts of time or money to represent different values and different currencies, stuff like that. JOËL: Do you have a guideline that you follow as to when something starts being worth extracting into some kind of data object? STEPHANIE: I don't know if I have particularly clear guidelines, but I do remember feeling frustrated when I've had to test really complicated hashes or just primitives that are holding a lot of different pieces of information in a way that just is very unwieldy when you do have to write a test for it. And if those things were encapsulated in methods, that would have been a lot easier. And so I think that is a bit of a signal for me. Do you have any other guidelines or gut instincts around that? JOËL: We mentioned the comment that is the unit. That's probably a...I wasn't sure if I would have to call it a code smell, but I'm going to call it a code smell that tells you maybe you should...that value wants to be something a little bit more than just a number. I've gotten suspicious of just raw integers in general, not enough to say that I'm going to make all integers data objects now, but enough to make me pause and think a lot of times. What does this number represent? Should it be a data object? I think I also tend to default to try to do something like a data object when I'm dealing with API responses. You were talking about hashes and how they can be annoying to test. But also, when you're dealing with data coming back from a third-party API, a giant nested hash is not the most convenient thing to work with, both for the implementation but then also just for the readability of your code. I often try to have almost like a translation layer where very quickly I take the payload from a third-party service and turn it into some kind of object. STEPHANIE: Yeah, I think the data class docs itself has an example of using it for HTTP responses because I think the particular implementation doesn't even require it to have attributes. And so you can use it to just label something rather than requiring a value for it. JOËL: And that is one thing that is nice about something like a data object versus a hash is that a hash could have literally anything in it. And to a certain extent, a data object is self-documenting. So if I want to know I've gotten to a shopping cart object from a third-party API, what can I get out of the shopping cart? I can look at the data object. I can open the class and see here are the methods I can call. If it's just a hash, well, I guess I can try to either find the documentation for the API or try to make a real request and then inspect the hash at runtime. But there's not really any way to find out without actually executing the code. STEPHANIE: Yeah, that's totally fair. And what you said about self-documenting makes a lot of sense. And it's always preferable than that stray comment in the code. [laughs] JOËL: I'm really excited to use the data class in future Ruby 3.2 projects. So I'm really glad that you brought it up. I've not tried it myself, but I'm excited to use it in future projects. STEPHANIE: On that note, shall we wrap up? JOËL: Let's wrap up. STEPHANIE: Show notes for this episode can be found at bikeshed.fm. JOËL: This show has been produced and edited by Mandy Moore. STEPHANIE: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes. It really helps other folks find the show. JOËL: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed, or you can reach me @joelquen on Twitter. STEPHANIE: Or reach both of us at hosts@bikeshed.fm via email. JOËL: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeeeeeeeeee!!!!!!!!!!!! ANNOUNCER: This podcast is brought to you by thoughtbot, your expert strategy, design, development, and product management partner. We bring digital products from idea to success and teach you how because we care. Learn more at thoughtbot.com.

North Meets South Web Podcast
Evaluating value objects, unspeakable forks, and moving validation down

North Meets South Web Podcast

Play Episode Listen Later Oct 25, 2022 45:54


In this episode, Jake and Michael talk more about using value objects, forking Saloon and backporting it for PHP 7.4 support, and moving validation deeper into your application.This episode is sponsored by Workvivo.Show links Using Value Objects in Laravel Saloon Using Saloon to integrate external APIs with Sam Carré

The Laravel Podcast
League CSV (and URI & Period), with Ignace Nyamagana Butera

The Laravel Podcast

Play Episode Listen Later Aug 12, 2022 47:36


Ignace's Website - https://nyamsprod.comIgnace's GitHub - https://github.com/nyamsprodIgnace's Twitter - https://twitter.com/nyamsprodBakame GitHub - https://github.com/bakame-phpSponsor Ignace - https://github.com/sponsors/nyamsprodLeague CSV GitHub - https://github.com/thephpleague/csvLeague CSV - https://csv.thephpleague.com/League URI GitHub - https://github.com/thephpleague/uriLeague URI -  https://uri.thephpleague.com/League Period GitHub - https://github.com/thephpleague/periodLeague Period - https://period.thephpleague.com/Domain Parser GitHub - https://github.com/jeremykendall/php-domain-parserThe PHP League - https://thephpleague.com/Frank de Jonge - https://twitter.com/frankdejongeStorage, with Frank de Jonge - https://laravelpodcast.com/episodes/storage-with-frank-de-jongeJonathan Reinink - https://github.com/reininkEloquent and the Query Builder, with Jonathan Reinink - https://laravelpodcast.com/episodes/eloquent-with-jonathan-reininkBarry vd. Heuvel - https://github.com/barryvdhLaravel Debugbar, with Barry vd. Heuvel - https://laravelpodcast.com/episodes/laravel-debugbar-with-barry-vd-heuvelPHP Manual for fgetcsv - https://www.php.net/manual/en/function.fgetcsv.phpComposer - https://getcomposer.org/PSR-4: Autoloader - https://www.php-fig.org/psr/psr-4/The SplObjectStorage class - https://www.php.net/manual/en/class.splobjectstorage.phpStreams - https://www.php.net/manual/en/book.stream.phpSymfony - https://symfony.com/PHP Releases - https://phpreleases.com/Doctrine - https://www.doctrine-project.org/Doctrine Collections - https://www.doctrine-project.org/projects/doctrine-collections/en/1.6/index.htmlLazy Collections - https://laravel.com/docs/9.x/collections#lazy-collectionsHelpers & Collections, with Jacob Baker-Kretzmar - https://laravelpodcast.com/episodes/helpers-collections-with-jacob-baker-kretzmarSushi - https://github.com/calebporzio/sushiEloquent - https://laravel.com/docs/9.x/eloquentPSR-7: HTTP message interfaces - https://www.php-fig.org/psr/psr-7/WhatWG - https://whatwg.org/parse_url - https://www.php.net/manual/en/function.parse-url.phpCarbon GitHub - https://github.com/briannesbitt/CarbonChronos GitHub - https://github.com/cakephp/chronosJeremy Kendall - https://github.com/jeremykendallPHP Domain Parser - https://github.com/jeremykendall/php-domain-parserCaneco - https://twitter.com/caneco

Three Devs and a Maybe
142: Domain Modeling Made Functional with Scott Wlaschin

Three Devs and a Maybe

Play Episode Listen Later Jan 30, 2018 68:33


In this weeks episode we chat to Scott Wlaschin about his new book ‘Domain Modeling Made Functional’. We start off the show discussing how the book came to be, the process of writing a book and melding the worlds of Domain Modeling/Functional Programing. This leads us on to highlight what Domain Driven Design is, the importance of communication and the difference between the solution/problem space to garner a shared model. Finally, we touch upon some of the common patterns that come out of modeling domains such as - how Entities and Value Objects provide identity, maintaing invariants using Aggregates, and communication between modals via Anti-Corruption Layers.

Devchat.tv Master Feed
RR 330: Functions vs Methods with Devon Estes

Devchat.tv Master Feed

Play Episode Listen Later Oct 3, 2017 62:38


Panel: Charles Max Wood Dave Kimura Eric Berry Special Guest:  Devon Estes The Ruby Rouges speak with Devon Estes, a return guess and Ruby developer who currently lives in Berlin, Germany. The topic of discussion is about Function vs. Methods, and talk about blocks and its functions. Also, some further digging into the behaviors of functions and designs. Devon explains that this topic will be of discussion at Ruby Dev Conf. Devon dives into the object orientation and the interactions between functions, editing or changing functions. The Ruby Rogues ask questions about, service functions, subsections of applications, application logic, and understanding the parts. In particular, we dive pretty deep on: Functions vs. Methods Blocks When do you want to go for a function? Editing Functions. Service Objects solving problems Methods and Function or classes? Placing functions in apps 30,000 lines Single responsibly principle Different classes of users Example or great uses of functions Keeping thing for being hard to manage among users Value Objects and phone numbers, and functional methods. Object orientation and functional programming Merging Elixer and Ruby? and much much more. Links:  DryRB Education Super Highway @devonestes devonestes.com devonestes.com/fir   Picks: Eric Pipe Envy Super Free Cheese Cake - Keto friendly Dave Amazon Free Time Chuck Ruby Dev Summit 2ketodudes Keto Clarity  Devon Nav to Tetris Season 4 Bojack Horseman Zoos

All Ruby Podcasts by Devchat.tv
RR 330: Functions vs Methods with Devon Estes

All Ruby Podcasts by Devchat.tv

Play Episode Listen Later Oct 3, 2017 62:38


Panel: Charles Max Wood Dave Kimura Eric Berry Special Guest:  Devon Estes The Ruby Rouges speak with Devon Estes, a return guess and Ruby developer who currently lives in Berlin, Germany. The topic of discussion is about Function vs. Methods, and talk about blocks and its functions. Also, some further digging into the behaviors of functions and designs. Devon explains that this topic will be of discussion at Ruby Dev Conf. Devon dives into the object orientation and the interactions between functions, editing or changing functions. The Ruby Rogues ask questions about, service functions, subsections of applications, application logic, and understanding the parts. In particular, we dive pretty deep on: Functions vs. Methods Blocks When do you want to go for a function? Editing Functions. Service Objects solving problems Methods and Function or classes? Placing functions in apps 30,000 lines Single responsibly principle Different classes of users Example or great uses of functions Keeping thing for being hard to manage among users Value Objects and phone numbers, and functional methods. Object orientation and functional programming Merging Elixer and Ruby? and much much more. Links:  DryRB Education Super Highway @devonestes devonestes.com devonestes.com/fir   Picks: Eric Pipe Envy Super Free Cheese Cake - Keto friendly Dave Amazon Free Time Chuck Ruby Dev Summit 2ketodudes Keto Clarity  Devon Nav to Tetris Season 4 Bojack Horseman Zoos

Ruby Rogues
RR 330: Functions vs Methods with Devon Estes

Ruby Rogues

Play Episode Listen Later Oct 3, 2017 62:38


Panel: Charles Max Wood Dave Kimura Eric Berry Special Guest:  Devon Estes The Ruby Rouges speak with Devon Estes, a return guess and Ruby developer who currently lives in Berlin, Germany. The topic of discussion is about Function vs. Methods, and talk about blocks and its functions. Also, some further digging into the behaviors of functions and designs. Devon explains that this topic will be of discussion at Ruby Dev Conf. Devon dives into the object orientation and the interactions between functions, editing or changing functions. The Ruby Rogues ask questions about, service functions, subsections of applications, application logic, and understanding the parts. In particular, we dive pretty deep on: Functions vs. Methods Blocks When do you want to go for a function? Editing Functions. Service Objects solving problems Methods and Function or classes? Placing functions in apps 30,000 lines Single responsibly principle Different classes of users Example or great uses of functions Keeping thing for being hard to manage among users Value Objects and phone numbers, and functional methods. Object orientation and functional programming Merging Elixer and Ruby? and much much more. Links:  DryRB Education Super Highway @devonestes devonestes.com devonestes.com/fir   Picks: Eric Pipe Envy Super Free Cheese Cake - Keto friendly Dave Amazon Free Time Chuck Ruby Dev Summit 2ketodudes Keto Clarity  Devon Nav to Tetris Season 4 Bojack Horseman Zoos

Fatal Error
8. Domain-Driven Design

Fatal Error

Play Episode Listen Later Nov 7, 2016 30:44


Soroush tells Chris about some of his takeaways from Eric Evans's book, Domain-Driven Design, and they discuss how we can apply some of its lessons in our day-to-day thinking about iOS development. Soroush's post on programming books: Resources For New Programmers Domain-Driven Design: Tackling Complexity in the Heart of Software, by Eric Evans Entity vs Value Object: the ultimate list of differences Value vs Entity Objects in Domain Driven Design Soroush: The Value of Value Objects The Swift blog: Value and Reference Types Tiny Types Soroush's post on enumerations Facade Pattern DDD: Aggregate Strategy Pattern Domain Driven Design and Development in Practice Episode 3: View Models, Again Episode 6: Singletons Cells

Devchat.tv Master Feed
095 iPS TDD (Test-Driven Development)

Devchat.tv Master Feed

Play Episode Listen Later Mar 5, 2015 60:24


Check out RailsClips on Kickstarter!!   01:56 - Testing and Test-Driven Development (TDD) The iPhreaks Show Episode #92: Unit Testing with NatashaTheRobot 03:23 - Panel Experiences with TDD Unit Testing The Difference Between Faking, Mocking, and Stubbing 08:10 - Value Objects 09:08 - How To Do TDD “Red, Green, Refactor” BDD (Behavior-Driven Development) The Cucumber Book: Behaviour-Driven Development for Testers and Developers  by Matt Wynne and Aslak Hellesøy The RSpec Book: Behaviour-Driven Development with RSpec, Cucumber, and Friends  by David Chelimsky, Dave Astels, Zach Dennis, Aslak Hellesøy, Bryan Helmkamp, Dan North 11:28 - Jaim’s TDD Process 13:44 - Value and Getting Started with Testing Ruby Rogues Episode #178: Refactoring Ruby with Martin Fowler 21:58 - Writing Tests First “If Code is Easy to Test, It’s Easy to Change.” 27:18 - Testing on a Team Automation guard (Ruby) clang Continuous Integration (CI) 32:47 - Higher Level Testing 36:54 - KIF 38:00 - Other Ways of Testing UIs 39:44 - Who Writes the Tests? 44:06 - Test Data and Environments Test Time => Feedback 46:50 - Lower-level to Higher-level Tests Transition Value ROI (Return on Investment) 51:51 - Recording User Interactions Picks John Reid: UIViewController TDD [Screencast] (Jaim) Test-Driven iOS Development (Developer's Library) by Graham Lee (Jaim) WatchKit FAQ (Alondo) This Idea Must Die: Scientific Theories That Are Blocking Progress (Edge Question Series) by John Brockman (Alondo) Martin Fowler: The Test Pyramid (Pete) Working Effectively with Unit Tests by Jay Fields (Pete) Avery Brewing IPA (Pete) A Wizard of Earthsea by Ursula K. Le Guin (Chuck) 80/20 Sales and Marketing: The Definitive Guide to Working Less and Making More by Perry Marshall (Chuck) Miracles and Massacres: True and Untold Stories of the Making of America by Glenn Beck (Chuck)

The iPhreaks Show
095 iPS TDD (Test-Driven Development)

The iPhreaks Show

Play Episode Listen Later Mar 5, 2015 60:24


Check out RailsClips on Kickstarter!!   01:56 - Testing and Test-Driven Development (TDD) The iPhreaks Show Episode #92: Unit Testing with NatashaTheRobot 03:23 - Panel Experiences with TDD Unit Testing The Difference Between Faking, Mocking, and Stubbing 08:10 - Value Objects 09:08 - How To Do TDD “Red, Green, Refactor” BDD (Behavior-Driven Development) The Cucumber Book: Behaviour-Driven Development for Testers and Developers  by Matt Wynne and Aslak Hellesøy The RSpec Book: Behaviour-Driven Development with RSpec, Cucumber, and Friends  by David Chelimsky, Dave Astels, Zach Dennis, Aslak Hellesøy, Bryan Helmkamp, Dan North 11:28 - Jaim’s TDD Process 13:44 - Value and Getting Started with Testing Ruby Rogues Episode #178: Refactoring Ruby with Martin Fowler 21:58 - Writing Tests First “If Code is Easy to Test, It’s Easy to Change.” 27:18 - Testing on a Team Automation guard (Ruby) clang Continuous Integration (CI) 32:47 - Higher Level Testing 36:54 - KIF 38:00 - Other Ways of Testing UIs 39:44 - Who Writes the Tests? 44:06 - Test Data and Environments Test Time => Feedback 46:50 - Lower-level to Higher-level Tests Transition Value ROI (Return on Investment) 51:51 - Recording User Interactions Picks John Reid: UIViewController TDD [Screencast] (Jaim) Test-Driven iOS Development (Developer's Library) by Graham Lee (Jaim) WatchKit FAQ (Alondo) This Idea Must Die: Scientific Theories That Are Blocking Progress (Edge Question Series) by John Brockman (Alondo) Martin Fowler: The Test Pyramid (Pete) Working Effectively with Unit Tests by Jay Fields (Pete) Avery Brewing IPA (Pete) A Wizard of Earthsea by Ursula K. Le Guin (Chuck) 80/20 Sales and Marketing: The Definitive Guide to Working Less and Making More by Perry Marshall (Chuck) Miracles and Massacres: True and Untold Stories of the Making of America by Glenn Beck (Chuck)

Dev Discussions
Episode 2 - ActiveRecord and Datamapper

Dev Discussions

Play Episode Listen Later Dec 31, 2014 91:37


In this episode, I talk with Mitchell van Wijngaarden, Davzie, N0xie, and Rafael Dohms about ActiveRecord, DataMapper, Doctrine, and Value Objects. Watch the original live video recording.

Being The Worst
Episode 16 – Adding Value

Being The Worst

Play Episode Listen Later Dec 2, 2012 36:20


A listener’s questions lead Kerry and Rinat into the details of Value Objects. They review several examples of Value Objects and cover some pros and cons of their usage. This very important concept is commonly used to represent the nouns in the sentences of our ubiquitous language. Direct Podcast Download Link: Episode 16 – Adding […]

Being The Worst
Episode 11 – Specs Of The Living Dead

Being The Worst

Play Episode Listen Later Oct 13, 2012 56:58


Kerry and Rinat discuss the code updates that were made to correct the car factory sample. After that, they introduce the concepts of Value Objects and Strategic Modeling. Direct Download link: Episode 11 – Specs of the Living Dead – (57 minutes) Subscribe via RSS | Subscribe for free in iTunes Episode References: Episode 11 […]