Straight-line code over functions - FunFunFunction #3

Поділитися
Вставка
  • Опубліковано 20 сер 2024
  • 💖 Support the show by becoming a Patreon
    / funfunfunction
    The Jonathan Blow talk that inspired this video:
    • Jonathan Blow - How to...
    💛 Follow on Twitch and support by becoming a Subscriber
    We record the show live Mondays 7 AM PT
    / funfunfunction
    💛 Fun Fun Forum
    Private discussion forum with other viewers in between shows. www.funfunforu.... Available to patron members, become one at / funfunfunction
    💛 mpj on Twitter
    / mpjme
    💛 CircleCI (Show sponsor)
    Robust and sleek Docker-based Continuous Integration as a service. I used CircleCI prior to them becoming a sponsor and I love that their free tier is powerful enough for small personal projects, even if they are private. Use this link when you sign up to let them know you came from here:
    circleci.funfu...
    💛 Quokka (Show sponsor)
    Wonder how MPJ evaluates JavaScript inline his editor. Quokka is the answer - use this link when you buy to let them know you came from here:
    quokka.funfunfu...
    💛 FUN FUN FUNCTION
    Since 2015, Fun Fun Function (FFF) is one of the longest running weekly UA-cam shows on programming 🏅 thanks to its consistency and quality reaching 200,000+ developers.
    🤦‍♂️ The Failing Together concept is what makes FFF unique. Most coding content out there focus on step-by-step tutorials. We think tutorials are too far removed from what everyday development is like. Instead, FFF has created a completely new learning environment where we grow from failure, by solving problems while intensively interacting with a live audience.
    Tutorials try to solve a problem. Failing Together makes you grow as a developer and coworker.
    📹 Each show is recorded live on Twitch in a 2-hour livestream on Mondays. The host, assisted by the audience, is tasked to complete a programming challenge by an expert guest. Like in the real world, we often fail, and learn from it. This, of course, reflects what the audience identifies with, and is one of the most praised aspects of the show.
    ⏯ On Fridays, an edited version of the show is adapted for and published on UA-cam.
    Content Topics revolve around: JavaScript, Functional Programming, Software Architecture, Quality Processes, Developer Career and Health, Team Collaboration, Software Development, Project Management

