OK i need to change your code. SORRY

Поделиться
HTML-код
  • Опубликовано: 16 мар 2022
  • Ok. In this video I will review and improve a bunch of code. The aim is to teach you how to write better code.
    Don't Forget to
    ===========================================
    💯 Subscribe to Amigoscode - bit.ly/2HpF5V8
    💯 Courses Available for free here - amigoscode.com/courses
    💯 Join Private Facebook Group and Discord - amigoscode.com/p/join-community
    🙊 Here are the goods for all my videos video 🙊
    ► Recommended Books
    ===========================================
    - Clean Code - amzn.to/2UGDPlX
    - HTTP: The Definitive Guide - amzn.to/2JDVi8s
    - Clean Architecture - amzn.to/2xOBNXW
    ► Computer and Monitor
    ===========================================
    - New Apple MacBook Pro - amzn.to/3464Mmn
    - Dell 27 INCH Ultrasharp U2719D Monitor - amzn.to/2xM3nW1
    - Double Arm Stand Desk Mount - amzn.to/3aYKKfs
    - USB C Hub Multiport Adapter - amzn.to/2Jz7NlL
    ► Camera Gear
    =============================================
    - Sony ILCE7M3B Full Frame Mirrorless Camera - amzn.to/346QIJn
    - Sigma 16 mm F1.4 DC DN - amzn.to/2wbic3Q
    - Sigma 33B965 30 mm F1.4 DC DC - amzn.to/39G37Fd
    ► IDE & Tools I use for coding 💻 🎒
    ===========================================
    - ITerm
    - VsCode
    - GoLand
    - IntelliJ Ultimate
    - Sublime
    P.S
    ===========================================
    💯 Don't forget to subscribe | bit.ly/2HpF5V8
    💯 Join Private Facebook Group and Discord - amigoscode.com/p/join-community
    💯 Follow me on Instagram | bit.ly/2TSkA9w
    ❤️ Thanks for watching
  • НаукаНаука

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

  • @amigoscode
    @amigoscode  2 года назад +20

    Join the community: amigoscode.com/p/join-community
    Premium programming courses amigoscode.com/courses

    • @testmsf5408
      @testmsf5408 2 года назад

      How to add icon build? Look at it funny ^^

    • @youssefsuimri9526
      @youssefsuimri9526 2 года назад

      I need your help plz if you don't mind. How we can stop people publish ing an image of us on Facebook and whatisup?

    • @babay-mp4bq
      @babay-mp4bq 2 года назад

      alhamdullillah da'wah and programming at the same time hehe

  • @mohammedsfr7514
    @mohammedsfr7514 2 года назад +276

    We want more of these series . It's very useful

    • @zoaybk
      @zoaybk 2 года назад +1

      True, please keep them coming 🙏🏽

    • @salehhassan6057
      @salehhassan6057 2 года назад +1

      True

    • @cigomba
      @cigomba 2 года назад +1

      Definitely learned a lot from this. I can tell you know the fundamentals very well and that goes a long way.

    • @parvathys6665
      @parvathys6665 Год назад

      True

  • @_blackmesa
    @_blackmesa 2 года назад +51

    One of my main issues when I first started learning code, was not being able to understand the logic behind the code. And everyone teaching back then only focused on making sure we memorized the style of the code instead of the logic behind it. - THIS for me, is one of the BEST part of your videos. Since you explain exactly what that code does and then, when needed, fix it, explaining exactly what the fix does.
    If there was a dedicated series on this, it would be amazing!!
    fantastic work. love what you do.

  • @salih.k8939
    @salih.k8939 2 года назад +73

    Just more of this. This was literally amazing.
    I enjoyed every single second of it.

  • @IvanRandomDude
    @IvanRandomDude 2 года назад +55

    19:25 Isn't REST standard to return 201 Created and include newly created object in the response body and URL in location header?

    • @cdhagen
      @cdhagen 2 года назад +9

      I thought the same, especially because in this example, an ID (random UUID) is assigned to the newly created object. One can argue whether to return the entire object or just the URL location, but the client should receive some reference to the stored object.

    • @mishikookropiridze
      @mishikookropiridze 2 года назад +7

      Yes, 201 with object is standard

    • @andrewcathcart
      @andrewcathcart 2 года назад +2

      Yup. 201 with the entity created. Otherwise how would the client know what GUID was saved in the db?

    • @Michaeljamieson10
      @Michaeljamieson10 2 года назад +1

      Yes 201 with object

    • @jorgebee65
      @jorgebee65 2 года назад

      @@mishikookropiridze Yeah, make sense to me.

  • @aykborstelmann8623
    @aykborstelmann8623 2 года назад +27

    Actually regarding the comparator you wrote. You could just do
    min(Comparator.comparing(booking -> ...))
    Then this would even be smaller and neater.

  • @medabotsss1
    @medabotsss1 2 года назад +11

    Disagree with listAll
    The class is called booking service and it only gets bookings.
    Calling it getAll is better because it is less verbose and you can still figure out the meaning from the class name.
    Same thing with delete,find,create

    • @rocketjack4865
      @rocketjack4865 2 года назад

      Yep exactly

    • @ivanjermakov
      @ivanjermakov 2 года назад +1

      Agree. Same as naming every date in entity with date: startDate, bookedDate, createdDate... It is inferred from type information, no need to type it twice.

  • @michelchaghoury9629
    @michelchaghoury9629 2 года назад +42

    @AmigosCode, i really love the codereview, please can you make in the future some e2e tensting tutorials, as well as CI/CD, and Cloud (AWS or GCP) pleaseee, and keep going

  • @edgelamer
    @edgelamer 2 года назад +7

    This is amazing. More of this! Watching a senior dev correcting lower tier devs is so nice and a valuable lesson for us all.

  • @yogeshchaudhary621
    @yogeshchaudhary621 2 года назад +2

    Man I'm just loving such kind of videos. This teaches you so much practical stuff.

  • @reggiebush49
    @reggiebush49 2 года назад +1

    New to the channel but I love this series. I haven’t used java since 1st year of uni and it’s nice to learn about declarative patterns that weren’t taught in uni.

  • @oliwer4987
    @oliwer4987 2 года назад +33

    Fair cleanup, but there are some points here that caught me off guard.
    7:40 - I'm curious as to why it's best practice to only import the used types and not wildcard said package. The only "issue" there is, is that it clutters the local namespace and in reality could ONLY cause you to receive a compile-time error if there were to be conflicting type names, which can be resolved on the spot. Other than the mentioned "issue", there is no obvious reason not to do this if you're certain of the type namings. You also decrease the amount of unnecessary lines of code.
    9:50 - 'listAll', 'all' or 'findAll' would be fine considering the fact that it's in a type of 'BookingService'. The type of listing is already made clear in the name so IMO 'BookingService#findAllBookings' seems very exhaustive and explicit.
    10:36 - same point for this as the one mentioned above. 'BookingService' already indicate that it handles bookings and therefore, 'deleteByCode' references the code of booking(s).
    29:29 - why would one NEVER reference the 'Collection' type? It's useful in many cases, and quite frankly required a lot.
    Feel free to prove me wrong if there are reasonable doubt and arguments to the points mentioned. As a backend programmer myself, I would be glad to receive said thoughts as we can never stop learning. Other than that; fun video, Amigos!

    • @StarzzDrak
      @StarzzDrak 2 года назад +2

      about the 9:50 and 10:36, it's never wrong or useless to be more explicit. You've got IDE helping you write all long names, but when it comes to reading it and tracing back it's always good to be more explicit, even if it's inside a type

    • @oliwer4987
      @oliwer4987 2 года назад +2

      @@StarzzDrak Of course. Don't get me wrong, I'm not saying it's not; what I am saying is that it is not a better practise nor is it needed. Quite frankly, I feel it's unnecessarily long. If you prefer to name it that way, go for it, but it's already indicated so in reality it's all good. In this case there was even multiple repositories, so even inheritance would do good with the original naming.

    • @adrianroed2178
      @adrianroed2178 2 года назад +3

      ​@@StarzzDrak Being explicit is good, but being concise is also important. I can't claim to be an authority on the best balance of explicit vs concise, but there is such a thing as being too explicit.
      It's the same as in 7:40. I don't think it is necessary to explicitly state every class you're importing, the domain names are explicit enough while being far more concise.
      To me, "listAll" is explicit enough, because this is the class "BookingService", it is the controller for the class "BookingDTO" and all it's functions implicitly refer to booking DTO. If for some reason listAll returned anything other than booking DTO I would agree that it needed to be more explicit.

    • @onebacon_
      @onebacon_ 2 года назад +2

      7:40 couldn't be more right. Explicit imports are just noise in your code and don't contribute anything

    • @gilzemer8113
      @gilzemer8113 2 года назад +6

      @@StarzzDrak "it's never wrong or useless to be more explicit"
      I strongly disagree. For example, if you have a class Person with fields like "name", "age", "address", it is better to have methods like "getName()", "getAge()" and "getAddress()", and not "getPersonName()", "getPersonAge()" and "getPersonAddress()".
      when the code is "person.getName()", it is clear to the user what the name field is refering to, however "person.getPersonName()" just makes the code inflated for no good reason.
      This is just a simple example but of course it applies to the case covered in the video as well. if you have a booking service, bookingService.getById(), bookingService.getByCode() is clear enough, no need to inflate the code with the obvious context (booking)

  • @aadlani
    @aadlani 2 года назад +12

    You are the best Trainer on Java so far in my experience.
    Keep rocking. Big Fan

  • @froshiga9197
    @froshiga9197 2 года назад

    WOW, I started as a junior java dev about a year ago and I learned more from these videos than most of my time at work!

  • @Qrzychu92
    @Qrzychu92 2 года назад +9

    Well, I must say that modern Java looks quite neat. Greeting from dotnet :)

  • @dcascato
    @dcascato 2 года назад +19

    Wow, I never learned so much in one video. I think the value here is you are tackling it from a professional perspective, which some of us newbies lack. Tutorials many time go around teaching things like syntax and that kind of stuff, but I believe learning best practices is really valuable. Just loved it

    • @codingwithcrisprg4274
      @codingwithcrisprg4274 2 года назад +4

      You can tell he has robust understanding of Data structures and Algorithms.

  • @TheDragon5215
    @TheDragon5215 2 года назад +2

    Thank you Sir for these videos. As junior for me your code review serie is more helpful than any courses I've every seen.

  • @adamk2251
    @adamk2251 2 года назад +32

    20:30
    honestly calling findAll on a repository and doing filtering in code is a huge code smell.
    you're loading an entire DB table into memory just to filter out one single entry.
    best case: it's just bad code, worst case: your operating cost explodes because of the memory consumption, also latency.
    the filter itself should be contained within a specialized DB query to the likes of (pseudo-SQL:) "WHERE startDate before now AND confirmed == true" then "ORDER BY start date ASC" and "LIMIT 1",. the repository method returns an Optional, since you're actually only interesented in one entry (which could not exist, e.g. if you don't have any bookins yet, therefore Optional).
    BOOM, your code just became extremely trivial.
    also don't forget DB indexes on startDate and confirmed DB fields fro proper DB query performance ;)

    • @adamk2251
      @adamk2251 2 года назад +11

      also, regarding RESTfulness:
      when adding new resources, you don't return void and 200 OK, you do return the saved entity with the generated UUID and respond with a 201 Created.
      a HTTP DELETE is supposed to be idempotent, which means that performing the same request several times should have the same effect. thefefore you shouldnt be returning a 404 when the entity to be deleted doesn't exist, just give a 204 No Content response (since the effect that the request asked for happened: the entity to be deleted does not exist after the request is completed).

    • @adamk2251
      @adamk2251 2 года назад +4

      but apart from that, great video, i pretty much agree with the way you structure and format the code and your way of thinking, love that you use assertJ. great educational stuff!

    • @mm1nt
      @mm1nt 2 года назад

      Thanks for the tips. Appreciate it

    • @verrigo
      @verrigo 2 года назад +2

      @@adamk2251 Yes. I was about to comment on this, but glad someone else did it before me :D

    • @volbla
      @volbla 2 года назад

      So basically keep a properly organized database instead of bodging in code?

  • @tinnick
    @tinnick 2 года назад +9

    I’m not a Java programmer so please take this comment lightly.
    I find that at 19:50, you refactored to not return anything but I think this differs depending on the context.
    If the frontend needs to be aware of multiple bookings, it should return that saved booking id instead of void.
    This is so that the frontend can be aware of the saved booking id to then maybe later in the same form send a patch request to update the booking.

    • @valentinpopescu6704
      @valentinpopescu6704 2 года назад +1

      That would be unclean code as you're adding multiple logic to one method. What you should do in this method is only book a room, like the name implies, and if you need the id, create a DAO to retrieve the id by the bookings name and optionally the start and ending date.

  • @chandrakanthpadi
    @chandrakanthpadi 2 года назад +14

    I think no RUclipsr had done this. This code reviews is so good to see. Please continue to.

    • @odkane
      @odkane 2 года назад

      ArjanCodes does some nice code reviews too

  • @DaBaSoftware
    @DaBaSoftware 2 года назад +1

    The cranberry juice caught me off guard. Instant like and sub
    But seriously, thank you for this resource. Everything from the shortcuts, the use of optional, and just the way you were critical about naming conventions really challenged what I've learned over the last few years in school and the bits of work where I've scripted or dabbled in some code snippets. Awesome video!

  • @paoloa89
    @paoloa89 2 года назад

    Learning through errors correction is one of the best way to fix new things in mind ! well done

  • @returncode0000
    @returncode0000 2 года назад +16

    The code review/refactor series is great, keep it 👍

  • @sweetmelodies01
    @sweetmelodies01 2 года назад

    Sir Amigo, i love your segment with this reviewing some created codes, its really so informative. I wish you can have this added as part of your weekly content. Thanks so much, you are so awesome. Ive learned so much about Java language. Thanks again and more power to your YT Channel.

  • @KolosBros
    @KolosBros 2 года назад

    It's awesome to see that is going to be a new series :) Code review is the best way to exchange knowledge

  • @mm1nt
    @mm1nt 2 года назад +2

    Amazing thanks for the help
    This way my first spring boot project and ive learned a lot from you !

  • @soumyadeeppaul2389
    @soumyadeeppaul2389 2 года назад

    We need more of this. Learnt a lot,gonna apply this in future for sure💯

  • @jorgebee65
    @jorgebee65 2 года назад

    I really appreciate this kind of videos, man you are awesome!

  • @Aspiiire
    @Aspiiire 2 года назад +1

    Even if I'am not learning Java I'am benefiting from this video, jazakAllahu khairan brother

  • @irina413
    @irina413 Год назад

    Best video on RUclips. your videos inspire me and make me more professional. Thank you a lot

  • @manolo6048
    @manolo6048 2 года назад

    this was really awesome, I felt like all code I've ever written was being reviewed, and it was great.

  • @Namelessssssssssssssss
    @Namelessssssssssssssss 2 года назад +1

    Please go on posting this kind of videos because they are amazing and full of tremendous concepts

  • @tienu
    @tienu 2 года назад

    Great video. For other watching, if you use findAll and filter afterwards its going to impact performance on a large dataset, always try to put your filtering inside your query (jparepository). You can even put your min max inside there.

  • @krammer123456
    @krammer123456 2 года назад +8

    This is awesome! I would suggest writing the test first and then re-factoring.

    • @CarlosDiaz-wh4jb
      @CarlosDiaz-wh4jb 6 месяцев назад

      I was going to comment that opinion as well 😀

  • @leewalker9851
    @leewalker9851 Год назад

    Very nice code review!! I find writing static test classes that setup the entities that you will constantly test against makes life easier. I would probably also use some verifications in the test as well

  • @luizfernandonoschang8298
    @luizfernandonoschang8298 2 года назад +8

    Awesome video man! I'm an experienced Java developer and I'm planning to take one of your online courses, because I'm learning a lot with you.
    Now, I want to argue with you in one thing. I think that the BookingService should actually return a BookingDTO upon insertion. This is because, when you send a 200 CREATED status, usually you send back a link to the newly created resource, so the client can actually send a GET request afterwards.
    In fact, mostly of the time the client will insert the new resource and do something with it afterwards(adding to a list on the UI, for example). So, sending the created entity avoids having to do a second request.
    If returning the whole Entity/DTO may cause a overhead, then at least the generated ID should be returned, so you can build the link for the client. Well, this is my opinion.
    Congratulations again for the video!

  • @AhmedAlawdi_
    @AhmedAlawdi_ 2 года назад +1

    I love the subtle arabic words you throw in

  • @martintopolanek448
    @martintopolanek448 2 года назад

    It is satisfying to watch it. Please continue 🙏

  • @futureghost6103
    @futureghost6103 2 года назад

    Love this series! Please continue!

  • @emmanueljr
    @emmanueljr 2 года назад

    thank you for this, i ;ietrally dont even know some of the built in methods used here so now i have some cool features to look into. i appreciate this. its in a way bettdr than tutorials i think

  • @daoviettu2334
    @daoviettu2334 2 года назад

    Extremely useful!! I don't see much video content like this... It's practical.

  • @Guillen8606
    @Guillen8606 2 года назад

    Keep up these series. This is worth every second!!

  • @ClaudesGomes
    @ClaudesGomes 2 года назад

    This is amazing, we need more videos like this!
    Hugs from Brazil!

  • @justgame5508
    @justgame5508 2 года назад

    On the delete booking by code (and other situations like that), rather than have them void, I like to return a bool stating where the delete was successful, for instance if an unknown code is passed it may be useful when using that function to know whether the action was successful or not and structure the logic accordingly

  • @Series0Tubes
    @Series0Tubes Год назад

    @Amigoscode this was a fantastic video. It's great to see you at work.

  • @youneselhamss2908
    @youneselhamss2908 Год назад

    Amazing stuff akhi, can’t wait to get on that level in sha Allah😍🔥

  • @javatmz
    @javatmz 2 года назад +2

    Amigos thanks for taking the time to explain this topic

  • @kingstonmocktail7744
    @kingstonmocktail7744 2 года назад

    Love your videos and this series a lot. Which font do you use for intelliJ? Is that the default JetBrains Mono?

  • @eladriladri
    @eladriladri 2 года назад

    Wow this is a great video, also I love your hat! You just earned a new subscriber :D

  • @adedamolababatunde2798
    @adedamolababatunde2798 2 года назад +1

    This helped me refactor my own project

  • @kenng2029
    @kenng2029 2 года назад

    This is great stuff! Thanks for these!

  • @lxdzii
    @lxdzii 2 года назад +1

    Nice video, please make more of these, I'm hooked!... A series of these would actually make us better java developers🙂💯!!!!;

  • @minhan4444
    @minhan4444 2 года назад

    I always like coding reviews and thank you very much for the topic.

  • @rafa16chagas
    @rafa16chagas 2 года назад

    It's amazing. I always learn something new from your videos.

  • @02Anderman
    @02Anderman 2 года назад +1

    Amazing Video, I love how you explain why you should refactor the code like you do here, it helps to get a way better view on the structure.
    Also I really appreciate you for showing the good approach of testing, am really pumped to implement tests into my backends to see some of the green bars

  • @420_FORTNITE
    @420_FORTNITE 2 года назад

    Thank you for making more of these!

  • @AlexG-sp7qn
    @AlexG-sp7qn 2 года назад +1

    Hello, Would be nice to have a Spring's course about Relation between tables, the cascades, constraints, when to use REST microservice or direct relation in module, joins, and other sql stuff ;)

  • @swapnilbodade1336
    @swapnilbodade1336 2 года назад

    Thanks. Please continue this series.

  • @Mac1355
    @Mac1355 2 года назад

    hello, thanks for your demonstration how we can be better coding.

  • @yogeshchaudhary621
    @yogeshchaudhary621 2 года назад

    This is really good. Plz do more of such stuff.

  • @kitsurubami
    @kitsurubami 2 года назад +1

    I would love to see more code refactoring videos like this.

  • @mugilbalagmail
    @mugilbalagmail 2 года назад

    Wow. Thanks a lot for this video. This is more helpful. Please drop more videos like this.

  • @Myrusaf
    @Myrusaf 2 года назад

    It was amazing and I learn alot from your video, keep grinding

  • @techstudies5005
    @techstudies5005 2 года назад

    Powerful Teaching Methods Here, Thanks very much!

  • @rumeysas.3357
    @rumeysas.3357 2 года назад

    It is amazing! Looking forward to see more!

  • @achrafbenkerri9743
    @achrafbenkerri9743 2 года назад

    Very useful video. Thank you for your efforts

  • @samisaleh6186
    @samisaleh6186 2 года назад

    Love this content! Thank you~

  • @burcubag7246
    @burcubag7246 Год назад

    Thank you for your contribution 🙏

  • @pejko89
    @pejko89 Год назад

    This is so useful! Thanks

  • @abeard1
    @abeard1 2 года назад

    I love this goofy format!

  • @abdelkader2848
    @abdelkader2848 2 года назад

    Thanks you so much amigoscode for this kind of videos

  • @andreas-fefe
    @andreas-fefe 2 года назад

    Here comes the incredible Nelson. Kuddos to you bro you are the best

  • @ShubhamPatidar16
    @ShubhamPatidar16 2 года назад

    Please bring again same videos for code reviews asap. These are amazing and you are doing great work. Thanks a lot!! Please bring asap...

  • @MT2LD
    @MT2LD 2 года назад +1

    السلام عليكم..
    hello brother.. thanks for everything you did for people..
    suliman from SaudiArabia ❤

  • @fullnaoufal
    @fullnaoufal Год назад

    Hey,
    Thanks for sharing your knowledge.
    I have a question about using dtp on service layer.
    What are the pros and cons please?
    Regards

  • @ivanflores8554
    @ivanflores8554 2 года назад

    Love this series!

  • @raffayhussain6717
    @raffayhussain6717 2 года назад

    This is great, please make more of these

  • @chandragie
    @chandragie 2 года назад

    More of this series please!!! 👍

  • @marxjung5751
    @marxjung5751 2 года назад

    Great video, I got a lot of knowledge and experience

  • @rovsenhuseynov8368
    @rovsenhuseynov8368 Год назад

    Useful video. Thanks man

  • @gurekodok
    @gurekodok 2 года назад

    Awesome, super helpful thank you so much :)

  • @KangoV
    @KangoV 2 года назад

    I love this channel btw -- Subscribed

  • @codingwithgyver1637
    @codingwithgyver1637 2 года назад

    @13:44, amazing, java already have throw something if null on its chaining method, just like Linq's FirstOrDefault which requires you an additional code for null checking

  • @briannkurunungi2837
    @briannkurunungi2837 2 года назад

    I like your good heart Sir
    Well done

  • @muaathali2852
    @muaathali2852 2 года назад

    Walikum Alsalam, Gaza’s Allah Khair…. Loving you code ❤️😘

  • @dawidplewik1181
    @dawidplewik1181 2 года назад

    Useful material, i like it!

  • @salehahmed8936
    @salehahmed8936 2 года назад +1

    Best coder around!

  • @AndyE7
    @AndyE7 2 года назад

    What editor are you using? It looks like Android Studio which I've used a lot for Flutter. Can it do Java too?

  • @smanqele
    @smanqele Год назад

    This exercise is quiet good. I'm just curious about testing. Would it not work better to first write unit tests before refactoring, or does it not matter?

  • @svalyavasvalyava9867
    @svalyavasvalyava9867 2 года назад

    thank you so much for the content!!!

  • @valeriov.2647
    @valeriov.2647 2 года назад +1

    At 21:00 would you really do all the filtering then and there "by hand" or would it be preferred to do the filtering right in the query to the underlying DB? I'm kind of torn apart between the DB usually being something slow one wants to reduce interaction with and on the other side the potential instantiation of a hugmongus amount of objects just to be filtered out right away. Would appreciate your thoughts @Amigoscode

    • @31redorange08
      @31redorange08 2 года назад +3

      DB slow? Fetching all data and filtering in the application code is a huge anti-pattern. You can do this in toy projects but not in real life.

  • @umadbroyo2388
    @umadbroyo2388 2 года назад

    When you "Assalamualikum", it made me so happy!!

  • @treibsandbohrer
    @treibsandbohrer 2 года назад

    amazing series!!

  • @oharaandrew314
    @oharaandrew314 2 года назад

    This is great stuff. I'm tempted to do a kotlin equivalent.

  • @theboredasfook
    @theboredasfook 2 года назад

    Nice video brother, I would like to see best practices advice for Rest API

  • @dd1.d
    @dd1.d 2 года назад

    Great content. I hoped my code was under your keen eyes. May be next time inshaallah

  • @yassinemessaoud8619
    @yassinemessaoud8619 2 года назад

    never new i'd be very interested in refactoring Thank you !

  • @invictuz4803
    @invictuz4803 2 года назад

    Is C# more or less the same as Java? I'm wondering if I can understand everything here with my beginner understanding of C#.

  • @OmbasaGeoffrey
    @OmbasaGeoffrey 2 года назад

    Great stuff. Thanks

  • @MohamedOsama-kl6ex
    @MohamedOsama-kl6ex Год назад

    Amazing 🤩 keep going bro ♥️🙏