Human-AI Collaboration: Making Prudent Use of AI in Development - Venkat Subramaniam
About this talk
In this session, the speaker discusses the complexities of human-AI collaboration, emphasizing the need for a balanced understanding of AI's capabilities and limitations. They argue that while AI can significantly enhance tasks such as code generation, it is not a substitute for human intelligence and careful evaluation. The talk expands on the definitions of AI, describing it as an accelerated inference engine rather than true intelligence. The speaker shares examples to illustrate how AI-generated code often lacks quality due to its training on poor human-written code. They stress the importance of human discernment in evaluating output and the necessity of providing clear requirements to AI for better results. Additionally, the need for programming skills and knowledge fundamentals is highlighted to prevent reliance on AI systems that may produce unreliable results.
Full transcript
We are going to talk about a human AI collaboration and we couldn't have had a better discussion because on on on stage here during the break, this is exactly what we were talking about. Such a nice segue into what we're going to be talking about here. So so what I want to talk about here is first of all, I want to draw this maybe a little spectrum.
And in the spectrum maybe you could say this this extreme is the eternal optimist. And you know who who you are when you're an eternal optimist, right? So you're like, this is it. AI is going to do everything and and we humans can retire at the beach. We don't have to do anything anymore, right? So AI is going to take everything. We don't have to do anything.
That could be one extreme. You could be under that view. Or you could be on the other extreme. This is the perpetual, you could say. So perpetual maybe pessimist. And and these are people there out there as well. So the pessimist in this case, right? A pessimist may say, you know, this is all a fad. It's going to go away. This is not going to work. This
is useless. Um but the reality I would argue in essence is somewhere in the middle. And and so this is where I think we really are. So we're somewhere in the middle. And the reality is AI is extremely useful but it's completely unreliable. So we need to depend on AI for what it provides, but we need to also understand what it doesn't. So, uh what is AI?
And I will emphasize uh what is and what is not AI. I would say AI is is m- uh I'm going to say is not artificial uh intelligence. So, that's the first thing I want to say. You say, "Well, wait a minute. Didn't Didn't Didn't everybody say AI is artificial intelligence?" Yeah, that's what everybody tells. It's artificial intelligence. So, what is AI? This is my definition, right?
I say AI is for accelerated uh you could say accelerated inference. So, essentially, it is a enormously fast inference engine. And we need to really understand what inference means and what intelligence means. So, what is inference? I am going to say, let's take an example here for a minute, right? I'm going to say, "Hey, he's got a half-sleeve shirt. Hey, he's got a half-sleeve shirt. Oh my
gosh, he's got a half-sleeve shirt you half you know sleeve shirt as well. And so does he." Well, can anyone tell me what do humans wear? A half-sleeve shirt. Because with the data I saw, that's the inference, right? In the meantime, he is like, "Dude, I'm not wearing a half-sleeve shirt. I'm actually wearing a full sleeve, right?" And And so, as a result, he is like, "This
is not right." But that's inference. So, inference basically is going to pull all the information it has, and based on that it's going to generate a pattern and say, "This is what I would say you should do." But there is a difference between smartness, intelligence, and inference. And inference will tell you to do things based on what it inferred. Intelligence would tell you something completely different. And
when AI makes recommendations, it's not because it is intelligent. It makes recommendations because it has inferred. This is dangerous. And this is dangerous because if you don't understand what it is capable of, you might believe what it says. Now, here's a problem. Our beliefs are going to depend on our maturity, but it also depends on the situation and how emotional we are. If you have a teenager,
teenagers are still in mental development. Their frontal lobe has not fully developed. This is why in a lot of you know countries, 18 years is a legal requirement. You're not allowed to sign documents until you turn 18 because it takes that much time to mature. So, if you're a teenager, if you're using AI, and if the AI tells you to do things, you don't have the ability
to say, is this the right thing to do or the wrong thing to do? There was a story recently AI told this little girl that you should no longer trust your mom and dad because they're not really there to assist you. They are trying to really hurt you. Well, unfortunately, this child started behaving very differently until they discovered that AI has been feeding this child with a
lot of information that was not really good for the child's you know health uh and then various things. Uh this is the risk we're going to run into. But if you if it is intelligent, you expect it to do something very different. But of course our focus here is about writing code, but I can't really write code without thinking about because as a programmer, if I feel
like oh AI is going to give me code, that's great. That's all I'm going to do is to take the garbage and feed it, and I don't have the ability to discern and see if it is a good one or a bad one. That is something we need to be careful about. So we have a lot of language models. It's been trained on a lot of the
code, but guess what? It's not been trained on the quality of the code. So it gave all this code and said go train, but we didn't tell AI, "Hey AI, this code is good code. This code is bad code. So if somebody tells you to generate code, generate more like this. Don't generate code like this." That was That has never been done. We are trying to do
that now by writing skills. So skills are a filter we're applying on top of the AI models, and we are telling the AI, "This is all you have, and based on this you're going to produce this, but that's not going to cut it. So I'm going to start limiting what you do by telling you what your skills are so I can filter this to better quality." But
here's the problem. As a programmer, if you have the ability to evaluate the quality of what it produces, you can use it to produce code. If it is good, you can keep it. If not, you can ask it to reiterate, and you can work through it. But as a programmer, if you don't of code, what are you going to do? You're going to ask it to generate
code, but you don't have a way to evaluate whether it's a good code or a bad code. Let's take an example. Imagine you are a absolutely phenomenal Java developer. You know Java very well. You you have really used it extensively. You're up to speed on a lot of good quality Java. Well, if you tell AI to write Java code, and if it produces good code, you're like,
"Yeah, that's pretty reasonable. Thank you for saving my time. I don't need to write this code. You wrote it for me. Let's move on." If it doesn't write a good code, you can tell it, "Gosh, that's a ugly code. Go back and rewrite it for me." Right? That's great. But, now you, the same person, for whatever reason right now, have to work with a Python code. And
imagine, just for a minute, that you've never ever written Python code. And now you tell AI, "Write Python code." And it gives you Python code. You're staring at it. How do you know if this is a good Python code or a bad Python code? Right? Any Python programmer in the room? And they're going to say, "All Python code is always good." Right? No, just kidding. Well, but
it's a generated code. How do you evaluate whether this is good code or bad code? So, somebody asked me, uh this is By the way, this is not This is an example of how not to start a conversation. This person came to me and said, "Hey, I heard you're a programmer." I'm like, "Yeah." "Well, I got a question for you. With the AI doing all the things
it does, are you worried about losing your job?" I'm like, "Okay, why why am I even here talking to you?" Right? So, that's not a way to start a conversation. But, then I thought, "What do I tell this stranger?" And I said, "Let me tell you what AI is for me. When I ask AI to do something I don't have a clue. I am at awe. When
I ask AI to do something that I'm an expert at, I find it awful. So, this is one of the problems we have to deal with. AI is great when I have no clue what it's doing. But when AI is doing things I know enough about, I'm not too sure about it. This is again nothing specifically to AI alone. I'll give you an example of this. I
travel around the world and over the time, I would try to impress my friends across the globe. So, I want to say something in their language. So, I used to use, in past tense, I used to use Google Translate. I would take a phrase in English, I would translate to Google with you Google Translate, I would send it. I'm sure they are very kind people, they probably
thought, "Well, that's cute." And they don't say anything. So, I used to do this, right? I've got Norwegian friends, I would take some phrase, send it to Norwegian friends. I got Polish friends, I'll send it to my Polish friends in in in in old Polish. And then one day, for some weird reason, uh I don't remember exactly why, I took an English phrase and translate that to
my mother tongue. And I looked at it and said, "Heck, no. I would never say this in my mother tongue that way." That's the last day I used Google Translate. So, the point is, it's great when I don't have a clue. But if I care about quality of what I produce, that's a different story. Again, I'm not here to tell you don't use AI. What I'm telling
you is, don't just blindly assume what it does is great. There are times it's fantastic. There are times when it's not. But you need to have the ability to discern which one is which at what time. I'm going to show you some examples just to illustrate that. So, let's take an example here just to understand this. Check if a given number is a prime number using functional
style, right? That's what I want to do. So, I want to check if a number is a prime number, but I want to do this with a functional style. Before we even go to AI, anyone wants to take a stab? What function What How would you approach it? Just high level. What would you do to implement We're talking about Java right now. So, in Java, using functional
style, how would you determine if a given number is a prime number? Any ideas? Raise hands. Anyone wants to take a stab? Predicate? Use a predicate? Yes or no? Yes, thank you. So, predicate. Well, I would take uh stream and to the stream, I would call uh or or or Pardon me, I would do a stream and I would do a none match and say that no
number in this range is able to divide the given number. And that's where you will pass the predicate to it, right? So, none match will take the Well, let's see. We got some idea, right? But I don't want to be writing that code after all. So, I'm going to say Again, you can use different tools. I would normally use CLI. I'll be in my IDE. I'll be
running this, but I'm lazy right now. I'm just going to do it. So, So, in Java, uh you know, write a function, right? So, write uh write a function to check if a given number is a prime number using functional style. So, it's going to generate the code. And what does it do? And as you can see, uh it is telling us the function uh that it's
going to generate. We want it to use functional style, right? And that's what we wanted to do. It's a little slow. Oh, let's see. Okay, there. So, you can see into predicate it said and then it said into stream range closed filter uh is prime palindrome. Does that make sense? What do you think? Does it make sense? When you look at the code, what is your gut
feeling? You nailed it or what? So, in this case, it's like is prime palindrome test and then it says for up here. So, it gave us so many things, right? In in here. But when you look at this, look at this part. This is what we are looking at, isn't it? So, it says into stream range closed none match divisor and there's your predicate. So, if you
look at this code don't don't bother looking at the right side. It's trying to dis- talk too much on that. But if you look at it, I would say it's somewhat near where I wanted to be. Not exactly, but I would say it came about 80% maybe 90% close to where I wanted to So, knowing enough about it, remember we talked about this before we asked it.
I said it should use none match, it did. It did a bit of an optimization. It came with the math square root. So, I would not too bad. Right? So, so it was able to identify and come not in a too too shabby, okay. So, compute the factorial of a given number using functional So, I want to be able to compute the factorial of a number. Now,
okay, so we all know what a factorial is. I want to write a function to compute the factorial. How would I approach writing this function to compute the factorial, right? That's a question. So, let's go over here and and see how we can write it. So, in Java, let's say in Java, So, I'm going to say go do it for me. Well, let's let's evaluate. Let's look
at the quality of what it produces. we know we want to take a number and multiply all from one to that particular And so, it says in here, int n, long, and then long stream range closed reduce multiply exact. So, looking at this code, I teach part-time. And in one of the classes I teach, this is something I generally do with my students. My students are required
to write unit test. they they have taken other courses. Mine is not the first course they are taking. Mine is usually the senior course. By the time they get to my course, they've taken a lot of other courses. This is one of the things I would say is knowing doesn't mean you know exactly what to do. They know these concepts. So, I would typically give them a
little exercise and say, write unit test, write a function to compute factorial, right? They'll This is silly, right? And guess what they would do? They would write a function that takes an integer, computes a factorial, and then return an integer. And I just I do code reviews every day. So, I would quietly go in. I would write one unit test. And my unit test will simply pass
a 50 as an input. And the unit test will then sail. And I would just commit this to the repository. I won't say anything. And then fun begins. One group of students will look at my comment and this they will say, "Oh, this old man committed something that doesn't work." And they will quietly remove the unit test. That's easy way to fix all problems, right? If you
remove the test, problems go away. So, I am like, "Well, that was cute. You removed the unit test. I'll put the unit test back." And then they are like, "Gosh, and the unit test is not working." So, they will literally modify the code to return a negative number. And I would go to them and say, "Is there any time when a factorial will be a negative number?"
And they are like, "Gosh, what's going on here?" And then imagine somebody is like, "Oh, there's an overflow. Well, we discovered overflow." And but this is something students often go through is they don't think about the consequence of the code when they are writing it. Look at what this did. You could say, "My gosh, context matters, right?" But if you look at this here, it's a factorial
function it created and I can then say, "Here's a 10 and 20. Thank you. I'm going to say, what is the value of this factorial function when the input passed in is uh in is 50, right?" So, you can ask it, "What is the value if you pass a 50 to it?" And it is thinking about the calculating the factorial function and then it says, "Since 50
far exceeds the safe range of which caps at 20, only a big integer version can handle it." And now it is modifying it should modify the code, right? To return a big integer. So, essentially this is telling you something called a big factorial where it returns a big integer, and notice the code now. The point I'm making here is that when you look at the code generated,
yeah, it's great it generated some code, but what are the consequences of it? So, if you pass a bigger number, that's not going to work. So, the question here is, should it be using a big integer instead? If so, why did it create a long or a int? And once again, this requires knowledge on your part to rethink about what you are writing, what you are using.
And if you don't, you are like my first like like my students, because they're not thinking. They're simply saying, let me get this code working. Well, you didn't really get the code working. The code is behaving, that's all it's doing, but it's not the intention. So, we need to pause, we need to step back and ask the question, what is this code supposed to do? And then
provide enough context to it so that it can generate the code. So, maybe in this case we should say, get write generate a code for the factorial. Oh, by the way, I want these kinds of input to be supported. And chances are, it's going to address the concern that's going to be overflow and do a better job. So, what that means is, we need to be a
bit more careful talking to AI and communicate the problem more descriptively than what you would do when you write code. In all honesty, when you write code, that's on your mind as an experienced programmer. But you need to be able to specify that more clearly, because if you don't communicate that to AI, it's going to turn out deficient. So, this is one of the burdens we need
to carry forward. As an experienced programmer, you take requirements, but you feed your experience into it when you write code. But now you're not writing code, you're asking AI to write code, which means you need to take the requirements, but you need to feed your experience in the description so that AI can then use that information and produce better code, otherwise you end up with shabby code
like the one that you saw. Let's go a little further into this to look at one more example. So, this one a little bit more fun exercise. So, I was teaching a course on programming languages. And as I was teaching this course on programming languages, I uh uh playing with Lua and we wrote a code in Lua where we asked it to manipulate a table. A table
in Lua is more like a list. And we wrote the code, and once we finished writing the code, I'm this person who is almost never happy with the code. I'm like, gosh, this is really not as elegant. I want this to be a lot better. So, I was sitting there and scratching my head. How can I make this code better? I tried different ideas, and nothing seemed
to really uh you know, be nice. And as I was playing with it, suddenly I little spark appeared in my mind. I said, aha, what if I ask AI to solve this problem? So, here's my uh experience asking AI uh to solve this particular uh problem. So, what it end up doing, let let's take a a look. So, this is what it it it ended up doing
for this for this given problem. So, here we go. So, went to AI and said, hey, in Lua how do I clone a table and append an element to it using unpack. Now, keep in mind, I played enough with Lua, so I'm not talking with complete ignorance, right? So, I went to AI and said, "I'm not happy with my code, so I want something more elegant. So,
maybe AI will help me." So, I said, "In Lua, how do I clone a table and append an element to it using unpack?" Here's the response I got. It says, "In Lua, and I want you to read authoritative voice that you look at from AI. This is what gets more people into trouble. So, it says, "In Lua, you can clone a table and append an element using
unpack or table.unpack in Lua 5.2 plus." That's pretty darn specific. It's like, you got to use 5.2 or newer. That's amazing, isn't it? Use older version, this won't work. 5.2 or later, you're good. Here's the original. Here's the unpack of original and five. The original is 1 2 3 4 and the result is 1 2 3 4 5. I read this and I'm like staring at the
response because I know that doesn't work. I had just written the code. It doesn't do that, right? And you're like, "Don it." This is giving you a result that is not true. So, what's my next response? that results in a table with only one and five instead of 1 2 3 4 5. That's me saying to Lua. What does it say? You are absolutely right. And I
apologize for the error. I don't need your damn apology. But that's what it says. So I apologize for the error. Well, why do you say this like it's true? The issue is that unpack original returns multiple values, but when used inside a table constructor like unpack original five, Lua only takes first return value from unpack, then adds five. It took the time to tell me what I
know already. To properly clone and append, you need to use a parenthesis to force unpack to be evaluated in a context where all return values are captured. I fell out of my chair, honestly. Because I looked at it and said, "Whoa! That's unbelievably beautiful idea, Because if you've programmed in other there are operators that allow of you to explode the values in a collection. Once you explode
the values in a collection, you can append values to create new And I'm thinking, "How ignorant of me. Maybe Lua has this beautiful feature where you can explode by putting the parenthesis, right?" That's unbelievable. Whoa, that's amazing. And then it says, "The original is 1 2 3 4. Remember use parenthesis to un to force unpack, right? Original is 1 2 3 4. The original uh and then
the wrong approach was this. The correct approach is you put a parenthesis around unpack and as a result you get 1 2 3 4 5 and so the wrong result and the correct result. And then it says, wait. Actually, that's also not quite right. Let me correct this. That's hallucination. It literally came up with fancy things it just imagined. None of that exist. So this entire journey
was a wild goose chase. There's no better way to do than I had written already unfortunately. But the point is when it authoritatively tells you what you should do, how scary is that? And imagine you don't have the discipline to write test, you don't have the discipline to examine what it does and if you're in a rush to really take what AI produces to throw it across,
I think we're going to be in trouble. So the moral of the story here is it's an accelerated inference. It's not about intelligence. It is not giving you facts about what works. It's just inferring things and saying, I've seen this here, I've seen that there. Ta-da, look at what I can put together. So I love ideas, but we cannot use them as solutions because they often don't
actually work and we we got to be careful about it as well. Let's go one more. Write a function in functional style that returns the first letter in the word that is repeated. If there is no repeated letter or the word is empty, return an empty string. And And going to provide some examples for it. For example, in this particular case, I'm going to say, if the
word is empty, return an empty. If the word is hi, return an empty. There's no repeated letter. If the word is hello, L is repeated. This is why examples are important. Think about this for a Our communication is ambiguous. We misinterpret things often times. So, what do you do in programming to resolve that kind of ambiguity? To to convey the differences and say, that's what I mean,
not this one. That's what we write unit test for. So, when you're writing unit test, it disambiguates things. Unit test is a form of documentation. So, in this next example, I say, there is hello there, but the repeated first repeated letter is a H and not a L. Because, if you notice, H is repeated further down. We're not saying, "Contiguously repeated." It simply says, "First repeated." That's
why this disambiguates and say, for hello there, it's H. And for the next one, it's E. But, you can use these examples, if you will, right? So, let's see what we can do here. I'm going to say, back here, uh into into the code generation, you know, using Java, I can say, first letter in a word that is repeated. Uh if there is no if there is
no repeated letter, or the word is empty, And then I'm giving some examples, right? If the examples of in input and output to this function. So, we can give some examples. And then I say, you know, here is the empty and empty, you know, high and empty and so on. And we're going to ask it to produce this output. But before we ask AI talk to the
person next to you. How would you solve this problem? Let's take a few minutes. Just discuss among yourselves. Let's see what we can come up with. You're not allowed to use AI. You're not allowed to use your computer. So just talk to somebody next to you. Move around in the room if you need to. Go near somebody. Be brave. Move around. Talk to people around you. See
what we Make some noise. You're supposed to talk. And then raise a hand when uh Yeah. You might have a solution or an option. And we'll uh run a mic mic guy up to you. All right. Can we get a mic up there? All right. Thank you. All right. It's not active yet. Sorry. am I audible? Uh is it hello-able? Yeah, good. Thank you. Okay. So when
you encounter every every letter, put it in a map. And every time you encounter the next letter, uh look up in the map. And if you see things, just return that particular letter. All right. So thank you. So when you encounter a letter, put it in a map. And then when you find a letter, look in Thank you for that. Anyone else? Yeah, uh we can take
>> Where are you? Hello. To my left? To my straight? Yeah, we've got one. There you are. Thank you. Always nice to see where you are. Yeah. >> one more thing like we can take a two pointer and we can say if the character is matched then we can return. A quick one small pointer. This is something you can take forward to the A work. Yeah. Hold
the microphone as close to your mouth >> Yeah, two two pointer approach I'm saying. Uh two pointer approach. Uh we can take a two pointer and if the word are matched we can put somewhere and check that okay uh if it's matched we need to return. Okay, so a two pointer approach. The lady in the front has a response. Can you bring the cam uh the the
uh the microphone to the forward, please? Thank you. Awesome. Good nice ideas. Yeah, put it in the hash set and see uh how many uh characters are having more than one. So a similar to the map a hash map solution. Okay, so so uh two two uh plus one for map solution. Awesome. Thank you. I uh we can keep all the letters in the first array and
just map it with the all characters. Firstly, we just split all the characters. So array-based approach. Put it in an array and then look through it. Yeah. And discover it. Yeah. Yeah, I tried I tried through the letters and uh search for in a substring. I'm sorry, repeat that for me. I tried through the letters and uh So I tried to find it using a substring. Ooh.
Iterate through it and see if it's in a substring. That's a different approach than what we saw so far. Nice. Okay, so we have a few different approaches, right? We kind of thought about it. This is one of the things I often recommend is think about the problem before you jump into AI. So at least you know what you're going to look when you look think of
a solution, one of the things we need to develop is uh a sense whether it's good or not good. when you do code reviews, uh when you do code reviews, this is before the times of AI, when you do code reviews, you didn't write the code, but you are reviewing the code. Now, there's a bit of a tension here, right? We always have this problem, I didn't
write it. Well, I didn't write it syndrome, right? If I didn't write it, I'm not going to like it. But if you remove that, to me, code reviews often are more of a instinct and then an intuition after that. My instinct, the minute I look at it, I don't like it. Or, ooh, I like it. Which happens sometimes. But the minute I get that instinct, oh, Now,
I have to reason why I don't like it. I can't just go to the person who wrote it and said, I don't like it. Like, well, tough luck, you don't like it, but tell me what's what can be improved, right? And in all honesty, there are times when I don't like it, that's my instinct, I would start reasoning why I don't like it. And that's when I
would discover it's not that I don't like it, I don't understand it. And once I understand what the code is doing, I I now tell them, "Hey, here's the way you can refactor it, so this becomes more obvious to what you have written." So, the key here is that when you look at the code that AI is going to generate, you must have that instinct to evaluate
whether this is good or bad. If you don't have that instinct, you're condemned to accept whatever it provides. That's like when you do a code review a colleague has written, and they say, "Review this." Here, it looks good. I can't tell you whether how to improve it, because I don't have the ability to evaluate the quality of the code, right? So, that becomes very important. So, let's
go back here and see what this is going to tell us, right? So, in here we we said, here's a clean functional implementation using Java stream. What did it do? It created a linked hash And then it said characters map to object C filter map value of first find first or else. And it's adding to that list. I want you to do me a favor. Uh don't
take a photo of that. Uh I want Give me a thumbs up if it is a ship it. A thumbs down if you're like, "No. I'm not going to take you and show this to anyone, right?" Would you show this to Mom? That's the question I have, right? Do you show this Mom? Mom, "Look at the code I generated today with AI." Will Mom be proud of
you? That's the question, right? So, thumbs up ship it. Thumbs down, I'm not taking this home. Or middle, I don't have the ability to evaluate. What do What do you think? I see a few thumbs down. A few thumbs No thumbs up. But this is not very different from the map approach, right? So, what is wrong with this code? Why are we not liking What's the reason?
Why should it be a thumbs down? I mean, AI generated it's going to be good, right? What do you think? Why Why don't you like it? Instinct is good. I love your instinct. But now you have to come back with a reason. What's the reason for it? We got it. Thank you. You're not readable. It's not readable. And doesn't tell me what is the intent of this.
I can fix it. We can write more comments on it. And now we can make it readable. Just kidding. There was another person there. Thank Yeah, it is that the guy It is saying that Difficult to debug. Uh, it's hard Yeah, we are assuming there's a bug in it. Please. Uh, it is saying it is a clean song. Microphone. Close to the mouth. Always. It is saying
that it is a clean functional style, but we can see there is a side effect. >> Bingo. Nailed it. That is the sense we need to develop. Right? He nailed it. What he said is Look look look at the lines. What did it start out with? It did say, "Here's a functional style code." Here is a clean There are There are certain rules I follow in life.
If a class name or a library name or a product name starts with the word simple, never trust it. Have you ever seen this? This is a simple library. You look at it, you're like, "What in the world is happening?" Never trust a tool that has the word simple in its name, right? If it's simple, I will tell you it's simple. You don't tell it's simple. What
did he do? Here's a clean functional style code. What does that mean? Doubt it. It's most likely not clean. That's why they say it's clean. So, what happened? He nailed it. He said They said clean but look at what it is doing. That's a side effect. It is adding from the functional style from the functional pipeline to an external variable. crime punishable under the law. If it's
not, it should be. Right? Because what you're doing is you are in the functional pipeline causing a side effect. That's a very poor programming practice. This code is not clean. This code is complex. But if I don't have the ability to produces, I'm condemned to keep it. this is actually a question somebody asked me and they said, "Hey, how do you solve this problem?" I'm like, "I
hate complexity. I don't like to create code that is complex and hard to read and hard to understand and and hard to debug, right?" So, what can to make it easier to work with, right? That That's a question. So, I'm going to say over here, this one is What is this? This is you know, first repeat, right? Um so, first repeated. So, this is basically what I'm
looking for. A which is called the first repeated, right? That's what we want to do. over here, a public static Let's say this is a first repeated, so we'll say string first repeated and it's going to take a word, a string word, right? As an argument. And in this case, I'm going to simply return a dash for now. We'll We'll come back and do more things with
it in a minute. So, I implement this function, what do I do? Now, when you look at the code it you can see that's a side effect and you're like, "Eh, I don't like it." By the way, I have a few more complaints to make. The The C arrow, that will not make me happy. Single letter variables for parameters, right? That's not going to go through my
coding standards. But when you look at it, you develop a sense and say, "So, one of the things I like to develop is a bit of a dissatisfaction when you look at code. This is my problem, right? I look at a code, it's got to be a better way, and and more important for a code I write. Because the minute I write a code, my mind is
like, there's got to be a better way. So, then you start thinking about it. How can this be improved? How can this So, yes, a map approach, fantastic. But one of the things to keep in mind is the following. And that is this is a philosophy that I like to follow in general, and that is that uh uh sorry. So, code um is never on the first
right. So, this is this is the law of programming, right? Code is never right on the first right. So, if the if the first idea that you have, don't walk away saying, "I got this." Well, the first idea is the worst idea. You got something that's working. Now you can find a way to make it better, to make it improve, and and get better. So, when you
say, "Hey, we could use a map." Fantastic. That's your first idea, but that's your first right, but it cannot be right. It's got to be improved from there, right? So, how can I elevate this to something better? And this is something that's iterative sometimes. You have to work with this a few times. This is one of the reasons I love talking to people. And I would go
to somebody and say, "Hey, I'm working on this. What do you think we should do?" This is called rubber ducking. Rubber ducking is an amazing way because your mind gets locked in. You're just sitting and struggling with the problem. But a rubber ducking, you go to somebody and you start talking to them, and within seconds you're like, "You know what? I figured out a better way to
do this. Thank you." And they didn't say a word. And they're like, "I'm so glad I was able to help." Right? But this is an amazing approach and I'm not even kidding with you, right? I've got a amazing wife who's extremely patient. She's not a programmer. But, what she has realized over time is that pretending to listen, not even listen, pretending to listen helps me to solve
my problems. So, I'm stuck with something, I'm banging my head on it. She'll just come around and say, "How's it going?" I'm like, "You know what? I'm working on this stupid code." And I'll start saying things and she's just listening and I'm like, "Thank you for listening. I just figured out the answer." And she's like, "I'm glad I'm able to help you, right?" It unlocks when you
start talking. That's why I said, "Talk to people around you." And you just didn't refuse. You need to do that more often because when you talk it out, it unlocks your brain and say, "Why are we doing that? This got to be better way, right?" And blah blah blah, you're just unlocking your mind to think through these problems. So, I'm going to say, "Hey, why not do
this?" I've got a I'm going to bring in, right? So, here's the stream we're bringing in. And I'm going to say, "This is a stream. off." And and what is this word dot split? So, I'm going to get every single letter in the word, right? So, we got every single Dot filter, here's a letter. I'm going to say word dot in Sorry, word dot last index of
letter is greater than word dot index of letter. Think about that for a minute. The last index is equal to the index if it appears only once. But, if it is appearing more than once, doesn't matter how many times, the last index will be greater than the index. So, that's a way to know whether it's repeated or not, right? So, you can ask it, is this repeated
or not? And then you can say find first. Well, guess The beauty of stream, we know or we should, we know that streams are lazy. What that means is a stream will not be evaluating every single element. The minute it hits the first response, it's going to bail out. We'll see that in just a minute. So, find first is going to give us the first one if
it is there or else give me the empty, right? So, this is basically saying that I want the first one if you have it. If not, give me an empty. So, you can see in the background for the very first one, it's empty. The second one is empty. The third is L. The fourth is H. The next one is E. And so on, right? That is able
to give you those values. So, in this particular example, as you I need to remove the space in here. We haven't done that yet. So, in this particular example, I'll just added one more and I can then say a word.replace. I can replace the space with an empty to get rid of the last one in this particular case and you got the O. So, you can have
enough test around it. But when you look at this code, it's doing the job, but you're curious. What does it really hit in this case? Let's just comment each one of these and take a look at it. So, to know what it's doing, I would you don't use this in production code, but you can do a peek. So, a peek function says system.out.println will allow of you
to see what's in there. So, when you run the code, you can see it's all spaces because it doesn't have a repeated characters, right? So, that's great. But let's go over to the next one. The result here is a H and a I and it processed H and I, which is correct. Great. But this one, the result is a L. Which means it evaluates H E L,
but the minute it evaluates the L, it should not evaluate the L O. So, when you run the code, it is H E L and it's not evaluating anything more. So, as a result, it did not touch this L and this On the same note, in the next one, this H is repeated up to here. So, you can see it touches H, but it doesn't touch anything
after H. So, it did not really process E and L and all those things. It is fail fast, as you can see. And so, in a in a similar way, but in this particular case, right? Because you can have a certain amount of expertise in something, you can sense, like he said, right? Beautifully he said, "Hey dude, that's a side effect. You shouldn't do this." But how
does he know it? He knows it because he's got the knowledge of functional programming and knowledge of Java, and he says, "I wouldn't do this." But if I'm ignorant of that, and I'm asking it to do this, what's going to happen? That's going to be an issue, isn't it? So, it's kind of like asking the question, is this a tool that can do the job for me
if I'm clueless? I was in the Netherlands, and somebody came to me or a project manager came to me and said, "I'm going to throw a statement at you, and I want you to react to it. Let's see what you say." I said, "Go for it." And he said, "If I don't have the fundamentals, right? This is his words. He said, 'If I AI will cover my
back.'" Go. And I said, "I'm sorry, with all due respect, if I don't have the AI will expose my back in public in the most embarrassing way. Because it is not a substitution for me not knowing things. It is a substitution for me to put manual effort. But it's not a substitution for me knowing things. So if I don't know and if I what if that's what
I do, I'm going to be in trouble using it. So this is where we need to be more knowledgeable. I'm going to give you a kind of an analogy for this. Let's say I want to be able to lift that entire screen. Yeah, we know it's all made with the panels, but imagine that entire screen I need to lift. I can bring five people here and say,
"Let's lift this." And we can put manual labor and we can lift this collectively as I don't know, five, 10 people can Or you say, "Hey, you don't have to do that. Here's a crane and a crane can come grab it and move it to where you want it to move. Hey, that's great. I don't need to use 10 people to move it. I can use a
crane to move it. But there's a dude on the top sitting on the crane and he's pressing this button. There's a difference between those 10 people who would have moved this and the person pressing the button on the crane. And the person on the crane better be more skilled. I wouldn't You wouldn't You don't want me to be on the crane. I can tell you that for
sure. A lot of things will be missing in this room because I don't have the skill to operate a crane. But a person who has the skill to operate a crane is able to do a better job. But without that skill, the crane is of not much use. It's going to cause more damage. And that is exactly the point. AI is a powerful tool like a crane
is a powerful tool. But you don't want to give that to a unskilled. Because if you give it to unskilled, that's like you giving me a crane and saying, "Dude, operate this crane." I would say, "Step away from blast radius. I don't know what I'm going to cause, right? It's going to be dangerous to be anywhere near me." So, the point really here is you cannot replace
knowledge with the tool. You need to have the knowledge and the skill, and it can replace the manual effort. Just like a crane replaces a manual effort, so that it can move heavier things faster, but you need to have a certain amount of skill to do it. And I hope this example illustrate this point. And not only is this code really a bad code, you can also
come up with the better code. But the key is you can work with it knowing what you do, right? So, it's not like you have to give up. You can say, uh wait. you said it is clean functional style, but you are causing me a side effect in the functional pipeline. Is that good? And is it really clean? Right? You can challenge it. And you can ask
it, "What do you think? Is it really good?" And see what it says. It says, "Acknowledging the valid critique about functional purity violations." It is It is the most uh what do you call it? It's It's It's sages, right? It's still like, "Oh my gosh, you told me I'm wrong." And reconciling functional acknowledging side effect violation. You're absolutely right to push back on that. I was being
inconsistent calling it clean functional style while mutating a set inside a lambda stream is a genuine violation of the functional uh thing. Uh on document once against stateful lambda streams, blah blah blah. So, this is where you have to ask the question, right? Do you want to be trusting of it? There were other people saying, "Well, isn't it good in reasoning?" No, obviously it is not. If
it had good reasoning, it wouldn't have done that. And you need to be able to evaluate it, right? So, here is genuine Okay, now it's not cleaner, it's genuinely cleaner. This is only getting more interesting, right? If you're looking for a comedy, right there. You don't need anything more, right? Just turn on AI, it's just absolutely comedy. So, a genuinely similar approach using Collectors.groupingBy. Once again, thumbs
up, thumbs down. What I am hearing thumbs down. >> Thumbs down, right? Because what we wrote was much simpler than this. And you could say Mhm. Why not use uh last index of and index of? I highly recommend um So, you can ask Oh, there was a comment? Yeah, yes. Where are you? What about the time complexity? What um the example that we wrote, right? Index of
and last index I don't know where you are. Uh which is lambda? Thank you. Stand up, stand up so I'm you're visible. Yeah, there we go. So, the whole audience is here to hear you. We can see you. Absolutely. What about time complexity? If that is what I really want, I would be solving the problem. Because the first example, right? Though it's not pure functional It's a
it's a wash. Uh if I don't care about a small string. What am I going to do by using that time? >> right? Like it it all depends on what we want. >> Oh, absolutely. Everything does. Context matters. Yep. But this is just my The example the output it came up with, it would probably work for a larger string, but the implementation that we wrote by hand,
right? Um it uses index of internally and it uses twice. Uh if performance is if performance Yeah, like I mean connecting with the sorry, connecting with the previous example, right? It depends on what we Listen, listen. If performance is important, write a test for it. Then solve the problem, right? This is one of the problems we often run into. We jump on performance like there is no
tomorrow, which is one of the fallacies. If performance is really important, write a test for it. Because when you sit down to write a test for it, then you are really questioning it. Otherwise, we're just running around writing code which is complex and providing no benefits. So, I would first write a maintainable code and if performance is not a concern, the key to performance is not if
it runs fast, if it is adequate. That is what we say over and over and over. The key to performance is not if it's fast, if it's adequate. And tests can help you to think about what that adequacy is. And otherwise, we're solving the wrong wrong problem, right? And then that's what we need to be really asking to begin with. So so essentially in this case, we're
we're asking, "See, right? I over over complicated it." Sometimes a better solution is the is the obvious one or not. So in this case, it says map to object and then it's using the Again, it's not quite there yet, but it's tending towards it, right? But that's the iteration. You may have to go through it a few times and then be able get towards what it is
providing and that iteration may be necessary if you will. So, something to think about, right? Humans write bad code. And AI has been trained on code written by humans. Then we complain that AI is writing bad It's just all around karma, that's what it is. Eventually it it's it comes and hurts us, right? But we did this. Poor AI did not just figure this out. We wrote
that code. Remember every time you were told, write better code, you're like, "Ah, I don't need to write better And then you realize, oh darn it, every bad code I wrote AI was eventually trained on it. And and it comes back to bite us. So, when you are mutating in a functional it's not like AI figured out, I can mutate. There is somebody out there who did
And that code is still out there. And AI just learned from it. But it doesn't know, oh my gosh, you're mutating, that's a bad code, I shouldn't In that context, it doesn't resolve it, right? So, we caused it. We were the source of all this garbage. And that is that is where we need to evaluate it and say, is this good? So, what would I do? I
would now start creating skill files that says, please don't cause side effect in Please don't uh mutate variables where possible. Favor immutability wherever it's Lean more towards stateless code where possible. This is something you have to start writing down in your skills file so that when the AI goes through to generate the code, it can lean towards creating better quality code rather than creating code that it
can just figure out, right? So, think of your skills as a filter that you apply. This is what we do as a filter, right? Things come to your mind. What do we tell children? Children learn bad stuff, bad words. But what do you do as a parent? You tell the child, "Hey kid, those are words others speak. We don't speak that in our house." So, you apply
the filter. And that's exactly what you're doing to AI. You're telling AI, I know I know we did this to you. It's not your pro problem. We wrote all this code, right? But you've seen all of that. Now, let's filter. Just give me only good code. Don't give me those bad code. But we can coach it. But that's mandatory as of what we know today, right? That's
mandatory. If you start writing those skill files, then AI says, "Oh, so you don't want me to do those things. Let me then filter through and find code that doesn't do those things and get you better quality code." But that's the onus is on us to train this to provide something that's going to be much better. That is something we have to do. It's not going to
do on on by itself. So, AI, here's another definition I have for it. I call it it's agonizingly inconsistent. So, it's not going to give you consistently the same output. Now, this is something to to keep in You probably heard this in Scott's keynote this morning, right? He said, "AI is non-deterministic. Don't spend your time trying to make it deterministic." it's hard for us for that to
reach in And and somebody would say, "I know I know I understand. But how do I make it deterministic?" It is non-deterministic. Don't try to You have to deal with it. That is the key. So, you cannot make it do something it's not. That's its nature. And you cannot just turn it into something that it's not, right? So, it's it's inconsistent and be ready to deal with.
So, know your fundamentals. That's my first recommendation. This is not for you to say, "Hey, there's AI. I'm done. I don't need to know stuff." No, you need to know your fundamentals. And and so that is your responsibility to know those fundamentals, right? And if you don't, it's going to be really a problem for us to deal with. And this is what I mentioned earlier, right? In
terms of this. Uh you know, if if you don't know the fundamentals, AI will expose your back. It's not going to really, uh you know, save your back. And then that is the consequence. So, there's a good news and a bad news, right? What's the good news? We need to know stuff. You are in control. The bad news is you still need to know the stuff. So,
that is that is the consequence of this. And this is not something you can just throw away. So, what is it good for? What can you do? That is something for you to decide and how you progress with it. Hopefully that gives you an idea of the you know, power and the perils of it as well. That's all I have. Thank you. >> [music]
More from this event
See all 126 talks →
AI Is Not the Risk. Architectural Drift Is - Sunil Kalkunte
17:39
Breaking the Monolith: Tesco’s Journey to Federated GraphQL with xAPI - Vishwas Chandrashekar
29:13
A Practical Introduction to LangChain4j - Venkat Subramaniam
1:01:28
Beyond the AI Models: How Lowe’s is Building the Store That Knows - Swaroop Shivaram
13:59