Clean Lambdas - by Victor Rentea at JBCNConf'17

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] my name is Victor inta and I'm here to talk to you about how can we write clean code using Java 8 features using lambdas hmm Who am I first of all to talk about these things I'm a consultant technically the lead architect around for the largest client of IBM Romania but if I find myself as what I liked what I think I'm doing I would like to say that I'm a clean code evangelist I'm a maniac about clinical and I'd talked about clinical dean architectures and clean lambda that all sorts of conferences seeing that works Poland if you if you go in a few days in the spare time what I like to do most is train I'm an independent trainer on various topics like architecture sprinkled spraying Java Enterprise design patterns even in faculty test-driven development coding dojo Java performance and many things on my website yes I have a website okay so what we'll talk about clink OH what about Java 8 features lambdas why do we love lambdas because they are cool right they literally caused a dramatic increase in the popularity of Java since they were added you can see here increasing the Java right we are number one right now you all know that right but the thing is that my concern since I'm since I'm a clinical maniac was whether this code with Java it is still clean maintainable elegant readable and so on that's why of course we can write expressive code but at point at some point it might become even cryptic right and I was a bit concerned when I got to the first code review I was what how can we maintain such code for that purpose I even have organized a little study of my own yeah this is why not let's code just to warm up again I hope you had a great coffee they told me you are all Java eight experts so this will be recorded understood so you can then slow motion and watch the movie afterwards only thing that I will do will be pushed on this get here that you can see afterwards as we as we develop it code okay let's warm up so now let's say we want to search from some items so we have a list of orders let's say order sickles neo-realist I'm using eclipse sorry orders but I mean working it IBM so yeah I'm biased how can you search for only those orders that match a given predicate for example is where they are not delivered one idea would be to collect them all in a list and then test the size of the list why not and this if the size if the site is greater than one that it means I've found the eighth item right but this is quite silly right this is one way to do it why not so let's try another way another way would be to do is empty and then negate it great another way let's try another way another way would be maybe why not let's if is any item that matches this predicate then if is present then this is my bulan test right this will also work hmm how many ways to write the same thing let me see another way would be maybe to directly count the items of the stream why not this is another this is another way to do it like this it's equally is equally just work just the same but still the simplest way isn't any of these right there is a more concise more expressive way to write it of course any match so what I wanted to prove to you is using this point is that you can find so many ways of writing the same logic in so many there are none does allow you all sort of forms to write the same thing so let me push this already this would be various ways pair program all this pair program ask someone to you how it feels of how he feels about the coat you just wrote but the point is always you should refine your Java heat code especially when you just started using it or research for the most simple and most expressive just like it was said you know talk before you need to write concise right but not too cryptic okay so you need to refine to find the best the simplest way to do it now let's talk about optional which is the best the best underused feature of Java it right how can the optional get rid of null pointer exceptions here either I'm using Lombok here to get rid of the clutter for Gators and Saturdays this is not doesn't matter actually the point is that from the customer I'm getting the profile I'm getting the gold card I'm getting the discount you know this is a train wreck it some sometimes referred to as a train wreck because it can crash in so many ways right for example nullpointerexception they the most frequent exception of the world right this is the wheel of it I mean we feel if you don't see a little pointer exception in a day then you don't feel right I mean so let's fix that what if what if the profile the point is the customer may not have a profile but for example if you place the order without creating a full-fledged profile just directly create an order without a profile for that purpose I would say that I could have whoa a getter which is tell me an optional of profile which is yet optional for example which returns me optional of nullable of movable moveable or profile no I'm using cleats I know but the point is that if I have such a method I can write the following code by the by the way how can you get low can you work around this this nullpointerexception you all know right you're doing an if before oh my god how nice and you have the discount there before equals zero initially and then in case the customer has a profile then indeed going to you know you're just if and if and if to avoid the note the note right instead of doing all this misery we can shorten this code by using optionals and if you do this then this method will give you an optional of profile that you can map furthermore and you can stay from the profile I want to get the yet gold card that is inside now I'm returned and an optional of gold card and I can do this same trick again map gold card I get discount right and then I'm left with an option of doubles that I can work around using or else and in case I don't have a profile or a gold card then I will return at zero and this works just as well without all the clutter of ifs now you will start loving this at some point and you will say okay I don't have I don't need any more get their traditional guitars in case something might be missing I will always I will always return an optional and you will like to do the same in all places for example the profile of a user might not have a gold card might not have purchased a gold card that's why you would like to replicate the solution again public optional optional and then you will say nice and you will not have any getter but then you will do that you won't we won't be able to invoke the get gold card they have just deleted the debtor so will invoke this but now you will end up with an optional of optional I won't talk about monads I will just quickly and silently write flatmap and let you read more why does this working what does this do but just how can we get rid of nulls right so optional versus no pointers this train wreck can be rewritten using map map map map sometimes flat map and this is optional versus no pointer exception all right cool now let's see what's next Stream Rex you know about train wrecks a huge concatenation of method calls let's look at a stream wreck great this is just what you want to read Friday evening at ten o'clock right great salmon was just being geeky here and what does this do filter order is not delivered so I'm only selecting the orders which are not yet delivered then I'm giving their order lines and I'm flattening the leaf that I'm returned oh my god this is awful why not writing it another way order lines and then I'm plating in case something that I've talked it's not clear you can find more more slow motion demo of this lama-june Java it features in some talk on my website but the point is by doing this dot stream you are now joining all together however at this point my mind is full my mind just stopped I mean what now I'm filtering those what I can do at this point it is to do the following I appoint I can collect them to a list and then I'm stream again and why the heck am i doing this because now I will extract this to be the other lines not delivered actually the not delivered yes I'm introducing a new explanatory variable that will put a name to a chain of such stream calls it from that point on my brain can understand again what I'm trying to break these streams these long chains of calls into into pieces into parts right cool so this is how you can do so which team lacks always try to introduce new new planetary variables and even new methods look at that so I can say that this is a method with the same name as the variable actually something like that right and if I do that I can get order lines not delivered okay this should have verb right we are using clean code here to get order lies not deliver something like that so I always try to express your code not avoid being so cryptic using glam I'm using Java it because it's so easy to write super cryptic code okay let's look at some lambda this is the lambda have an arrow interesting what does this lambda do is he and you're reading this code return our age stream map a arrow and now again an interrupt request s' occurs in my brain what the heck is going through and I'm entering a block of stuff this is stuff right something I need now to understand in the context that I were why not make it more expressive what does this bit of code say this is basically an anonymous function implementation and that's my problem it's anonymous let's put it a name so what how would you name are coded from a a returns a be perhaps map to be why not so given a our map to be right then this variable is useless I can just treat then as syntactic sugar allows us we can write like that it's equally identical right and then then I'm looking in a same room how can I write this even shorter think you know this for that cool I'm passing the egg as parameter to the instance method map to be hmm you see how the arrow disappeared good thing now this is one way to do it and I'll even call this another way to do it is to put it in a separate class let's say I would have public start because any inner class a beam mapper which does exactly this using a public like this and then a beam mapper I will pretend I will inject here I just pretend somehow and then from the a B mapper I can refer to the instance napa needs this method map to be you see what i'm doing i'm using a separate class and external instance to get it instance method for my use still this is using external mapper 4.4 that then for this example in particular because I don't need to go to the database I don't need to integrate with other services this is just trivial stuff we're not pushing it in the constructor oh my god I'm pushing it right in the constructor why not depending on the direction of the abstractions actually this might give a valid solution so a constructing B now becomes possible based on an e you see and here we go here we go we can simplify this one then I would say that instead of having a dedicated mapper just to hold some method that does nothing I could say something like that why not and I completely destroy the mapper completely and since we're here tell me for that yeah I will love Java we love Java we just love Java it's so enlightening right but the point is should the code becomes shorter and it works why not so this is using new you get a point so you can push all these functionalities means avoid having long lambda that you need to decipher to reverse engineering to understand what what they doing there put some name to that what map to be so the point is you can put an interesting method in the same class you can use an another instance to get the reference to an instance mapper or you can even push these things in the very constructor of that other class cool a big part of a big part of the Java IDE code that we will write will be focused on predicates we will be working with predicates a lot of things we should we would do around predicates let's let's refactor this code ok so what do we have here we have this filter let go slow now so given an order I will get your delivery due date if that delivery due date is before the warning date right and another stuff this is tough this is hard understand actually and we all love boolean expressions that span two rows right we just love to have end and then enter and then a lot of parentheses and or and then another end and then we are Friday evening we are deciphering the parenthesis and we are clicking contempor and this is to see what it closed right we love to do that so never have boolean expressions spend more than one line introduce explanatory variables to put names to the part of that expression and then compose all the expression in a single line in this particular case however I'm filtering by actually two subsequent criteria I couldn't refactor this by applying two successive filters it's just the same I'm filtering by one criterion that I am filtering by the other criteria right so two successful filters but I'm still not happy why because I need to hunt down the scrollbar and crawl you know it's just great and you're sitting in the newborn position in the airplane right and you want to grab the scrollbar it just is just that's what you're hired by the programmer to click on the scroller but the point is you you're you never forced your reader to scroll horizontally of course so what do you do you do an enter right that's it yes perhaps perhaps but still still I'm not happy why because I'm opening a stream in another stream watch this I'm already streaming the orders and now I'm opening the stream of all the lines inside of this oh my god again my my head just blue never open a stream in another stream do something about that in caps rate this stuff in a method in the clinical practice the point whenever something is too hard understand breaking it into multiple methods why not try to do that here first of all you have this bit of theft here this is a boolean test on the order line level that I find it very probable that you would need to reuse the same bulent it in other places in your application so then what can you do how can you hide this bit of reusable logic inside why not have a method that does this which is named is not you stock so something like is not in stock you see little helper method that I create on the entity level actually come on come on you wrote your stock why does it just create I and I'll create this new method so this is boolean and returns this right pretty is pretty simply not understand I'm now having expressive methods this is sometimes called a synthetic getter it produces some blue line based on some other values it just computes something for you and it's highly reusable short enough to be placed right in the entity or the your domain name or domain object interesting but now of course when I make where am I going UK you would see a pattern I hate arrows but I'm still not happy because I'm still opening a string another stream what can I do about that well clean code says that you should in extract things up into smaller methods so let's make a method out of that how can we name a method that does this thing I would name have ordered lines not in stock let me let me try to do it has order lines not in stock I can even go even shorter because this is a private method head in line at this talk and the signature is like that you see it's pretty straightforward to understand what it means and this is how I buried I buried the stream call in an hour meant to keep the reader relaxed then I run my reader to beat them to be reading stuff without breaking his head up now again what I'll do here for you again you see a pattern I hit arrows why not why not like that with expressive names interesting let go further okay this is something that you should never do each online now can we do the same about this one interesting enough if we try to extract this bit of logic we will find out that this function is new function will require both the warning date and the order if we will extract a method with two parameters it will be impossible for us to reference this method using before dot notation and I will not be happy since Java doesn't support currying in its syntax we will have troubles so this won't work as it was as it did before but what if we would extract this part then what would we end up with this is a predicate how would you name this predicate you will name has a delivery date before warning perhaps and here we go I have a variable of type predicate I have a variable which holds a function and again my brain's parts start taking smoke but the point is I'm working with functions as first level citizens in Java eight cool interesting but now suppose you would want to use this predicate in another place in your application how can you do that why not create a function that returns a predicate I'm creating a function this function does need to be private well they need to be instance it can be even reusable in a public static order predicate like this and I can put it by the weight class I can put it anywhere and I can reference it using a static call to the function ooh Lala I mean working the function to give me another function yes I'm doing it I'm calling a function that returns me a predicate this is how he can you can implement parameterized predicate let's say you can give some parameters to this Factory methanol in a sense it will give you a predicate which is parameterized which is configured according to what you said and we can reuse this in other places you can do stuff you can even import static that and you can even compose predicate right you can do whatever you want you can work with predicate in your application and you use them in from your various use cases Allah let's push this one because this was good so loving cherishing your predicate this is what you want what I mean here so with filter basically highly reusable if it's a bit of highly reusable code push it in right in the entity if it's use case specific put it in this in a matte and a private method in the same class and implement stuff there just explain the code even introduce local variables that hold predicates and even create static methods returning predicates okay this is mind-blowing I agree but still if you are using generate from for long enough you can even go there okay now a more complex example type specific functionality now I'll move fast because this is a switch and you all love switches right we are competing price based on days rent and and the worst thing about switches is that in case someone comes and adds a type of movie here we will have a problem right therefore what you always do here of course even find bugs that throw new Ram panics or maybe even ever give legal argument exception why not oops come on argument exceptions like that never never just fall through any other left-left cases always be sure that you will the code will break whenever this flows happen ok ok ok but still how can we avoid switches one who could say polymorphism and let's do that to see how awful it is abstract la compute price and this is becoming NEFT it one because this is abstract and I'm now having an abstract movie and the first class let's say we were children movie oh my god my fingers hurt expand move extend movie and then the compute price for the children we will just return five yes we did then let's do the following that's regular movie right you get the point regular movie ok extend and then we return a plus three good then let's create the last one and the main the major problem with this approach it that it varies the type system right in your type here it is too static for me it is too rigid but the advantage is that you can never forget you no longer needed type actually and here instead of instantiating new movie new release movie Allen Stern I don't even I don't even need any type anymore it's just written in the type system and things will work because compute price will pull more freakily delegates to the knee release movie interesting enough this is awful because in case you want to split the movie here gen1 other criteria let me let me show you what could that mean something like that right then what you you have a class explosion you will split the classes by two criterias will be 3 x 5 and it will be a mess and it's all and it's also 2 what would you do in case you had to change the type of a movie you could do nothing about that right some movie will not be a new release anymore at some point so that being said I will just reverse but still let's commit commit commit commit just to poor over sweet don't try this at home anyway let's revert and I want to show you one more interesting idea to do that what I often do actually did you know that enums can have methods did you know that I didn't up to some point the children compute price what should you do it returned five right the regular movie what should it return engineer in the middle is what should it return now I know it's a bit mind-blowing this having functions in the enum but the advantage is that the functionality the type specific functionality is written right in the type system they are now here what we need to do only is to return directly type compute price of the is rental and you're done the advantage is the following in case someone ever adds a new type here the Java system Java compiler won't allow him to forget to define the function it will be read right it won't compile which is a good thing no one can forget to define the specific functionality interesting and this is enums it functions inside ok let's revert anon to show demos mind-blowing idea you could ever have and i actually delivered in production with that and i'm sorry about that i will show you in a moment what is what is what is this will hurt sorry what if you will have a public static map between the type and a function it takes an integer integer and returns double which is price algorithms equals new hash map you should be automatically to complete it but anyway static okay and since we're do that do we will say 40 children what should I put for the children I should put a function that takes days rented in return fine now for the regular I could put this bit of code and for the knee release I could put this bit of code you see if you do that if you do that you could return here directly price algorithm dot get the device breaks when I write this kind of changes II apply on the day is rented and you have a lovely nullpointerexception lurking in there summer you could do get or default anyway think this this is creepy this is super creepy but the advantage is that you can later on add new values here in theory you could have this as a string perhaps and then set this type to string and then add new types and parameterized configure the price algorithms even at runtime if someone could imagine it anyway this means creepy creepy static map between type and functionality right this is what I did actually and actually switch the conclusion is used switches use switches in enterprise applications at least it's perfect it's ok we should have a default row of course don't do a polymorphous unless you're writing your hi sir and a an in faculty homework and you want to be smart or something don't do that either it's creepy stuff I mean what the heck but this is our interesting these are interesting if you aren't afraid to interesting language language functional possibilities this was allow you to keep the behavior next to the type system right buried in that enum actually and it's super interesting okay the adapter pattern I told you to be intense I really had I really hope you had a good coffee before you can afterwards slow-motion me but the idea is this is a lovely composition of function right I am making to uppercase I'm escaping the HTML bits inside and then I'm collapsing the spaces if I run that I can get a less than B and be very happy about that however just just excuse me for what I'm about to write just sorry what if I could define a normalized function that is initially string to upper case and then I could say normalize then and then compose dot escape HTML keep HTML I'm composing I don't know in my country we learned about F little circle G you know from high school composition of functions and then you derive the function get -1 of that function pretty stuff some rare from our sub functions this is what what's actually happening here and composing function I'm but this what does this work two approaches what string 4.2 upper case why isn't it oops okay and then compose escape to HTML and then collapse spaces and then be super dick about that and say s equals normalized apply of s create and I've did a great job right no one could ever fire me right like she said so who could understand such a code I was a term job position insurance or how was they could refer me who could maintain such code however if for some cases something I could apply a steep HTML or perhaps escape markdown for if some some steps in the chain of functions are configurable are optional at some point you might consider using that because you can compose them dynamically that being said I never use that in production is too creepy to understand to compose because when you change this or when they all these code executes nothing is invoked you are just composing functions and just at the end when you apply it it is all applied one after the other it's creepy but still needs to be checked in this is like composing composing functions against just calling one after the other now one question for you one hard question if I go with that how many methods are there on the stack at one point let me revert to the first how many functions will there be at maximum when I will invoke the will there be two upper keys and escape HTML Bolton memory both on the stack at the same time what do you think these will be this will have this one function more or less as the first where the first forum now if you look at this will to uppercase be invoked in the stack in the same time as the escape HTML no Java will first invoke to uppercase the result will it will give to escape HTML the result will give to collapse spaces at most there will be one single function in the stack at one point but what if I want what if I want to measure the time that a method takes to execute then I would need to have a block like the following you see long T zero equals right long T 1 equals and then system out took T one minus T zero right and what do I need what do I need to do here what I need to do here I need to invoke the actual method I need to measure right I need to call the method that I need to measure the time okay so I let's suppose I will want to measure this function like this if I would want to measure this one I could call this one instead of the old method and now I will print on the console if it works I will print on the console the time that it took to insert the languages in nanoseconds right but when I do that I need to have this method in the stack frame of the insert languages method right I'm in from this method I'm calling the other function I am calling it so I'm in its stack frame and I can help state from before its execution and to after its execution how can we if now the change request comes in I need to measure this one too what would I do tell me it's so easy copy paste that's right it was invented right and I will write insert countries here and I will be very proud of my work this is wrong you feel it's wrong it is fin literally a fin that you do in code so what else happens what if we could pass in the function to measure as a parameter what if we could pass in the function to measure then a function that takes no parameters and returns nothing what can it be in London it's a customer take something if I don't take I don't return anything it's a it's a runnable the runnable have the signature a method which takes nothing and returns nothing right so I can I can basically reference this method as a method which is the runnable basically I can cast its I know it's supposed to be hard I can cast this method to a runnable oh my god because it takes nothing and returns nothing ooh la la and if I do that let me simplify the code a bit let's suppose like that [Music] languages what did they did wrong measure time of a given function so basically like this and if I do that I only need to call the run method of the runnable that I take as a parameter if I do that I'm able to execute around a certain existing block of code so the point was that I had these two functions I didn't want to change those I just want to measure their execution time so what I did actually I managed to run code before and after to wrap around their execution basically hmm bypassing functions parameters because this is their D variable bit between the two functions that I had before this is D watch what was different demerged the function tiny to to invoke inside so we need to be in the call stack of another function right for example to measure the execution time but one more interesting example let me give you that what if I would do something like just imagine start transaction oh la la execute execute in transaction start transaction commit transaction if anything goes wrong more exactly a runtime we are implementing spring now then roll back finally finally finally come on I have to type this all and then I will release right release the transaction resources interesting if I do that I am able to run here in between the function actually this is a function let's say function function now you can imagine that that at this point I will open this rejection if everything goes well I will commit the transaction afterwards if runtime exception is thrown I will roll back just like string and then it's I think if anything happens whatever it happened I will release the transaction resources and now it actually makes sense to do something like that it's actually business useful to do that right at some point so if you do that you were let me commit this one wrap around some existing block just like something like manual our page I would dare to say in our pair D : they didn't occasion that you do is intercepted by a proxy and spring does things there in this particular example there is no spring you are invoking stuff around another method so when you want to start end transaction some sort of manual aspect oriented creepy stuff here now the best one bet of template method you know goof you heard about go see you should have had for that Jenko for long ago a set of patterns one of which was the template method let's see the use of the template method hmm and this will be the most hard let's suppose we have this little function that sends an email that says order received to a certain email that I'm I'm given as a parameter okay okay what is now I would want to create a similar method that will send the order shipped email for to a customer the first thing that I could do is to copy the method right then say here order shipped shipped email right and then what will be different tell me what will be different instead of what they received I will do order shipped true and instead of the body of this method I will say the your order who has been shipped your order has been shipped with the ship and then the question is what is different between those two methods because there is a is a principle to encapsulate what varies or better yet to parameterize the things which are different only these two lines are different you realize only these two lines then I get an idea I know that copying code is bad it's sin that's why I revert it but now I've figured out that I need to change only this bit of code between the two functions so what do I do I will create a method fill email and I will need to have one implementation for the send or the received and another one for send or the shipped so what do I do first of all I make it protected then I make it abstract and then the entire class becomes abstract and then you expand the email service using a class named for example order send order received email perhaps and very the very name of the class tells you you are screwing things up it's a verb here still I'll put to you to you that in a moment it's more tricky but the point is this will extend the expense the email service and will provide the missing implementation for the field email function you see my point and this is how you managed to extract the things which were varying which were changing because now you can simply do that create a new one third order shipped email and they all say order shipped and I will say here your has been shipped ok and then let's say you have some some client code of this miserable good can still be seen from the back yeah and it must be you know the code grows which is a bad thing client code and what if the client could do for example it should instantiate one or the other you see it should instantiate this or this and let's do that in the client code I think I've written it too low this is the configuration stuff doesn't matter this one that matters I will instantiate this one and I will send by the way the name is bad st. email should be ok to a at b.com ok and then if I wanted to send also the order received I will instantiate this other one and I'll call it's super method right like that and this will actually work let me to you this would actually work because the point is that this code actually tries three times to send the email in case the first time fails and so on cool but now you are having you are having problems self-conscious and I mean you really can't sleep anymore why because of this word this word and I really have a big problem with this word this word is bad if evil is despicable its Maleficent is there was a principle that some some years ago many years ago favorite composition over inheritance you know to have things instead of of expanding of being things that's wrong in in and in life you don't want to have things you should prefer being things but anyway for this particular example I'm not happy with expanding first of all I will tell you want one hardens this is not state less this is stateful tell me how will ever work this my problem is that I will I'm instantiating this class I'm coming from an enterprise application development environment and I have a obviously string but you could have any other container the point is that at some point you want to invoke you want to inject some dependency if you do auto wire like that no one would ever process your annotation because you are instantiating the class by yourself this is a tricky point a super tricky point but no one has the chance of injecting you dependencies there and more more dramatic this class is state full and stateful is bad is evil it has this hard to refactor hard to understand hard to evolve it's it's ugly for although all these reasons I don't want to extend this other class I want to have it as a parameter and now it will hurt a bit but let's suppose you could take this method as a parameter here III think you expected that right tell me this method that takes something but doesn't give you anything in return what is it it's a child I mean it's it's a consumer I hope let's see consumer of of email actually it's a female and feel email dot apply a pattern except okay and interesting this fast is no longer your abstract this class just takes the missing step as a parameter takes the missing step as a parameter I can even put it at at service or otherwise realized like it at component whatever the point is right now this is the field email for order received this is the field email for order shipped I no longer need to extend the email service before and these two method can even be placed in the client code in the code that actually needs to send the emails and I make them static because I'm I will spit up a bit I just wanted to show you how this turns out Indian this is the email service that I need to instantiate there although I don't need actually to establish it I can inject it it doesn't matter D at this point and I will send this email using if I want to send the order received I will just say client code will receive the email and feel ship you see the point here I dunno I didn't use explained anymore I've just passed the missing the missing functionality as a parameter to the other one okay so the the predicate where did we put them we put them in methods in this we put them in Gators in the entities we even worked with local variables and eventually we even push them to static methods that create predators just the takeaways learn this entire stream API you just heard before if you don't know a thing it will never appear simple to you make sure you know the Java eat the stream API but use it progressively don't use all the features from day one because all the other developers will be puzzled will be will be what the heck never use multi-line lambdas whenever you have a multi-line lambda the creative method in the same class and reference that method is using four dots for example you can introduce maven build plugin that fails the build in case you detect this sequence of characters they're just an idea adopt the optional use the map change your predicates push them whenever you want and find the simplest form you are running a new language here so make sure somebody else sees that code that you just wrote and this isn't the main point to take away peer-review better programming use that other developer which is sitting in front of the blue-skinned of that I mean Facebook I mean which is just staring at its monitor make him review your code right okay I'm running out of time so thanks thanks to you all for for this this is the Bible Lily let me introduce it no it is not enough but to start with it's essential thank you in case you have any questions I think we'll handle them outside thank you so much for your time I hope you liked it [Applause] [Music]
Info
Channel: Barcelona Jug
Views: 11,640
Rating: undefined out of 5
Keywords: Java8, Lambda, Streams API, Clean Code, Functional Programming, jbcn17
Id: qcIiufH_u7c
Channel Id: undefined
Length: 51min 48sec (3108 seconds)
Published: Mon Nov 06 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.