justforfunc #1: A Code Review

Поделиться
HTML-код
  • Опубликовано: 12 янв 2025

Комментарии • 94

  • @Deathened
    @Deathened 7 лет назад +38

    I really liked most of what I've seen here, even learned a few things. One thing I really don't like is moving the site struct to a slice of strings. This switches out a useful abstraction and data cohesion for something that is prone to ordering errors and makes it harder to keep the structure in mind.

  • @stillcuriouslychase
    @stillcuriouslychase 8 лет назад +18

    That was a really great walk through of a code review / pull request!
    I had a few thoughts:
    - pulling all of the code back into main seems like it would make it hard to unit test
    - tests would've been super useful for the code and for me as a viewer
    - talking about the underlying mechanisms about how tests work and table testing would've removed a lot of the mystery and "ew" that it seems most people associate with testing in go.
    Thanks for all you do Francesc!

  • @LewisCowles
    @LewisCowles 7 лет назад +14

    Watching everything get moved into main bothered me. I Feel like the original would have been simpler to add some more edge case handling for, such as detecting if there is any data and raising an error.
    I did like the refactoring of the goroutines, and as someone relatively new to Go, but not programming, I see where you're coming from, I just didn't know how to fix it in go until now :blush:.

  • @jandy0077
    @jandy0077 8 лет назад +3

    Thanks for a great video, being new to go, I find these kinds of video's a great way to become a better gopher:)

  • @Marko-nx9eq
    @Marko-nx9eq 8 лет назад +3

    Just great! Fun, simple and useful. Waiting for more.

  • @JoeAmRhein
    @JoeAmRhein 8 лет назад +7

    As a newbie gopher, this is a great watch. I learned a lot. Thanks!

    • @phillewis3108
      @phillewis3108 4 года назад

      You don’t want to learn anything from this, it’s a terrible, terrible example of extremely poor coding practice.

  • @shibasispatel6624
    @shibasispatel6624 6 лет назад +1

    Awesome tutorial! I like this type of videos because it shows your thinking pattern and your workflow. Although I am a newbie in Go, I learned a lot. Thanks for making this video, Looking forward to more such videos.

  • @aimbrock
    @aimbrock 4 года назад

    It's 2020 now and if you're like me and trying to follow along watch until 2:43 and then do the following:
    git clone github.com/philipithomas/iterscraper
    git checkout 0b5202d3d79d4e3 # this will set you right at 2:43 in the video. The next git command will create a branch, and lets you save your work.
    git checkout jforf1_start_point

  • @_shawnm
    @_shawnm 7 лет назад +45

    Are you aware your playlist is in descending order?

    • @greenkodex
      @greenkodex 4 года назад +1

      This drove me f**king nuts.

    • @greenkodex
      @greenkodex 4 года назад

      Yes, but you realise that the content should be followed in numerical order. And s o should have the earlier videos on top?

    • @lanpu6396
      @lanpu6396 4 года назад +1

      ruclips.net/p/PLYM-T7FMoZiSmZZHlpAsU7KnX6SG9FaBH

  • @responsive_random
    @responsive_random 6 лет назад

    Thanks! Learned a bunch of useful tricks, especially closing the channel once you finish sending stuff to it so the consumer can use it in a for loop without leaking any goroutine.

  • @HowardCShawIII
    @HowardCShawIII 8 лет назад +34

    Overall, I could see the utility behind most of your changes... bar one. When you removed the log.Fatal on the 429 status of rate limiting, you went beyond just refactoring, and actually changed the behavior of the program in a negative way. Doing log.Fatal caused the program to *stop* when it was rate limited, which surely would be the polite thing to do - if you are querying a website and they say please stop querying us, stopping would be polite.
    Your change means that the code will *continue* to run every single query, even as each one returns the same, "Please stop hitting me" message from the server, unless there's something about it I'm missing?

    • @SlavaVishnyakov
      @SlavaVishnyakov 8 лет назад +7

      Came to the comment section to note exactly that. Upon hitting 429 the program should stop or dramatically slow down and retry later.

    • @Tresla
      @Tresla 6 лет назад +18

      But that's one of go's idioms, to return errors from functions. Calling log.Fatal() produces a side effect that, upon initial inspection of the function signature, isn't obvious to the function caller.
      I do admit, that the way he's done it here isn't the way I would have done it. Instead I would have defined an error constant type, like:
      _const ErrRateLimited = errors.new("error: rate limited")_
      _if resp.StatusCode == http.StatusTooManyRequests {_
      _return nil, ErrRateLimited_
      _}_
      Then, the caller of the function can switch on the error returned and decide what to do next:
      _results, err := fetch(...)_
      _if err == ErrRateLimited {_
      _log.Fatal(err)_
      _} else if err != nil {_
      _log.Print(err)_
      _}_

  • @nickandrievsky5705
    @nickandrievsky5705 4 года назад

    I would like to say that for a bigger real world project keeping things in separate files and respect rate limits are must, as well as many other things. For such a toy project I completely agree with all your choices.
    Thank you for a great vid.

  • @Noisecooore
    @Noisecooore 5 лет назад

    emitTasks despite being in a goroutine is still synchronous at is serially loops over the url base and adds the id, therefore it's perfectly fine to not have it in a goroutine.

  • @daveteare1960
    @daveteare1960 7 лет назад +2

    Great video! Thank you so much for posting this. ❤️
    One point of confusion for me is at the 26:52 mark you returned nil in the writeSites method. During your GopherCon16 talk you said it was a bad idea to do this. IIRC it was because it could get wrapped by a future method and any comparisons to nil would fail. Could you clear up if this is a bad practice or not?

    • @Tresla
      @Tresla 6 лет назад

      I think that in this case it's okay, because it's being returned with an error. If the function returns a non-nil error value, then the other returned value should be considered invalid and shouldn't be used further on in the code.

  • @animeshmkjee8944
    @animeshmkjee8944 3 года назад

    Sorry for using RUclips as stackoverflow, the first command go get does that work today? I am not getting the repo downloaded in my local

  • @F0Xguy
    @F0Xguy 8 лет назад

    First time I look at Go, thanks for the tour!

  • @tdenizci5756
    @tdenizci5756 4 года назад

    Please do more of this. Like when i open a project on github, i dont know from which file to start. When you check a project, to which files do you look at? Thank you for the videos, please do more projects, much love

  • @antoniotroina5909
    @antoniotroina5909 7 лет назад

    Thanks for the video, I found it really interesting and useful, and a very nice way to understand how you approach a code review ;-)

  • @m1ch0pv
    @m1ch0pv 6 лет назад

    Just started to watch these series (finally!!, bit late). Great video from a technical perspective. Just a minor suggestion: coming from being very fond of @mpjme and his “Fun Fun Function” channel myself, I believe it would be maybe good to make it sound more accessible or polite by avoiding phrases like “really simple” or “weird code”. Recognizing that what you are doing might not be that simple for everyone could help to connect better with different types of audiences, overall for developers that have recently started with Go like me (sort of). Awesome video series though, Thanks!!

    • @JustForFunc
      @JustForFunc  6 лет назад +2

      That's totally a good point! I'll try to keep it in mind in the future ❤️

    • @m1ch0pv
      @m1ch0pv 6 лет назад

      Actually you already did!, I should have seen more of the series before rushing into making those comments, I really enjoy the videos, thank you again!

  • @OktavianiHendrawan
    @OktavianiHendrawan 8 лет назад +1

    Great refactoring code, will be wait for next video.Thanks

  • @sanjeevsiva17
    @sanjeevsiva17 3 года назад

    This is amazing, hopefully someone does more of this

  • @dipenpatel5226
    @dipenpatel5226 7 лет назад +1

    Very high quality upload, thank you for posting :)

  • @sohamkamanitech
    @sohamkamanitech 7 лет назад +2

    Very informative! Just had one question: why would you move the smaller code chunks from tasking.go? Yes, there is an extra file and extra function, but doesn't that make it *more* modular and *more* readable, rather than one huge block of code in the main function block?
    It would be better IMO to at least move it into its own function if you do not want separate files.

    • @subhashishbhattacharjee4636
      @subhashishbhattacharjee4636 6 лет назад

      In my opinion, function in Go provides modularity whereas package provides isolation. Keeping the code in tasking.go doesn't seem to provide any extra isolation, rather can be kept in a separate function inside main.go.

  • @sadhasivam
    @sadhasivam 8 лет назад

    Nice . Thanks for the good work. just curious how concurrency forloop goes well with bunch of task channel. when ever i run most of the request goes to one go rountine. i tried having huge delays as well.

  • @subhashishbhattacharjee4636
    @subhashishbhattacharjee4636 6 лет назад

    Hey Francesc, really cool video! However, wouldn't it be nice to take functionality out of main.go, as this will make unit testing easier?

  • @bogaczew
    @bogaczew 3 года назад

    don't like replacing site struct with string[]. compiler now cannot check the datatype, you can have some hard to know errors. also, writing everything in main.go is not a good practice. .

  • @andrasshowcase3442
    @andrasshowcase3442 7 лет назад

    Great video
    In addition what others commented, there is another small issue regarding the performance
    Both tasks and results are unbuffered channels, capable to hold only a single element. This will block the goroutines if the reader(s) acting slow). I suggest to use some buffering on both, so there will be tasks available for workers and workers can publish the results without latency.

    • @JustForFunc
      @JustForFunc  7 лет назад

      +András Laczi thats a big "if" right there. I wouldn't add buffering to the channel unless I prove with profiling and benchmarks this is a problem.

    • @andrasshowcase3442
      @andrasshowcase3442 7 лет назад

      JustForFunc you are right, benchmarking helps. Although it's easy to see, as you increase the number of workers, they will be more likely to finish on the same time and be blocked on the writing to result channel. Small loss, but can be significant in long run.

  • @randeepwalia604
    @randeepwalia604 5 лет назад +1

    Why go get instead of 'git clone'?

  • @sam790trhfr
    @sam790trhfr 8 лет назад +1

    Nice font, what is it ? love the ligatures

    • @JustForFunc
      @JustForFunc  8 лет назад +5

      FiraCode with ligatures, yes 😊

  • @chaochen1992
    @chaochen1992 5 лет назад

    Which go vscode plugin do you used ?

  • @AnthonyVoutas
    @AnthonyVoutas 8 лет назад +1

    Francesc this is so great. Thanks!

  • @woeitje
    @woeitje 8 лет назад

    Love it! I'd say: keep them coming :) Thanks!

  • @carloslfu
    @carloslfu 4 года назад

    Wow! Insightful content, thanks for sharing!

  • @dukeballer11
    @dukeballer11 8 лет назад

    Really great video, I look forward to seeing more soon!
    Just a few questions- is it really better to have a function that takes 5 or 6 parameters, rather than use global variables? At what point would it be "too many" parameters? Obviously, you could use a struct if you are regularly passing in the same values, which would probably be cleaner, but it's not always possible.
    Also, those are some seriously wide tabs you've got there ;)

    • @JustForFunc
      @JustForFunc  8 лет назад

      As some say "If you have a procedure with ten parameters, you probably missed some"
      I think that if your function receives too many parameters you should reconsider what the function is doing and simplify it
      also structs help keeping cohesion of the data you're passing

    • @dukeballer11
      @dukeballer11 8 лет назад

      +JustForFunc I agree. I just noticed that you had a few functions there with a decent amount of parameters.

  • @firmanfirdaus1105
    @firmanfirdaus1105 8 лет назад

    how to handle concurrency from http request ?

  • @Simon-xi8tb
    @Simon-xi8tb 6 лет назад

    Why not pass a struct as a parameter ?

  • @小武-g1n
    @小武-g1n 6 лет назад

    Why use tasks/results as unbuffered chan?
    this will block the multi goroutine until read is done?

    • @JustForFunc
      @JustForFunc  6 лет назад +1

      Why not? Did you prove that was an actual bottleneck before just assuming it is?

    • @小武-g1n
      @小武-g1n 6 лет назад +1

      Yep,comparing unbuffered vs buffered chan, having no actual difference(sometimes buffered chan even make worse)
      single goroutine write to tasks, single goroutine read results, multi fetches which take the most time.
      Thx Francesc ~

  • @davidyanceyjr
    @davidyanceyjr 8 лет назад +1

    Loving the shirt... Where do I get one.

    • @JustForFunc
      @JustForFunc  8 лет назад

      www.ooshirts.com/designapp/sharing/1303261115

  • @ThanhCNgo
    @ThanhCNgo 8 лет назад +1

    Holy Cow, I saw your talk on nil @GopherCon. You literally wore the same shirt... This is so funny XD

    • @JustForFunc
      @JustForFunc  8 лет назад +10

      I promise I washed it in between :-)

  • @pdffs
    @pdffs 8 лет назад

    Is there a reason for the preference to use `flag.String` over `flag.StringVar` and dereferencing the pointers everywhere, rather than just moving the global vars to local vars of the `main()` func?

    • @JustForFunc
      @JustForFunc  8 лет назад

      Local variables are easier to track

    • @JustForFunc
      @JustForFunc  8 лет назад

      +JustForFunc also testing is hard with global variables

    • @pdffs
      @pdffs 8 лет назад

      Read the second part of my question again ;-)
      func main() {
      var (
      a, b, c, d string
      e, f int
      )
      flag.StringVar(&a, `blah`....

    • @JustForFunc
      @JustForFunc  8 лет назад

      +Peter Fern less lines 😊

    • @pdffs
      @pdffs 8 лет назад

      Christoph Seufert I get that in this case flags will never return a nil pointer, but all that dereferencing without nil checking makes my skin crawl

  • @maheshsundaram8012
    @maheshsundaram8012 8 лет назад

    Excited for more!

  • @CompletelyCovered3
    @CompletelyCovered3 7 лет назад

    Awesome, valuable, helpful. Subscribed!

  • @gabeguz
    @gabeguz 7 лет назад +1

    Why does your != look like a =/= sign? Is that just an IDE thing?

    • @JustForFunc
      @JustForFunc  7 лет назад +1

      +Gabriel Guzman it's font thing: twitter.com/francesc/status/753638854188339201
      Watch episode 10 for more info!

    • @valentindeleplace2078
      @valentindeleplace2078 7 лет назад

      I went straight to the playground to try a ≠. But no, that's not what the compiler expects.

    • @nikolaykolesnikov4912
      @nikolaykolesnikov4912 7 лет назад

      Thanks a lot! Very pretty feature

    • @MatthewButler
      @MatthewButler 7 лет назад

      Just for anyone curious and didn't see. It's a feature of the font, combined with "font ligatures". Some IDE's will enable the font without the ligatures unless specifically specified to use them (eg: a check box)

  • @JacobMischka
    @JacobMischka 7 лет назад

    this was really interesting, thanks for the video

  • @thedarkdefender8
    @thedarkdefender8 4 года назад +1

    Thanks, this was useful as for a Golang newbie. But as an engineer having experience in other languages, I have to say some of your changes were terrible (mostly in the end, starting with the struct replacement) and went far beyond the refactoring scope.

  •  6 лет назад

    You are making a great job!!!

  • @hunterr113
    @hunterr113 6 лет назад +4

    good stuff. I hope one day I will be this good
    also, damn itunes jumping up and down lol

  • @jeremylmassey
    @jeremylmassey 7 лет назад

    are you using a virtual server , your entire vscode and terminal is dif than mine.

    • @jeremylmassey
      @jeremylmassey 7 лет назад

      you git extension is honestly whats dif than mine. What is it called

  • @jgo2432
    @jgo2432 8 лет назад +2

    Nice t-shirt!

  • @СергейМосолов-э5ю
    @СергейМосолов-э5ю 3 года назад

    all comments of this codebase be like:
    var cat Cat // This is a cat

  • @GertCuykens
    @GertCuykens 8 лет назад

    vscode is such a great ide for gophers :D

  • @YandryPozo
    @YandryPozo 8 лет назад +3

    yes man, where we can get that t-shirt ?? say the secret and don't be evil :)

    • @JustForFunc
      @JustForFunc  8 лет назад +1

      there you go :-)
      www.ooshirts.com/designapp/sharing/1303261115

    • @YandryPozo
      @YandryPozo 8 лет назад

      thanks, ala Barça !!

    • @janithegreat3831
      @janithegreat3831 6 лет назад

      Nice. This is more than 1 mo wage of the Ethiopian worker sowing that shirt according to Bloomberg:
      www.bloomberg.com/news/features/2018-03-02/china-is-turning-ethiopia-into-a-giant-fast-fashion-factory
      We'd better code :-)

  • @phillewis3108
    @phillewis3108 4 года назад

    This is a video about how not to code.
    He spends half an hour making a mess of some well factored code, turning it back into 1970’s fortran.

  • @rajendragosavi2233
    @rajendragosavi2233 3 года назад

    Clubbing everything into main.go , well not a good idea always. :) Thanks for the content :)