Wish To Remove Primitive Obsession? Try This Effective Technique!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
String is not your friend. String has no structure nor meaning in any   business domain you may happen to be modeling. Once it becomes a habit to use unstructured   types in domain modeling, we  call it a primitive obsession.  An application becomes obsessed  with strings, ints, decimals...  Bugs... they come next. And an inability to develop complex features.  Today, I will show you how limited an application  can become if it is obsessed with primitive types.  And then, then I will show you the way out. I will teach you how you can substitute primitive   types with proper domain classes. Let's start with a simple example.  Would you ever pass a decimal number  in place where money is expected?  I guess not, because money, a proper money  type has other responsibilities and other   abilities that the decimal numbers don't have. For example, a money type is managing rounding.  It is managing how many  decimals there are in money.  Also, a proper money domain model is  forcing the existence of a currency.  You will never be able to add or  subtract different currencies.  Decimal number, a plane decimal type,  also doesn't have such a feature.  You see, this Money model is defining  arithmetic operations on money.  And what is specific is that some of those  operators end up calling these methods, which   are checking whether the currencies match in two  money instances that we are adding or subtracting.  If you ever used the bare decimal, you  would lose this ability and that would   be a very dangerous situation. An application could have a   nasty bug to mix up currencies. Oh, that would be a disaster.  Let's get on to a more serious issue. I will run this application to show   you where is the missing feature. I want to implement a new feature   and you will see that I cannot do that  because there is a primitive obsession here.  This is the application which is selling books. And look at this list of authors of the book.  It is unstructured. I want each author here to   be a link to the books of that author. But I cannot implement it right now.  You will see why. There's the same problem here,   if you go to the details of a book,  there's the list of recommended books.  Well, the author is still not a  separate link, the entire row is just   one link to the details of another book. I want these also to be separate links.  I want this application to look rich. But I cannot do that.  Let me show you the code. This is the interface which   we use in this application to format  the look of a book anywhere in the UI.  And look, it's returning a string. It is obsessed with a string.  String has no structure. If we get a list of authors, separators,   then the title, it all gets into a single string. We have lost the information   what is what in there. We have lost information what   is the author there, what is the ID of the author,  what is the ID of the book, where is the title...  We have lost all the the relevant  information from this business domain.  All thanks to converting a  domain model into a string.  Here is the Razor page which  is rendering book details.  As you can see, all it can do  is just display that string.  Even this ID of the book that is used to construct  the URL is coming from a different place,   not from this string, obviously. We have a request from the customer   which we cannot even implement at this  moment because we have lost the information.  From this point on, I will teach you how to  improve an existing application and to move   it away from primitive types, to substitute  primitive types with proper domain types.  But there is one additional constraint. The application must work   through the entire process. I'm not allowed to add a feature in   such a way that it breaks anything else in the  application so that we must correct it later.  Because correcting the broken parts  of the application could fail.  I could miss something that I have broken  and in that way effectively introduce a bug.  We must not add bugs to an application  while developing a new feature, of course.  So, the technique I will show you now is  based on augmenting an existing primitive   type and turning it into a more complex domain  type before implementing the entire feature.  There will be a proper class that will do this. I will call it Citation.  But now we have a problem. This is where the book is formatted for the UI.  The result is declared as string and  now I want to use a Citation class.  And this is how that object is produced. This is the concrete implementation   of that formatter. It is just using strings.  It is producing a proper string  by concatenating smaller strings.  It's all strings everywhere here, you see? And that is the problem in this application.  I will let both concrete implementations of  that interface return the Citation model.  But how? Of course, the   page model will also serve the model instances. And we have just declared the simplest possible   solution to the immediate problem we are  having, the problem of using bare strings.  The problem is now moving  one step lower underground.  The UI will use ToString  to display, which is wrong.  We don't have ToString implementation  and, even if we had it, ToString   should not be used to render the UI. And both concrete implementations are   just trying to return the string. So, implementation fails.  But declaration is there. The first step in augmenting   the string into a proper domain class will be  to wrap it into the class and do nothing else.  Just make the code work with the class  which is behaving the same as the string.  I hope you are following me on this. It might become clear when I do it.  There will be a string, just  a string, inside this class.  What I'm really doing is making  a better string as the first step   towards creating a better domain model. I will declare an implicit operator   which will allow me to assign a  string to an object of this class.  So, wherever we used strings, we will be  able to just assign that to an object,   to a reference to this class, and that string  will be wrapped into the object of this class.  And the other way around, the  Citation used as the string.  Implement ToString. And now we have stitched   this new model, which is still very  primitive, it's still not doing anything.  We have stitched it in all the  places where we used strings.  We are now ready to start removing  those strings from the rest of the   code and teaching all elements of the  code to use this Citation model instead.  Once that step is over, and that process is  over, we will be able to even remove these   two members from this class. Do you see the way now?  I'm really making small, safe steps. The application is compiling   fine after this point. And it is also working the same as before.  I haven't broken anything that already  works and we are ready for the next   step in developing a proper domain model. Before that, don't forget to press the Like   button on this video, thank you very much. And also, if you want to see the source   code before and after this change, the  source code is available to patrons, to   sponsors of this channel, so become the sponsor! Help me keep this channel free for everyone else.  Thank you very much, I'm really  grateful to all the sponsors who   are already sponsoring the channel. That will give you access to the   source code of this video and all the  other videos on this channel, thanks.  We are ready to deepen the domain model and to  cut all the relations to common plane strings.  There are two supporting formatters. One is formatting the author list,   and the other is formatting a single authors. These formatters are used under   the hood when formatting the book. They will both return Citation models this time.  We get back to the Citation class. What is it?  This is the place where we  start developing a domain model.  And, as I said, cutting all  connections to the plane string.  We need proper domain modeling at this stage. What is the Citation?  The request is to segment the citations  in the UI, so that every element in a   citation becomes clickable. So, there will be segments.  Why not hold zero or more  segments inside every Citation?  This design is already pulling me in the  direction, forcing me in the direction   of designing this Citation class so that we can  build a Citation object at runtime incrementally,   out of smaller parts, the parts of the citation,  the segments: an author, a comma, another author,   another comma, a title of the book. Every element in what used to be a   string will now become a proper object which is  telling something about what is inside of it.  So, I'm exposing Empty static  property getter for convenience.  You can always start not from an empty  string and then concatenating elements,   but from an empty Citation and then  adding - let me add that - adding   more citation segments at the back of it. This design is already getting out of hand.  I will dedicate an entire video  to developing this class further.  So, stay tuned. There will be a   video which will explain how we move forward. There will be a lot of code behind this point.  I will only make the next step  here and we will stop there.  But that step will also be interesting. We need to bridge the gap between the strings and   this complex Citation which consists of segments. Initializing a Citation from a string means to   wrap that string into a CitationSegment  and add it to an empty Citation.  You see, there is complicated logic here. But nobody will know that.  Nobody else, all those classes that are still  serving strings, will know nothing about this.  We will enhance them later, when the time  comes to walk through all the rest of the   application and clear it from strings. The other way around, turning a Citation   into a string to be displayed in the UI. Well, just walk through all the segments   in this immutable list, turn every one  of them into its textual representation   and concatenate them into a single string. We have made a giant leap away from strings.  We already have a domain class  which is better than the string.  There's a lot of work here remaining. As I said, there will be the entire   video dedicated to implementing this  domain model, which will be complicated.  Just to tell you where this is heading,  there will be multiple kinds of segments.  One will be the author with the author ID. The other will be a book, or book   title with a book ID, so that we can  construct an anchor tag in the UI,   for example, for an author and for the book. There will be a lot of work in all the code   that is producing instances of the  Citation because every class in the   system will need to tell all the details. Every formatter will say: this is the author,   this is the book's title, this is  the delimiter that stands in between.  And all those things were impossible with strings. Impossible!  Let me just run the application right to now in  its current state and you will witness that it   is working exactly the same as before. Authors are still nicely separated.  Recommended books are still formatted using  a different citation formatter this time.  I have not broken anything in  this application, anything.  Everything is working the same as before. But we have a new domain model that we will   be able to develop further so that we will  eventually get a much better application.  Stay tuned for the next video where I will  effectively implement this entire feature.  There will be a lot of code to complete that. And that endeavor will have its own pitfalls.  You will have to learn a special  coding technique that goes hand   in hand with what we did in this video. That is the technique of doing incremental coding.  Stay with me, come back for  the continuation and enjoy   watching other videos on my channel, thank you.
Info
Channel: Zoran Horvat
Views: 9,023
Rating: undefined out of 5
Keywords: csharp, dotnet, programming, object-oriented programming, functional programming, c#, zoran, horvat, zoran horvat, c# programming, learn c#, c# tutorial, primitive obsession, primitive types, domain model, domain modeling, oop, fp
Id: 2izb2y819KU
Channel Id: undefined
Length: 15min 27sec (927 seconds)
Published: Fri Jul 14 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.