КОМЕНТАРІ • 301

  • @Joenr76
    @Joenr76 8 років тому +106

    This is the first time that I'm completely not in agreement with one of your videos. The logical division between high-level code and the implementation details invariably adds to readability. Even in your example. It's easier to test, easier to reuse and easier to find you way in as a new programmer on a project.
    EDIT: of course, maybe js is a bit different in this regard, than Java or C#.

    • @funfunfunction
      @funfunfunction  8 років тому +63

      +Jeroen Rombouts I think I've been unclear in the video if that is what you've gathered. I'm not suggesting that extracting things is bad. The point I'm trying to make is that it has a understandability cost that is often glanced over, so that that you should make sure that you're adding a lot of understandability when doing extraction - otherwise you'll end up with a net negative in readability. That said, if you were always in agreement with my videos I honestly don't think I would be doing a good job with them. :)

    • @bugs181
      @bugs181 8 років тому +4

      +Jeroen Rombouts I was about to make a similar comment. I always love the idea of breaking code out into separate functions or blocks. I feel like it improves readability and also adds value - especially since you can now reuse that code later in other places if needed. Code reusability is extremely important. If that's not funfunfunctions intention, then I feel like I've missed the mark here too.
      Edit: Seeing some of your counter-arguments in replies - I have to agree with most of them. Now I'm on the fence about my coding styles! eek! Look at what you do to us - making us better developers and all. ;)

    • @getbrutal4388
      @getbrutal4388 8 років тому +1

      +Jeroen Rombouts I agree about the testability however I also find it crucial to not over use functions. A healthy balance!

    • @MrAzulay
      @MrAzulay 8 років тому +11

      @bugs181 By bringing up code reusability I think you just proved that you didn't (fully) get his point. Sure we should bring truly reusable blocks of code into functions, thats great. Just like MPJ mentioned with toLowerCase(). BUT, I don't see how a DOM-selection and some weird if-statement-stuff in a very specific context is reusable. Nor would it be easy to test this function as it depends on and event-object fired from a very complex DOM-context.

  • @KevinPeno
    @KevinPeno 8 років тому +6

    Great talk man. I'm a dev of 11 years now and I think you hit on the head in this episode what a lot of people miss about not only functional programming, but compartmentalized programming (not a real term I guess). It helps to think this way because functions that do one thing, especially if they can prevent external changes, are amazing because of their testability. Keep on keepin' on!

  • @Coeurebene1
    @Coeurebene1 8 років тому +15

    This somehow illustrates your video on how programmers evolve over time. First you write big blobs of code. Then you learn about splitting it in smaller parts, see that it's good, and do it everywhere. finally you really understand why and where it's useful, and become pragmatic and do it where it makes sense.

  • @CottonDrifting
    @CottonDrifting 8 років тому +112

    I think you're doing five separable tasks here:
    1. Get the letter of the key pressed.
    2. Check if the target's parent is the right scroll container
    3. Otherwise, get the first scroll container on the page.
    4. Extract the URI for the scroll container
    5. Dispatch the event.
    When I come across a 30 line function, I don't appreciate it. That's a lot of lines to keep track of if I'm not familiar with the code and a lot of local variables in scope and current state that I need to keep track of. A small function clearly defines everything I need to care about for the current task in the parameters.
    Plus, it's also nice to have the main function describe the logical flow of the operation one level of abstraction above the others, so I can trace which path my bug resides in and just ignore everything else. I shouldn't have to read or care about how you've implemented parsing a key press if all I'm worried about is how the URI is extracted from the scroll container.
    You're right to worry about increasing API, thats why the subfunctions should all be local in scope. This is easiest to do by puting the function in a separate file, say scrollContainer/keyPressHandler.js and only exporting the main function. Also, you should declare all of you dependencies in the main functions parameters.
    This is what the main function should look like roughly:
    export default function keyPressHandler(event, target, _document, dispatch) {
    const letter = getLetter(event);
    if(!letter) return;
    const scrollContainer = parentScrollContainer(target) || firstScrollContainer(_document);
    if(!scrollContainer) return;
    const uri = getURI(scrollContainer);
    if(!uri) return;
    dispatch.emit(.....);
    }
    This way I can get a feel for what the overall plan is pretty quickly: we're looking for a letter, scrollContainer and URI, and then we're emiting them.
    I can also see what each part depends on: the letter is taken from the event, the scrollContainer should either come from the target or from the document, and the URI comes from the scrollContainer.

    • @jfuruskog
      @jfuruskog 8 років тому +4

      Very true, I agree

    • @arturgrzesiak1130
      @arturgrzesiak1130 8 років тому +10

      +Max White Glad you wrote this as I had exactly the same feelings. I would surely prefer to work with your code than mpjme's. Moreover hardcoding (and duplicating) some magic-strings in code is imho a really bad practice -- like 99,9% they should be extracted to config/const module.

    • @nizki121
      @nizki121 8 років тому +3

      +Max White Completely agree with you. You have put my thoughts into words.

    • @tomaszkauzny6406
      @tomaszkauzny6406 8 років тому

      +Max White I was also thinking how to put my thoughts in a comment on this video. Basically it's just not a well code example and structuring it even more doesn't give any visible benefit, but in the case you refactored it completely suddenly make sense.

    • @FuryOfASquirrel
      @FuryOfASquirrel 8 років тому +6

      +Max White I'm not sure this is objectively better. I get a high-level overview of what the code does, but why do I need that? Just because I'm reading the code... like.. for fun? I don't read production code for fun. I read it because something broke and now it's my job to fix what's broke - and that (usually) implies some detail somewhere for some edge case isn't taken care of (usually, sometimes it is a high-level problem in code-structure, but usually not).
      I do think that breaking out into these functions makes it easier to run through quickly and get the gist of the intent of this code, but the problem is the focus. Are we focused on the gist of the intent of the code? Then your multi-method way is better. But what if there's a bug, and I'm interested in the details - which function has the bug? What if getURI throws an error, but it's actually because the const scrollContainer is messed up because of an unknown bug in parentScrollContainer OR firstScrollContainer - of which I'll need to look at both - and the returned container is actually wrong, but still returns a truthy value.
      Straight-line code

  • @shinkicked3686
    @shinkicked3686 5 років тому +1

    Finally someone that address this!!!.. You have no idea the kind of trouble this "separation of concerns" gets me when I am trying to read others code.. I mean divide and conquer I find it reasonable when re-usability is in place. But if I have a function that will only do stuff once then Why modularize something I will not use ever again? People often get too carried away for the sake of readability but honestly I hate jumping around code trying to see the what's and how?.. Now, others may disagree because unit test would be easier on modularize code and is true, but in case likes the one pointed in the video that function is easy to test by itself as a whole unit. I know there are many design patterns out there.. and many principles but not everything has to follow each of the principles or design patterns in order to have a nicely written code. If the code is easy to read, easy to understand and works fine at the desired speed with the desired functionality.. why change it? why refactor it? What are we trying to prove as programmers? that we know patterns and principles? In my opinion, a good programmer not only knows the principles and patterns but also know the most important thing which is when to apply them and when not to. Kudos to this guy for this eye opening video!!

  • @stelioskiayias493
    @stelioskiayias493 8 років тому +30

    Moral of the 'story'... don't refactor code into new functions if those new functions are going to be used only once. Great video as always :)

    • @housecor
      @housecor 8 років тому +12

      +Stelios Kiayias I disagree with the moral of the story. There are many reasons to create a function beyond reuse. Functions are like paragraphs in books. They give the reader a signal that the topic has changed. They reduce cognitive load by allowing reasoning in isolation. They reduce the number of variables that one has to hold in their add while trying to understand a chunk of logic. Functions aren't just to avoid copy/paste. They're a tool that helps our fellow humans. Computers can understand long functions with many variables. Humans can't.

    • @stelioskiayias493
      @stelioskiayias493 8 років тому

      For the examples that he showed, i think it made sense to simply add a comment instead of refactoring the code into a separate functions.
      But if the code was perplexed, its better to be in its own method. Its easier to debug complicated code if its split up into segments.

    • @Machuse
      @Machuse 8 років тому

      +Stelios Kiayias that is not the moral of the story at all ...

  • @AngusMcIntyre
    @AngusMcIntyre 7 років тому

    This is a big grey area in programming style that isn't often considered in enough depth. Its really great to see it talked about with some examples, and no hard-n-fast conclusion about how it must be done. Good food for thought. Thanks MPJ.

  • @sergeyzarovskiy7189
    @sergeyzarovskiy7189 8 років тому +1

    Hi, Sergey from Canada here.
    Everyday developers read lots of code (much more than they write) and during this process they try to imagine what the code is doing. The more execution scenarios they see in the code, the harder it is to keep track of what is going on. That leads to misunderstanding and therefore to hacks and buggy implementations. Conditional operators increase cyclomatic complexity - number of scenarios we need to keep track of while we're reading the code (also the same number of test cases we need to cover), so it is a matter of keeping them under control. We break down code into functions not only to make sure that we don’t repeat ourselves, but also to define a scoped scenario which we can understand more easily. If code inside function was written without side effects (does only one thing and exactly what it says it does - that is what we’re expecting from APIs which does not belong to us, right? ;)), it is enough for us take a look at function’s name to get the idea about what it is doing.

  • @christosemmelink235
    @christosemmelink235 6 років тому

    I am a self taught programmer and have always been unsure as to what is regarded as best practice and as a result I just followed other system engineering design principles I was aware of. It is really nice to hear you say explicitly the things that I have come to realize over time learning to code. For you sir I say thank you, and will gladly buy the most expensive drink in the bar if our path should cross.

  • @5imian
    @5imian 8 років тому +47

    I've really enjoyed most of your other videos thusfar, but I strongly disagree with just about every point put forth in this video.
    Breaking code out into more single-purpose functions has lower maintenance cost, not higher. Right now to understand what on keyPress does, you have to cover 32 lines of code, and many steps. Its not extensible, it is not closed for modification, and none of it is reusable. It has high cyclomatic complexity, SLOC, and is encapsulating too many ideas in a single function.
    If I want to optimize HOW I get the dom node, for instance, I have to touch all the other things that functions does. Its less maintainable, therefore. If I want to optimize what I DO after I get a node, again.. again...I'm touching the rest of the code. What if I want to reuse any of that? Would you expect a new developer to read the guts of every function to hunt for that? If you use a properly named function, that's your first line of defense in refactoring.
    Finally- onKeyPress is a bad function name. Don't name functions after where they live. What does the function DO? Does it update the page? Does it validate something? Could that be reused? For instance, if on every key press I validate some business logic, but I ALSO validate that logic when interacting with another field, or refreshing a page, I've welded the idea of validation to a particular handler. Decouple those.
    I understand you're trying to present the pros and cons of in-lining things in an even handed way, I just feel like the example you have here isn't very convincing. Our goal as developers is to reduce complexity, not increase it. I mean that in the way Rich Hickey means it: reduce the intertwining of ideas, keep things single purpose, reduce tight coupling. I think breaking this down *even further* into sub functions would yield more parts- but each part is more cohesive, and thus, reusable.
    And most importantly. How do you test "onKeyPress" ? At least with the "getSuchAndSuchNode()" I can run my function against a DOM and see if I have exactly the correct number of elements, and they have the right tag, and so forth. I can break this down into testable, verifyable parts. When onKeyPress breaks, you're going to have to start console.logging through a sea of branches. Wouldn't it be easier to handle one piece at a time? Isn't it easier to automate a testing solution for that? In my experience - it absolutely is.
    I appreciate your series, and I appreciate you putting your ideas out there. I hope you don't take my tone negatively, and you frame it as feedback. This video has issues though. Large, multistep functions are like reading a book with no table of contents. Relying on "multicursor" ways of maintaining code in a clear way, tightly couple your process to a particular editor. All your if statements with no brackets can result in bugs if you ever need to extend the internals of that conditional (see Apple SSL bug). Naming functions after where they live and not what they do make them impossible to move around. Not caching your selectors makes this run slower than necessary, and furthermore..you constantly repeat yourself. I am aware what I am saying is more "traditional" advice, but in my experience it holds up.
    Thank you again for making your videos and sharing your thought. You have a lot of ideas, and I hope you continue to be as prolific as you are.
    TL;DR I respectfully disagree with most of this, and I still clicked "like"

    • @okaybenji
      @okaybenji 8 років тому +1

      Fancy meeting you here!

    • @5imian
      @5imian 8 років тому +1

      +Benji Kay small world!

    • @okaybenji
      @okaybenji 8 років тому +1

      +Jesse Harlin Do you have any thoughts on my comment on this video?

    • @5imian
      @5imian 8 років тому +2

      +Benji Kay I think you made some valid points.
      "If the new functions were placed inside the existing function, there would be no ambiguity as to whether they were safe to remove later on";. This is completely true in my experience, and is exactly how most languages work that don't support inline functions. There is clarity of local declaration, better self-documentation, and if necessary the function is easily transportable to a higher scope if necessariy. Inline functions to me are all the cons without the pros.
      I'm sure you could have predicted that what I believe to be his argument against over-engineering isn't agreeable with me. I don't think the degree of modularity he is preaching against is over-engineering, rather I think he is making a case for what would ultimately be "under-engineered" and quite frankly, monolithic.
      Elsewhere +Max White also made some good commentary as well, about how to break apart this code into more cohesive pieces. He spells it out pretty nicely. Across the comments thread there is a plethora of information pointing out the counterpoint to this video, and all considered, they are more convincing to me - your arguments are included in that.
      Despite disagreement, I'm glad this guy put this video out, and I hope anyone who sees it will take the time to go through the comments and see what reactions folks have. Its good to be having discussions like this.

    • @okaybenji
      @okaybenji 8 років тому +1

      +Jesse Harlin Thanks for your response! You brought up another point I had considered but didn't mention before about how placing code inside a function block makes it easier to extract later on if it proves reusable. Along with that, you have the added benefit of knowing exactly where that action/train-of-thought ends. You mark that spot with just one character (a closing brace). If the code were all straight-line with comments, you'd either have ambiguity there, or you'd have to maintain comments both at the beginning and end of each section of code to eliminate the ambiguity.
      True, the video sparked some good discussion! And I'm quite enjoying the series. Love the one on composition over inheritance.

  • @maagiapall
    @maagiapall 7 років тому +12

    I disagree slightly on the point of removing the "selector" variable in favour of hard coding the selectors twice. Sure, having to look up and down again adds some mental work, but that work pales in comparison to the potential bug whereby you change the selector in one place, but forget to change it in the other. Sure, changing them at the same time is easy with search and replace - as long as you're aware of the fact that there's multiple places where the selector is.
    I think the better solution is proper variable names. If instead of "selector" you had some name that better describes what it's selecting, then the developer wouldn't *have* to scroll up to see the implementation, because they can infer from the name what's happening. Selector is way too generic for that. Call it scrollThingSelector, or something, and suddenly it reads like a book.

  • @danielvianna9126
    @danielvianna9126 8 років тому +4

    I do break stuff into little functions, even when the function is not used anywhere else but in one linear assembly line. I do that exactly just so I can compose each function gramatically as statements I can read fluently. I don't choose between self-documenting and comments, I use both. Part of making the code readable is to place the little functions in a logical order in the file, so they can be read as paragraphs in an essay.
    I get your point about not breaking apart things that cannot be seen as self-contained. Fair enough, I have my share of big functions too. But I do think this tends to be the exception rather than the rule.

  • @autochton
    @autochton 8 років тому +17

    Immediate reaction to this video: Nonononono, bad idea.
    Later, more thought out reaction having watched the whole thing: So inlining code is a good idea if you can't think of good, meaningful names for your abstractions, is that it? Maybe ask someone else what to call things?
    Seriously, 'selector'? How about 'scrollContainerSelector' instead? It's not like you don't have autocompletion, and Uglify will turn it into a single letter or two anyway. And of course, you should have meaningful semantics for the concept of a scroll container in the first place. And with that, getScrollContainer suddenly makes perfect sense as an abstraction. Or if it doesn't, maybe call it 'getParentScrollContainer' or 'getNearestScrollContainer', instead.
    Names have power. Use them wisely, and name things well. Then you can abstract and encapsulate till the cows come home, and be fine.

  • @TheArakan94
    @TheArakan94 8 років тому +1

    Awesome video!
    As for making functions, I follow this rule: If you use same code on several places, make a function.
    And that's it! Don't overuse abstraction and don't use OOP everywhere.. It's crazy what can some programmers produce.. Adding abstraction will make your code slower and often less readable. Of course, if it's bigger project, then by all means - abstraction becomes "worth it".

  • @SwirlOfColors
    @SwirlOfColors 8 років тому

    Yes, finally someone who gets it! I actually have one such function in the codebase I'm working on, and I did it after watching Jonathan Blow video too. It just works for a linear sequence of events like in this case: debugging is easier, because you do not have to jump to helpers and print variables there, also if there is a need for a change, you would would probably need to "unroll" these functions inside anyway. huge time saver in the long run.
    Edit: Oh, yeah the introduction part.
    I'm junior JavaScript programmer - I deal with Ember, it's dreadful, there are no tests, but I see you have a video on how to get started.
    I knew about functional programming already, few years ago I did the course:
    "Systematic Program Design" back then it was on Cousera, now its on edx, so I'm redoing it, because recently I felt I need to take it to the next level and learn in properly.
    So right now I'm honing my JavaScript skills, learning Racket, and in near future I will tackle F#. I would also like to fit in somewhere in between some C, as I have only some well-grounded basics (BTW rigorous input checking in C made me a better JS programmer I think).

  • @aneternall
    @aneternall 8 років тому

    I'm watching your videos to learn more about functional programming. It seems like you're demonstrating a new thought process to arrive at the same conclusion that I would come to, which is definitely intriguing and much appreciated (I'd say why create functions if they aren't being reused). The concept of "adding value" probably has even more meaning than what is conveyed in this video, in the context of finding strengths in a system that might otherwise be underutilized.

  • @SeanMatheson
    @SeanMatheson 8 років тому

    Hi, Sean from South Africa. Javascript enthusiast focusing on React/Redux and trying to introduce a more functional flavour to my code.
    Thinking about it, I have definitely used the "divide and conquer" approach purely to create distinct blocks of work, so this video will be very helpful to making me think a bit more critically about this in the future.
    In regards to keeping a straight-line code style (where appropriate); I read about an interesting approach this morning that may help those of us who feel overly encourage to try and clearly represent the blocks of work within our functions - explicit blocks.
    For example:
    function foo() {
    var bar = ...
    { // explicit block 1
    ...
    }
    { // explicit block 2
    ...
    }
    }
    You may need to be careful with the let/const scoping of ES6, but it could be something to play around with. :)
    For those interested, it's about 3/4 down this page: github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch3.md

  • @VladAlive
    @VladAlive 8 років тому +3

    As a big fan of state of art in programming, I was a but confused for a minute, why a large function could not be broken down to a couple of smaller functions for the sake of readability. Though it seems reasonable sometimes to keep the code plain and straight forward. It might be the cost of maintaining and support. Also there's a point in refactoring, when the code gets such a new level of abstraction, so it doesn't look like your favorite language anymore. And you have just created new DSL, with no documentation, so new developers have to go in depth first to figure out how it was supposed to work. Sometimes it is better to KISS.

  • @MattCowski
    @MattCowski 8 років тому +6

    Awesome, I'm glad it's not just me. Thanks for validating and providing the name ("indirection") to what I realized happens when functions are overused. I completely agree, and I would even add that functions do imply multiple use, and cause you to double think (whether you're breaking dependent code, etc) unlike comments which are harmless.

    • @Belliger1991
      @Belliger1991 5 років тому

      I agree with the issue of overusing funktions. But the harmless part of comments i disagree on.
      I learned the hard way that comments are a pure suggestion of the reasoning behind the next few lines.
      Especially when combined with overuse were people start to comment specialized subsection in (for example "claculation for component A because of xyz")
      I did run multiple tims into it while cleaningup code, were B and D also did use that (no comment change)
      And for the breaking code you do testing (unit) to exactly avoid that, sadly my boss still does not get that

  •  8 років тому

    Hi, I'm Cristian from Costa Rica, I don't miss a single video, thanks for taking time to do this series, please keep up the good work!

  • @matthew_schrepel
    @matthew_schrepel 8 років тому

    I am a fullstack javascript developer with about a year and a half of experience at this point.
    I have written a fair number of applications that contribute to one larger application which is a real time collaboration app. It is in production and it is generally holding up under the weight and it is stable.
    However, I feel as though the success of this application doesn't have a lot to do with me, my experience, or any excellence in my code. Someone built a smart framework, told me how to use it, and that in turn, prevented me from failing more than I knew how to succeed on my own.
    What I really want to learn are fundamental things that allow me to structure my code into the most easily reusable, testable, and maintainable code that it can be.
    This involves a lot of theory and questions and, in my case, trying to learn from others' mistakes before I make all of them myself.
    Such questions are: Is there an appropriate size for a module? When is it better to use functional programming over object oriented programming? When you use OOP, you can introduce race conditions, but... in what instances? How do I account for that? How can I tell if code, or online examples or whatever sucks? What are a fair number of reasonable "bad code smells"? What does it REALLY mean to write maintainable code? What are appropriate computer science things to know as a programmer without a computer science background? What is the real meat there?
    These are a few things I wonder.

  • @wayne7936
    @wayne7936 8 років тому

    i'm a 29 year old advertising analyst who has been loving my deep dive into development over the past month or so

  • @BenHofferber
    @BenHofferber 8 років тому +1

    I'm Ben. I've been enjoying the show thus far and I've enjoyed the content. I'm starting a startup working on an app that has yet to be released and I'm interested in JavaScript. I'd describe myself as an intermediate developer with a strong C background. I'm currently working on a mobile application and so I am very focused on managing memory on the application and reducing havoc in the wake of garbage collection.
    I really enjoyed a lot of the videos that you've been posting on your channel, but I felt like this video kind of skirted around the the key point I got from the Johnathan Blow video. The main point being that benefits for benefits sake have many hidden costs.
    Although I agree with you that often breaking functions up can increase the complexity of reading the code, I think that the opposite can also be true. I think deciding on what you want to do and sticking with it to make your code base as readable as possible is the best solution. "Working code is the greatest measure of progress."
    Often I find that functions are helpful for maintaining scope but I've also reverted a lot of broken up functions for performance gains due to inefficient memory usage. There isn't an easy rule to follow about whether to break something up into a function except maybe that "It depends on the circumstance." If you're working with Unit Tests as others have said in this comment section, I would definitely rather have small functions to test. But Unit Tests might not be the best fit for some applications. "It Depends"
    Side note: If the function where you in-lined the string was called N^2 times, the allocation for those strings alone could have a dramatic memory overhead. This could apply for any other objects that were created any time that function is called. In-lining may not be best for long-term performance in these situations, but in-lining could lead developers to finding this problem much faster than if those memory allocations were broken up between a large number of functions.
    A video discussing how to profile and debug JavaScript code may be a good topic to cover in these FunFunFunction videos.
    All and all, I enjoyed the video and the link. Thanks for your courage bringing up hard discussions like this one :)

    • @funfunfunction
      @funfunfunction  8 років тому

      +Ben Hofferber Hey Ben! Glad to have you on funfunfunction!
      I agree that I skirted the main issue - it was not my intention, when I looked through the script I thought I was clear and communicated that point, but there is a lot of posts here saying "I disagree strongly" and then go on writing a lot of things I agree with and that I think is in line with the video. :)

  • @madflanderz
    @madflanderz 8 років тому

    Hi, Martin from Berlin here. I'm already a big fan of your show. Big Thank You.

    • @funfunfunction
      @funfunfunction  8 років тому

      Hi Martin from Berlin! I was there just a couple of months ago, great city! Welcome to funfunfunction!

  • @stefanobettinelli5782
    @stefanobettinelli5782 6 років тому

    Hi MPJ, I'm a full stack developer with CS background, once I discovered you channel I just sorted your video from the oldest and started watching a couple of them every day, every topic that you talk about are explained very clearly and on top of that you mentioned Blow which is one of my favorite game designer/developer...so keep it up with the content

  • @wlainerribeiro1285
    @wlainerribeiro1285 8 років тому

    I"m Wlainer a Java developer from Brazil. I like to learn new technologies and break some paradigms.
    I met your videos when i was searching about javascript functional. And as you said in other video I'm trying to become a better programmer learning the fundamentals of how the things work.

  • @JoseL786
    @JoseL786 8 років тому

    I am Jose, Web developer... Really very thing involved with getting a site/app (small ones) on a server(s) . I've been doing this for about three and half years. Just got into Javascript at work using the nodejs ecosystem.
    I want to get better at Javascript design pattern, and how to better structure applications.
    Keep it up man

  • @SpaceShot
    @SpaceShot 8 років тому

    This was a great episode. Many experienced developers would fear taking this on and espousing this opinion for fear of others coming in with ironclad commandments like: "You should never use comments!!"
    You make some great points about indirection for indirection's sake versus taking the time to consider whether you are solving a generic problem (the point of a function) or describing a specific method. It's one thing to paint houses and another thing to paint MY house.
    I completely fear comments going stale to the point that I dislike comments myself, but you made a great point that often times the NAMING of things goes stale. What was once a function to get a scroll container today could in the future be a function that gets a scroll container and writes something to local storage and creates an embedded canvas element because future maintenance programmers merely found the spot where adding code worked... so they did it.
    Does this make them horrible people? No less horrible than people who would add the new parts without updating the comments.
    Very insightful and thank you for making me think about something I was getting somewhat hardline about.

  • @Jethorus
    @Jethorus 8 років тому +3

    ah thats funny I was looking for this Jonathan Blow talk over the weekend, thank you!

  • @skinneejoe
    @skinneejoe 8 років тому

    I really enjoy your videos, I'm a part time JavaScript/Node programmer and these have been helpful. I say part time because I work for a small company and I do IT Consulting as my primary job function. Because of this I'm a solo programmer (coding on an in-house app) and have not had much experience working on a team of coders. I would love to see an episode about overcoming pitfalls in team environment. Also, I would love to get your perspective on build processes.To the point of the video, I guess I've always broken my code out into smaller functions but I can see the advantage of only breaking out code that does something very specific. But I feel like with all rules there are exceptions, I think you are best served by looking at the particular case at hand and weighing the pros and cons. Blanket rules force you to do things that will turn out to hurt you later simply because you went against your better judgement and followed a rule.Great vids keep it up!

  • @Silkspar
    @Silkspar 8 років тому

    hey, really like the show, keep up the good work!
    I'm currently a front end dev but have worked in a number of different languages over the years. I am loving functional programming even if Haskel hurts my brain!
    I have run in to this issue from time to time. When I do, I do the following:
    func() {
    code
    code
    if(func1()){
    some
    more
    code
    }
    let foo = func2()
    code
    code
    //-------------------- comments about func1, func2 or ID the section e.g. support funcs
    func1() { some code; return Boolean }
    func2() { some code; return value }
    }
    This:
    1) allows the logic to be clear
    2) keeps the documentation aspect
    3) lets the dev know the func(s) are bound to this implementation / location
    4) encapsulates the functions to the parent function scope so they can't leak out and be used anywhere else in the app
    The down side includes not being able to test those scoped functions, but I can test the main function and the scoped functions should be small enough to not cause to many issues debugging if necessary.

  • @fiddur
    @fiddur 8 років тому +1

    Interresting points in this episode; I mostly hear from seasoned programmers the need to break out things to smaller functions. Arguing the cost of indirection is a good way to find out when to break out and when to keep it inline.
    To answer you final question, if I haven't already done that; I've been programming for a bit more than 30 years, am working mostly with systems architecture nowadays but enjoy writing well-formed single purpose libs and microservices when I get the time.

  • @ExpHPKun
    @ExpHPKun 7 років тому +1

    Many many times have I given myself a great big pat on the back after "refactoring" an ugly module into many small functions, only to come back months later and finding that I need to put it all back together just to verify that it is correct!
    Unfortunately, my primary tool of choice tends to be Python, which has (more or less) the ES5 "var scope" issue--perhaps even nastier as there are no explicit declarations! Big functions = longer variable lifetimes = harder to reason, so I am often still driven to break things up beyond their minimum complexity.
    My solution as of late has been to limit scopes with inner functions; I was so glad when I discovered the term "IIFE", because I finally had a name for "that weird thing I sometimes do which probably gets me weird looks from any other Python developer!"

    • @funfunfunction
      @funfunfunction  7 років тому

      +ExpHP yes! This is exactly what I do a lot. IIFEs ftw!

  • @johnshearing
    @johnshearing 5 років тому

    I agree with this video. I write rather long functions commenting every line of code with a big story about what I am doing any why I made that choice. All the comments and not having to jump around when I am trying to read my code helps me when coming back to it after several months or years.

  • @kelvinzhao4960
    @kelvinzhao4960 8 років тому

    Heyo, I'm Kelvin from Singapore. Not exactly a programmer here. I came from a design background and started picking up programming this year so I can create small side projects on my own without depending on external help. Am loving MeteorJS and thus trying to improve my JS! =) Great videos. Really enjoyed them and learnt much!

  • @mcalavera81
    @mcalavera81 8 років тому +31

    I completely disagree with the video summed up in this: "the fact this is a function doesn't really give you any kind of security; you have just essentially written a comment". Functions should be small enough to do just one thing, like UNIX shell cmds. A function gives "live documentation". Comments are hard to keep in sync with the code. Functions are testable, they lend themselves to be mocked, comments are ideas of the author at the moment of writing. Comments add dissonance to the code because they are in a different language from the original one. Comments encouraged to explain your motivations, the whys, to address something the code cannot in an orthogonal manner. Also by breaking up functions into smaller function you separate in layers the level of abstraction of your code, from a high-level narrative to the nitty-gritty details of the lower level functions. And finally, from a troubleshooting perspective you get a lot more info in a stack trace to pinpoint a bug or a source of a problem.

    • @funfunfunction
      @funfunfunction  8 років тому +3

      +Manny Calavera functions are not inherently testable, and function names are not easier to keep in sync with code than comments.

    • @funfunfunction
      @funfunfunction  8 років тому +2

      +Manny Calavera breaking things into small functions does not inherently do what you describe. Code that have the characteristics that you describe does tend to have short functions, but just breaking your code into small functions does not cause it, rather the opposite if you just do it wildly.

    • @mcalavera81
      @mcalavera81 8 років тому +2

      In fact, functions are the ONLY thing testable, especially if we are talking about pure functions.

    • @funfunfunction
      @funfunfunction  8 років тому +7

      +Manny Calavera it does absolutely NOT make it easier to pinpoint a bug if you make the stack deeper, sorry. A line number in a straight piece of code will be a lot easier.

    • @mcalavera81
      @mcalavera81 8 років тому +9

      If you take a look at the functional programming style, you will find lots of tiny pure functions composed in an high level manner describing WHAT the code is doing not HOW. Really, It's all about rising the level of abstraction. I'd rather read code like this:
      R.compose( output('#student-info'), csv, findStudent, normalize, trim));
      You can pretty much guess what that composition is doing without digging deep into the hows and even without knowing what language we are using.

  • @webkoros
    @webkoros 8 років тому

    One of the most iconoclast video on programming. Excellent point made.

  • @Danik112
    @Danik112 8 років тому

    Thanks for the video, I totally agree!
    I have one point to add though. Extracting code into functions limits the scope of the variables in the code, making it less likely you accidently mix up or reuse variables, which can happen if you have multiple counters for example (at least it has happened to me). One way to get around this problem is to open a new block for the separate parts to contain declarations local to that part (unfortunately not all languages have block scope to support this though).

  • @mr7clay
    @mr7clay 8 років тому +1

    Nesting the new functions within onKeyPress() would reduce the indirection a bit and eliminate any suspicion that the functions are used elsewhere. I do agree that breaking out into functions isn't always a winner for the reasons you gave, but another reason is that it can make the start of program flow less clear. If I open open a file and see 3 functions, where does execution begin? With 2 of the functions nested, I know execution begins in the outer scope.
    The best we can say with this advice is YMMV. I've definitely seen code that was clearer by having a full algorithm inline even though it spanned over a hundred lines.

  • @okaybenji
    @okaybenji 8 років тому +2

    Preface: I love your videos and it seems clear you know more than I about programming in general and JavaScript in particular! So I disagree here not to be disagreeable, but rather to learn: It seems to me that the problem with the refactored code isn't that functions are favored over in-line code as you say, but rather that those functions were placed incorrectly and therefore scoped incorrectly. If the new functions were placed inside the existing function, there would be no ambiguity as to whether they were safe to remove later on. Even better, the functions could call themselves and thus solve the scrolling problem. On top of being self-documenting, in almost any editor they could be collapsed if the coder wanted to think at a higher level about the problem being solved, or expanded if he/she wished to more deeply understand how it was being solved. Am I wrong in this? Thanks and keep up the good work!

    • @funfunfunction
      @funfunfunction  8 років тому +1

      +Benji Kay That would work, but I think that blocks of code would work pretty well too. The point with the video is mainly to just "exercise goddamn restraint" when it comes to function extraction. :)

  • @mikemannakee6201
    @mikemannakee6201 8 років тому

    I totally agree that too many functions that don't really need to be there results in spaghetti code, which is hard to follow.
    The point where I usually find myself inclined to break out a separate function is when I find myself writing the same code over again. "Hey, wait a minute. This looks familiar. Ah, right, I already solved this in another place. Time to separate that out into a function so I'm not repeating myself."
    To me it's a worse crime to write the same thing multiple times. Because later, when you change one copy, you'll forget to change the other and cause regressions.

  • @JeyPeyy
    @JeyPeyy 3 роки тому +1

    A problem with commenting a big block of code like this is that you don't really know when it ends. Usually, when I see a single line comment, I assume it's just referring to the next line of code, not a whole block. With functions, you know where it ends. Also, it's a bit hard to get a good overview of what the top function does because you may have to scroll a lot to see all the steps.
    A compromise to this that I use, at least in C#, are the #region and #endregion preprocessor directives. In VS Code using javascript/typescript, you can write "//#region". This way, you get all the benifits without the negatives IMO.

    • @thatoneuser8600
      @thatoneuser8600 Рік тому

      I don't think this is a problem if the company has programming styling guidelines (which they should)

  • @jlsm7746
    @jlsm7746 8 років тому

    Hi, I'm Jose Luis from Peru. I also used the metodology of Uncle Bob's ( extract until you drop). So i'm a bit confused. However it makes sense to be selective, because it made me remember a project where i had the problem of multiple indirections and it was very difficult to navigate the source code. Thanks for your videos !

  • @norcal6181
    @norcal6181 8 років тому

    I am a new programmer (2nd year CS Major). In my intro to Java class we started out doing work with straight line code. I felt like I was not getting it, to the point that I was beginning to tell myself that I wasn't cut out to be a programmer. As soon as we shifted into modularized code and OOP I got it. Coming from a noob, imo when code is modularized it is so much easier to understand... Most of the time.

    • @funfunfunction
      @funfunfunction  8 років тому

      +Philthy Phil Hey Phil! Glad to have you on funfunfunction. Yeah, I know where you are coming from. This is not a video (or my videos in general) for beginners (which tend to under-modularize) but for intermediate programmers (which tend to over-modularize, because you grow very fond of it once you learn it). I made a follow-up video about this here: ua-cam.com/video/2qYll837a_0/v-deo.html

  • @kiksonzh
    @kiksonzh 7 років тому

    Ah, the everlasting battle between "keep things close" and "keep things decoupled"...
    I think there is a point in keeping it inline, although in most cases I'd refactor out. This method is still somewhat readable and maintainable. A few comments would help, as long as maintainers are good citizens.
    I usually sacrifice the indirection cost with the cost of long-lived variables and lengthy functions.
    Whether to inline or not, I suppose depends on the imposed style guide.
    In my case it helps me to think of some reasonable yet imaginary limits like max_function_size, max_variable_lifetime, max_file_size, max_files_per_module, etc. Having those in mind, writing doc comments and making things decoupled helps out a lot after say a 6 month break from a particular piece of code.
    I'd conclude that inlining is good up to a certain limit and to get things going in an early stage. But when similar patterns start to emerge in other places or the function starts growing, it's time to break it up and make the pieces reusable.

  • @SoeaOu
    @SoeaOu 8 років тому +5

    i appreciate the high quality episode, but i would go with Robert Martin "Clean Code" on this one
    i would agree on one thing: worse then no information is disinformation
    if we name extracted functions badly, or we extract them badly (too much arguments, etc) we can accidentally add more cognitive load for the next coder compared to if we left the code as it was before

  • @robertperry8588
    @robertperry8588 8 років тому

    Unlike a lot of other viewers, I agree with Mattias because unlike those viewers, I took the time to watch Jonathon Blow's video that inspired Mattias. Just because his example, in your mind, didn't do justice to the message as a whole, doesn't mean that the message isn't valid. The message isn't "functions are bad". It's "functions are good but don't over modularize your code" + makeWordCalledOtherwise()+makeSpace()+makeWordCalledYour()+makeSpace()+makeWordCalledCode()+makeSpace()+makeWordCalledEnds()+makeSpace()+makeWordCalledUp()+makeSpace()+makeWordCalledLike()+makeSpace()+makeWordCalledThis()

  • @aidanbrumsickle
    @aidanbrumsickle 7 років тому

    Another risk of breaking out a chunk of code as a function is that you are less likely to think about the preconditions of your new function than if you had written it from scratch. So there may be several unspoken assumptions in your new function that were obvious when it was a chunk of inline code, but is less obvious when it is by itself. Then if the code around your call to your new function changes, you might invalidate those implicit assumptions.

  • @danielk8627
    @danielk8627 8 років тому

    Hi I just watched this episode and once again you mentioned some very importants points developers need to consider during code production.
    That's great.
    Using TDD I feel like in your example I would have extract those function to ensure coverage. So I see value there.
    Regards

  • @ClySuva
    @ClySuva 7 років тому

    The code you are showing is what I usually refer to as "typical front-end noodle" :D I have noticed it before that people sometimes go and try to refactor it and split it out into arbitrary functions. And I have noticed it does actually make the code less maintainable indeed. Never really thought about how to actually deal with it or whether one even should.

  • @bftjoe
    @bftjoe 7 років тому +11

    Nested functions would have made more sense.

  • @j2fed
    @j2fed 8 років тому

    Hi! I am 25, amateur developer. Started learning JS about 1.5 year ago without much experience in programming, my goal is to become a professional. I've been messing around with Backbone, Marionette, Node, MongoDB. Began learning Angular, want to check out React and trying to up my JS skills and knowledge. I would love to see something about other stuff then code that is used at every day basis when you are a professional. I mean things like GIT. Or maybe regular expressions. I love your channel, thank you!

  • @mejiamanuel57
    @mejiamanuel57 8 років тому

    Hi i'm Manuel , Web Developer from Dominican Republic, i really like your show, i like the way you explain the contents, short, directly and fun.
    I would like to hear a show about jobs in the developer's world, maybe what skills do you need to have, experience, salaries,etc... is a very open topic, but in my case this year i would like to start working in the USA or remotely, and an advice from an experience developer is very welcome.

  • @pabloorellana7631
    @pabloorellana7631 8 років тому +5

    Hi, I am a enthusiastic javascript developer...
    This is the first time I am not completely agree with your explanation. Maybe breaking a large function could be seen only as an "stylistic" change, so that new function is very specific and will be used only in a particular scenario so probably for practical reasons it seems to be easier to keeping it as it is.
    But the main arguments against this IMHO are the unit tests. A large function does a lot of things so it is hard to write good tests for that, if you break the function into smaller units you can unit test them separately and be sure that everything is working fine, otherwise you have to write a test assuming a lot of cases and conditions for a complex piece of code and when something changes and fails inside those "inner units" you'll have a hard time figuring out where the error is.
    So that's my opinion correct me if I am wrong...
    Continue making this videos, they are really fun and instructive
    Regards from Bolivia!

    • @funfunfunction
      @funfunfunction  8 років тому +3

      I state in the video that I'm not against extraction in general. If you watched my previous video on unit testing you'll see that.
      The point that I wanted to make with this video is that extracting something into a function often gives a false sense of decoupling and documentation.
      I'm not saying that breaking things out into functions is bad - I'm saying that it is a very common and widely accepted mistake to do extraction without actually considering if the benefits outweighs the costs of it. I.e. it's not bad to drive your car to work, but its bad to do it without actually considering if you can take the train or bike instead.

    • @connor43057
      @connor43057 8 років тому

      +funfunfunction Ha. What a perfect analogy. I feel like a good chunk of viewers are misinterpreting this video. P.S. I am a high school student who spends most of his time in the programming room. I hardly ever relate to your videos because I'm not in the industry yet but I always learn from them none the less. Keep up the insightful content!

    • @pabloorellana7631
      @pabloorellana7631 8 років тому

      +funfunfunction during this time I've been moved to another development team, and now I understand completely your point, in my current project I see a lot of unnecessary extraction and a lot of micro-improvements that only add noise and make the code hard to read. Thank you! you opened my eyes!

  • @khai96x
    @khai96x 8 років тому +10

    A moment of silent for who think comments are bad

    • @skattabrain
      @skattabrain 8 років тому +1

      ha-ha... I think the point with those that think comments are bad is that if your code is not simple enough to understand by looking at it, than rather than making a comment you should make it more simple. They might not really believe comments are harmful but rather think they encourage sloppiness in a way or can become a crutch.
      I think like most things in life, it's not that simple and black and white. I believe that is MPJ's main point here... we have to be careful not to be dogmatic and we need to look at the case/task/code at hand instead.
      I'm still not sure a few words before a function are ever truly a bad thing though.

    • @Joenr76
      @Joenr76 8 років тому

      +Khải Hoàng no-one is saying that. The argument being made is that comments are a failure to communicate your intent and should be only used when your intent can't be made explicit in code. other types of comments, like API documentation or why a certain approach was used are, of course, still very much used..

    • @funfunfunction
      @funfunfunction  8 років тому +7

      +Jeroen Rombouts I think you're on to something here, Jeroen.
      I think that we should give the advice of "make sure that the next programmer can understand your intent" instead of the simplification "don't use comments", because "I'm not allowed to add comments, I'll extract to a function or variable" is a common response to the advice. What I wanted to communicate in the video is also that breaking out things into a function is often the same thing as adding a comment, with a lot disadvantages coming with it. If what you actually want is to name a block of code, just add a comment, that's what it's for. Functions are not made for that.

    • @amidaobscura
      @amidaobscura 8 років тому

      +mpjme I tend to use comments or split into functions for *domain knowledge*. Because it's obvious that a function named "getScrollContainer" will "// get the scroll container".
      But, if what I am doing is something related to the business problem, like your example of "toLowerCase", a new person won't understand much of why the code was written this way until she acquires all the specific domain knowledge.

  • @evolutionxbox
    @evolutionxbox 8 років тому

    I like this show. It's definitely the best JavaScript related show I've seen in a loooong time.

  • @thestonerstrategist9648
    @thestonerstrategist9648 5 років тому +1

    I still find myself sometimes unsure of when to break stuff out into separate functions. The "Clean Code" Bible seems to suggest that you should almost always do this ("functions should only do one thing!"), and the FP paradigm (which is apparently the new Hotness) basically enforces it. But I find sometimes in my "real world" tasks that trying to force this sort of pattern results in awkwardly passing around arguments that made sense as a simple var definition at the top of the bigger function, but make little sense as arguments for the smaller functions -- except that they need access to that data and wouldn't have it otherwise.
    And then, just today, I was browsing the source code for Prettier out of curiosity, and found that there's a single function, "printPathNoParens" (in language-js/printer-estree.js) that's some _3000 lines long!_ And hell, I'm definitely not as competent as the folks who made Prettier. Do they know something I don't?
    I've kind of settled on reusability as a loose rule of thumb: if (and _when_ - not preemptively!) I need to call that piece of functionality in more than one place, then it gets a function definition. If not, it (usually) stays inline with a comment. (Tangent: comments are good, people! What the hell does "sortlistLetterJump" even mean??) Sometimes I break out single-use functionality just for the sake of abstraction and making things less cumbersome, but I think I would feel more confident as a developer if I had a consistent _rule_ about it instead of being so wishy-washy.
    Anyway, I'm glad I'm not the only one who has reservations about this "componentize literally everything" sort of pattern. I was beginning to think I was crazy! Old video I know, but thanks for this.

  • @JordanDavisaur
    @JordanDavisaur 8 років тому

    Really interesting. I've been doing a lot of this type of extraction in my code... I think it definitely feels good to do it, gives you the illusion of writing better code. This will definitely make me re-consider lots of my extractions...

  • @Sharwul
    @Sharwul 6 років тому +1

    What about using IIFEs inline?
    That would break it into chunks, without disrupting the flow/readability.
    It would make the code easier to reason about, since you know that only what the IIFEs return can be used elsewhere in the code.

  • @Iloerk
    @Iloerk 8 років тому

    I totally agree with this, when code gets broken up into functions it should mean that it has been encapsuled into a well thought out unit that is being tested and maintained.
    However, jumping back and forth should not be a problem for anyone. In most IDEs and advanced editors there are hotkeys for easily jumping back without getting confused. Like gd or gD in Vim, or Ctrl+Shift+I in IntelliJ

    • @funfunfunction
      @funfunfunction  8 років тому +1

      +Iloerk of course it's a problem. It might not be a big problem if you use an IDE (even though that's a bit like saying that a high crime neighborhood is not a problem, just get a dog) but it's still a problem that doesn't have to be there in the first place.

  • @raimeyuu
    @raimeyuu 8 років тому +1

    Hi, Damian from Poland here ;-)
    Great video, interesting suggestions.
    I will add another perspective on breaking code into separate functions. When travelling around the code base inside the project, sometimes I like to ask myself how much details I would like to show. I can feel the pain of fellow developers who see entire guts of a method and just feel overwhelmed. By the time of getting the general purpose of piece of code, they can mildly 'enter the dragon's den'.
    What's more, even visually (or cognitively) it may feel that there's less stuff to be understood. We can feel as a brave hero who starts his great journey, until entering the dragon's den... ;-)
    Do you plan to present more about functional programming in next videos? It'll be great :-)

    • @funfunfunction
      @funfunfunction  8 років тому

      +raimeyuu Dzień dobry, Damian from poland!
      I really like that perspective - putting yourself into the mind of the other developer. What I'm trying to get at is that there is a tradeoff. If the problem that you're extracting is genuinely different from the main issue, and it makes sense to think of separately, then extraction might be a good idea. But very often, extraction is done just as a way of adding a comment to a block of code without actually adding a comment, which is sort of like pulling out paragraphs from a book and putting them as footnotes instead - it doesn't help the reader, it just forces them to have to jump around.
      Welcome to funfunfunction!

    • @jaimedelpal
      @jaimedelpal 8 років тому +1

      +mpjme I think the "extract a paragraph into a footnote" metaphor is right on, and that's exactly what you should be doing. If the paragraph does not add to the understanding of the plot/story and just expreses some details, then it may be better off in a footnote... that way you don't pollute your main story line with details that are not relevant at that level of abstraction.
      That being said, I totally agree with your last statement that you should not pursue indirection for the sake of it. Indirection comes with a cost that has to be offset by the benefit of it.

  •  8 років тому

    I tend to err on the side of extracting code chunks into their own functions. Whether it helps or hinder other developers’ understanding of the code can be argued one way or another, but I don't think there is a correct answer to that question. Some developers will appreciate the abreaction, others will not. What I do know for sure is that I've found it help me understand it months down the road, and that's a benefit I can't ignore. I do think it's a good idea to be more selective with this practice, though. There is such a thing as too much abstraction.
    I avoid the last problem you pointed out by defining the extracted functionality within the keyPress function’s scope. In fact, most event handling functions I write end up as a few lines that clearly indicate the steps being taken (by virtue of function names) followed by several functions defined within the scope of the event handler function. That way, it is clear that none of those child functions could possibly be used elsewhere in the project because they are only available to that event handler.

  • @Adam.Garrett-Harris
    @Adam.Garrett-Harris 8 років тому

    Hi, I'm Adam. I'm a front-end developer. I mostly wok with d3.js creating interactive data visualizations for the web. I'm really interested in learning functional programming and test driven development with JavaScript.

  • @Ultriix
    @Ultriix 8 років тому +1

    Hi there! Im a junior web dev, loving your content so far, really helpful to get a experienced point of view. JS is my favourite language for both back and front end, trying to move away from using php+js etc, I've switched from Angular 1.x to React recently (maybe at least until 2.0 matures) and as its only a view layer for 'components' im looking to improve my javascript writing that'll help both backend and frontend code for me. Im trying to maintain a TDD tho im not in the habit yet as my last job didn't test (or even use VCS, just ftp) but althought it takes me longer to code I find it sets clear documented goals for me and prevents breakage later when im refactoring so I'd like to improve that also which I know is a huge topic.

    • @Ultriix
      @Ultriix 8 років тому +1

      I also need to learn to talk less :)

  • @jonhuh3519
    @jonhuh3519 8 років тому

    I think the best measure is to both comment and factor out, but if I had to choose one, I would agree with you.

  • @ajbertra91
    @ajbertra91 8 років тому

    I love your show. I find it very useful (coming from a Graphic Design background and now working as a front end developer) ... I would love to see more on HOW to approach thinking in FRP style compared to OOP style thinking. Like actually making the comparison. I've watched your functional programming videos. Angular 1.x is my dev context. The future is obviously FRP. (The mental process required is still eluding me.) maybe that's too general for a single video.

    • @funfunfunction
      @funfunfunction  8 років тому

      +Adam Bertrand Yeah, it's a bit tricky. FRP is highly requested, but it doesn't even have a clear definition yet. I'll keep thinking about it.

  • @joemiller3937
    @joemiller3937 8 років тому +1

    I'm trying to be a js maestro and it's slow going. Currently I freelance. Your videos are top notch.

  • @mybigbeak
    @mybigbeak 7 років тому +29

    For me it's simple. Can I use this anywhere else? Yes=> function. No=> inline

    • @vibhorejain
      @vibhorejain 7 років тому +5

      How do you make sure that the function you've left inline would not be required at some place else in future?

    • @5imian
      @5imian 7 років тому

      In my experience folks usually do not go back and extract inline functions, especially if they have no name. Its less likely to get refactored than inline CSS

  • @mrNormatron
    @mrNormatron 8 років тому

    Hi, my experience in a nutshell, is that I graduated University with a CompSci degree in 2014 and have been doing front end development for the last 2 years. I just wanted to say that I appreciate your opinion, I liked your explanation about indirection (helpful!) but overall I don't think that I could agree. Other opinions such as Martin Folwer's "extract method" from hi Refactoring book and Uncle Bob's Clean Code seem more readable, self documenting, and maintainable. Thanks, I will definitely watch more of your videos!

  • @dklmph
    @dklmph 8 років тому

    This is a very subtle problem indeed, and it takes some time to realize that the maintenance cost of doing that outweighs the benefit of the seemingly cleaner code. I doubt anyone will reuse the getScrollContainer function as it's too logically tied with the rest of the code and it definitely will force future developers to have to read its contents whenever they want to change something in the onKeyPress handler. I admit I've been doing pointless block extraction exactly like that, but after watching the video, I'm going to second guess it from now on. Thanks, mpjme!

  • @BLOOMS
    @BLOOMS 8 років тому +5

    1. Can't Unit Test
    Imagine that OnKeyPress wasn't working, and you were trying to figure out why. Is it from the way we get the 'scroll container'? or is it how we dispatch the event? Since we left it all in a single function, there is no way to unit test these behaviors individually.
    2. Results in code bloat and hidden duplication
    Next imagine that another developer comes along and implements something very similar. Maybe it doesn't happen on a key press like yours, and maybe they called theirs an 'embedded box', but by and large, it is the same behavior/logic. Detecting this similarity becomes much more difficult when we don't have the higher abstraction functions available to compare. All of a sudden, your presumably "un-reusable code" missed its opportunity to be re-used, and you have nearly twice as much code as you needed. Or worse, someone will come along, see the giant function, and think "I basically want to do that, but with one minor tweak." They copy and paste the code, make a small adjustment, and you've missed the opportunity, to add a configuration flag to a function, and re-use code.
    3. Harder to maintain growth
    You should always assume code is re-usable.
    Do you think you'll have only 1 scroll container in your whole web app throughout the duration of your project?
    Even if it seems like it, you'll be surprised what happens as software grows, and more complexity is needed. You can't predict the future. Just wait until 'getScrollBar' requires one additional check, and 'sortListLetterJump' needs an extra config option. Complexity rises quick, and you'll drown in it if you don't these steps already separated.
    4. Indirection is worth the abstraction
    In your example, making the sub functions was the right thing to do. Detrimental indirection would be something like:
    a scrollContainerGetterFactory giving back a scrollContainerGeter which calls 'getScrollContainer' which calls 'getContainer' passing a scroll-able attribute, etc etc.
    What you've done is nowhere close to bad indirection.
    5. Creating functions does more than move code somewhere else
    Functions help express the pipeline of inputs -> outputs.
    What exactly is needed to get a scroll bar?
    With the functions I would be able to tell from the parameters.
    Does getting a scroll bar change anything else?
    Again, assuming your functions doesn't have side effects(that's a whole different story) we would be able to tell from the parameters, and the return values. It wasn't very obvious that 'sortListLetterJump' needed to use the scrollContainer and a letter until you expressed it as a function.
    Thanks for these videos. They are wonderfully produced and you always cover prevalent and important topics.
    You have a great way of teaching, and I've learned a lot over the past months while being subscribed.

  • @yuchunc
    @yuchunc 8 років тому

    Great episode! I was just about to broke a function into many smaller parts.
    This video caught me just in time.

  • @anthonypipkin
    @anthonypipkin 8 років тому

    I think this is a very good point. If you are making a function for the sake of adding value make sure you are actually adding value. This is a great measure for understanding your code and making decisions for modifying the code. Your example is a superb use case too. With this, it would make sense to not abstract out a function until it is needed elsewhere.
    One problem I've seen with this in large codebases is a duplication of utility scripts because one team doesn't know that another team has created something very similar inline of another function (or event). How do you go about mitigating this duplication of logic across teams or sections with a project written by multiple people?

  • @dzikens
    @dzikens 8 років тому +4

    Hey Mattias, firstly, thanks for the episode, I watched all of your previous ones, great job!
    I think that the point of your episode was to have a balanced approach to writing code, but you focused a lot on saying that decoupling code into functions is not good. I am afraid that some of the more inexperienced programmers may think of it as a green light to create multiline unreadable mastodon functions (please don't).
    Also, in a general sense, while for JS creating many small functions is not a great idea indeed, if we take for example Java, it is better to decouple too much, than to have methods that are too big. Deleting code is not a problem as well, since IDE will instantly point out which methods are no longer used

  • @stephenkamenar
    @stephenkamenar 8 років тому +14

    There's a bunch of dislikes, but there shouldn't be! So I'll help clarify.
    This video is about adhoc code. The idea is that you shouldn't modularize adhoc code! It's nice to keep it together as 1 encapsulated mess! This lets you know its adhoc. If you broke it into functions, then you're not sure who else uses those functions. Is this the only place it's used? If I make changes will I add bugs elsewhere? I don't think I'm using this code anymore, but is it safe to delete?

    • @AYust22
      @AYust22 8 років тому

      Exactly what I was thinking while watching the video, I was looking forward to hearing him say that as well, believe that would surly clarify people confusion

    • @incarnateTheGreat
      @incarnateTheGreat 7 років тому

      I like the way you explained this. Good points.

    • @Blast-Forward
      @Blast-Forward 5 років тому

      Visual Code: Shift + F12?

  • @modernclics
    @modernclics 8 років тому

    This is great, how many times we've seen functions that are only used by another function? The indirection problem could get worse if that function is moved to another file.

  • @sawomirbudzynski8914
    @sawomirbudzynski8914 4 роки тому

    Fast comment, but subject is very enjoying🙂 I think that it is different situation when you magnify inputs and outputs of this new function then you can reason about it independently and after one checking you can have some sort of trust to it when it is simple and clear. And the good function name is really important. I like your videos, good start of discussion, but example could be transformed in better way I think🙂

  • @housecor
    @housecor 8 років тому +4

    Hi Mattias - I've thoroughly enjoyed an appreciated all your videos (and posts on Quora) until this one. While this is very well presented (as usual!), I disagree with your conclusion. I believe developers should think of themselves as authors. Small functions serve the same purpose as paragraphs in a book. They signal that we've moved on to a new thought. They provide the reader something to think about in isolation.
    Since we write code for humans, small, singe responsibility functions allow the reader to speed read through our code. The reader can collapse to function definitions and quickly get to the desired function by merely scanning function names. The signal to noise ratio is higher when a single function can be read and thought about in isolation. It's the foundation of functional programming: Given this input, I always get this output. General functions with comments run directly opposed to this goal. Small functions also honor the rule of seven: Humans can only hold about 7 items in memory at once. I regularly find it difficult to follow long, inline functions. But I never say "I wish these separate, well-named, single purpose functions were all placed together in a single function with a bunch of comments."
    I spend a great deal of time in my Pluralsight course on Clean Code conveying these thoughts. Robert C. Martin's "Clean Code" preaches the same.
    All that said, keep up the great work! I thoroughly enjoy your style, despite my disagreement on this lone vid. :)

    • @funfunfunction
      @funfunfunction  8 років тому

      I agree with all that but that is not what I argue against in the video.

  • @alexgarces1400
    @alexgarces1400 6 років тому

    Thanks MPJ, now I feel really bad about my last refactoring 😂

  • @nutbunny10
    @nutbunny10 7 років тому

    Your shirt is the first time I've learned Swedish.

  • @ilanlevy78
    @ilanlevy78 7 років тому

    I agree that there is NO need in doing abstractions if they are not reusable. Also they don't need to be separately unit tested. Only the business should be tested and not HOW the unit does the job, this way it will not break when changing the implementation.

  • @Charlostacos
    @Charlostacos 8 років тому +2

    (hey I'm Charles from Canada, front end bla bla)
    I like this observation. I came here to write a retort but somehow can't articulate one that can convince me. So I'll have to think about that a little more.

    • @funfunfunction
      @funfunfunction  8 років тому +2

      +Charles-P. Clermont Hey Charles, very nice to have you on the show!
      Please do write a retort when you feel ready, I love to discuss this stuff. To a large degree I think this is a matter of style and opinion, we don't need to agree. Rather, the core *fact* that I want to expose and that I actually want us to agree on is that us programmers are humans and susceptible to cognitive biases just as everyone else, and that's an underlying theme in a lot of the videos. I feel like we as intellectuals would like to think that we aren't controlled by emotions. Being guided my emotions that you understand is great, but if you don't understand them, you are their slave.

  • @mindbodysouldeveloper9688
    @mindbodysouldeveloper9688 8 років тому

    Currently, I'm a C# Developer (10yrs+) trying to jump (back) into the JavaScript/HTML world.

  • @dtkedtyjrtyj
    @dtkedtyjrtyj 8 років тому +1

    TL/DR: Comments bad, variables/functions good.
    What makes comments like that bad is that they are ambigous. Ok, the following code looks for a scroll container, but where does that code end?
    With a function you still have to verify that the code does what you expect. But after you've done so, it can easily be understood/ignored as it is a single block, reducing cognitive load.
    "Blockifying" code could be done by using ironclad commenting conventions instead, but then you have to answer why you are introducing another construct for doing something that functions already do.
    Comments like that are like dead code, only lingering on because someone is afraid to remove it. Only worse, because that comment was _never_ used.
    And about inlining the string. In _that_ particular instance, I'd agree it probably is harmless; but I feel you are missing the point. Using a variable there says "these two strings are the same and it never makes sense to change one without the other". Much of that can be inferred by looking at them, but only because the strings are close to each other, unique and recognisable.
    Had the string been 'table', you'd have to lusläsa the code to figure out if they are incidentally the same or actually the same. (If they were different, I'd probably have initialised them in two different variables just to "document" that they are different.)
    Or if the string was 'cdd6c7v76d6d7c64ac577564' comparing them visually would be hard. (And if such a string was used, even once, I'd probably extract it to a variable just to give it a name.)
    Overall I felt that in _this_ particular case, not extracting those functions was reasonable. If the original function was longer, had loops or the variables didn't have block scope... it would have been different.
    I guess that is the point: in some cases you dont have to refactor.
    By the way, my first thought was to extract the event-handling functionality from the DOM handling functionality. That, I think, would have been an indisputable improvement.
    Good, thought provoking video.

  • @darkdjordje
    @darkdjordje 8 років тому

    While your points really challenge my experience and intuition, I'll try to keep an open mind. After all, it's a good idea from time to time to rethink why you are doing something the way you are, and whether you can do it better. I'll definitely be more mindful of what value I am adding when splitting up my code.
    That being said, I think you skipped or skimmed over the reason for splitting into functions that I find most valuable. The code does not become more readable simply because divide-and-conquer, but splitting it up forces you to divide it into more logical chunks with a minimal interface, since you always strive to make the function do only one thing and avoid side effects, as well as take as few arguments as possible.
    For example I know just from looking at the sortListLetterColumn interface that it takes only a letter and a scrollContainer and cares about nothing else from onKeyPress, whereas if it were a code block the only way I could get information about its dependencies is by reading the code block.
    When the code is split into functions I could also infer some more information from the call without reading its code, like I could assume getScrollContainer returns a scroll container, and that it does not modify the passed target. If I've ever read the code of that function before, I would probably never have to read it again, so there would be no indirection most of the time. I might only check whether the function may return any special value, if there is some edge case, but these should be documented in a doc comment, which my IDE should display without me having to shift my attention. This depends on how much you trust the quality of the existing code - it's perfect if there is a small tight team of people working on it and practicing mandatory code reviews.
    There is also the point of separating different levels of abstraction. I don't know about you, but when I see a function that, for example, makes a database query but also just a few lines later iterates through the characters of a string, there is a "gear shift" in my brain. Not a big one, but I feel it take a second before I switch modes of thought.
    But as I said in the beginning, I think a video like this is ultimately beneficial for making people think, so a "like" from me. Keep up the great videos!

  • @nicolasiensen
    @nicolasiensen 8 років тому +2

    Yo, I'm Nícolas from Brazil.
    I want to point another argument about why it's bad to wrap this kind of code into a function.
    Let's suppose that the onKeyPress doesn't need getScrollContainer anymore, so you are good to remove that function right? No, cause since you wrapped that into a function you no longer knows if it's being used somewhere else.
    Off course you can remove it and run the tests to check if something else have broken, but you shouldn't be worried about it because it is not a reusable function by definition.
    Thanks @mpjme for the awesome channel!

    • @gaborszekely8387
      @gaborszekely8387 5 років тому

      In that case, placing the function within the parent function makes a lot of sense, IMO.

    • @gaborszekely8387
      @gaborszekely8387 5 років тому

      Also, if you are not sure whether the code is being reused elsewhere in your code base, that likely means the code was reusable to begin with, thus validating your original decision to abstract it out into a function.

  • @gabriela.ts_
    @gabriela.ts_ 7 років тому

    I liked your pronunciation, my english listening is really bad but I had facility to understand you
    Great video :D

  • @IvanTorresJmz
    @IvanTorresJmz 8 років тому +5

    I also disagree with this video, specially when it comes to event handler functions. Even handler functions for me are always almost empty. This makes it way easier to unit test.

  • @zeekiezeke
    @zeekiezeke 6 років тому +1

    nested or private functions are the answer

  • @JonathonBroughtonUK
    @JonathonBroughtonUK 8 років тому

    If its not by unit test design ahead of time I'll break out functions as I come to them for DRY purposes only. There are only few occasions where I'll split code out even when instinctively it might seem a good idea as you mention simply as a matter of time. Testing and DRY are the only measures of time-value payoff we have. Everything else is too purist for negligible gain.

  • @mustafaradhi7527
    @mustafaradhi7527 8 років тому

    But when I need to update the old function instead of update it I can make new function has a name of the new task and has a call for the old function I want to update it in the first place and with that arrangement I reuse the old code without messing any thing. Thanks!!

  • @jfuruskog
    @jfuruskog 8 років тому +1

    Thank you for a good show.
    What about making a episode about nested if-statements and for-loops?
    Why is it bad/good? How deep should you go? What to do instead?

    • @jfuruskog
      @jfuruskog 8 років тому

      +mpjme *bump* 😀

  • @mikemo9727
    @mikemo9727 7 років тому

    Thanks, I was feeling kind of weird about separating code into functions as it seemed I was doing it whimsically no real understanding why you would.

  • @ruegen_9443
    @ruegen_9443 8 років тому

    I am Ruegen - programmer from Australia. Coding web apps in Ruby/Rails currently but have done some research in node.js & know javascript, vba, html, css, sass and other languages. Would like to know node stuff if you ever go there. Enjoying the javascript design pattern stuff. The why & how of something in javascript working, is important to me when learning.

    • @funfunfunction
      @funfunfunction  8 років тому +1

      +Ruegen Aschenbrenner Hey Ruegen from Australia, welcome to the show!

    • @ruegen_9443
      @ruegen_9443 8 років тому

      +mpjme Thank you :)

  • @casualcomputing
    @casualcomputing 8 років тому

    If it is something you do more than once, factor it out to a function. If your one functions is too long, consider doing things a bit differently.

  • @AdamHoffmanG
    @AdamHoffmanG 8 років тому

    C# developer by day, HTML5/Nodejs developer by night (as a hobby). My JS practices are sub par and i'm always looking to improve. Best practices, and old wisdom are very valuable for me.

  • @RobertFerentz
    @RobertFerentz 8 років тому

    Like the last one, great video!
    I disagree about the duplicate string (the selector in the code) but that is just a little bit of my OCD :P
    As for breaking things into functions, I tend to do that only when a function gets really long, or if a part of the code will probably be used in multiple places.

    • @funfunfunction
      @funfunfunction  8 років тому +1

      +Robert Ferentz Thank you so much!
      OCD is not a good reason for code design. I have a serious OCD too, I just started to keep it subdued the last few years. Believe me, I WANT and FEEL that I want that duplication to go away as well. Removing duplication is fun and satisfies an urge within me, that's why it's so easy to do too much of it. It's the same thing breaking things out because you "probably" will need it elsewhere. I've actually done an write-up of that specific cognitive bias: qr.ae/R44UTg
      As for long functions, my advice is a applicable there as well - the example in the Jonathan Blow talk linked in the show description is actually for a very long function.

    • @RobertFerentz
      @RobertFerentz 8 років тому

      +mpjme I said 'tend' :P I apply self-discipline whenever I can, sometimes I don't succeed. I'll make sure to watch the Jonathan Blow video soon.

  • @Marco9603
    @Marco9603 8 років тому

    Hi Mattias,
    I really enjoy your show. I would like to see a video about function application in javascript, along with the way "this" works.
    Thanks!

  • @thomashjelm2928
    @thomashjelm2928 8 років тому +1

    I really appreciate your videos. I'm Thomas. I'm a front-end developer at a medical startup in Dallas. We are transitioning to React from straight jQuery, so I am trying to get better at functional/immutable/composible.
    Also learning Swedish. Where can I get a mjölk shirt?

    • @funfunfunction
      @funfunfunction  8 років тому

      +Thomas Hjelm Hi Thomas! Welcome to the show!
      Unfortunately, it's a bootleg of one of Max Anderssons drawings (www.maxandersson.com/) - nowhere that I know of where you can buy it.

  • @lpaulger
    @lpaulger 8 років тому

    What about abstracting these private functions into libraries that could be unit tested themselves?
    I find in code I work with that the private functions are complicated and do a lot, yet because they are private, they are really hard to test, and that is why I think abstracting them would add testability/understandability.
    thoughts?