 Helo, semua. Saya telah menghantar sebuah bulan terakhir kerja pada projek Marvin. Sebabnya, saya bekerja pada projek Marvin adalah untuk menghantar bagaimana kita boleh melakukannya lebih baik. Jadi, kemudian ke atas keadaan, sebuah bulan yang lebih lama, kemudian, saya sebenarnya bekerja pada bagaimana saya rasa akan menjadi sebuah cara untuk menghantar kota kita. Dan ini sebenarnya menginspirasi oleh Uncle Bob bercakap tentang klinik. Saya akan bercakap lebih banyak tentangnya dan keadaan. Jadi, untuk orang yang menonton video ini, yang bukan dari Marvin, dan juga untuk orang di sini, jika bukan dari Marvin. Jadi, bagaimana Marvin? Jadi Marvin, apabila kita membangun Marvin, kami ingin melakukannya pada interface chat yang akan dapat berbicara dengan... ...berkawan-kawan yang berbeza dengan aplikasi yang sama. Jadi, apa maksud kamu? Jadi, mari kita katakan bahawa di sini, saya mempunyai selag dan telegram. Jadi, Marvin akan duduk di tengah-tengah antara klien chat dan aplikasi anda. Jadi, mari kita katakan bahawa anda menggunakan selag, anda menggunakan komand untuk selag. Selag akan menghantar aplikasi untuk aplikasi. Dan di sini adalah Marvin. Dan Marvin akan menghantar aplikasi untuk aplikasi anda. Dan aplikasi anda akan menghantar kembali ke Marvin. Marvin akan menghantar kembali ke selag. Jadi, ini di dalam perjalanan tangan adalah apa yang Marvin lakukan. Dan untuk latihan ini, kita akan mencari perjalanan kembali ke Marvin... ...yang adalah perjalanan yang saya telah memberikan di sini. Ini adalah untuk menerima perjalanan kembali ke klien chat... ...dan menerima kembali ke servis remote. Menerima kembali ke servis remote dan menerima kembali ke selag. Jadi, perjalanan ini akan mencari yang kita akan mencari... ...untuk video ini. Jadi, seperti yang saya katakan, bagaimana anda memulai? Jadi, saya sebenarnya mencari bagaimana kita boleh membuat perjalanan lebih baik. Dan sejak kita membangun dalam perjalanan, kita sebenarnya melihat bagaimana... ...awak sebenarnya membuat perjalanan dalam perjalanan. Kerana, terutamanya, perjalanan mempunyai... ...masa cara membuat perjalanan. Jadi, saya mencari perjalanan perjalanan dan ini yang saya dapat. Jadi, pertama, anda perlu memulai perjalanan perjalanan. Dan kemudian, anda mempunyai pembangunan. Apabila seorang pelanggan mempunyai perjalanan, ...saya mengambil perjalanan perjalanan. Beri beberapa perjalanan. Perjalanan yang sebenarnya mendukung... ...perjalanan yang sebenarnya mendukung pelanggan. Dan ada pelanggan. Dan kemudian, ada beberapa mesin yang anda perlu memlukai... ...semasa anda mempunyai perjalanan. Satu adalah mendukung. Untuk pastikan bahawa anda mendukung perjalanan... ...saya akan mencari yang akan diperjalanan. Jadi, hanya sebab... ...awak dapat menggunakan dari pelanggan... ...mencari. Dan kemudian, itu adalah keadaan melekat... telah dibuatkan. Jadi di sini di ekstrasi spring guide, saya akan periksa nama terlebih dahulu untuk mengecewakan jika itu mempunyai spesialan atau kecewanyaan. Dan kemudian saya akan membuat kecewanyaan untuk adresnya. Jadi itu di atas kota bagaimana spring guide sebenarnya mempunyai bagaimana anda membuat kecewanyaan. Dan anda dapat memikirkan saya, itu nampak seperti quite a bit of code, and well they have their good intentions for separating out in a validator. So I suppose they are trying to adhere to the single responsibility principle whereby they have the validator class just do the validations and leave it out of the object, which I believe is fine. Coming from the Rails background experience working with Rails, I do like the convenience of having it define a class so I know right away what has been validated. And that got me thinking, can we do something similar to that as well? Sorry just to clarification, when you say define a class you mean you like your entity to be able to do its own validation? Not just to do its own validations, I would able to tell at a glance what views have been validated because not necessary all views have been validated. So it got me thinking, can we do better than this? And that's where I find out that hey, there is actually a way of doing annotation style validations and that is using java axel validations. And that's the time to call for code. So let's look at some code that I've written. So this is what I come up with. And in java axel validations, you are given this annotations, not blank as one of them, you do have annotations such as not noun, not empty and you can even validate against a pattern as well to make sure that a particular string matches a regex pattern and there's even credit card length if you're interested and to validating against credit card detail so on and so forth. And this annotations actually allows you to pass in the error message everyone show. And what I like about this as I mentioned is you can see at a glance what views are being validated. In this case, this object is pretty much just a detail so it's very simple whatever views that comes in form a hash. If the key is not there, I'm going to set it to noun and then if I were to call validate if I were to run the validations on this object it would tell me which validation will fill. So what I'm actually not showing over here is I also created a base class over here called validation object. What this does is just give me nice methods that cause is valid. And this just do the internal wiring up of the validators collecting all the arrows and checking whether it's valid or not. So it's pretty simple and if you're to look at the spring validator so if you're to go for the spring validator approach your class will probably look something like this without the annotations but then you end up having the validator class and in the validate method you have to use the validation you choose to call multiple times on that. Any questions so far? We'll base on what you see. Is that clear? I have questions but I don't want to derail you so I'm going to answer the ask. Sure. I actually have a question. It's being a bit more how you're using validation object or is that a bad drill? It's actually part of my implementation. So what validation object allows you to do is allows you to invoke is valid and is invalid methods on the object you're validating instead of creating a validator class passing it in and doing it for you. I'm doing the same way over here as well for the example I'm using spring validator framework as well so if you look at this it extends for a validation object in this case it actually picks up the validator over here. So in this case this is actually a quick example to illustrate that you can actually have validation object support either ways as well and over here I'm just hard coding the validator that we need in this case which I believe you can inject it or just have a way to define it from the implementation class as well. In this particular case it's hard coded to a particular type so if you have a type definition D on a task but in this case it's just fixed to provide an example of what might be valid. The reason why I do a T is because it needs to get a handle to the target instance you're validating reason being when you call validate you actually need the reference to the object it's validating. So you can't recall this because this is validation object you need the actual concrete implementation of this class. Can I ask the question which I understand your approach? I don't think you can test on any other question. The question is it looks like you're using the annotation style validations which are usually used to serve as validation capabilities on an entity that's also doing other stuff. But you were like no, I want to use that same strategy on our class that's only job is to be a validator because I like that DSL if you were better. So just to run through some of the benefits of doing that. So it actually gives you a clear correlation between what is being validated and you can see at a glance what views on this class needs to be validated just by the annotations itself and actually forces you to declare these validations upfront and it's clear to someone who's looking at the views oh, some of these views need validation and you can even have methods that has these annotations as well. So one thing in the last point is actually eliminates the possibility of typo. So if you're to look at the example that I show you in the validator you actually need to pass in a string few name that you need. So what happens if I have fat fingers and I type in a wrong name and for some reason this is not being tested and there's an error and I'm actually forced to figure out what actually happened over here. But you don't get that issue if you were to use the annotation style because it's clear which view you're being validated. So I feel like that's a big win for me. But then that got making as well. Can we do better than just annotation style validations because if you look at annotation style validations one good thing it gives you is it tells you what individual views need to be validated but what happens if you have validation that cross cuts across different views and you have associations and you need validate against. As I was thinking about this I was looking at the marvin code. So let's look at the marvin code and you feel a rough idea on what I'm talking about and for this I'll be looking at a controller and this controller is the use case I was talking about. Index that receives the request from Slack. So over here I have the same detail that I was talking about previously the incoming Slack request. So actually it receives the parameters and also takes in a Slack token which will be validating and then it calls the method that's provided by the validation object. And then it checks if there's error for this I'm going to throw unrecognised API token. So this is the first step of refactor that I did after introducing this DTO and having validations on this DTO as well. And as I was thinking about it and looking through it the original piece of code and if I were to show you actually it looks like this When the request come in I'm going to check for the token if it's not there or if it's not equals to the Slack token throw the exception and I check that there's a text there if it's MP I'm going to return a default response Otherwise I'm going to pass the commands that's sent from a check client and then I ask if the command exists in my system if it doesn't return a default response and then this bit of code what is checking and it's checked if there are sub commands and then it ask if sub commands are present if it's not return a default response and finally it start to pass the argument send send as part of the command and it feels passing I'm going to return a response and then finally this is where the remote service is called so you can see that we've actually gone through like 20 to 30 lines of code just for the validation bits and as I was thinking about this it seems like there are certain things that may not be a good approach when you use validation style annotation style validations things like this part where passing fails this should but right be a validation as well because you are checking whether particular arguments can be passed and then you have some sort of validation that check whether sub commands exist in the database similarly for commands as well we are checking against the database as well and you got me thinking hey, seems to be a pattern around this because there is a particular type of validation that is structural and that means things like checking a string is not blank the data string actually matches particular reggit's pattern and there is the different type which is domain level validation where you are checking whether there is a command object that exists and you do have some uniqueness check as well yep so let's go back to the code and see if you can identify quickly which type of validation this falls in so for this part which type of validation do you guys think that it falls in structural i think it's both the first part is structural checking whether it's now is structural but in the second part checking whether it goes to the select token in the system actually that falls in domain oh, this part it's clearly structural to me as well this part because this is tied to your entity that you have you need to look up the database checking whether the command is present similarly this part same check checking against database and i feel that this falls into the domain level validations and then checking it ya, this clearly i feel is domain level as well well, we can argue that it may fall into structural but then because it has to do a look up several steps to look up before that in order for you to achieve this check or whether it's able to pass so i feel that it falls under domain level as well slides so as i was thinking about this and Gabe happen to share earlier he was talking about hexagonal architecture where you show a prototype of how we could actually split up in terms of having objects to do certain task and having like models having a lot of behaviour code in the models itself and asking the model to do certain task you have you structure a code such that you have use cases whereby you have business use cases and you create classes based on this business use cases for this case particular use case make remote api call there will probably be a use case for this and then i was thinking hey why not put those domain validations in this use cases and then leave the structural validations at a control layer because that's what is being sent to us why not just do the structural validations at a step and if you look at this diagram as i was saying in a green layer where our controller sits that will do the structural validations and then in the rate layer where the use cases sit that will be the domain validations so in this case you actually remove the amount of churn that you normally have in probably the entities or even the controllers as well because that will be the bulk of the validations in the previous version of this code that I was showing you because right now we do see a lot of validations happening in the controllers based on the code so that got me thinking asking this question and that's where this journey begins because took me a while to actually do some refactoring and this bit will be more on sharing what I've learnt and this is the part where I will sit down and we will walk through the code before we do that do you guys have any questions so far it's good yes I think you can address later but if you separate out the structural validations from the domain validations your domain layer if it's sitting in its own surface right it talks to these controllers over the wire right so how do you guarantee that what the controller is sending you is actually structurally sound if it's getting transmitted over the wire and does that mean you need to have those validations inside of these interfaces inside of the domain as well so you're saying that if the controller is in one service and then you lose that and you lose that type safety that you have when everything is separate out of packages but it contains the same box just thinking along those lines so for one I'm not sure which scenario you split up the controllers and the service but then to address that part what you could do is actually you code based on abstractions so you work with interfaces instead so both sides know of these interfaces that you're going to pass in like somewhat like a request interface that I'm talking about and it has methods like is valid so when you pass it to the use cases what you could just do for a check is call is valid on this object just passing to me just to ensure that it's in the right state or maybe you can have some contact just ensure that can I contribute one thought to this question I don't think your scenario matters if I'm understanding it correctly because the reason why we do the validations is so that we can tell the user you fuck something up I don't know how to handle this data right so the controller can handle that pass that back to the user if the controller ends up somehow after that point passing us back stuff to a different service that's not doing the structural validations it's just an authority exception is something like that and that's fine that's fine because the contract between the service that's doing the domain stuff and in this case the other service that was just doing the structural validation is you pass me what your data do if you don't you're going to give an exception for being in that's your business so you can't enforce that contract on a code level unless you have these sharing fixes sure but the contract is you will get an exception daily yeah i think that's the difference between data that you can control and data that you can't so in this case data you receive from the user I would say you be more strict and check what's needed whereas data among the service you can be a bit more lax and do certain checks as I mentioned to you check that is valid before you actually do any operations on it yep and let's look at some code let me check out my branch so I've shown you how the code for the refactor looks like and this is what after refactor looks like so similarly I will still have validations the structural validation done on the incoming slack request and if it's invalid okay I'm going to return a response and this is what in Uncle Bob's blog he talks about interface adapters whereby you use the adapter pattern wrap around objects and cherry pick whichever fuse that you need for the nicks nicks layer in this case nicks layer use case which in my code I'm calling interaction so as you can see what I'm going to do is after wrapping around incoming request this is actually an interface and I'm going to pass it into the use case and this is the use case where the meat this operation is doing create a use case and I'm also injecting in the service and the repository for this service to work and for the validations the domain validations that what I'm doing I'm actually creating decorators and what do this decorator look like so this decorator would implement these same methods as a normal interaction which is run so actually does the usual validations that we've seen in the first part of code checking whether is it present checking if the sub command is present and then subsequently check whether the passing works and if all of this successful I'm just going to call the decorator object so if you look at the previous bit of code the decorator object is actually the use case the one that actually does the work so what I'm doing over here with the decorators which this approach was something that experimented with and I thought that is probably pretty clear to split up what type of validations we're working with so over here I have validations just for argument passing and I have another validations just for the verify API token step and what this decorator pattern actually gives you is also get to define which validations had to run first so over here I kind of put I created the verify API token decorator last because I want I want this check to be done first similarly to similar to the previous version of this code before the refactor the API token check is always done first Do you think it's a little bit confusing that it happens in the opposite order because you're wrapping and wrapping? Yes so that's one thing that I feel there's still some room to improve so but I feel like this is a good first step in terms of splitting them up into their own concerns and responsibility because if you look at individual decorators the run method and the validation they are really short and it's maintainable and you don't need to change this and the good thing about this is you can reuse this decorator in subsequent interactions that you have as well okay and finally cost run and this is another interface adapter which is the outgoing slack response so based on the interactions result I'm going to wrap around it and I'm going to expose what is needed to the client and return the call back to the chat client and there's one bit of code that I haven't showed which is the make remote API call so what this means is actually gives us pretty straightforward call to make the remote API service so this operation if you look at a previous version of code it was actually all the way at the bottom of 20-30 lines of code but now what it can do is it can just straight away retrieve whatever entities it needs straight away pass it because the validation have already been done by the previous decorators and then just call it right away and you can just return the result that you need over here which I feel it gives you clear understanding of what is needed over here in this interaction and in terms of testing it's pretty straightforward what you need to set up and of the assumptions that we've already made that already exists a command there are arguments created and the arguments are in a possible state before I continue is there any questions I will dive a lot a little bit deeper into some of the pieces of code that may look unfamiliar to you in subsequent slides before we proceed any questions or anything that you're going to look at any particular bits of code that you want to look at in particular no okay so some learnings that I come across while doing this refactor is use data transfer objects when you cross boundaries between layers in the code you can see that I do have incoming select request so this is a detail similarly outgoing select response it's a detail of sorts but it's more like adapter and then I have another adapter so it's creating really small simple implementations if you look at implementation of select interaction request it just has a bunch of get methods the fetch what is needed for the interaction to work and internally it has a select text parser that what it does is just breaks up the command into tokens and then returns it back so there's not a lot of logic happening it's just really simple returning whatever that the interaction needs based on what is being passed in and once you have the details what you could do is just perform the structural validations on these details because this details what it does is just having those fields and you can just add the annotations that you need on those fields that you want to be validated so it's pretty clear detail what is necessary to ensure that the program will work and also use adapter objects to actually pick the fields that I need for the next layer so that I don't expose unnecessary information to subsequent inner layers as you move towards the core of the onion if I put it that way so in a way you are actually so this is a way of doing information hiding whatever that's not necessary and also you can do some translation or mapping in terms of information that you can prepare for the next layer that they need and one thing that come along which I find helpful was to enforce preconditions so what are preconditions let's look at the code so over here for instance on the slack interaction request I have some preconditions check so this preconditions class is actually provided by guava if you look at implementation for check not now it just throws the now pointer exception if whatever object reference that you pass in is now otherwise it just returns it so it just ensures that the collaborators that you're passing in to this class is actually in a state that the class would meet so over here in the slack interaction request I just have to make sure 2 things one is it's not now and it's in a valid state so what precondition does is it's actually one of the items and design by contract whereby you have a contract to say that or what this method needs actually needs incoming slack request and what is the state that you need incoming slack request to be in order for this class to work and these are the 2 preconditions that I need one is not now and the object slack request is actually valid so in a way actually what this gives you is actually in a way it actually helps you to narrow down every time you see bugs within your code because what this precondition check is to guard against runtime exceptions whereby you have like now pointer exception but you have to go through dig through like many levels or stack trades and not find where it is and it's not readable so this is especially the case when you are going through you're running the code and you're testing it doing some exploratory testing and it just crash and you have to go through scroll through the many many levels of stack trades and not find where exactly it is so over here actually gives you like a nice message that you can pass in and to say what is the exact error and based on this stack trades you can actually know which file is actually storing this error yes, you have a question Is this precondition almost equal to the structural validations that you spoke about? So yes there's a difference so preconditions is something that we check against developer errors whereby people who are using this object they are not adhering to this contract that you have set up so let's say you would have this class being documented somewhere in the documentation and you say that you need the incoming select request for this constructor and the documentation say that hey I would thrown the now point exception if this is now and I would throw the check argument which is the illegal argument exception error if you're passing me an incoming select request that is not valid so this is slightly different from the validations that I showed you in the select controller because what you actually don't throw an exception from that saying hey, please enter your name so there's a difference between these two is because the reason why you don't throw an exception when you do structural validations on a step is because if you throw an exception that means that the user who is using a system they can't do any action to rectify it because it's a system error that's facing but over here within the code base itself these are errors that you want developer to look at and fix immediately and it's something that we could handle itself do you consider using applications like I am not an algorithm for an algorithm it's the same thing they understand the opinion but the reason why I ask because I know I am not an algorithm to ask you against before you run this thing you will see the compiler tell you as a warning to pass it in a lot yep that's one way as well because I do see to go using it but I feel that what helps is the message they will pass it at the top and what the advantage that Gwaba pre-condition gives you are able to interpolate any parameters that you need so let's say you want to show the state of this object we can actually call I think it's percent s and then you pass the object which you want you do it to interpolate so this is something that the normal assert and the Java will assert that so this is something that Java provides you on the box and one thing that I like about having these pre-conditions you can see at a glance one needs to be there and you actually have a lot of freedom in terms of defining what type of cheque state you can do because you can do like quite a bit of this and not just that you can invoke your own methods which you want to check with this as well that is congruent to the application style and while going through the code you may have seen this build-up pattern and I felt that it's really useful especially when you have a lot of arguments and you pass in the constructor because in Java language there isn't like name arguments that actually tells you what you're passing the constructor and sometimes you're relying a lot on ID to tell you what's the name of the argument that you're passing even though that helps but then it doesn't really tell you much about what is name that you're passing what is name I'm talking about So some places where I've used the build-up pattern is when building my interaction result for instance the simplest one over here where I'm calling builder there are different approaches of doing this so this actually inspired by Joshua Blotch book on effective Java so where he came up suggested using this pattern and this is the one that he suggested where you have a class within it and it basically just defines setters for the properties that you have on the outside and over here I do provide some nice methods that you can invoke that automatically sets like enum values for you It's a nice pattern Ya Ya so another popular way of doing things is instead of having a class instead of invoking on the class you can have a static and invoking the builder method so this will return a new instance of the builder within the class itself so now instead of calling interaction result dot uppercase builder you can call the lower case builder method which will give you what you need on the outside may I done something I don't see okay let me just get rid of this code first if I can see constructing your builder with the static builder here so the magic have been set this step do so what do it does it pausing to build an instance to do an interaction result so the reason why you can do this is because this is actually private and nobody can construct it on an interaction result so now what this construct will do is just take whatever and assign to itself and then you have to control so what's nice about this is you can even assign like default values over here yeah if people do not invoke the method over here declare it to be final so yeah so yep and throughout the code I've been using a lot of this and I feel that it's a good pattern as well next thing that come across is well exceptions is something that the Java community they can't decide on along the way I feel that if possible avoid throwing exceptions because it kind of I feel that it's an anti-pattern because let's say I want to present more readable error to the user or developer then I will need to create my own custom exception that actually have reference to the object that is causing this exception so on and so forth and I'll do that but instead I can actually create a result object to actually capture this information and present it to if the developer or even the user itself so if we look at the previous version of the code let me look at the class that has this issue is the regex argument over here you can see I'm using a builder pattern as well but before that let's look at what it looks like let me just discard changes okay so over here is doing the pass and you will try to pass the results and if it encounters any errors you just throw an argument pass exception which this is actually a custom define exception the reason being because we want to have our own error message and we also want a reference to this object so that we can poke and actually ask what state is causing this error and if you look at the current style what I do is I actually use a builder result builder object build whatever I need to in order tell whoever in the upper levels or upper layers what they need to know about this result whether it's success or failure and if it fails return another builder object that tells it it's a failure as well and as I've just said this makes the controller actions handle these results in a much more uniform fashion but because you're eventually getting nice follow-up from all of your interactions you don't have to do special things for each different type of failure that might happen from different types of interactions ya, correct so that's actually what you see in the controller where I don't even know whether it succeeds or not it makes your controller much simpler to review so there's actually pushing some of this logic breaking out into the individual classes to handle this then one thing I also learn along the way handle exceptions at a right level abstraction so in the argument pass example that I show you so the argument pass exceptions is throwing internal exceptions like index out of bounds and some other exceptions as well which is internal to the pass logic so what you should do instead is to wrap around it handing back in a manner that subsequent objects that call pass which is able to understand ya, so this is for if you were really you have to create your own exceptions you have to handle it at the right level abstraction some things as while going down this approach I also realise that well it is actually encourage it's not encourage it is the thing to do which is to inject dependencies using a constructor and avoid the reliance on the framework so this is something that Uncle Bob is trying to champion which is keep the framework out of this and actually inject whatever you need into constructor so what one nice plus point about this is it actually makes testing really easy it actually keeps spring out of testing and this is something that Mike G when you're here he was telling us about as well don't order wire your dependencies and bring spring into the picture when you're testing just a very simple DTO or use case itself because if you look at a code individual interactions just pojo even if you look at the most complicated one the make remote API it's just really simple pojo with no dependency on spring or anything and you can actually mark your service and report the tree really easily in this manner and one thing this is this learning is from actually the D in solid which is dependency inversion which is to depend on abstractions rather than concretions so one area where you can see this happening is in particularly this lack controller so over here in the decorator itself I'm actually passing in an implementation of interaction and not the actual I'm actually passing in interface not actual implementation of a make remote API call so what this gives you is it actually leaves whoever is calling this without having to worry what make remote API call might do in future and actually prevents you from changes because now you're actually adhering to this interface which is I just need a method called run so if make remote API call what are other methods as long as it's run the decorator would know how to do that job and similarly you do see it in interaction request as well similarly is an interface and this is being passed in to the individual use cases over here and slack interaction request is a concrete implementation okay, some afterthoughts so the funny thing is Uncle Bob actually gave a talk if you guys have watched it it's called architecture the lost years it was brought up during stand up few times in the team as well the first time I watch it before I actually did this refactor I had no clue what it's talking about I thought whatever he's trying to make make sense how difficult it is to do it so that was my own naive thought after that after going through this exercise there was actually a particular she dedicated a few slides to this hand drawn animation which she did which I will show you so in the talk she talks about this diagram where he has user at the bottom left corner that interacts with your system your system will be this entire thing and delivery mechanism will be in this case the web so the web will actually serve the request to the controllers then that's where the controllers would handle everything from here onwards and actually talks to interfaces which is what we did which is to depend on the abstractions and then subsequently the interactors in this case and the code base will be interactions actually depends on whatever that the controller has passed in which is in this case interaction request object and then once it's done you actually pass it down and ask the entities to do its job so we actually meet a really nice not animation but just separate slides of pictures where it sends the request pass the interactors and then you call entities do its job what interactors spits out is the result model and it passes it back to the user so as I was going through as I realised hey so I rewatched this another time after doing this refactor actually Sanquin is after going through a refactoring process you actually realise hey whatever you're doing actually is pretty obvious when you're going through the process yourself and actually screams at you that certain decisions have to be made things like depending on abstractions and not concretions separating objects into smaller bits and pieces splitting into requests and results so on and so forth this became obvious as you go through the refactoring process and after watching it for a second time I was like hey ok so I actually coincidentally actually adhere to what he actually suggested and proposed during the talk so that was pretty it's actually something which I learnt along the way which is just sometimes you need to do it yourself and not understand what's being thought because otherwise you're just passively taking it in and you wouldn't be able to understand why certain decisions were being made and why it's been structured out that way as well Very differently people talk about oftentimes in our community we get obsessed with programming design patterns design patterns are just the same thing figured out by a lot of different people and that's exactly what happens to you the same patterns of the bubble stock yeah correct yeah so that was pretty neat and what lies ahead and I feel that a few things that can be done actually you can integrate this pattern with CQRS and vent sourcing that's something we didn't do in Marvin and I feel that if you were to look at it this way it's actually not that difficult because there's actually parallels between CQRS where it separates combine and query and how we're actually doing it it's hexagonal architecture and you can see there's actually a somewhat separation between how you're doing command whereby use cases they're actually invoking on the commands and a read side is actually the result and you can actually change your code to actually integrate with CQRS and subsequently with vent sourcing as well and what actually would be nice is actually to integrate with other check lines because that's when you know how the interfaces that you have actually interact with would actually work with many more different vendors subsequently so I guess that's it for this presentation thank you any questions feedback would be appreciated as well I've got a question Yes Did you experience one of the things that quite a few people normally concerned about is how long it takes to develop Java software I would is your gut feeling now that you know how to implement your application using this method and the way that you would have implemented before this is there a time penalty with one over the other or was it same time what did you what did you feel So while working on Marvin the index method on the Slack controller was something that was really huge and really monstrous whereby nobody wants to touch it and making changes where it was really difficult testing it was really difficult as well so I feel that that is now for one but people usually would just live with it because to refactor it would require a lot of time because for me I was working alone on this and I was actually refactoring actually took me like a week plus to actually refactor poor everything to ensure that everything is working rented when I was going through this exercise we were going to look at the branch that I was working on that don't test because we already have the integration test and the bits needed and the reason why we have those integration tests for itself because there is no way to break up the method itself things like validations you have to bring up spring and actually do all those validation steps and this was causing actually the test to run really slow as well so actually moving that bit after you've done this and writing individual unit test for the interaction so really simple and that will actually spit out the test run so back to your question I feel that it's something that we need to take a step back and think whether when is the right point to start going down this approach because it's really easy for someone to actually go down the route of having that index method where you throw validations in and what's important is having that not having this knowledge is the first thing to do is how to break up into smaller interactions and how to start to draw the boundaries between how certain things should be done so you take this approach for your next if you're doing new project from scratch you take this approach because in terms of testability maintainability and readability I feel that this approach would actually trump in the long run as well that's it thank you terima kasih, Alan