hello this is Alomar junior friends amico and today we will talk with Vladimir karakov Vladimir polokov is a plural side outer and recently wrote a very interesting book about principles patterns and practices about the unit testing good morning mr. vladmir coracles welcome good morning thanks for having me it's a pleasure it's a pleasure in your book by the way let me show your info here in your book about you intersting you made something very interesting in my opinion today the current year is 2020 and there are a lot of people reasoning about why adopting unit
testing there a lot of people still reasoning about why adopting unit testing but in your book fantastic by the way you go far away this point discussing some economic aspects could you share some of your thoughts about this subject yeah yeah so I think today these conversation about whether or not you should do unit testing itself is not as prevalent as maybe five years ago or even 10 years ago but it's still there yeah I agree with you on that the some well what I see mostly is then these discussion shifts from whether or not
you should unit test to how to do that correctly or how to do that in a way that makes sense and with this book I tried to answer this question I tried to show how you can do the unit testing in as you said in an economical way so that it on one hand you still have all the benefits of unit tests of unit testing but on the other hand they don't drag you down they don't slow down your project and you don't have to spend too much time maintaining them yeah that's amazing that's amazing
do you talk about the costs of maintaining some unit tests so it's about why to write or why not to write some kinds of unit testing that that's very that's very very interesting by the way changing the subject a little what's the biggest impediment in your opinion for lamentation people who wants to write you in tests what prevents what prevent them to write good unit testing today yeah yeah so I think in the book I provided the four components of a good unit test which you can use to to assess any unit test or just
test automatic testing your test suite and these are how good they are at revealing bugs in your code so protection against regressions how good they are at not raising false alarms I named these component or resistance to refactoring or you can also say that it is resilience to refactoring and then fast feedback and minute maintainability so facilities how good how fast your tests are and when they mean and the fourth component is how maintainable your tests are and the the component that is least understood among developers is the second one it's the resilience to refactoring
so how to write your tests says that they don't raise too much to too many false alarms and this is now I this one I see a lot MA in the in the modern projects so people write tests and they write a lot of them but then there is the there comes this point at time where you have to refactor something in your code base and then almost all your tests are breaking and they are breaking not because you broke something but because you just wrote them in such a way that they bind to implementation
details and because you modified those implementation details after the refactoring you basically have to rewrite all of those tests and this comes up a lot when you mark internal communications between your domain objects and when you when you bind to other implementation details and that's the biggest factor that I see nowadays that contribute to people writing not maintainable tests or not valuable tests yeah I got it I got it but when people still talk a lot about having a good level of code coverage and people usually associate a high level of code coverage with good
tests but this is not true and your book will you to you provide a lot of guidance about how to analyze the quality of testers and the use of code coverage could you talk a lot a little bit more about coverage and your considerations about that yeah yeah in the book is I showed that code coverage it's a it's a metric that is better than nothing but it works in only one direction it's a good negative indicator but it's a bad positive one and what I mean by that is that when your test coverage number
shows some small number something less than 50 or 40 percent then it's a good indication then there is something wrong with your test suite you're not testing enough and that's what I mean by good negative indicator but it's a bad one but positive one because even if your test coverage shows some high coverage number something like 90 or even a hundred percent there's still no guarantee that the the test suite your test would is good enough and as I as I said I saw a lot of projects were you have lots of tests and they
cover your project pretty much 100% with with 100% code coverage but they still are hard to maintain because of because of the second component because they are not resilient to refactoring yeah I got it I got it what are considerations about legacy code there are a lot of code pieces over there with no unit essence at all and good coverage zero where to where to start what should be a good start point to start to cover legacy code use tests yeah there is another great book it's called ads from Michael father's it's called something like
working effectively with legacy code and it speaks to this point how to start writing tests in the project and that doesn't have any test and one of the key takeaways from this book is that you need to identify themes in your application so the the borderline between well something like the view or UI and the demo in logic and that is something that you need to do anyway when you were factor your legacy application and this will also help you to to cover your start to start covering your project with unit tests another approach that
you can take is that so in the book I said that I showed that it's pretty hard to write valuable tests when your code is written in not an optimal way so when it's entangled with hard to test dependencies is pretty hard to separate the two and start writing good unit tests and so now to write good unit tests you also almost always have to refactor your underlying code base but that that introduces the circular dependency because now you in order to refactor your underlying code you have to have some test because you need to
make sure that your factoring is correct and on the other hand to write good unit you you need to refactor your code so how to resolve these circular dependency in this case I recommend that you start with end-to-end tests and so if you picture your tests in your test suite as it has pyramid the highest level is the Anton test they are the tests that normally you should have only a small number of them and they should go they should test your application and tiant including the user interface any external dependencies and something like such
as the database and so on and so when you don't have any test at all and when your project is written well is it's too entangled the main logic in that project is too entangled with hard to tell dependencies you basically don't have any other choice other than to start with those Anton tests and you can definitely do that so this is a good approach as well you as I said you start start with end-to-end tests and then refactor your underlying code and then start to push those tests down the test pyramid so you start
to replace and turn tests with integration and unit tests and then remove those and ten tests all together and this is also a good approach it it will help you to both refactor your your project your the code of the project and also to put some valuable tests unit tests and integration tests amazingamazing emission the microfarads book and that was publish it some some time ago a long time notebook yeah yeah what change it since the the book was published it what should consider before reading that book had don't getting in our wrong way he
Mike Farris shares a lot of examples written in C++ or in other technologies and today I write code in c-sharp I think your examples are in c-sharp as well what change it from the micro fetters book and we need to take in consideration before following his recommendations do you think something relevant here there is something relevant here well his recommendations are a lot of them are still relevant for sure what changed I think hmm.well technologies changed for sure but in terms of the attitude I would say that you're you see much fewer projects that don't
have any tests in them even legacy projects that you inherit from some other developers you still see some tests and sometimes there are a lot of them and I'm not talking about projects with good code quality so those are definitely those definitely have unit tests in them but even projects with lacking good lack and code quality they still would have some unit tests or integration or intern tests and so right now it's not it's less of a question how to start introducing tests to those projects but how to refactor those tests along with maybe at
the code base itself so just so that you will have better quality tests so that's at least my experience nowadays I'm not I don't think naturally food now if it applies to every team probably not but at least that's what I see nowadays and that's amazing you started talking now about refactoring unit tests and that's a very interesting point because code or it's sorry tests or coved anyway in it needs some maintenance in some there are a lot of costs involved with maintaining good code for unit testing or in kind of testing by the way
this vo this this spy novel considering that test is our code is something interesting because people don't use to think about maintenance of exactly exactly yeah and oftentimes people assume that tests are some addition to their production code and they don't need to pay too much attention to the quality of that of those tests whereas in fact it's yeah as I said tests are your code so it's you you have to pay as much attention to your tests as you pay attention to your production code and use you need to write them such that they
are clear they are highly maintainable so yeah basically approaching them the same way as you approach the production code there should be no difference yes yeah that that's amazing you have been talking about DVT for a long time as well you have versus in in Pluralsight about DDT diamond during design and how do you relate domain-driven design belief unit testing could you talk a little bit about this yeah that's actually fascinating because not two but three areas of programming are yes I find that they are related to each other quite well so if you if
you take the main German design unit testing and functional programming they all have some central theme in them in such that now they all preach for separation between your demo model and out of process dependencies and it's even more evident in functional programming in such functional languages as for example Haskell they have even a built in language construct it's called IO yeah IO construct that tells you if this particular code refers to the external world so to any input output such as for example the database and so for example if you try to call this
a euro method from another method it makes so it it kind of makes the caller niño method as well so it works in only one direction you cannot make a pure method all the impure one because that impure method makes the caller an impure method as well and so why it's important the importance here is kind of the functional program in the meandering design unit testing they view this importance from different angles but still they coalesce to this central point of the separation between the two in demand driven design why it's important is because your
Des Moines model is the most important part of your application and so it's important to keep it separated from any other responsibilities basically from anything else other than the Des Moines modeling and so your domain classes shouldn't be responsible for saving let's say themselves now to the database they shouldn't be responsible for querying some external service anything like that so any instructor infrastructure code any code that works with out of practice dependencies it should be separate it should go separately from the domain model and as I said the reason is that the domain modeling responsibility
itself is complex enough and you you shouldn't include any more responsibilities to that to your atomic model because that would make your domain model exponentially more complex and the mentoring design is all about complexity managing complexity so and in unit testing you see it is subject to when you when you separate out of process dependencies from the domain model and but for different reasons so here you are seeing that now this recommendation because when you separate out of process dependencies from your domain model it it becomes much easier to unit test that that that way
model because one of the characteristics of good unit testing of good unit tests is is how many collaborators they work with and and the type of those collaborators if you're if you are trying to test let's say user class that works with the database or with some message bus it's harder it becomes harder to test it because now you have to either maintain their database to set up some test data in the database and stuff like that or if you mark the the message bus you will have to write complicated mark machinery which is also
hard quite hard to maintain and so your tests become larger and in order to using the size of those tests and therefore make them more maintainable you need to separate the two and now when you do this separation when you implement the separation now you are able to unit test your domain model directly without involving all those out of process dependencies without thinking of them and you can push this responsibility of testing how your domain model works with those out of practice dependencies to integration tests so you can push it higher than the test pyramid
and this is much more I would say economical because now you can have a lot of unit tests quite a lot of cheap very cheap unit tests which are still really very valuable because they test your domain model and you still can have integration tests that verify how your domain model works in in integration with those out of practice dependencies and so your test pyramid now starts to work really well all those different types of tests start to complement each other and the corner the major way so the main way you to achieve the separation
is to again separate your domain model from out of prancy dependencies so there I find it fascinating how all these areas of programming they call as onto each other and they preach for the same thing but for different reasons that's really fascinating yeah that that's the three amazing that's really amazing can can we understand that the most important part of the codebase to test is the domain model to your grief that should we start with the main model and if you have an additional time to start to test another parts or is that wrong this
is definitely true so I would recommend so there is there are two ways to approach your your development of your application first is an old-school way and when you start with the database you come up with your data structure so say if its sequel database you come up with the structure of your tables relations between them and so on and the second more let's say modern approach is to start with your domain model and this is a better approach because as I said you're the main model is more is the most important thing and you
should start with your domain model and then go outside so this approach is called I think it's called middle-out development so outside you have outside in inside out and this one is middle out so similar to inside out when you start with with the bottom layers layers of your application but here the domain model is in the center for application so that's why it's called middle out so yeah you're basically I what I would recommend is that your you should start with determine model and try to maybe a model your domain with some some large-scale
strokes when you just try to see how it may look eventually and then at this point you probably don't need to even write any tests and then when you have when you have a good understanding how your domain model looks then you can switch to two outside in development and try to write a feature one feature that is as small as small as possible but it works with all layers so it works with your my model it works with the database and when you and this is called this is something that is called your application
skeleton so you build this skeleton and then you will be able to see how your application will look eventually so you will have a thin slice of all components in your application so within slice of your the my model of your database maybe even some UI and yeah so basically that's that's how I would approach how I approach all software development nowadays so guilty thin slice of some feature that touches upon all layers in your application then and when you start when you build these these thin slice you still start with the main model then
you apply you add database and cover all that with integration and unit tests yeah fantastic in your answer dimension in the UI and this days the front end is getting more and more complex and I don't know if you agree if that but what about the unit testing from for the front-end code what you have malicious about that that's a good question I don't have a lot of experience with front-end development unfortunately so my in last time when I attached the front-end development it was server generated HTML like classic asp.net stuff like that and also
WPF Windows applications that's where I stand currently in my knowledge of UI development and so I I looked a little bit how modern react applications work they are pretty much Euler as well and that's really good so but I still I'm not sure how I would approach testing them I would I would need to get into the weeds more to start recommending something because nowadays I mostly mmm I'm mostly involved in him back-end development in API development I am as a back-end developer the last time I tried to design something for different and I use
some kind of tables in the HTML so today I think it's not correct but something about micro services there are special considerations about you in test your testing you know for micro services what you recommend what's different when talking about micro services in testing well I don't think there is anything different so any you should approach micro services every single one of them as a separate application and when these micro service talks to other micro services that's where you need to apply well the so I told I talk to you in the book where you
when you should apply marking and where you shouldn't mark some out of France's dependencies and the main point is that all out of process dependencies can be categorized into managed and unmanaged out of practice dependencies and managed dependencies are out of process dependencies communications with which are not observable externally so for example your application database isn't managed out of France s dependency because and when you talk to them database and the result of that communication is not visible to anyone because all external applications they go to your database through your application they don't go through
into your database directly and so now communications with managed out-of-practice dependencies should not be marked because those are internal implementation details and you should test how your application works with those dependencies directly so your integration tests should check should set up your database and then verify the state of that database when the test is over so the second type of out of practice dependencies is is unmanaged dependencies and that is not of process dependencies communications with which are visible to the outside world and that a typical example is something like an email an SMTP service
or a message bus and because these are the applications that are built specifically for that reason so that when you communicate with those applications those communications are visible externally because when you send an email then your your the person who you send this email to they should be able to view this email outside of your application and so when we're talking about micro services different micro services are also unmanaged dependencies for each other and so when you talk to another micro service you need to mark these communication out and yeah basically a check what exactly
what calls you make to those micro services and if it's an asynchronous communication what messages you put on the bus for those micro services to observe one thing that I think is different here is that it becomes the end-to-end testing becomes more important than with with a monolith application and that's because there is much more many more moving parts many more micro services and there is more so you have more room for a mistake between where your application communicates with those external micro services whereas when you build in a monolithic application you can pretty much
sure that the only dependency pretty much the only dependency out of practice dependency you work with is your database but that's not the case with micro services and so here I would say that the number of end-to-end tests tests that go through all your micro services but maybe not all in each test but still at least some of them so the number of those Hanten tests is larger when you do micro services architecture compared to when you just to a typical monolithic application because it becomes more important to test how they all integrate with each
other and also another approach that I think it's it was proposed by Michael by by Martin Fowler it was that you can introduce service contract tests it's when you ask you know the team so let's say you develop an amicus service that is consumed by another maker service that is developed by another team man so you can ask that team that consumes your application your market service you can ask them to provide you with examples of those requests so let's say they want you to provide them with I don't know with a product catalog or
they they want you to build functionality for modifying that product catalog so you want you you can ask them to give you examples of those calls and so including just the data contracts and so you include those calls to your test suite and then they become a part of your test suite they run constantly and they make sure that when you emulate this call from that second team your application responds correctly so it responds with the same data let's say when they request a product catalog and also the side effects of the modification they still
remain the same so yeah I would say these are the differences between a typical monolithic application and microservices or in terms of Testament fantastic and that's very good one last question you have been teaching people how to write better software for a long time and I would like to know if Lottie what are your recommendations for people who wants to write write better code how to improve these skills to write better code we know that you cuz they're testing a very important thing but besides of tests or including tests what because what what would be
your recommendation yeah that's a really good question hmm I would say that I would say that you definitely need to learn the mind driven design that's another topic that fascinates me personally a lot and also functional programming so all all these areas are inter intercurrent connected with each other in you cannot achieve mastery without looking into all these three areas so I'm trying to think what else yeah every most of other topics let's see some technical stuff you can learn them on on the fly basically because they change more often and there shouldn't be any
issues with learning some new stuff when you already learned the previous-generation stuff but these concepts from the main German design from functional programming from unit testing they are essential and I would say you will be able to reuse them in a lot of projects and they don't change often so if you learn them once you will be able to apply them in pretty much any of your project yeah yeah recently in an interval you recommended us to look at fish shark but now C sharp is getting more and more functional or getting more and more
functional functional behaviors I don't know how to say that now correctly but C sharps getting more and more functional do you agree with that is that a movement that we can inspect what are your opinion about that yes the Sharpe has been borrowing a lot of features from F sharp for a long time that's definitely true but there still are some differences and the difference the main difference I think between the two languages that C sharp is still an object-oriented language first language so it's its default approach is to follow a typical object-oriented programming approach
that's not a bad or a good thing on its own it's just something that keep in mind whereas F sharp is functional first language and so even though you can do pretty much well not all but a lot of things that can sharp do so you can do them in c-sharp you're still have to put some additional effort into that and still there are some features that are in F sharp and other program functional programming languages like for example Union types that are not still they are not in c-sharp or for example handling nut malleable
reference types you still you we are start having them some support for that in C sharp and C sharp aid but still not the same level of support as in F sharp words built into the language itself and where you basically do not use and now anywhere that's that's what was done from the very beginning and this will help you guide with building better quality code and that's pretty good difference because that again the difference I would say is that in c-sharp you have to constantly put some effort into maintaining the quality of your software
whereas in F sharp you don't have to put as much effort as in c-sharp because all those concepts that they you you go with them by default and let's for example the in other concept is you have it immutable types that are immutable by default and in order to make them mutable you have to put some additional effort so you have to in F sharp you have to put effort to break those best practices so to violate them whereas in c-sharp you have to put effort to follow all those practices and that's the main difference
I think between the two languages that's that's that's very very good point man at Thomas Petri check who is a guy who writes about of a lot about f-sharp it says that a good starting point for who wants to learn where sharp pieces start to write you in testing in tests he f-sharp testing c-sharp code from f-sharp would you recommend that what do you think about this yeah I'm not trying to I'm not trying to make a point between you and Thomas B to check alright okay it's just a question would you recommend to write
cause you never to a c-sharp yeah III think I read about that maybe from Thomas or maybe from Russian I don't remember so yeah they recommend well if you want to introduce gradually introduce f-sharp into your organization you may start writing unit tests in F sharp so not the production code but unit tests and I think that's a good recommendation but you have to keep in mind that in F sharp all your tests follow the output based testing style so when you have some input some arguments and have some outputs and that that's basically it
you need to provide an argument and then verify the output in C sharp you also have a lot of communication base testing when you need to set up some marking and state-based based testing when you have to verify the state of your system under test after their test is completed and that's something that F sharp is not as good with so f sharp is perfect when you have come output based testing because that's basically the functional approach when you just provide an input and verify the output and you don't mutate anything and for this functional
approach yes f-sharp is perfect but again you usually don't have very very many of such tests and in c-sharp you will also have a lot of state-based testing and communication based testing for which F sharp is not as good as just regular or C sharp tests okay okay I'm sharing in the screen right now the address of your website I think this is the best way to get heritage we feel and to learn more about your trainings about UN testing and DVD and all the technical stuff I I think the the are there some there
are some are there some additional points that you want to talk about or do you think what we had have now is good enough yeah let me think no I don't I don't think so so yeah all great questions fascinating discussion I'm trying to think what else yeah we covered pretty much all I wanted to talk about today so yeah we're good so so thank you mr. vladmir it's it was a pleasure to learn from you it's fantastic to learn about you in testing and good testing practice it's it's fantastic thank you very much for
your time thank you for having me LMR was pleasure to talk to you thanks bye-bye so