0:02 please welcome Bobby [Applause]
0:13 [Music] [Applause]
0:19 Bowman extra special effect
0:22 right good morning Amsterdam well good
0:25 morning Amsterdam are we ready LaRon
0:32 well as K already mentioned I'm Bobby
0:34 Bama it's awesome being here it's
0:35 actually my 10th time speaking at
0:38 aericon so I'm very excited about that
0:40 and uh we get some extra smoke today
0:42 it's so good you won't see me that's
0:45 better for the
0:47 talk can you see the screen now
1:03 it's all good now it's all good so I
1:05 work as a product engineer at hospitable
1:07 uh we build software for vcation rental
1:09 owners our goal is to give them as much
1:11 time back as possible and we do this by
1:13 syncing calendars between platforms like
1:15 Airbnb and booking.com we give them one
1:18 Unified Inbox we use a lot of AI um and
1:20 much more stuff so um but that's enough
1:22 about me let's talk about
1:25 pipelines so as the name suggests
1:26 something is being passed along in a
1:29 pipeline um so you put data in it it
1:31 process it and then it returns or passes
1:33 it through to the next pipe and then
1:35 eventually it returns something um and
1:37 as you already see there's some pizzas
1:38 here we're going to do a lot of pizza
1:40 slides today um there won't be any
1:44 pizzas until maybe tonight I don't know
1:46 um You probably get
1:49 hungry so if we have a pizza here every
1:50 step is independent every time we add an
1:53 ingredient it's a new Step um and every
1:56 step can focus on a specific task so it
1:57 doesn't really care about the preview
1:59 step like it doesn't really matter if
2:00 you add the vegetable first or the meat
2:02 first you can do it in different
2:04 directions and eventually we will end up
2:07 with a pizza with multiple ingredients
2:09 when we translate this into code it's
2:11 very much like adding multiple items to
2:13 an array and returning it at the
2:16 end and a pipeline can also be a
2:17 sequence of actions on a certain object
2:19 so for example if you have an order you
2:21 have a package it's going from the web
2:23 shop to the warehouse then being shipped
2:25 so we're taking actions on that specific
2:27 package uh this is similar to performing
2:31 various actions on an object
2:32 and in this case we don't really change
2:34 the state of the uh object we just pass
2:36 it along maybe we give it an update
2:38 status so we can either do both you can
2:40 change the status of this object and
2:42 pass it along and take a certain action
2:45 so the pipeline pattern is very flexible
2:48 there so typically a design pattern is
2:52 uh a common solution to a very um a
2:53 common occurring
2:56 problem so the goal of the pipeline
2:57 pattern is to make sure that each step
3:00 is independent and it focus on those
3:01 specific task and does not worry about
3:04 the other tasks and what you want to
3:05 achieve is maintainability readability and
3:06 and
3:08 flexibility so you want to maintain your
3:10 code and you want to make sure that sure
3:12 that every step is well tested and
3:14 especially when it becomes more complex
3:15 if you just have to take one or two
3:17 actions then the pipeline pattern might
3:18 not be for you but if you have five or
3:20 six actions you have to take it becomes
3:21 more complicated and that's where you
3:23 want to maybe use this pattern and you
3:26 can write tests for each individual
3:28 step and what a nice thing about it is
3:29 that you also can reuse certain steps I
3:31 will give you examples of that
3:34 later I first want to give you an a deep
3:36 dive of the basics so how the API is
3:38 defined in larell and then I will give
3:41 you specific use cases around
3:44 that so a pipeline is always separated
3:45 in three different steps so we first
3:47 start with a subject so that's what we
3:49 do when we call send we pass in an
3:51 object or a collection it can be
3:53 anything that's what we call a
3:55 subject and for every pipeline that we
3:58 edit it can be one or many um for every
4:00 pipeline we the it will go through that
4:02 subject it will perform something on the
4:04 subject and then returns
4:07 it and eventually you will have the end
4:09 result of your
4:11 object and laral supports multiple ways
4:14 of passing in a pipeline so for example
4:16 you can pass in a closure uh that's what
4:17 the documentation for example shows you
4:19 as well using that you can just pass in
4:21 a class string and L will resolve the
4:23 class from the container which is very
4:25 helpful or you can just new up your own
4:26 class pass it in as well so you can just
4:29 pass in an object basically
4:32 um and then finally you will return it
4:33 so if we look at one of these pipe
4:35 classes you can see here that we have a
4:36 basic class it doesn't extend anything
4:38 it has a handle method the first
4:40 argument is the subject that it gets and
4:42 the second argument is the closure which
4:44 is called next then we perform our
4:46 action our on our pipe or in this case
4:48 our object we do something there and
4:50 then we return next with the object
4:52 again basically we're saying here pass
4:54 it on to the next
4:57 pipe and this approach makes it really
4:59 easy to swap the order of pipes because
5:00 we're just passing to the next pipe and
5:01 we don't really care what the next pipe
5:04 is because we assume that every pipe can
5:06 handle whatever the object is and do
5:12 it so that's the basic setup here um
5:14 laral offers a simple way of changing
5:17 how this works so as we saw before here
5:18 it's using the handle method which is
5:20 the default in larl but if you use the
5:22 FIA method you can set a different
5:23 method for example if you have action
5:26 claes which have an execute method by
5:28 default then you can tell the pipeline
5:31 hey use this method instead and
5:32 otherwise it will by default search for
5:35 handle or if you use an invocable class
5:40 instead and then laral has two options
5:42 so we have a den method which will give
5:44 you a closure with the end result and
5:46 you can do something with it or you can
5:48 return the result so then return it's a
5:51 very self-explanatory method name um I I
5:53 personally like to use then return more
5:55 than then but um yeah you have two
5:58 options here so it's very
6:00 helpful and finally there's an option to
6:01 dynamically add more pipes to an
6:03 existing pipeline so you can just start
6:05 a pipeline with a few things and
6:06 depending on your code you can add more
6:08 or less so this is
6:10 configurable um and larl has this
6:12 conditional trade that you can that is
6:14 being used on almost all classes within
6:15 larl but now it's also used on the
6:17 pipeline so with the when method you can
6:18 just put in something that returns a
6:21 Boolean and then if it's true it will
6:22 apply something on the pipeline so
6:24 that's very helpful or you can also do
6:25 your own if statement and just apply it
6:28 on the pipeline it both works it's just
6:30 I guess preference of syntax in the end
6:32 so this is one way of building up a
6:34 pipeline as
6:36 well so I think we have a good
6:38 understanding of how the API looks in
6:41 larl um you can try this out on your own
6:43 um you might have already been doing
6:45 that uh but today I want to focus mostly
6:47 on use cases when can you use this
6:48 pattern and when does it really shine
6:49 when is it really
6:52 helpful and then you can play around see
6:53 it as homework you can play around with
6:57 it um during the
6:59 breaks so laral actually using this
7:01 pipeline pattern as well inside the code
7:04 base um let's have a look at this so
7:06 this is the actual kernel class um and
7:08 you can see here it's creates a new
7:09 pipeline it passes in the application so
7:11 in this case the subject is the the
7:13 whole application and it sends the
7:15 request uh sorry it's the request that's
7:17 being is the is the subject so it sends
7:20 the whole request through the pipeline
7:22 and then the pipeline the pipes that are
7:23 in there are the middlewares so each
7:25 middleware that you have to find
7:27 wherever that's coming from it's looping
7:29 over those middlewares and then passing
7:31 on next and you probably have seen it
7:33 like a lot of times right you have a
7:35 basic middleware class it has a handle
7:37 method with a request and a closure so
7:39 this is actually the pipeline pattern
7:40 it's using it the same way and that's
7:42 why you always have to return next
7:44 request to make it work otherwise the
7:46 pipeline would stop and it wouldn't know
7:52 next okay some more
7:55 examples add hospitable We sync prices
7:56 between different kind of platforms like
7:59 Airbnb and booking.com and to do that we
8:00 need to make make sure that we have the
8:03 right price in the right currency um
8:05 with the right markup and with markup I
8:07 mean um for example you want to have
8:08 your prices on Airbnb a little bit
8:10 higher than on booking.com because the
8:12 fees on Airbnb are a little bit higher
8:14 so you want to have the same revenue
8:16 from both platforms so this is where we
8:18 need to apply a lot of different things
8:19 on a
8:21 price so if we look into this as code we
8:23 just start with value object we set a
8:26 base price and then we apply a pipeline
8:28 which will then help us to change the
8:30 current price to whatever ever we need
8:32 at that point in time so in this case
8:35 for example the um we start with $100
8:37 which is the flat we turn it into an
8:39 integer because it's easier to work with
8:41 then we apply the markup and then we
8:44 convert it to a different um currency in
8:45 this case it might be that it's going
8:48 from USD to Euros so it's using the
8:49 actual current exchange rate and
8:51 translated it to there so this is where
8:53 it's really helpful to have a pipeline
8:55 because it will just apply the steps and
8:57 if we for example in the future decide
8:59 that we have another kind of Mark
9:01 applying we just add the class there and
9:02 it just works you don't have to change
9:04 any code you don't have to uh change
9:06 anything in there so that makes it really
9:08 really
9:10 powerful and if we look at one of these
9:12 pipe classes uh you can see here we have
9:14 the handle method again um in this case
9:15 we're extending a base class because we
9:18 can reuse some things from there um but
9:20 we start with the value object we have
9:21 the back there we set the current
9:23 working price in this case we're going
9:26 from floats to integers so we're setting
9:28 that value and what the nice thing is
9:30 because you now have a value object or
9:32 dto we change something in there but we
9:34 still have the original price we just
9:36 set the current working price but we
9:37 still have the initial price set in
9:39 there so the next pipe has all this
9:41 information now it doesn't have the
9:42 initial price but it also has the new
9:44 working price so it becomes more
9:46 valuable to have this object so you can
9:48 also be smart about the order of pipes
9:50 where you just initialize some data on
9:52 the object and then start applying
9:54 things so that makes it very
9:57 helpful and it's very easy to write a
9:58 test for this specific case we can just
10:01 write one test that changes the price
10:02 and we can just check against the value
10:04 object if the actual price is set or not
10:11 helpful um at hospitable we also love a
10:13 lot about AI um and we use all we use it
10:16 for all kinds of things um but I'm just
10:17 going going to talk about messaging so
10:19 whenever we have a message um we have
10:22 the whole conversation of someone and to
10:24 give a correct answer we need a lot of
10:27 extra information and to do that um we
10:28 use the pipeline pattern to determine that
10:30 that
10:32 so this is a little bit of a simplified
10:33 version of the uh code otherwise it
10:36 wouldn't fit on the screen um but here
10:37 we build up all the data for the
10:39 pipeline so we start with a back it's
10:42 just an empty back with conditions um so
10:43 you can use an empty collection or an
10:46 empty dto in this case and we can add
10:49 all these classes here so we check are
10:50 there any pets involved are there any
10:51 children involved when is the last
10:53 message coming in all that kind of
10:55 information can be very helpful for
10:57 generating a message to the host or to
10:59 the guest
11:02 um and as you can see if we just um for
11:03 example they're requesting for a parking
11:05 spot well if we if we want to add that
11:07 to one of the messages we just add one
11:09 more class and it just works the prompt
11:11 will understand it
11:12 now so if we look at one of these
11:15 classes it's a very simple class we just
11:16 check are there any number of pets and
11:18 if that's the case then we add the
11:20 condition to the back so we keep track
11:22 of a list of met
11:31 isn't it annoying that
11:34 the the lid is still stuck to the bottle jeez
11:36 jeez
11:38 man um so let's do one more one more
11:40 pipe a little bit more
11:42 complicated so you can make these
11:44 classes as complicated as you like um it
11:47 can even dispatch a job it can do an API
11:48 call it can do all of those kind of
11:50 things um so I'm not doing too
11:51 complicated things otherwise it wouldn't
11:52 fit on the screen you wouldn't be able
11:54 to read it um but you can go as far as
11:57 you want with these kind of things um so
11:58 that makes it very helpful and what I
12:00 really like about the pipeline pattern
12:01 is that you can combine it with other
12:03 patterns like for example the if you
12:04 have action classes it's very easy to
12:06 inject an action class in a pipe and
12:08 just call the action and return
12:14 there so one more thing where the
12:16 pipeline pattern really shines is if you
12:18 if you have to do a lot of operations on
12:20 a certain set of data so let's say you
12:22 have an incoming request that either
12:24 creates removes um updates different
12:27 kind of things on a model and the model
12:28 is connected to multiple other relationships
12:30 relationships
12:32 uh in that case it's very hard to do
12:33 everything in your controller because
12:35 it's just a lot of
12:38 logic and then the pipeline can help out
12:39 there because you can Define each step
12:41 in separated actions action Clauses that do
12:42 do
12:45 something so for example we have this
12:48 update commission request so as you can
12:49 imagine updating a a commission a
12:51 commission always starts at a certain
12:54 start date and might have an end date so
12:56 there might be for some cases it might
12:58 be that it needs to create certain fees
13:00 or certain uh commission rates at a
13:02 starting point but that also means that
13:04 it might delete certain things at
13:06 sometimes so for example the end or
13:09 delete fees uh class might depending on
13:11 the end date delete some stuff or just
13:14 set the end date based on
13:17 that um so we don't really want all of
13:19 this logic inside our controller and
13:20 this is where the pipeline pattern
13:21 really makes it easy because you just
13:22 have input your request Clause with all
13:25 the data that you posted um you can even
13:27 turn it into a dto if you like that and
13:28 then you can just apply all your actions
13:30 that you need need to do on the database
13:32 to do this and then if you wrap all of
13:34 this in a TR catch or transaction it's
13:44 way so collections are very easy to use
13:45 with pipelines because it's basically
13:48 just an array on steroids so you can
13:49 keep call a lot of methods on it and
13:51 just keep passing on the collection to
13:53 the next pipe so usually you can start
13:55 with an empty collection like we did
13:56 with the prompt stuff we just have an
13:57 empty collection or we can start with
14:00 initial data uh but since it's Lile we
14:01 can easily create our own custom
14:03 collections which makes it very easy to
14:05 add custom methods which makes it a lot
14:07 easier to work with in
14:08 pipelines so let's say we have this
14:10 controller that Returns the health
14:12 checks of our application um in this
14:14 case we want to have a pipeline that
14:16 sends the health checks collection
14:18 through certain pipes and then returns
14:20 and in this case we're using the config
14:22 because we want this to be dynamic
14:24 depending on the environment we want to
14:26 do certain checks so this is where you
14:27 can combine all kinds of features within
14:30 the Pipelines and then uh we have this
14:31 result which is the health checks
14:33 collection we have a method for it has
14:35 failures because it's a custom
14:36 collection we can add these custom
14:38 methods to make it easier to read the
14:42 code and to apply the code as well so
14:44 that's when we return the code um and
14:46 then you can use um this for external
14:48 monitoring tools or use it as a health
14:50 check in your kubernetes cluster
14:51 anything that works for
14:54 you so this is the config for example uh
14:56 we have the health checks list and
14:58 there's a list here of the checks that
15:00 we're doing but you can also combine
15:02 this with environment variables or if
15:04 statements if you want to so it's very
15:06 flexible to do it this
15:08 way and then finally we have the custom
15:10 collection Clause you can easily spin up
15:11 these things right you just create a new
15:12 collection Clause extend the base
15:14 collection uh which is illuminate
15:16 support collection just add your own
15:18 methods and it just works and it's very
15:22 easy to work with so um yeah use that um
15:24 lots more examples to
15:27 go so if you are reading about pipelines
15:29 or Googling about Pipelines you will
15:31 probably see one or two um tutorials
15:33 about using the query Builder as an
15:34 object because basically it's just an
15:36 object you're applying new things to it
15:38 um and usually with the pipeline pattern
15:40 you're adding extra data to it but in
15:42 this case we might be filtering down
15:44 data so that's where the query Builder
15:46 comes in U but this is very helpful if
15:47 you either have a post request or a get
15:50 request um the query Builder can help
15:52 you very easily start with something and
15:55 then build it down so how does that work
15:58 so let's say we have a payouts model and
15:59 we stuck with a query so you start with
16:02 a query Builder that's what we that's
16:03 the subject that we're going to send
16:05 through and then we have the pipelines
16:07 and those are just filter claes so they
16:10 just apply a certain condition on the
16:12 query Builder and then finally then
16:14 return so then return returns to query
16:16 Builder so the nice thing about this we
16:17 can just keep chaining on it because we
16:19 know we get a query Builder back we can
16:21 just G paginate on it and it just works
16:23 so it's very clean code so if you would
16:24 like to have like a controller that
16:27 returns a list of for a table this is a
16:28 very nice way of doing things and you
16:30 can easily extend by adding more filters or
16:39 not so if we look at one of these
16:41 classes you can see here that we use the
16:43 we method again the conditional we
16:45 method so if we have a certain condition
16:47 met in that case we are applying a
16:49 certain condition on the query and since
16:52 we return the query again it will be the
16:54 turn to the the filtered query will be
16:56 passed on to the next query Builder and
16:58 so on so you can easily build up these
17:00 kind of queries
17:02 but this m makes it very flexible
17:04 especially when the query becomes more
17:06 complicated when you have to do a lot of
17:07 joints or if you have to do do something
17:09 with relationships or if you have to
17:11 fetch some kind of data to make a wear
17:13 in this is very helpful to it this way
17:16 and it makes it very readable um like if
17:18 you go to the overview here um if you
17:20 just want to know what the how the table
17:22 is filtered you just see the classes and
17:23 they are very have a very good name so
17:25 it's very easy to understand and if you
17:27 want to know more about specific R you
17:33 there okay so I I want to talk about
17:34 reusing uh pipes because I think that's
17:37 a very nice way of reusing it because
17:39 eventually you just have an object
17:40 that's being passed through a pipeline
17:42 and you can do the same one twice if you want
17:43 want
17:45 to um I can give you the boring example
17:48 of doing like a trim on a string um but
17:50 uh within hospitable our one of our key
17:52 things that we need to take care of is
17:54 double booking protection which means
17:57 that if we are syncing the calendars for
17:59 Airbnb booking.com if a res res a comes
18:01 in at the same time we want to notify
18:03 the host because they get penalized if
18:05 they have a reservation on both uh
18:07 platforms at the same time you can only
18:09 accommodate one guest at the same time
18:11 so we need to protect against that so
18:13 for example in this case we whenever we
18:14 get a new reservation in we store the
18:16 reservation we check against double
18:18 booking protection and then we apply
18:20 certain availability rules and what this
18:22 means is that we block the calendar
18:23 around the reservation so you might have
18:25 a setting where you say I want to have
18:26 one day extra after reservation for
18:29 cleaning or in that case we apply those
18:30 availability rules to block the calendar
18:31 after a
18:33 reservation um and then it might be a
18:36 parent child setup where different um
18:37 properties are connected to each other
18:38 and then we want to do the double
18:40 booking protection again just to make
18:42 sure that we are actually
18:44 good um since we are updating the
18:46 calendar in those pipe glasses we just
18:47 want to make sure that we actually did a
18:49 good job so that's why we do it twice
18:50 but it's totally fine because we're just
18:52 passing through the reservation every
18:54 time we can apply the same checks again
19:02 I love enms who is using enms in the
19:06 codebase almost all of you nice nice um
19:08 so I think enms are a a life hack to
19:11 pipelines or to reusing pipelines so
19:13 earlier we talked about the markup rate
19:16 where we applied a bunch of
19:19 pipes so we also have the reverse right
19:22 we get the the money from or the price
19:25 of a of a room rate from Airbnb and we
19:27 want to turn it down to the markup rate
19:28 or we want to turn it to the base price
19:30 that that we show them and that we need
19:33 to sync again to booking.com for
19:35 example so to do that we need to apply
19:37 it both ways um and this is where an
19:39 enum is very helpful because we can just
19:40 start an enum and we can add a custom
19:42 method to it where we Define all the
19:45 pipes that are part of the enum so uh we
19:48 had the um class where it goes from a
19:50 float to an integer well you can apply
19:52 it on both uh pipelines in this case
19:54 because the the starting result the the
19:58 price back is everywhere the same
20:00 so in this case the enum creates a great
20:03 overview of whatever is possible within
20:04 the pipelines and you can just click
20:06 through the classes if you want to know
20:09 more so for example if we have um an
20:11 action class or a place where we handle
20:14 this um you can see here that we just
20:17 pass in the enum as the as the through
20:19 in the FR method and just call pipes on
20:21 it and it return just Returns the list
20:24 of actionable pipelines in there and
20:26 it's a very nice way of coding it's very
20:27 readable if you want to know more you
20:29 just click through um it's it's very
20:35 things so this is the final use case I
20:37 want to talk to you about uh which is
20:40 called sagas um so one downside of
20:43 pipelines is that they run after each
20:45 other and there is no way to roll them
20:47 back because they're just applying
20:49 things and then that's it uh you can
20:51 wrap them in a transaction for your
20:54 database queries uh to prevent um issues
20:56 with your database but what if your one
20:58 of your pipelines is doing an API call
21:00 to the external world how do you handle
21:02 that how do you return from that there's
21:03 no way of doing that so this is where
21:06 Saga has come into play and I don't want
21:08 to go too deep into this matter I'm
21:10 going to give you homework again um you
21:11 can just look it up yourself but I would
21:13 just want to give you a basic example of
21:16 how this works and then um you can try
21:17 it out
21:19 yourself so let's say we have a pipeline
21:22 here uh we um we work with smartlocks
21:24 for example so whenever you have a
21:26 reservation coming in we generate a code
21:28 based usually based on the phone number
21:30 of a guest so the last four digits of
21:32 their phone number that's being sent to
21:35 the API of the lock and then it will set
21:37 the lock code so whenever the guest
21:39 arrives they are able to check in with
21:41 the lock code that they
21:44 received um so depending on the state of the
21:44 the
21:48 reservation um we might create the code
21:49 or we might update the code or we might
21:51 even remove
21:53 it but this canol all kinds of
21:55 exceptions for example the code already
21:56 exists or there might be other things
21:58 happening so this is where the s comes
22:01 in so this is a very very basic
22:02 implementation of a saga so it's just a
22:06 collection of events that are happening
22:07 and we have this method called add
22:09 compensation so whenever something goes
22:12 wrong um or we expect something might go
22:14 wrong we add a compensation to it which
22:16 is eventually just a call back that
22:18 handles a certain exception as you can
22:19 see on the compensate method which which
22:22 we will call on on the catch if you
22:24 compensate it will just pass in the
22:26 exception and every uh compensation can
22:29 use its own um WI way of doing things
22:37 exception so if we for example look at
22:40 how this works in with a pipeline we
22:43 have a new value object we start the
22:44 pipeline we send it through the
22:47 pipelines and then on the catch we have
22:49 this compensate
22:51 action where we pass in the exception
22:53 and every compensate can decide on its
22:54 own exception so there might be a
22:56 specific API exception that we are
22:58 looking for to compensate on there might
23:00 be another exception we don't care about
23:01 and then we don't compensate so that's very
23:02 very
23:05 flexible one important thing here is
23:07 that the lock code also needs the Saga
23:10 inside the object so if we are if we're
23:12 going to send a value object through the
23:14 pipeline we need to have access to the
23:16 Saga to add a compensation to it so I
23:18 usually just create a new value object
23:20 at The Saga in the value object and then
23:22 pass that along so how does a pipeline
23:24 of this looks
23:27 like um so here we're doing the external
23:29 API call
23:31 um and then whenever something might go
23:33 wrong we add a compensation to it so we
23:35 cue a job that will delete the code on
23:37 the lock for
23:44 compensation so in this case when
23:46 something goes wrong we compensate we
23:48 will go back to the original state and
23:49 we can combine this with a transaction
23:57 well so the pipeline patterns are is all
23:59 coming down to making it EAS easier to
24:01 understand your code um the options are
24:03 endless um I hope you learned something
24:05 about how you can apply this to your own
24:06 code base you get some ideas from this
24:09 that's the whole goal of it um and if
24:11 you have any use cases you want to show
24:13 me today I will be walking around in the pink
24:14 pink
24:18 shirt um so finally no pizza images um
24:20 this is a stro waffle which is a Dutch
24:23 cookie um hospitable is sponsoring the a
24:25 fresh Str waffel truck this year I think
24:28 it's in your booklet as well
24:30 make sure you grab a delicious Dutch
24:32 cookie today and maybe we can eat one
24:34 together and uh come say hi to us in the
24:37 pink shirts thank [Applause]
24:52 you oh my
24:55 God I have questions you have questions
24:59 okay let's I have questions
25:03 So uran Divine is
25:07 asking can one of the steps invoke an
25:10 early return of the pipeline without
25:12 throwing an
25:15 exception I haven't tried I don't know I
25:17 I I think it will break because the
25:20 expects to return next always okay you
25:22 can just not do anything in the pipeline
25:24 just return return next in stad life
25:26 finds a way life finds a way yeah yeah
25:28 okay it might show an exception I don't
25:30 know I haven't tried I I don't write
25:32 breakable code
25:35 maybe I don't know like my AI helps me
25:36 it just doesn't write those kind of
25:39 stuff that's always the the right answer Yeah
25:41 Yeah
25:44 Siri is asking how to
25:49 prevent a Pizza Pipeline to accept
25:51 pineapple that's a good one you should
25:52 you should add a pipeline at the end
25:55 that removes any pineapple yeah I think
25:59 I think it works yeah and uh
26:02 I'm asking what's your thought about p
26:05 uh pineapple on Pizza I I don't like it
26:08 but my wife eats it so I have to accept
26:11 it that it exists either
26:14 way you're going to be tricky okay but
26:15 don't needed myself
26:18 so okay that's all a big Applause for