Better Software Design with Domain Modeling

I was honored to receive an invitation to speak at Func Prog Sweden about the topic of my book.

Func Prog Sweden (prior talks) is an online meetup with great topics. Check them out.

Download slides

Transcript

Welcome to Frank Prague Sweden the last of the year for this year and of course we'll be back next year as always. First I would like to welcome all our recurring viewers welcome back to Frank Prague Sweden and then I would like to welcome all new viewers of Frank Prague Sweden. This is the meetup where we deep dive shallow dive go into functional programming of course and we cover all sorts of topics from Huskill super Huskill Agda and into C++ and you can do functional there so check out our YouTube channel if you want to know more about functional programming but now over to today's agenda first up intro by me Magnus then we'll do a better software design with the main modeling by Eric Norman and then the second-person presentation go JS diagrams in pure script by Andrea that will be really interesting it's like a combination of pure script and JavaScript what could possibly go wrong yes then I would also like to thank our video sponsor other beat other beat is the night the consulting is a company based in Stockholm with office in Stockholm and in Hushimin city Vietnam where other beat is a company that is focused on functional programming and if you want to know more about other beat head over to their webpage or check them out on social media the schedule for the coming year that 2024 will be back on the 16th of January with another meetup and then of course we'll run one in February March and onwards we'll come back with the schedule and if you want to know when just go to the meetup page and you'll see when we announce them and if you want to support the funk Brooks Sweden community head over to meetup and make sure to follow us there follow us on YouTube we also started the discord server if you want to ask more advanced questions head over to discord you can ask all sorts of questions and if you have questions during the presentation or on the presentation you either ask them on the discord server or you ask them in the YouTube chat and I will read it up for the presenters with that said let's get started with the first presentation of the day and welcome Eric to funk Brooks Sweden it's really nice to be here welcome warm welcome yes the stage is yours Eric okay yeah thank you so much magnus yeah you're welcome so my name is Eric Norman and my presentation is called better software design with domain modeling I'm writing a book on domain modeling and so these are a lot of the ideas that I'm gonna be talking about can I get my slides up yeah cool so one of the things that I noticed when we talk about software design is that we often will try to give rules rules of thumb some guidelines and principles but to me they always fall short either you're already good at design and so yes they they're helpful to remind you or but so then you don't really need them though or you're not good at design and they don't really help because at that point there there's more exceptions than there are actual cases that follow the rule so I'm trying to take a different approach to talk about software design from rules and guidelines and principles and if I could summarize my talk in one line like this it would be that if you want to do good design you need to make good decisions because software design is all about making software decisions and if you want to make good decisions then you need good information so when I'm talking about decisions I'm talking about everything like I've looked for definitions of software design and there's so many out there it's basically every decision you have to make from whether you are doing a for loop or a while loop or how you structure your modules all the way up to architectural decisions all those things fall under this umbrella of software design it's basically just programming right once you once you put it that way it's just programming but it's with this attitude that you are making conscious decisions so in my book I'm organizing the content into what I'm calling lenses each lens gives you a different perspective on your software and on your domain and hopefully if you get enough of those lenses together you can make a full picture of your domain and the software that you need to write for your domain I've got the book is still work in progress but right now I've got ten different lenses and I don't have time to go over all of them today so I'll just talk about three the data lens the operations lens and the volatility lens so let's start with data so when I I'm about to show something that probably everyone here can already do but I'm gonna go through it quickly so that we're you know I don't bore you but the point is that we're gonna go deeper into the actual mechanics of what we're doing so if it looks like yeah I know how to do that this is boring like you're on the right track it means I'm I'm showing something that you know how to do and we're gonna go a little bit deeper and it'll help explain what domain modeling is all about okay so we're our domain is a coffee shop this coffee shop makes coffees it's sort of like a Starbucks I think we all understand Starbucks there's three sizes super mega and galactic there's three roasts raw burnt and charcoal and then there's all these add ins that you can add to your coffee like soy milk you know have a shot of espresso some hazelnut syrup chocolate syrup etc now if I was gonna model this an order for a coffee in Jason I would probably do something like this I would have string representing the size a string representing the roast and an array of strings representing the add-ins and let's see how we got there because this kind of just comes automatically to me and I had to it took a lot of time and introspection to figure out what I was actually doing to get those strings to get this structure okay let's just look at the size for now let's zoom in on this so we have the three sizes and they're actually they actually have a relationship between them we can only have one size a coffee can't be like large and small at the same time so we have this one of relationship and I'm calling that an alternative meaning you have to choose one of these alternatives and so then we give each alternative a name a string to represent it in our code and then we need to maintain that same one of relationship between those strings and so I'm going to use TypeScript here we're just gonna do tiny bit of TypeScript so if you don't understand TypeScript that's fine I'll explain everything but we're defining a new type called size and then we're saying it's either the string super the string mega or the string galactic that's what those pipes symbols are just means or okay now roast is going to be very similar they have the same thing you can only have one roast so we have a one of that's an alternative we give each one a string and then we want to maintain that same relationship between the strings so we have a very similar type called roast now this is gonna come up a lot where you see something in your domain you see a relationship and you want to maintain that same structure of relationship in your code all right now add ins are a little more complicated because we can have multiple one it's not one up and still we're gonna do a one of it's gonna be like two different levels so the first level is we need the one of right like any particular add-in is one of these choices so it's gonna be an alternative and so we'll we'll do the same thing I'll skip drawing the arrows and stuff just for space but we'll have a similar kind of type there but then we have this other relationship with the coffee is that you can have zero or more add-ins and that will call a collection instead of an alternative and we'll just make it like this for now okay so this just means add and define a new type add-ins that is an array of the add-in type we have up top all right now we need to combine all of these into one single coffee order so what we need what we want to say is that we have all of these not one of but all of them we have a size we have a a roast and we have a set of add-ins so I'm calling these a combination because we're combining these things and obviously we just went through this each one has its own type and so now we can make a type for coffee which has a size of roast and an array of add-ins all right this should be pretty clear right now this should be like pretty standard like you know we do this every day as programmers but I want to go a little bit deeper now so this is the size again same thing we saw before I'm gonna draw a line here everything above the line is the model it's the idea we have in our head of how this is supposed to work and below that we have code okay so we've taken this model from our head and we've encoded it into our programming language above we've found the relationship and then we've made that and then coding for that okay now I'm gonna move that line up and like erase the picture so we still have the same stuff but it's at the top and we're just gonna look at all these different options we have for encoding we chose one which was this it's called a union type in TypeScript but we have other options so that's the first one the union type strings with union type we have string with enum so we could define it like this is also valid TypeScript and it has different semantics and different ergonomics to it then we have this other option that we could use JavaScript classes and a TypeScript interface so we could define an inner space that has a name and then we can define three different classes one for each size super mega and galactic and those classes could represent the same values the instances of those classes okay so I'm bringing this up because we have these choices when we're programming just like we choose between for loops and while loops we have these choices all the time for how we're going to encode the model and we often forget to we often have habits that just say oh I'm just going to use this because that's what I always use or that's what I was taught and if there's something I'm going to pause it as like something I can't prove it's that you get better design by having by evaluating more options more encoding options okay so we have these three but how do we evaluate them well we have to use something one thing we can use a thing called fit okay let's let's look just at the size in the roast because the the add-ins complicated a lot so how many different kinds of coffee can you make with three sizes and three roasts well we can all multiply it's nine right and how many coffees can we make with this TypeScript type well it's the same we have the nine different ones one showing up at a time there we go so we have super in raw super in burn super in charcoal right these correspond to those same things from the images before so we have our model in green and our code in red we have and we're looking at size and rows we're looking at nine things that are both in the model and the code and zero things that are just in code so in theory you could have things that you can write that are valid in your type that don't correspond to anything that you know you've got in your head and in theory also you there's things in your model that you can't write in code like your type won't allow it so in this case we have zero unrepresentable things and zero meaningless things they're all everything we can represent is in the intersection and so this is perfect fit this is where you your your model and your code correspond perfectly now let's look at another thing that we could have done which I didn't mention before to get perfect fit we could also just say well we're just gonna give each of these combinations of size and roast a number from one to nine so we have nine numbers and we have nine coffees we can make so that's perfect fit so fit isn't everything but fit can show you a lot let's and let's look at a case where fit isn't perfect so let's look at the add-ins because we've got zero or more of five different choices it's actually gonna be kind of hard to figure out exactly how many there are we can you know you can you can basically list them out you do it on a computer really easily to count them but we're just we're just gonna see what how how far we can get and whether we learn something from it so we have zero add-ins so that's one possibility we have one add-in so that would be five more so that's six total we have two add-ins well now we're talking about all these different combinations but but look at just writing some of them out we can see that there's already kind of an issue that we have soy with a espresso shot and a espresso shot with soy these are both representable they look different they're encoded differently but they're basically the same coffee right it doesn't matter what order you mix those two into your coffee same for three add-ins right we've got soy twice and almond once but we got all these different ways of writing that out so even without counting them we can see that yes we can represent everything we have this intuition that yeah we got it we can do everything we need so that means zero are unrepresentable but we do have all these meaningless distinctions so maybe this encoding of an array is not ideal can we find something that has fewer things that are meaningless and so let's let's look for those things yeah so there's less than perfect again here's our here's our add-ins we're going to draw that same kind of line and this time for collections let's just look at all the options we have or some of the options so we can use an array that's what we've got already we can use a set except that won't work because we do want to be able to have duplicates like two soils in in our coffee we can use an object so that would be where we did something like this where we had the the key is the is the name of the the name of the add-in and then the value is the number of times it's in it's you know how many shots we put in it and so now we can have two soils represented this way one almond and because in an object the order of keys doesn't matter now we've gotten rid of that other problem too so we've gotten rid of the ordering problem by doing this but of course now is a conundrum our key like the type system can't show us this we can't use a type besides string in the in the key position so now we we do have to remember we're gonna have to validate this that we're not using the wrong keys at runtime okay now let's compare the array and object because both seem possible we've got all these different things that we can express and object seems to be winning so far we could do a thing it's important to know that like there's not gonna be a clear winner right nothing it's never perfect but one way we can mitigate the lack of perfection is by doing a normalization so ordered didn't matter in the object and we don't want order to matter so we can do a thing in a ray where we always sort it and that way we can compare them for equality you know we we just sort before we compare for equality and that would get rid of the the order dependence of an array and here's another thing we've opened up the door in objects that we have a soy zero that that's totally allowed by that type and so we would have to normalize this to oops sorry went too far we have to normalize this to by removing zeros and maybe even negative numbers you know things like that so both of them have their issues so it's not an easy it's not an easy choice just I can't do audience interaction so easily but right now just think what side are you on right now array or object I'll let you think for a second okay so another thing we can do we looked at fit we can also use other lenses to constrain one of the advantages of having all these lenses is each one gives you a different perspective and so if you can't figure out if you have a lot of choices and they all look kind of the similar you know they're all they're all valuable but you can't figure out which ones to choose you can just look it from another perspective and see if one of the other perspectives gives you some insight and we're gonna do that in a second but right now what I want to I want to kind of blow your mind a little bit while we're here I have it all loaded so this is that line I showed before the size you got on the on the top we got the model on the bottom we got the code let's move it down instead of moving it up we built this model or we were given this model let's say Starbucks already had this model and so we just used it and well you know there's three sizes and there's alternative but you can imagine a different model in the same domain in the same domain of a coffee shop like you could imagine them selling coffee by the volume right it's like they just you say I want you know 40 milliliters of coffee and they they charge you per milliliter instead of these like discrete sizes but in a more traditional coffee shop the size is kind of dictated by the kind of drink you get it has you know each drink has a different cup style and size and it's not really really about like the small medium large I I'm bringing this up to say that like one of the reasons software design is so hard is that we're not only trying to figure out how to how to code what we've what we've got in our head but we also have to experiment with the model that we've got in our head and maybe a different model is more correct or you know more advantageous so here's a I'm trying to draw a diagram of the whole process of what we're doing we got this domain we've got to get it into code and you know it's gonna go through our heads because we're the ones programming it so oh sorry I missed a T on that abstract supposed to be so we we got this domain and we're gonna abstract it meaning we're gonna remove some details some details that don't matter and develop a model of of our domain and then we need to encode that model into code and then we can use the code we rewrite the code and we can play with it and we see okay this one has a good fit for my model this one doesn't this one maybe this too slow I need to change it and so we can have this like feedback loop going on between encode and evaluate figuring out the best way to encode it but then we also might have to go back and revisit the domain and say this this whole model isn't working and go back and abstract something else from just you know just trying to drill in how hard software design is there's so many variables all right let's look at a different lens operations so at the coffee shop the cashier has a touchscreen that looks like this they can select the size the roast and they can like click plus and minus on each of the add-ins and right now the size is highlighted and the roast is highlighted we can see that they've already added some add-ins now from this we can look at what are the operations that they need to be able to do they need to be able to set the size so meaning when they touch super it sets the size of the coffee to to that and I'm I'm gonna stop using TypeScript now because when you write a function with TypeScript it starts to get really long and we don't need it we're just I'm just I just use my own little syntax there's a comment at the end that just says that this returns a cough so set size takes a coffee and a size and it returns a cough we also have to set the roast also takes a coffee and a roast and returns coffee oh and this is functional program I have to mention like that's pretty commonly done right where you you have the current value and then you return a copy that's modified and then we have to be able to add an add-in so that'll just increment it by one and remove an add-in will will decrement I wrote wrote those out because I find that function signatures are like really great for representing these kinds of use cases they've got the inputs they got an output and they're they're like little easy to easy to write they're a little concise notation for it much better than something like in UML where you have like methods and arrows and stuff okay so here's a function signature it's actually what I should explain what I mean by it it's got a name it's got the arguments in their types and you'll just have to infer the types based on the names which I think we can all do and then it's got a return type so that's the three parts of the function signature they're so concise and precise they show you what you know as long as you're talking about a pure function they show you exactly what you're gonna need to perform this operation what you're gonna get when you're done and they're because of the name it gives you also semantic hook because you know you you can also see that there might be some some ways of implementing this function that just like return the same coffee without modifying it like just ignore the size argument but because set size you know you know what it means it's the right level of abstraction for reasoning when we don't want to start reasoning about the implementation yet but we also want some token that's like a step towards implementation right and we can easily implement this later very very easy to see how to do that I should mention another thing that I'm really into is instead of writing out your specs and stuff in something like UML like we want to be moving toward code right and we want something formally enough that we can have some guarantees about it and we want it to be a step toward implementation all right so here we have this problem where we are passing in a coffee that has size mega and we're also passing in a size mega so what should we do okay I call it a problem it's not a problem it's a choice we there's there's a number of things we could do we have a choice we have to remember that while there while once we do the analysis we might find that one choice is clearly a winner we have to evaluate that a good designer is always going to look at their choices and choose choose the best one they're not just gonna plow forward with you know the way they've always done it or or the way they were taught so what do we do first we got to look at our choices so one choice is we can throw there's some languages that do this for stuff like if you have a a some I think some languages like tickle for instance if you try to set a value in a hash map and the key is already there it throws an exception and you know it's a choice they made this choice I don't think they're happy with the choice that they made but we have this choice here now of course I don't think that that's a good choice I this is a one of the only recommendations I'm gonna make in how to code we should be aiming for total functions and I think this is a concept that is super important and it hasn't really escaped the functional programming world and I hope it does so when we have when we're looking for a total function where we have this behavior that could possibly throw an error we can do three different things one thing is oh I should mention what total function is it's a valid it means the function has a valid return for all valid inputs okay so any coffee any size you pass in as long as they're valid you know they type check or whatever you know validate then you're gonna get a valid coffee when you when you know as a return value but one thing we can do is we can augment the return value so we have this case where it's kind of weird what to do we can return no instead of a cock right and so we just augment the type and we say we're gonna return coffee or no okay or you can use an either type or maybe okay so that's augment the return type another thing we can do is we can constrain the arguments so we can say well the size before you call this function you got a check that the size of the coffee is not the size you're passing okay so that's that's restricting the argument types and finally this other choice is to kind of change the meaning of the function so the meaning before is set size well if it's already set to that how can I set it it's I it doesn't make sense well we can relax it and say well set size really means set the size or leave it unchanged if it's the same I should mention there are languages I know it seems weird that I'm like saying that this is a choice but there are languages that that like Python for instance that do one of these weird choices of like returning null in a certain case or don't return the thing unchanged you know to me it seems very weird you know like if you say take this string and replace all the X's with Y's and there's no X in the string like just return it unchanged right but there's some languages that'll be like no I didn't find any X's so that's an error I just want to say that's a choice that you can do that I don't I don't like the that choice but we have to remember that it's always there okay so there's three things that we can do we can augment the return problem with that is it creates this new weird return type we have to handle the return so if you return null instead of a coffee we have to check that we can restrict the arguments but in somewhere something is going to have to check that that coffee that size is not equal to size if you can figure it out with your type system if you've got something like a like an interest that has a types that can look at the values sure you could do that maybe you have some kind of runtime check somewhere but you have to do it somewhere so it's kind of putting a burden on the caller again change the meaning that that's the best way but it's not always possible and then just you know something I'm going to recommend is like avoid throwing errors the more total your functions are the easier they are to compose that's that's a big problem is people will write code that doesn't compose because something in there is throwing an exception and it's not clear how to put two things that throw exceptions together okay we still haven't we that was just a concept we had to talk about the operations and signatures writing out the signatures but now we have still got to figure out are we gonna use an array or an object so let's go talk to other people can I get my slides back please so we got let's go talk to the barista they have an operation so they need to be able to figure out how many add-ins they need to leave space at the top of the coffee so they so that they can pump you know syrups and soy shots and whatever in there so they need to know how many add-ins are in this coffee and in particular they also want to know how many so I'm at the soy station how many soy shots do I put in right now so they have this operation that they they need marketing it's gonna want to use these orders that we're writing down and they are asking well I don't care how many soy shots are in there I just want to know how many coffees have soy at all it's soy popular and so to do this query they're gonna need to know does this coffee have this particular ad finally the cashier is saying hey I need to tell the customer the price so I need to take a coffee and turn it into a price so there's all these operations that need to be done based on the different users of this data okay so we can use these signatures of operations and even in our heads you know I can't do it in my head on the slides like that doesn't make sense but I can do it you know I can write down what's in my head without actually implementing these things we can see look if I have to implement how many add-ins I'm gonna do a filter and get the link so I'm gonna look for all the add-ins of type that are equal to add-in and I'm going to do dot that's gonna be a linear search no matter how I implement it it's linear in an array now if I'm using an object when I implement that it's actually really fast it's just constant time look up and then with a default of zero if it doesn't exist hmm so that's a little tidbit of information that's helping us make this decision maybe object is a winner here let's look at one of the other operations so we have has add-in and again we're doing this linear search we're using index of and we're seeing if it's negative one versus if we use an object we're doing we're just looking up the add-in and if it comes back zero or undefined we just double bang it and that turns it into a Boolean so this is also again constant time so in my mind I'm starting to think that object is better and and we used a different a different lens to constrain this so we weren't just evaluating on fit we went to a different lens and started looking at it that way all right let's look at the final lens called volatility so volatility is basically change change in requirements your model changes your domain changes the business needs to pivot do something else so we can ask okay I need a rant a little bit we right now in software design we have this fear of change we think that fear that change is maximal meaning it's everywhere and that it could is unpredictable but a lot is and is true that there is some some change that's unpredictable but so much of the changes that our business is going to require of our software are predictable and we don't need to add extra levels of indirection all over the place just in case something changes I think that's a really bad habit that our industry gets into but we do need more information and the best source of that information is the domain itself so we ask the business how often do the sizes change you know you've been running this company for 20 years like how often does it change and they say like never we've always had three sizes like maybe in 10 years we might change them like it's not worth even thinking about changing them right now so okay that's good to know we asked the business about the roasts and they say yeah it's well we maybe we added raw once you know 10 years ago but we can't we don't have plans for changing anything in the near future so like don't even think about so we just there's no I mean basically we consider it never but the business does change sales and promotions they have seasonal changes they have monthly promotions even weekly sometimes and so those are going to need to change more you know more frequently than never and then what about add-ins well it's complicated because there's seasonal add-ins so like in the fall we do pumpkin spice and in the around Christmas time we do peppermint so they have these seasonal ones but then you ask a manager of a shop and they say well you know sometimes we run out of almond syrup and we don't want to sell it anymore so we want to remove it from the web interface so you know there's there's this change that's happening hourly like as we run out we need to remove it so that it's not an interface okay so we can plot this the the the frequency of change between decades and hourly and you can imagine it also goes off to the left all the way to never and we can put our different icons in there and what we want to do is align these frequency of changes with our development cycle if something's never gonna change just write the simplest thing and hard code it like hard code the three sizes as a type and commit it deploy it done but the if you hard code the add-ins well you can't change them hourly you can't deploy hourly based on every shop in the in the in the world changing their their inventory levels like that so we need to think about how this is gonna work and it's too hard to think in terms of like you know decades and years and seasons and stuff so I just bucket it into three different things so stuff that never changes we just close it I'm bucketing call codes this if we need to change it you know something changes that we couldn't predict it's gonna require code change and a deployment and we're betting that that is so infrequent that that's fine well just the developers will just like add a size to that type and then everything will be fine there's open where you know that you're gonna need to change this but not that frequently when you just have to add new code so you're not having to change existing code you can add a new promotion type maybe it's a new class that implements an interface called promotion and you just code that class and it doesn't affect any of the other classes that are promotions either and then finally we have runtime so this requires no code changes they're just values that you stick in a database or in memory somewhere and that the trouble is you don't get any type safety from that because you know they're just values they're gonna be strings but and you can and but the nice thing is you can store them in the database and then you can clear the database this is what's you know these are the add-ins we have right now okay so this is just an example of closed you just hard code this type with three different three different strings open one option again I'm just going over one option you have to look at the particular language you're using that you're implementing stuff in and use that to you look at all the features that your language gives you and how do I encode this but in in TypeScript we can do this we can have interface with different classes notice we can add a new class that implements the size and we don't have to change the old and then finally there's runtime and we can just say size is a string and we'll just get it out of the database of course maybe you want something more structured you know you're gonna have a size a name and a price and other things also though it just comes out of the database not saying you have to use strings I guess is what I'm trying to say okay so let's review we went over data modeling data modeling is about encoding relationships that you have in your model we evaluated the fit of different encodings we'd look at the operation modeling we talked about function signatures and how useful they are for talking about different use cases I suggest you use total functions so don't throw the implementation complexity it's not just big O of N it's also how hard it is to implement you know how complicated is the code to write and understand but also the computer has to run a computer so that might be important as well and then volatility modeling we're going to bucket our changes that we can predict onto these things we're just we're making bets this is gonna change never this is gonna change frequently and that will help us figure out what we're gonna use to implement it with I'll write and then again I just wanted to show this model of the process we take our domain we're abstracting it into a model that's in our head we encode that model we can evaluate the code to see if it fits our model so we can run tests against it we can make a little prototype but we can write a little simulation in a scenario and then we get we might have to we might find that our model is not right it's not good enough we have to go back to our domain and abstract again here is my website I am writing this book and if you want to sign up on for my newsletter you'll get updates about when you know when chapters come out my plan is to publish it a chapter at a time on my website for free so if you want to if you want to follow along sign up and there I have to put this because I used the coffee cup image and it required a license so thank you that's it thank you very much Eric thank you very much thank you talk we had some in the shots shall thing I would go with arrays with COVID awesome awesome yeah it's nice good got some participation yeah very nice presentation how come you came into this type of like thinking when did you start like your coding journey did just jump off into HTML or Python or something and then you stumbled upon my whole coding journey yeah okay well I always liked program I'll tell a story I was into to programming from an early age I remember doing logo when I was like eight or nine on like Apple twos you know we had a computer lab at school and in high school I was really into Unix I ran Linux and I was reading an article by someone who said that engineers programmers and in their informal poll they they found the writer of this article found that people said that they liked the program because they like to control they liked that they're making like this intricate watch like and and having to make everything work correctly and together when I read that I thought that doesn't sound like me at all that's not what I'm into I'm into the expression of ideas and programming is a way of expressing your idea in like a formal way it has to run has to compile and run and do the right thing and so when you find that it doesn't do what you thought it would you have to you know if it's not just a typo right it's something like oh that didn't work the way I thought it should you actually change the way you see the world you see the domain and I love that process of learning by creating a thing in the same way you might make a an architectural model and feel oh these two will never fit together right I need to change the walls here is it the same kind of process and so when I've been programming on teams professionally I realize a lot of people aren't doing that they are thinking more like you know I'm making this cool machine that's doing all this work I'm like yeah but you're not expressing the ideas like you're not you know so anyway just talking with people and gaining experience myself working in different domains I realize this isn't common this isn't common knowledge people focus so much on the code they want their code to like you know we talk about clean code or we got all these refactorings that you know move code around and organize it better all that's really important but we're not talking about like what does the code represent what is the semantics of what does it mean what does it do like is that really what do you want it to do and I find that the more you can encode the domain into a good model the the better design your software will be like instead of trying to like clean up your messy code like it's sort of like cleaning up a room like yeah you can put all your toys away but are those the toys you really want that's a different question right so yeah yes thanks yeah have you ever worked with the app or function that's never changed you know the customer comes or someone comes with this is the requirement list the box it will never say no no but I'm also not afraid of change no like I don't I don't know why you know so I do know why I do know why I mean this might my hypothesis for why we fear change so much or why we try to put it in direction in to to make change easier when we have no reason to suspect it'll change it's just fun so let's say we put in a hundred in directions and one of them hits it feels way better like it feels so good that we like didn't have to change anything we could just like add a new line here and like oh look now we have this whole new feature is changed it feels so good that we forget that it cost a hundred times because only one of them hit and so it's kind of like this gambler reflex like gamblers don't remember how many times they lose so they just like the feeling of winning so much yes so I feel like it's that we we get the hit so hard that we're we're willing to put all this work you know there's this whole phrase of like why write 10 lines of code today to save 10 lines of code tomorrow and that tomorrow may never come like just write the thing straight forward and then use get use your code editor and delete the code and write new code like I don't understand why we we have to fear it so much I don't know no me neither I'm just I'm just curious I agree I never worked in a project where things hasn't changed especially people come and say this is the final draft or not final we know it's the final we start developing and then it goes a week or two and then oh by the way well I mean that's it that's also like an interesting discussion in itself like could I mean in some situations in some some scenarios I would just call that unprofessional like you asked us for X we estimated it and now you're asking us for X plus Y like we have to start over like let's start negotiating again and if if we were maybe a little tougher on them instead of saying yeah I guess that's possible and we do that for Y and for Z and you know we just keep doing it like eventually they're like well why is the system taking so long and we're like well you've we did all these changeable why did you I asked you if you could do it he said yes like it's our fault right so I think they're being unprofessional we're being unprofessional and we should maybe be tougher yeah I usually tell people or especially business people and like never ask software developer if it's possible to do because they would all right yes it's always possible right do you mean wait possible and on time and on budget different of yeah I'm the same way I had a manager who asked me hey can you do this you know I would just pass by him in the hallway and he'd say like hey do you think you could do how long do you think it would take to do X be like oh three days and he's like okay have it by Tuesday like whoa that is a different that's not what I was answering and not like from now like from from this moment like I meant like the amount of work it would take is three days of work not like I have stuff to do now yeah but yeah that that kind of thing you have to you have to check thanks a people in the chat are really happy oh that makes me happy yeah I yeah because I sometimes worry you know I have anxiety about whether people like the ideas or I'm hitting all the right getting all the right idea good to hear one one final question I guess gonna put out the presentation somewhere on your page so we'll link to it during the or below yeah below the for sure we are so you can find the link to his presentation yeah we're interesting interested in looking at that yeah yeah I'll email you the presentation with that thanks again Eric for coming to Frank Brooks Sweden thank you very much it was very nice presentation I liked it a lot was a lot of thanks Magnus and not so much for like thinking and as you said like code brain yeah concepts thank you very much again thank you