<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Modasser Billah</title>
    <description>The latest articles on DEV Community by Modasser Billah (@billah_tishad).</description>
    <link>https://dev.to/billah_tishad</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F69153%2F387e4fed-a0e3-476c-b7bc-8fa5b3af2330.jpg</url>
      <title>DEV Community: Modasser Billah</title>
      <link>https://dev.to/billah_tishad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/billah_tishad"/>
    <language>en</language>
    <item>
      <title>Going Remote for Life</title>
      <dc:creator>Modasser Billah</dc:creator>
      <pubDate>Sun, 06 Sep 2020 22:02:12 +0000</pubDate>
      <link>https://dev.to/billah_tishad/going-remote-for-life-4514</link>
      <guid>https://dev.to/billah_tishad/going-remote-for-life-4514</guid>
      <description>&lt;p&gt;Remote work is trending. But the remote revolution started long before the pandemic and will stay powerful even after the hype subsides. As with any change, how well you adapt and improve will determine whether you get the better of remote work or run back to offices once the external factors go away.&lt;/p&gt;

&lt;p&gt;I decided to go remote 3 years ago and I'm glad I did. My last workplace was BriteCore, a remote-first company based in the US. And tomorrow, I'll be joining Doist, a pioneer in the world of remote work. I have gone through a lot of interview processes in the recent years.&lt;/p&gt;

&lt;p&gt;This article is an attempt to answer the why, what and how of remote work. The intended primary audience are developers from developing countries like me (I'm from Bangladesh) who do not want to relocate right now but wants to work on exciting products and teams all over the world. The general ideas apply to all professions that can be carried out remotely and to professionals anywhere in the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Remote
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Better Opportunities
&lt;/h3&gt;

&lt;p&gt;Going remote means your employment is not limited to your physical location anymore. That opens up a world of opportunities. You can work for your dream company or with the colleagues and experts that you cherish. And all of it while staying in the place you like with the people you love. If you are the nomad type, this gives you great flexibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Financial Gain
&lt;/h3&gt;

&lt;p&gt;💵 Remote work opens up much better opportunities with much better compensations if you're, like me, living in a developing country. The compensations are generally much better than the local industry.&lt;/p&gt;

&lt;p&gt;📈 The high exchange rates between the powerful currencies and the local ones allow you to leverage the asymmetry and save much more. In fact, you can end up with a higher net savings per month than someone earning more than you in expensive places like San Francisco or London for example.&lt;/p&gt;

&lt;p&gt;📉 Tax rates are also generally lower and most developing countries have generous rebates if you're bringing in foreign remittance.&lt;/p&gt;

&lt;p&gt;✅ Even if you're living in a developed country, remote work saves you a good amount from commute, lunch and everything in between that comes with showing up in an office.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Self-actualization
&lt;/h3&gt;

&lt;p&gt;Remote work allows you to do deep work and puts you in control of your routine and interruptions. In a world of constant connectivity, the option to go deep as needed can give you an unfair advantage in knowledge based work that reward craftsmanship and superior skills. Read the interesting book titled &lt;a href="https://www.calnewport.com/books/deep-work/"&gt;Deep Work by Cal Newport&lt;/a&gt; to learn more about this.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Remote Skillset
&lt;/h2&gt;

&lt;p&gt;Remote work comes with its share of challenges. You need to adapt and overcome these challenges to thrive in a remote work environment for the long term. And the process starts with adopting the remote skillset.&lt;/p&gt;

&lt;p&gt;I use a handy mnemonic  to summarise the skillset essential for remote work. I call it the &lt;strong&gt;IBM CI&lt;/strong&gt;. IBM, as you probably know, is the name of a famous company and CI or &lt;em&gt;Continuous Integration&lt;/em&gt; is a term developers are quite familiar with.&lt;/p&gt;

&lt;p&gt;The mnemonic comes from &lt;strong&gt;I&lt;/strong&gt;ndependence, &lt;strong&gt;B&lt;/strong&gt;alance, &lt;strong&gt;M&lt;/strong&gt;astery, &lt;strong&gt;C&lt;/strong&gt;ommunication and &lt;strong&gt;I&lt;/strong&gt;mpact. I borrowed it from &lt;a href="https://doist.com/"&gt;Doist&lt;/a&gt;. So, all credit goes to the awesome team there. I just came up with the mnemonic to remember it better. You can find it in any of their job descriptions. Their &lt;a href="https://blog.doist.com/"&gt;blog&lt;/a&gt; is chalk-full of great articles on remote work. Subscribe to the blog to get the best out of it.&lt;/p&gt;

&lt;p&gt;I'll only touch on two aspects that encompass everything else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manager of One&lt;/strong&gt;: Going remote means you're unlikely to have colleagues by your side. If you're working from home, it can be quite a challenge to put a boundary between work and non-work time. You're in charge of yourself and your schedule. So, you need to be able to do it well if you want to succeed in remote work in the long term.&lt;/p&gt;

&lt;p&gt;I borrowed the term &lt;em&gt;Manager of One&lt;/em&gt; from Basecamp, a pioneer and advocate of remote work. The ability to manage yourself is pivotal to a successful remote career. Read more about it on Basecamp's &lt;a href="https://signalvnoise.com/posts/1430-hire-managers-of-one"&gt;blog post&lt;/a&gt; on the topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Communication&lt;/strong&gt;: Bulk of the communication in remote work happens in the written medium. You need to harness your ability to express your thoughts and ideas clearly in the written form to thrive in a remote setting. This is also going to be the primary mode of making connections with colleagues across the company. You don't need to become a literary genius though. Clear and concise technical writing goes a long way. &lt;a href="https://twitter.com/david_perell/status/1208930197702995968"&gt;This tweet &lt;/a&gt;sums up a  lot of great points.&lt;/p&gt;

&lt;p&gt;The tone gets lost in transmission in written medium. It's always good to pay extra attention to not come off harsh. Warm your messages with emojis :)&lt;/p&gt;

&lt;p&gt;Most remote settings will have a diverse workforce. It's important that you stay sensitive to cultural diversities and refrain from saying anything that may be acceptable in your culture but not in others. Avoid using swear or curse words in all settings even if you deem it to be informal. I have had a manager in the past who would use the f-word in meetings. Please don't!&lt;/p&gt;

&lt;p&gt;As for technical skills, I advice to work on-site when starting out if possible. Most remote jobs expect you to do your job with minimal supervision. It's easier to find jobs and perform better when you have some experience under your belt.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Remote Toolbox
&lt;/h2&gt;

&lt;p&gt;Remote work means managing yourself well. Most of your communication will happen online and it is expected that you'll be using a lot of collaboration tools. Here are some of my suggestions to organise yourself better and produce quality output.&lt;/p&gt;

&lt;p&gt;📝 Use a task management tool. Put all your tasks as they pop up in your list and plan them accordingly. I use &lt;a href="https://todoist.com/"&gt;Todoist&lt;/a&gt; for this but any tool that you're comfortable with works, even pen and paper.&lt;/p&gt;

&lt;p&gt;📓 Use an app for writing and taking notes. I prefer &lt;a href="https://ia.net/writer"&gt;iA writer&lt;/a&gt; for long documents and &lt;a href="https://evernote.com/"&gt;Evernote&lt;/a&gt; for quick notes synced across devices. But again, anything that you're comfortable with works fine.&lt;/p&gt;

&lt;p&gt;🛠️ Familiarise yourself with communication tools like Slack, Teams, etc if not already. Most companies use one for communication. While there's not much of a learning curve, you should at least know that they exist. Same for project management tools like Jira, Trello and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shades of Remote
&lt;/h2&gt;

&lt;p&gt;This section is more focused on developer jobs. Remote work can mean a lot of things for a developer. It can be consulting, freelancing, working for steady clients or full time contracts with companies. I'll categorise them in 3 buckets and list some resources where you can find opportunities for that category.&lt;/p&gt;

&lt;h3&gt;
  
  
  Freelancing Platforms
&lt;/h3&gt;

&lt;p&gt;You can freelance on projects remotely on freelancing platforms. Examples include Upwork, Freelancer, etc where you can join, create a profile and start bidding on projects.&lt;/p&gt;

&lt;p&gt;While this is a good option to work on projects you're interested in, I tend to prefer not working on them as a career choice. All clients are not the same, so it needs a lot of calibration every time you start a new project.&lt;/p&gt;

&lt;p&gt;Clients generally choose these platforms for cost optimisation. So, the engineering standards are generally a bit lower and the deadline pressures are more intense.&lt;/p&gt;

&lt;p&gt;This also means variable workload and variable income, which makes planning your time and life harder. But I have worked on projects intermittently on Upwork before and it can be a good path to pursue if it suits you.&lt;/p&gt;

&lt;p&gt;Here's a list of popular freelancing platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.upwork.com"&gt;Upwork&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fiverr.com/"&gt;Fiverr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.freelancer.com/"&gt;Freelancer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.guru.com/"&gt;Guru&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.peopleperhour.com/"&gt;peopleperhour&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Agency Platforms
&lt;/h3&gt;

&lt;p&gt;Some platforms employ a vetting process and only allow successful candidates on their platforms. For the lack of a better word, I call them agency platforms. These platforms are on the rise and I see new ones every now and then.&lt;/p&gt;

&lt;p&gt;Once you're on the platform, you may have to bid for projects again or you may be paired with companies depending on the type of the platform. But you'll be working as a member of the platform and the platform will take a cut off your earnings.&lt;/p&gt;

&lt;p&gt;One major downside of both these types of platforms is that you don't get any paid time offs (PTO). If you don't work, you don't get paid. You don't get any other perks or benefits either. But once you get yourself on these platforms, it may be easier to land clients or contracts (and better ones) than on platforms mentioned in the first category. Remember to check reviews before joining. Do not join if you don't like their practices.&lt;/p&gt;

&lt;p&gt;Here's a list of some platforms in this category:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.toptal.com/"&gt;Toptal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://x-team.com/"&gt;X-Team&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://turing.com/"&gt;Turing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://triplebyte.com/"&gt;TripleByte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vettery.com/"&gt;Vettery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://6nomads.com/"&gt;6nomads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.crossover.com"&gt;Crossover&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This list is not exhaustive and there's a lot of other platforms like these. I haven't worked on any of these, so do your review before you decide to join.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remote Companies
&lt;/h3&gt;

&lt;p&gt;Remote-first or full-remote companies fall in this category. The number of such companies is increasing rapidly, thanks to the pandemic. You can apply to these companies directly from their job posts and work as independent contractors after you successfully complete their recruitment process.&lt;/p&gt;

&lt;p&gt;I prefer this category of remote work because you get to work for the company directly. Generally, the teams and cultures are better in companies who hire directly.&lt;/p&gt;

&lt;p&gt;Similarly, the compensations and benefits are better as well. Most of them will provide PTOs and have good practices around remote work.&lt;/p&gt;

&lt;p&gt;Some popular companies that hire remotely are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://doist.com/"&gt;Doist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zapier.com/"&gt;Zapier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://buffer.com/"&gt;Buffer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.com/"&gt;Gitlab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://automattic.com/"&gt;Automattic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://basecamp.com/"&gt;Basecamp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many job forums and aggregate websites that you can subscribe to for job openings in remote companies. You can create email subscriptions according to your choices. Here's a list of some popular remote job forums:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://weworkremotely.com/"&gt;We Work Remotely&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://remoteok.io/"&gt;RemoteOK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://angel.co/"&gt;AngelList&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/jobs?r=true"&gt;Stack OverFlow jobs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.glassdoor.com/Job/remote-jobs-SRCH_KO0,6.htm"&gt;Glass Door Jobs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://remotecircle.com/"&gt;RemoteCircle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/RemoteJobs/"&gt;Reddit Remote Jobs Forum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://remotive.io/"&gt;Remotive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jobs.underpin.company/"&gt;Underpin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://remote.co/"&gt;Remote.co&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://remote4me.com/"&gt;Remote4Me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/jobs/remote-jobs/"&gt;LinkedIn jobs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://remotepython.com/"&gt;Remote Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.remotetechjobs.com/"&gt;RemoteTechJobs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These platforms are great for job search. Make the best use of them by subscribing to filtered job searches so that you get alerts for jobs that suit you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Hired
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Cast a Wide Net
&lt;/h3&gt;

&lt;p&gt;You can find tons of job postings on the internet. But the sad reality is most of them won't reply back to you. And you'll only proceed to final stages on a few of those that do reply. So, you need to apply to a lot of jobs to interview at a few of them and then eventually get offers from a handful of them. Don't get discouraged by rejections or no replies, instead keep applying to opportunities that you like.&lt;/p&gt;

&lt;p&gt;Don't refrain from applying if you feel you don't fulfil all the requirements for the role. As they say, if Internet Explorer can ask you to be your default browser, you can apply to jobs that &lt;em&gt;you think&lt;/em&gt; you don't qualify for. If you never try, you'll never know.&lt;/p&gt;

&lt;h3&gt;
  
  
  Focus on a Niche
&lt;/h3&gt;

&lt;p&gt;This applies two-fold. Firstly, choose a set of technologies or industries that you like and preferably have experience in. And apply for jobs only in that category. For example, I tend to focus on roles that focus more on the backend and requires Python and AWS skills.&lt;/p&gt;

&lt;p&gt;There's an ocean of platforms and frameworks out there. Getting the basics in place is important. But you can get better results if you focus on certain skills, languages and technologies while starting a new job search.&lt;/p&gt;

&lt;p&gt;Secondly, companies generally have two major modes of recruitment. One type of companies will send you timed coding challenges and require live coding interviews. You need a more &lt;em&gt;Cracking the Coding Interview&lt;/em&gt; style preparation for this type of recruitment processes.&lt;/p&gt;

&lt;p&gt;The other type of companies will have a more thoughtful recruitment process suited to remote work. They'll test your communication skills with descriptive writing tasks and behavioural interviews with some technical questions to gauge your technical depth. Then they'll pair it up with take home assignments that match closely with the work you'll be doing for the company if they hire you. I prefer this process and tend to focus more on companies that follow this process.&lt;/p&gt;

&lt;p&gt;Pick your battles wisely and prepare for them accordingly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting the Foot in the Door
&lt;/h3&gt;

&lt;p&gt;Cover letter and CVs get your foot in the door. This is generally the first step of the recruitment process. Make sure you pass this initial screening by tailoring your CV according to the job and a thoughtful cover letter.&lt;/p&gt;

&lt;p&gt;Most applicants ignore the cover letter altogether or send a generic one. Stand out by crafting a great cover letter that shows your interest in the company and the value you offer for them and the role. There are tons of resources on this on the internet for free. Make good use of it. Here's a &lt;a href="https://blog.doist.com/remote-job-application-advice"&gt;great article&lt;/a&gt; to get started on the overall process.&lt;/p&gt;

&lt;p&gt;If you're applying to a company you like, make sure you let them know that you admire them and the reasons for it. I admire Doist and have been using their product for some time. Their blog has also been a source of inspiration for me. So, I made sure to make a note of this in my cover letter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do Your Research
&lt;/h3&gt;

&lt;p&gt;Once you hear back after applying, do some research on the company. Read the glassdoor reviews on the company and look for interview reviews as well. Go through the company website, follow key persons of the company and employees in the department you're applying for on social medias.&lt;/p&gt;

&lt;p&gt;If the company has a blog or some of their employees have been on podcasts and webinars, spend some time on those. This will give you a lot of perspective on the company and the culture and help you come up with some good questions to ask during the interviews.&lt;/p&gt;

&lt;p&gt;Read the job posting carefully and list out the important technologies and concepts they emphasise on. Focus on these during your technical preparation. Glassdoor interview reviews and the job posting can offer you important insights on the interview process. Take advantage of them to gain an edge.&lt;/p&gt;

&lt;p&gt;One unconventional strategy is to find ex-employees of the company online and ask them for advice. Most people add work histories on their social media profiles and you may get lucky finding some of them.&lt;/p&gt;

&lt;p&gt;Most people are generally friendly and helpful and they can give you valuable advice on how to prepare. You can also talk to them about the culture and environment in the company to understand whether it suits you. Remember, you're interviewing the company as much as they are interviewing you.&lt;/p&gt;

&lt;p&gt;I actually did this when I found an ex-doist employee on LinkedIn, Ahmet. He was very helpful and his inspiring words and valuable advice helped me a lot to prepare for the interviews at Doist.&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoid Unforced Errors
&lt;/h3&gt;

&lt;p&gt;Prepare for the interviews well.&lt;/p&gt;

&lt;p&gt;👉 Choose a quiet place.&lt;/p&gt;

&lt;p&gt;✅ Have a backup internet plan if the power goes off.&lt;/p&gt;

&lt;p&gt;📷 Always keep the camera on even if they make it optional. Face to face interaction is very important and don't waste the opportunity.&lt;/p&gt;

&lt;p&gt;✨ Make sure the background is nice and you're dressed for the occasion. You don't need to don a suit though, just don't look like a shabby hacker.&lt;/p&gt;

&lt;p&gt;🗣️ Communicate well all along the interview process. Reply to emails in a friendly manner.&lt;/p&gt;

&lt;p&gt;😄 Smile a lot during the interviews, it does wonders for you and creates a positive impression on the interviewer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nail the Take Home Assignments
&lt;/h3&gt;

&lt;p&gt;It's easy to think doing what is asked is good enough. But if you really want the job you'll go the extra mile. Yes, it's important to do what you're asked to do, but it is equally important to do it in a way that showcases your skills. Here are some simple yet overlooked advices for test projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a syntax formatter.&lt;/li&gt;
&lt;li&gt;Follow a style guide (e.g, PEP8 for Python).&lt;/li&gt;
&lt;li&gt;Name your variables well.&lt;/li&gt;
&lt;li&gt;Write some tests. These don't need to be exhaustive but cover the most crucial parts of your code at least. This shows that you care about it.&lt;/li&gt;
&lt;li&gt;Write docstrings if possible, even if one-liners.&lt;/li&gt;
&lt;li&gt;Use comments thoughtfully to explain the why but not the how.&lt;/li&gt;
&lt;li&gt;Write concise and meaningful commit messages. Squash commits to present a coherent and polished workflow.&lt;/li&gt;
&lt;li&gt;Ask clarifying questions. If you make assumptions, try to write them up in a markdown document along with your approach to the given problem.&lt;/li&gt;
&lt;li&gt;Don't go overboard with your solution. Don't complicate it or add features that are not asked for. How well you understand the problem specification and implement accordingly matters a lot.&lt;/li&gt;
&lt;li&gt;It's a test project for a reason, so don't try to cover all aspects of a system, instead focus on solving the major problems. Do it in an organized way and then write up a document on the improvements that can be made on further iterations on the problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Grow from Rejections
&lt;/h3&gt;

&lt;p&gt;Rejections will come across aplenty. Recruitment is something no one has figured out precisely yet and you can be rejected even if you're qualified. So, don't lose heart for getting rejected.&lt;/p&gt;

&lt;p&gt;People rejected by big tech have done wonderful things going forward. If the recruitment process uncovered a shortcoming on your side, maybe a gap in your knowledge, make sure you don't make the same mistake again.&lt;/p&gt;

&lt;p&gt;Interviews have no fixed boundaries and you can be asked literally anything. So, don't be too hard on yourself if you don't get all the questions right. Look them up and learn. If you're learning from every experience that means you're growing and increasing your probability for success.&lt;/p&gt;

&lt;h2&gt;
  
  
  Staying Employable
&lt;/h2&gt;

&lt;p&gt;So you did it  and got your dream job. Don't slack off now and be too indulged in your success. Getting the job is only the beginning of the challenge. Onboarding in a new team and codebase is more challenging than the interview process. You have a point to prove too.&lt;/p&gt;

&lt;p&gt;So, stay focused with a growth mindset and make the most of the opportunity to learn and grow in your role. Have personal learning goals and invest in continuous learning. Absorb knowledge from colleagues and help people around you.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Did You Know?&lt;/strong&gt;&lt;br&gt;
💡 &lt;a href="https://www.acm.org/"&gt;ACM&lt;/a&gt; offers special membership rates for members in developing countries. If you become an ACM member, you will get access to &lt;a href="https://www.oreilly.com/online-learning/"&gt;O'Reilly Learning&lt;/a&gt;. This can be a great deal for you. Check out rates for your country &lt;a href="https://www.acm.org/membership/special-member-rates-developing-countries"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can be putting in a stellar performance and still lose your job. The pandemic has demonstrated this very clearly. So love your job but be prepared to get back on the market. Change is the only constant in life. If you have the right mindset, you can turn adversities into opportunities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Develop a Digital Footprint
&lt;/h3&gt;

&lt;p&gt;If you like to write, start a blog.  If you don't enjoy writing, start a blog anyway 😁&lt;/p&gt;

&lt;p&gt;Here's how you can get into the habit:&lt;/p&gt;

&lt;p&gt;💎 Put up short posts on the things you learn or issues you solve in your projects.&lt;/p&gt;

&lt;p&gt;📝 Take notes from books you read and post them.&lt;/p&gt;

&lt;p&gt;The benefits of writing will compound with time and your future self will thank you for it. It also gives you a positive exposure to potential employers and clients.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build Your Network
&lt;/h3&gt;

&lt;p&gt;Networks are always the best source of leads and referrals. Make sure you grow meaningful connections along the way. Here's how you can start growing your network:&lt;/p&gt;

&lt;p&gt;👨‍🚀 Follow experts and veterans in your industry on social medias. I learnt about the opening in BriteCore from Daniel Feldroy's tweet. It worked out wonderfully well, I worked under him for a while at BriteCore and recently we started &lt;a href="https://bd.feldroy.com/"&gt;bd.feldroy.com&lt;/a&gt; together! [Update: we had to shut down due to the pandemic, but you get the point.]&lt;/p&gt;

&lt;p&gt;🔖 Subscribe to blogs and newsletters you like. Interact with them and grow your network.&lt;/p&gt;

&lt;p&gt;🔧 Contribute to open source projects if possible. This is also a great way to build your network.&lt;/p&gt;

&lt;p&gt;👥 Don't forget to network with your colleagues in the company. Talk to people in different departments, connect with them on social media. Connections you create along the way are priceless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep It Simple
&lt;/h2&gt;

&lt;p&gt;It's been a long read. If you've read this far, that means you're quite convinced to go remote. All this information can be overwhelming and there's a whole lot more out there on the internet. So, I'll end with a note to keep it simple and focus on a few key things.&lt;/p&gt;

&lt;p&gt;🔮 Mindset matters. If you think you can or can not do it, you're probably right.&lt;/p&gt;

&lt;p&gt;🔎 Focus gives you an edge. Stay focused on your goal. Don't run after shiny new things and change course too often.&lt;/p&gt;

&lt;p&gt;✊ Be Resilient, better yet be &lt;em&gt;antifragile&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The resilient resists shocks and stays the same; the antifragile gets better.&lt;/p&gt;

-Nassim Nicholas Taleb
&lt;/blockquote&gt;

&lt;p&gt;📚 Read voraciously, in and out of your area of expertise. There's no better way to leverage what other smart people have figured out already.&lt;/p&gt;

&lt;p&gt;Finally, don't take yourself or the job too seriously. Enjoy the nice things in life and have a balance between your ambitions and personal life.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You are not your job, you're the person you are.&lt;/p&gt;

-Toni Morrison
&lt;/blockquote&gt;

&lt;p&gt;If you have questions or want to talk to me, feel free to reach out to me on twitter &lt;a class="comment-mentioned-user" href="https://dev.to/billah_tishad"&gt;@billah_tishad&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Now go get that job and say goodbye to office spaces!&lt;/p&gt;

</description>
      <category>remote</category>
      <category>dev</category>
    </item>
    <item>
      <title>Book Review-The Temple of Django Database Performance</title>
      <dc:creator>Modasser Billah</dc:creator>
      <pubDate>Wed, 05 Aug 2020 18:51:56 +0000</pubDate>
      <link>https://dev.to/billah_tishad/book-review-the-temple-of-django-database-performance-3alh</link>
      <guid>https://dev.to/billah_tishad/book-review-the-temple-of-django-database-performance-3alh</guid>
      <description>&lt;p&gt;I recently bought an interesting tech book themed on fantasy adventure. And it was money well spent. &lt;a href="https://spellbookpress.com/books/temple-of-django-database-performance/"&gt;&lt;strong&gt;&lt;em&gt;The Temple of Django Database Performance&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; was a great read.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The only way to master Django is to master database performance. The difference between junior, mid-level and senior Django engineers is usually a function of this mastery.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The author starts his book with the bold claim above. But I'd say the content applies beyond Django and helped me get more low-level with databases than before. I encourage django devs to read this book. If you need a glimpse into it, here's my notes from the book:&lt;/p&gt;

&lt;h2&gt;
  
  
  Profiling: The Yardstick
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Before you start your ritual of performance tuning, you must be initiated in &lt;strong&gt;profiling&lt;/strong&gt;. In human terms, profiling is all about measuring your results. Without profiling you have no way to measure if your tuning pleased the database deity.&lt;/li&gt;
&lt;li&gt;APMs or &lt;strong&gt;Application Performance Monitoring&lt;/strong&gt; tools are your friend here. Think New Relic, Datadog or more recently Sentry. The book touches on details in New Relic, but I'll skip that part as that is too application specific. You can get up to speed with any of these quickly.&lt;/li&gt;
&lt;li&gt;Slow Query Logs can help as well but not at the level of APMs.&lt;/li&gt;
&lt;li&gt;For locally producing issues and gauging performance, use &lt;strong&gt;Django Debug Toolbar&lt;/strong&gt; and/or &lt;strong&gt;Silk&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query Plan&lt;/strong&gt;: The query plans details how a database intends to execute a query. Get comfortable reading these. The book is chalk-full of examples of query plans.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Indexes: The Magic Wand
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Without indexes, databases have to do sequential searches every time. O(n) every time, oh no! 😟&lt;/li&gt;
&lt;li&gt;B- Tree to the rescue. Indexes are generally &lt;em&gt;B-trees&lt;/em&gt;. B-tree maintains a tree whose leaf nodes are pointers to the disk locations of table records.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Fun fact&lt;/strong&gt;&lt;br&gt;
🛩️ Engineers at Boeing invented the B-tree data structure. But no one knows what the &lt;code&gt;B&lt;/code&gt; in &lt;code&gt;B-tree&lt;/code&gt; stands for.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Databases store data in units called &lt;code&gt;pages&lt;/code&gt;. &lt;code&gt;Page size&lt;/code&gt; is also used for index storage. In theory, the speed of the index is proportional to page size. But it has a lot of external factors like storage medium and application. So, when in doubt or in the mood to tinker, &lt;strong&gt;profile&lt;/strong&gt;!&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Postgres Tip&lt;/strong&gt;&lt;br&gt;
📌 You can see indexes defined on a table by executing &lt;code&gt;\d &amp;lt;table name&amp;gt;&lt;/code&gt; command in the &lt;code&gt;psql&lt;/code&gt; shell.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;❓ Django ORM question: How do you add an index to your Django model?&lt;/p&gt;

&lt;p&gt;💡 Specify &lt;code&gt;indexes&lt;/code&gt; field inside the &lt;code&gt;Meta&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Class Event(models.Model):
    ... # omitted for brevity
    name = models.CharField(max_length=255)
    ...
    ...
    class Meta:
        indexes = [
                    models.Index(fields=['name'],
                    name='my_first_index')
                ]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;
🔵 The &lt;code&gt;name&lt;/code&gt; attribute of the index is optional but helpful for later use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Postgres Tip&lt;/strong&gt;&lt;br&gt;
🔓 Postgres locks the table for write operations by default during the indexing process. This can take a long time  on large tables and cause headaches for your live system. Way around? Use, &lt;code&gt;CREATE INDEX CONCURRENTLY&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;☝️ This is called an &lt;em&gt;Online DDL operation&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DDL: Data Definition Language =&amp;gt; modifies the schema of the database.&lt;/li&gt;
&lt;li&gt;DML: Data Manipulation Language =&amp;gt; acts on data&lt;/li&gt;
&lt;li&gt;In relational databases, both DDL and DML are just two tribes of SQL commands.&lt;/li&gt;
&lt;li&gt;MySQL InnoDB engine doesn't lock by default.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Postgres Tip&lt;/strong&gt;&lt;br&gt;
💎 Force it to update statistics by &lt;code&gt;VACUUM ANALYZE&lt;/code&gt;, then check performance with &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;🚨 &lt;strong&gt;In general, indexes slow down write operations.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;For write-heavy applications, you need LSM Trees or SSTables instead of B-trees. Checkout &lt;strong&gt;Cassandra&lt;/strong&gt; and &lt;strong&gt;RocksDB&lt;/strong&gt; for these. &lt;strong&gt;&lt;em&gt;If you're using Django+MySQL, check out MyRocks from Facebook&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Most columns do well with B-tree indexes. However, if you are storing exotic data, you may benefit from alternative index types&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;GIN indexes for JSON data, Postgres&lt;/li&gt;
&lt;li&gt;GiST indexes for spatial data, Postgres&lt;/li&gt;
&lt;li&gt;BRIN indexes for very large tables, Postgres&lt;/li&gt;
&lt;li&gt;Hash indexes for in-memory tables, MySQL&lt;/li&gt;
&lt;li&gt;R-tree indexes for spatial data, MySQL&lt;/li&gt;
&lt;li&gt;GIN = Generalized Inverted Index

&lt;ul&gt;
&lt;li&gt;Works well with &lt;code&gt;contains&lt;/code&gt; logic for JSON data and full-text search&lt;/li&gt;
&lt;li&gt;Only available in Postgres&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Indexes are not a silver bullet (well, almost)&lt;/li&gt;
&lt;li&gt;The query planner may ignore an index and not use it! 😮&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❓ Why?&lt;/p&gt;

&lt;p&gt;💡 There can be many reasons. For appetisers, check your query plans after introducing an index to confirm whether the query plan chose to use the index.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tuning parameters/configs of the database can help, too. &lt;a href="https://www.revsys.com/writings/postgresql-performance.html"&gt;This article&lt;/a&gt; has some nice pointers about this in Postgres.&lt;/li&gt;
&lt;li&gt;If everything fails and indexes don't heal you, it may be a sign that you need to move some work out of the database and into your application, denormalise or move it into an asynchronous task.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Covering Indexes&lt;/em&gt;&lt;/strong&gt;: An index is said to &lt;em&gt;cover&lt;/em&gt; a query if the database can return all the data needed for the query directly from the index, without having to search through the table data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❓ How do you create a &lt;em&gt;Covering Index&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;💡 Multi-column indexes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE INDEX CONCURRENTLY le_index_name
ON le_table_name(le_attribute_1, le_attribute_2);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;
❗ Order of the attributes matter! An index on &lt;code&gt;(id, name)&lt;/code&gt; is not the same as the index on &lt;code&gt;(name, id)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;💡 Using the &lt;em&gt;INCLUDE&lt;/em&gt; parameter&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE INDEX CONCURRENTLY le_index_name
ON le_table_name(le_attribute)
INCLUDE (le_another_attribute);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Partial Indexes&lt;/em&gt;&lt;/strong&gt;: An index with a &lt;code&gt;WHERE&lt;/code&gt; clause is a partial index. It limits which rows in the table get added to the index.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE INDEX le_index_name
ON le_table_name(le_attribute)
INCLUDE (le_another_attribute)
WHERE le_attribute = 'le_frequently_used_value';
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Clustering
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;If the table changes infrequently and most of your queries filter on the same set of columns, you have another option: Clustering.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Clustering restructures the table data on disk in accordance to the structure in the index.&lt;/li&gt;
&lt;li&gt;Clustering is a one-time operation. Postgres does not maintain the structure of the table, so the structuring gets violated with new writes.&lt;/li&gt;
&lt;li&gt;It also requires an &lt;code&gt;ACCESS EXCLUSIVE&lt;/code&gt; lock on the table, which blocks reads and writes.&lt;/li&gt;
&lt;li&gt;So, before you say I do to Clustering, read the quote above again and decide whether you should.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;MySQL Tip&lt;/strong&gt;&lt;br&gt;
💎 Tables are automatically clustered by primary keys in MySQL InnoDB engine. And no, you can not cluster by a secondary index.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Querying: The Weapons and the AMMOs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;n+1 problem&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;1 query fetches &lt;code&gt;n&lt;/code&gt; records&lt;/li&gt;
&lt;li&gt;Then you do 1 query for each of those records to fetch some related data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;1&lt;/code&gt; (the original &lt;del&gt;sin&lt;/del&gt; query) + (One additional query for each record) &lt;code&gt;1 * n&lt;/code&gt; = &lt;code&gt;n + 1&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Healing potion?&lt;/p&gt;

&lt;p&gt;💡 Django uses lazy fetching, that's why it doesn't fetch related models in the original query.&lt;/p&gt;

&lt;p&gt;💡 Force it to be not lazy, use &lt;code&gt;select_related&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;select_related&lt;/code&gt; makes a JOIN to get data for each field name you pass in.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;events = Event.objects.select_related('user').all()
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;
    ❗ Joins can negatively impact performance. So, like any other super power, use &lt;code&gt;select_related&lt;/code&gt; with care and only when you need to.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;select_related&lt;/code&gt; only works with single value relationships like &lt;code&gt;ForeignKey&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🤔 What about &lt;code&gt;many-to-many&lt;/code&gt; and &lt;code&gt;many-to-one&lt;/code&gt; relationship (i.e, reversing a ForeignKey relationship)?&lt;/p&gt;

&lt;p&gt;💡 &lt;code&gt;prefetch_related&lt;/code&gt; to the rescue!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User.objects.all().prefetch_related('events')
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Relevant Resource&lt;/strong&gt;&lt;br&gt;
    📚 &lt;a href="https://schegel.net/posts/optimizing-django-orm-queries/"&gt;This article&lt;/a&gt; is a great place to start on &lt;code&gt;select_related&lt;/code&gt; and &lt;code&gt;prefetch_related&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;More ammunitions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;only()&lt;/code&gt; to specify which columns/attributes of a table/model to fetch
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User.objects.only('name')
&lt;/code&gt;&lt;/pre&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;defer()&lt;/code&gt; is the opposite of &lt;code&gt;only()&lt;/code&gt;. Defer fetching all columns that you don't need immediately.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;values()&lt;/code&gt; fetches data without instantiating any models. You get the data as a dict.&lt;/li&gt;
&lt;li&gt;Consider using &lt;code&gt;values()&lt;/code&gt; when you're willing to trade Django models for more speed and lower memory usage.&lt;/li&gt;
&lt;li&gt;For large set of data use &lt;code&gt;iterator()&lt;/code&gt; to read data in chunks.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;update()&lt;/code&gt; when

&lt;ul&gt;
&lt;li&gt;Updating all objects in a query set to the same set of values&lt;/li&gt;
&lt;li&gt;The update does not need any signals or custom save() methods.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;bulk_update()&lt;/code&gt; when

&lt;ul&gt;
&lt;li&gt;The query set is large&lt;/li&gt;
&lt;li&gt;Objects in the query set are updated to different values&lt;/li&gt;
&lt;li&gt;The update does not need any signals or custom save() methods&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;F()&lt;/code&gt; expressions allow you to refer to a value of a column in the database without querying for that data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;func()&lt;/code&gt;, &lt;code&gt;annotate&lt;/code&gt;, &lt;code&gt;aggregate&lt;/code&gt; are some more advanced weaponry. Skipping details, just remember they exist and pick up as needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Relevant Resource&lt;/strong&gt;&lt;br&gt;
📚  &lt;a href="https://hakibenita.com/"&gt;Haki Benita's blog&lt;/a&gt; has some great articles on databases, Django ORM and Python.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Pagination
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Pagination if often overlooked when building a new system. But it bites you eventually when the data grows in size.

&lt;ul&gt;
&lt;li&gt;Offset pagination&lt;/li&gt;
&lt;li&gt;Keyset pagination a.k.a &lt;em&gt;infinite scroll&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Offset Pagination&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Django comes with a &lt;code&gt;Paginator&lt;/code&gt; class that does offset pagination off-the-shelf.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Flaws&lt;/p&gt;

&lt;p&gt;❌ Results can be inconsistent. This can happen because of new insertions while a user is viewing a paginated page.&lt;/p&gt;

&lt;p&gt;❌ For large set of data, pages in the tail end can take longer to be queried.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Keyset Pagination&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The client sends a &lt;code&gt;keyset&lt;/code&gt; representing the last item in a page (instead of an offset and a limit). The next page is then defined as the records following that last item in sorted order.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;keyset&lt;/code&gt; is a set of columns that can be used to sort records in a stable order.&lt;/li&gt;
&lt;li&gt;Make sure an index exists for the columns used in the &lt;code&gt;keyset&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;DRF has it built-in,  use &lt;code&gt;CursorPagination&lt;/code&gt;!&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;django-keyset-pagination&lt;/code&gt; is another third party library for this.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Flaws&lt;/p&gt;

&lt;p&gt;❌ Lack of tooling support in vanilla Django&lt;/p&gt;

&lt;p&gt;❌ Can not select arbitrary pages, only the next page or the previous page.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I enjoyed the technical tidbits as much as I enjoyed the accompanying fantasy adventure. If you're interested to buy the book, head over to &lt;a href="https://spellbookpress.com/books/temple-of-django-database-performance/"&gt;Spellbook Press website&lt;/a&gt;. Support indie publishers!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover Image Credit: Spellbook Press web page of the book&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://modasserbillah.ml/2020/08/05/temple-of-django-database/"&gt;my personal blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>database</category>
      <category>bookreview</category>
    </item>
    <item>
      <title>Generate Generators Repeatedly</title>
      <dc:creator>Modasser Billah</dc:creator>
      <pubDate>Mon, 15 Jun 2020 16:59:38 +0000</pubDate>
      <link>https://dev.to/billah_tishad/generate-generators-repeatedly-2jd8</link>
      <guid>https://dev.to/billah_tishad/generate-generators-repeatedly-2jd8</guid>
      <description>&lt;p&gt;Generators are great. We all know it. They save us all the memory lists take up yet give us the same results and more. Well, almost. &lt;/p&gt;

&lt;p&gt;The only catch with generators is that they generate the values only once. Let's look at an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;
        &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The function above gives us a generator. It takes a number as an argument and produces all the numbers from there down to 1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;generate5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generate_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we print &lt;code&gt;generate5&lt;/code&gt; it will show us that it holds a generator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generate5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt; &lt;span class="n"&gt;generate_numbers&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="mh"&gt;0x10dcb2b88&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we can do something like the following to generate the numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;generate5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And this will print:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But if you run it again&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;generate5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You won't see any output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/6uGhT1O4sxpi8/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/6uGhT1O4sxpi8/giphy.gif" alt="Where did it go?"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, this is what generators do. They generate values on the fly and then stop. You can't run them again and again unless you run &lt;code&gt;generate5 = generate_numbers(5)&lt;/code&gt; each time. Generally people will tell you in cases like this you should use a list. &lt;/p&gt;

&lt;p&gt;But there's a way around if you insist on using generators yet want repeated outputs. Let's see how.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NumberGenerator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__iter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;
            &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The code from the &lt;code&gt;generate_numbers&lt;/code&gt; function is copied over (well, almost with slight class related modifications) to the &lt;code&gt;__iter__&lt;/code&gt; method for the &lt;code&gt;NumberGenerator&lt;/code&gt; class. Whenever we loop through an object, it looks up the &lt;code&gt;__iter__&lt;/code&gt; method. If it's there, Python will use it to return an iterator. &lt;/p&gt;

&lt;p&gt;So, now you can do something like this to instantiate the class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;generate5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NumberGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And then loop over it as many times as you want using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;generate5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that this may not be the optimal thing to do all the time but it's an interesting tidbit to know that you can hack a generator this way to work more than once. &lt;/p&gt;

&lt;p&gt;Happy hacking!&lt;/p&gt;

&lt;p&gt;This post was originally published &lt;a href="https://modasserbillah.ml/2020/06/15/generator/"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>generators</category>
      <category>hack</category>
    </item>
    <item>
      <title>Crack the Code</title>
      <dc:creator>Modasser Billah</dc:creator>
      <pubDate>Sun, 12 Apr 2020 17:56:32 +0000</pubDate>
      <link>https://dev.to/billah_tishad/crack-the-code-8pe</link>
      <guid>https://dev.to/billah_tishad/crack-the-code-8pe</guid>
      <description>&lt;p&gt;With quarantines and lock-downs, most people around the world are stuck and bored in their houses. A lot of fun riddles are circulating in news feeds on social medias. Here's one of those.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmodasserbillah.ml%2Fimages%2Fquiz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmodasserbillah.ml%2Fimages%2Fquiz.jpg" alt="riddle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Can you crack the code? It's fun to solve by hand but can you crack it using Python? Here's how I did it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;itertools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;first_fifth_condition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;common_elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;candidate&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;common_elements&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;common_elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;common_elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;second_condition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;common_elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;candidate&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;common_elements&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;common_elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;common_elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;third_condition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;common_elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;candidate&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;common_elements&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;common_elements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fourth_condition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;common_elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;candidate&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;common_elements&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_code&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# for completeness test all possible permutations with repetition of digits for length 3.
&lt;/span&gt;    &lt;span class="c1"&gt;# We can further optimize by eliminating 0,5,2,3 from the possible candidate calculation.
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;candidate&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;first_fifth_condition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;second_condition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;third_condition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;fourth_condition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;first_fifth_condition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No solution found.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;find_code&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Got better code to crack the code? Share links to your solution in the comments! Happy hacking!  &lt;/p&gt;

</description>
      <category>python</category>
      <category>fun</category>
      <category>codechallenge</category>
    </item>
    <item>
      <title>Level Up Your Python Code Reviews</title>
      <dc:creator>Modasser Billah</dc:creator>
      <pubDate>Sat, 11 Apr 2020 14:31:17 +0000</pubDate>
      <link>https://dev.to/billah_tishad/level-up-your-python-code-reviews-2fh1</link>
      <guid>https://dev.to/billah_tishad/level-up-your-python-code-reviews-2fh1</guid>
      <description>&lt;p&gt;In the world of software development, there are many things that classes and books will prepare you for. But there are some topics that are often overlooked in learning resources yet hold immense value for the craft. Code review is a topic very high on that list. Knowing to review Python code well can land you into senior positions in no time.&lt;/p&gt;

&lt;p&gt;In modern software development, code reviews play a pivotal role in ensuring the quality of software. This article takes a shot at explaining how to adopt Python philosophies to review code and then perform code reviews in a more Pythonic way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At the end of the article, you'll be able to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand the different aspects of Python code review&lt;/li&gt;
&lt;li&gt;Develop a process to review code thoroughly and professionally&lt;/li&gt;
&lt;li&gt;Detect areas of improvement in code with a higher probability&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This article assumes you know how to use git and how collaborative software development works using Pull Requests. If you're not familiar with git and GitHub, check out the &lt;a href="https://guides.github.com/activities/hello-world/"&gt;Hello World GitHub Guide&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Objectives of Code Review
&lt;/h2&gt;

&lt;p&gt;Before you dive into how to do a good Python code review, let's first contemplate on why good code reviews are important. Peer review is the scientific process of verifying new knowledge. This is a widely practiced method in the scientific community.&lt;/p&gt;

&lt;p&gt;Code review is the equivalent process in the world of software development. No one is perfect. That's the primary reason for code reviews. It always helps to have a fresh pair of eyes go through the code.&lt;/p&gt;

&lt;p&gt;The benefits of code review can be broadly categorized in the following 3 categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Catching bugs&lt;/li&gt;
&lt;li&gt;Ensuring code quality and maintainability&lt;/li&gt;
&lt;li&gt;Building relationships&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's explore how code reviews help us achieve these benefits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Catching Bugs
&lt;/h3&gt;

&lt;p&gt;Code review helps catch bugs before they go into production. Performance issues are also addressed in code reviews. This helps enhance the quality of the software in terms of both efficiency and correctness.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ensuring Code Quality and Maintainability
&lt;/h3&gt;

&lt;p&gt;Code is read much more often than it is written. Like in any engineering discipline, maintainability matters a lot in software. Code reviews ensure that someone has already read your code and understood it or raised the issue and helped you make it more readable and maintainable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building Relationships
&lt;/h3&gt;

&lt;p&gt;Friendship happens on the way to something else. Think of all the friends you have in your life. You didn't become friends just for the sake of being friends. Rather you shared a pursuit with them and in the process became friends.&lt;/p&gt;

&lt;p&gt;This is often overlooked but code reviews can spark conversations. Through collaboration, discussion and sometimes, the disagreements that happen on code reviews, you can often befriend fellow developers if you have the right mindset for code reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python Code Review: The Human Aspect
&lt;/h2&gt;

&lt;p&gt;The human aspect is often the one overlooked in code reviews. Good technical reviews can lose effectiveness due to poor communication and lack of empathy. You should try to keep it human. Having a few pointers in mind helps in this regard. Let's try to establish some.&lt;/p&gt;

&lt;h3&gt;
  
  
  You're Reviewing Python Code Written by Humans
&lt;/h3&gt;

&lt;p&gt;When reviewing a piece of Python code, it is important to factor in the human aspect. You need to make sure that your legitimate concerns and feedback are not nullified by your lack of empathy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; People often make jokes about developers for lacking social skills which is not entirely true but has some truth to it. So, choose your words carefully and try to be positive. Be critical but courteous.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you point out an issue, always try to explain why. It may be obvious to you and you may feel inclined to just make a one-liner comment to change this to that. But it may not be obvious to others including the author.&lt;/p&gt;

&lt;p&gt;Explaining the why helps you to connect with the authors and gives them a chance to respond correctly. It also serves as a learning point for anyone going through the pull request.&lt;/p&gt;

&lt;p&gt;The tone and warmth of the reviewer is lost in transmission on a written medium. As a result, comments with the best of intentions can be perceived as harsh. So, whenever possible, try to keep it warm with appropriate emojis to propagate your good vibes 🙂&lt;/p&gt;

&lt;p&gt;However, the other extreme can also occur at times. Sometimes people overdo it to sound less critical and the message loses its meaning. Writing generic comments or always following a certain template can expose the mechanical nature of the review and make the author feel like you don't mean it.&lt;/p&gt;

&lt;h3&gt;
  
  
  There's No Exclusively Correct Opinion
&lt;/h3&gt;

&lt;p&gt;While best practices do exist, there are very few binary rights and wrongs in coding. Building software is an art and like any other art, a lot of it is subjective. So, while you should not shy away from expressing and defending your opinion, remember that your opinion is not the last word on the topic.&lt;/p&gt;

&lt;p&gt;There may be other perspectives, there maybe flaws in your argument and there may be more convincing argument behind the original proposal. So, keep your mind open while you express your opinion and don't hesitate to change your opinion once there's compelling evidence to do so.&lt;/p&gt;

&lt;p&gt;Even if there's none, accept the fact that your opinion can be disregarded. Remember the phrase, &lt;strong&gt;strong opinions loosely held&lt;/strong&gt;. You fight for your opinion but don't cling to it like revelation.&lt;/p&gt;

&lt;p&gt;At times, developers tend to go overboard in the heat of the moment while defending an opinion. This reduces the objectivity of the discussion and makes the author take it personally.&lt;/p&gt;

&lt;p&gt;One trick to avoid this is to make a context switch before you finally post your review. Let's say you wrote a long review and explained how it can be done better. Don't hit the comment button instantly.&lt;/p&gt;

&lt;p&gt;Instead, take a moment to get your head out of the zone. Maybe check your mail or twitter feed for a moment or take a sip of the coffee waiting on your desk. Then come back and read your review. More often than not, you'll feel inclined to change a word or two, or rephrase a sentence. It may feel like a small thing but it can do wonders!&lt;/p&gt;

&lt;p&gt;You may not know the author in person but you know for sure that it is written by a human. So, be nice and follow the golden rule, &lt;strong&gt;treat others the way you want to be treated&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Embrace Feedback Don't Dread It
&lt;/h3&gt;

&lt;p&gt;On the side of the author, code review can be a stressful event, especially for people with less experience. It's easy to feel demoralized and think you don't know how to write code when someone requests some changes.&lt;/p&gt;

&lt;p&gt;Imposter syndrome is real and everyone feels it. This can also make people defensive and rigid about accepting reviews. That's why it is important to keep in mind that the reviewer is trying to help.&lt;/p&gt;

&lt;p&gt;There's nothing personal and no blame game going on. Objectively taking feedback is a great skill. Whenever it feels personal, remind yourself that the ultimate objective is to improve code quality.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TIP:&lt;/strong&gt;&lt;br&gt;
If a review is unclear or you don't understand the reason behind it, don't be afraid to ask why. As said before, coding is an artistic endeavor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, ask for reasons politely and present your arguments if you disagree with the reviewer. Learning is also an important outcome of the code review process. If you accept all requested changes without asking questions, you are depriving yourself of valuable learning opportunities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python Code Review: The Technical Aspect
&lt;/h2&gt;

&lt;p&gt;This is the most critical part of the review. A review has to be technically sound to add value to the process of building softwares. You should have a rigorous process to sift through the code during a review. Keep iterating over the process to make your review a little better every time. Good news is, you can borrow from the collective wisdom of the developer community in this regard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stand on the Shoulder of Giants
&lt;/h3&gt;

&lt;p&gt;Software engineering has a rich history. A lot of smart people have already figured out a lot of cool things to help you build better software. Be smart and don't reinvent the wheel. Rather, build from what's already in place. Let's dive into some of the first principles you can use all the time.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Zen of Python
&lt;/h4&gt;

&lt;p&gt;Python is much appreciated for the design philosophy behind it. You can build your Python code review muscles by starting from the guiding principles of the language. Much of this is beautifully condensed in &lt;strong&gt;The Zen of Python&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can read the &lt;em&gt;Zen of Python&lt;/em&gt; any time you want from a Python shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; import this
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wisdom and first principles are often simple but not simplistic. That's why it's easy to overlook them. But sticking to them can really improve the quality of both the code and the review.&lt;/p&gt;

&lt;p&gt;For example, you can often come around code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_authenticated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;some_private_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;not_allowed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But &lt;em&gt;Zen of Python&lt;/em&gt; teaches you that &lt;em&gt;flat is better than nested&lt;/em&gt;, so you can suggest this to be done this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_authenticated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;not_allowed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;some_private_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The example above is over simplified but you get the point.&lt;/p&gt;

&lt;h4&gt;
  
  
  Readability
&lt;/h4&gt;

&lt;p&gt;Readability is often underestimated but it's very important for maintainability. It is a central philosophy that guided the development of Python as a language. Think about the ideas of indentation based scoping and no semicolons. Remember, the first consumer of your code is you. So make it readable for your future self.&lt;/p&gt;

&lt;p&gt;When you're new to Python and learning a lot of cool tricks, it's easy to assume that writing complex one-liner code demonstrates that you're a good Python developer. Same can be said about reviewers, you can feel that you have suggested an improvement by recommending a one-liner in place of a code block. Look at the following snippet for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x is 3"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="s"&gt;"x is not 3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It's only one of line of code but takes the reader longer to understand what it does. Whereas you can just write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x is 3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x is not 3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is easier to read and understand but you may not feel like a genius when you write it. That's where you need to be more careful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code is communication.&lt;/strong&gt; Computers only do maths and shuffle bits around. There are infinite ways to make a computer take a certain input and create a certain output.&lt;/p&gt;

&lt;p&gt;The code you choose to use should mainly and most importantly tell other developers what it does. That's why Python is such a great programming language, it's readable. The &lt;em&gt;Zen of Python&lt;/em&gt; backs it up as well.&lt;/p&gt;

&lt;h4&gt;
  
  
  Best Practices
&lt;/h4&gt;

&lt;p&gt;Best practices exist for a reason. It helps you to benefit from the experiences of the people who figured things out before you. So, use them as guiding lights. If you see a single letter variable name while doing a Python code review, then ask why. Don't stop on why, suggest a better descriptive name.&lt;/p&gt;

&lt;p&gt;Similarly, when you read a code block and understand what and how it does but not the why, ask why. Suggest that the why should be included as a code comment.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tests
&lt;/h4&gt;

&lt;p&gt;In a Python code review, it's important to ensure that the piece of code under review is well tested and documented. Tests ensure integrity of the code. If the Python code you're reviewing has new functions or classes added but no tests, then politely ask why. One hundred percent code coverage is not always feasible, so it's important to understand the author's perspective and suggest writing tests based on the case in hand.&lt;/p&gt;

&lt;p&gt;There are different well accepted testing libraries like &lt;a href="https://docs.pytest.org/en/latest/"&gt;&lt;code&gt;pytest&lt;/code&gt;&lt;/a&gt; and Python's own &lt;a href="https://docs.python.org/3/library/unittest.html"&gt;&lt;code&gt;unittest&lt;/code&gt;&lt;/a&gt; library. It is better to choose one instead of mixing different approaches together.&lt;/p&gt;

&lt;h4&gt;
  
  
  Documentation
&lt;/h4&gt;

&lt;p&gt;Tests are a good documentation of what the code does. But it is also important to document Python code, especially public APIs. That's why you should check functions, classes and methods for docstrings and suggest adding one if there's none.&lt;/p&gt;

&lt;p&gt;There are a few accepted styles of documentation. For example, &lt;a href="https://numpydoc.readthedocs.io/en/latest/format.html"&gt;NumPy-style&lt;/a&gt;, &lt;a href="https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings"&gt;Google Docstring convention&lt;/a&gt; and so on. Any of these should be good to follow but it is important to remain consistent throughout the project.&lt;/p&gt;

&lt;h4&gt;
  
  
  Style Guides
&lt;/h4&gt;

&lt;p&gt;One other important resource that you can readily borrow from others and put to use is style guides. Style guides keep code organized. Remember, coding is akin to art and art is subjective. If an agreed upon style is not enforced, the codebase can become messy and hard to maintain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pep8.org/"&gt;PEP 8&lt;/a&gt; is the guiding principle in this respect and you should refer back to it from time to time. Most IDEs come with linters. Linters check for style violations and display errors. Using a Python linter like &lt;a href="https://flake8.pycqa.org/en/latest/"&gt;Flake8&lt;/a&gt; can help reduce a lot of style related errors. You can also use a formatter like &lt;a href="https://black.readthedocs.io/en/stable/"&gt;black&lt;/a&gt; to handle formatting for you.&lt;/p&gt;

&lt;p&gt;Nevertheless, it is essential to have a good grasp on the PEP 8 guidelines and look out for related issues when you're doing a Python code review. &lt;a href="https://www.flake8rules.com/"&gt;Flake8 Rules&lt;/a&gt; is a great resource to learn about it from examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Value Structure and Encourage Systems Thinking
&lt;/h3&gt;

&lt;p&gt;So far, this article focused on how you can benefit from the collective wisdom of Python developers in your Python code reviews. &lt;strong&gt;But each project is different and strictly sticking to any guideline out of context can cause more troubles than it solves. That's where your situational awareness comes in.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You need to know the objectives of the project. The type of the project, the deadlines you need to meet, the people that will be using your product -- all should be factored in your overall strategy.&lt;/p&gt;

&lt;p&gt;For example, if you're working at a start up and building a prototype, then functionality may be prioritized over maintainability. Code with less test coverage may be allowed to go through. In this case, your Python code review should be more focused on functionality and testing.&lt;/p&gt;

&lt;p&gt;But if you're working on an enterprise solution, then you may need to focus more on maintainability and quality. Issues that could have been overlooked for a small project may not be allowed to go through in an enterprise solution. You may also need to be more rigorous in following up on style guides and internal coding standards.&lt;/p&gt;

&lt;p&gt;Similarly, you may need to adapt your reviews depending on whether the product is in production already or not.&lt;/p&gt;

&lt;h4&gt;
  
  
  Be Aware of the Structure of the Project
&lt;/h4&gt;

&lt;p&gt;This is where another &lt;em&gt;Zen of Python&lt;/em&gt; principle comes into play, &lt;em&gt;practicality over purity&lt;/em&gt;. You need to be pragmatic about your approach. &lt;strong&gt;Have a clear idea about which parts of the codebase can be more flexible and which parts need to be more airtight&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Disregarding principles is a bad idea and in most cases, &lt;em&gt;special cases aren't special enough to break the rules&lt;/em&gt;(Yet another &lt;em&gt;Zen of Python&lt;/em&gt; wisdom). But irrational adherence to them is not ideal either. So, keep the trade-off in mind when you suggest a change in your Python code review. &lt;strong&gt;Keep an eye out to ensure that the codebase is modular and well structured.&lt;/strong&gt; One component should only do one thing. Otherwise, soon every module will have a dependency on every other module and the codebase will start looking like a big ball of mud.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't let perfect be the enemy of good.&lt;/strong&gt; Sometimes it's better to get something merged and improve on that work in future pull requests.&lt;/p&gt;

&lt;p&gt;Code in isolated components, modules, or packages often shouldn't be held back for minor issues. Instead of holding back the pull request, point out the area of improvements and approve the existing work on the condition that your points be considered during future iterations on this. Importantly, be sure that you always highlight these desired changes and follow up on them.&lt;/p&gt;

&lt;p&gt;In general, you can be more lenient regarding the &lt;em&gt;how&lt;/em&gt; of a system than the &lt;em&gt;what&lt;/em&gt;. For example, what a public method does should be thoroughly inspected but the implementation of the method can be improved upon iteratively. This is because future improvements should only have effects within the system not with the outside world.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But know when to stand your ground.&lt;/strong&gt; Contrary to the case of isolated components, shareable components should be held to a higher standard. Unclear naming or overly complicated interactions between parts of the system are a very real problem and will quickly become difficult to alter.&lt;/p&gt;

&lt;p&gt;It's still important to avoid letting perfect be the enemy of good, but if significant changes will be difficult to perform later due to widespread usage, it's usually worth spending a little time on that early in the development process.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
Public code (for example, public interfaces, APIs) should be critically evaluated for ease of use and understanding before releasing because future changes may require changing every interaction throughout the system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Often times, people come into a project and start suggesting changes that are Pythonic in principle but may not be in accordance with the existing codebase. No one and no codebase is ideal but you need to ensure local consistency before you suggest a change otherwise.&lt;/p&gt;

&lt;p&gt;For example, a codebase may have been using single quote docstrings but you prefer the NumPy docstring style of double quotes. It is important to not introduce a change that creates confusion and parallel conventions in the codebase. Remember this from PEP 8:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A Foolish Consistency is the Hobgoblin of Little Minds."&lt;/p&gt;

&lt;p&gt;-- &lt;em&gt;Guido van Rossum&lt;/em&gt; (&lt;a href="https://www.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds"&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, make sure you're locally consistent before trying to achieve a general consistency.&lt;/p&gt;

&lt;h4&gt;
  
  
  Leverage Systems Thinking
&lt;/h4&gt;

&lt;p&gt;Systems thinking is the ability or skill to perform problem solving in complex systems. &lt;strong&gt;Software systems are inherently complex.&lt;/strong&gt; In order to provide useful feedback, you need to be able to identify the constituent parts of the system and the interactions between them. Developing a mental model for systems thinking can help you detect areas of improvement in your Python code reviews. Think of code as a collection of systems and the interaction among them. This applies to reviews as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The whole is greater than the sum of the parts.&lt;/p&gt;

&lt;p&gt;-- Aristotle&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's easy to get pulled into the code block under review and forget the bigger picture. So, it's important to step back and think about what the code does without getting into the how immediately. That's where the quote from Aristotle comes into play. The code may work fine in isolation but cause issues when it runs as a part of a system.&lt;/p&gt;

&lt;p&gt;Reflect on how the feature could fail. Think about ways to break the code. Many a times, developers code for the happy path. That is, they write code in such a way that it only handles the best possible path.&lt;/p&gt;

&lt;p&gt;But real world is messy. Users can do stupid things, machines can fail and cause errors. So, look out for scenarios that are likely to happen but not considered in the solution. Here's a very simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_velocity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The function above calculates velocity. It works well for most cases except when &lt;code&gt;time&lt;/code&gt; is &lt;code&gt;0&lt;/code&gt;. So, it will throw an error in that case but the code doesn't handle that error.&lt;/p&gt;

&lt;p&gt;This is bad and no foreseeable errors should go unhandled. So, thinking like a hacker can help you provide good insights in your Python code reviews.&lt;/p&gt;

&lt;p&gt;Similarly, you should try to think of the problem without being influenced by the solution of the author. This helps to point out the assumptions made by the author in the solution. This conforms to another &lt;em&gt;Zen of Python&lt;/em&gt; principle: &lt;em&gt;In the face of ambiguity, refuse the temptation to guess&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For example, look at the following code block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;assign_random_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The function above assigns a random number to each user in the list of users passed in the argument. It creates a dictionary mapping between the users and a random number and returns the dictionary.&lt;/p&gt;

&lt;p&gt;It may look like a good solution at first glance but it has two assumptions attached to it.&lt;/p&gt;

&lt;p&gt;Let's look into the assumptions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It uses &lt;code&gt;user&lt;/code&gt; as the key for the dictionary. But for that to hold true, the elements in the &lt;code&gt;users&lt;/code&gt; list must be hashable.&lt;/li&gt;
&lt;li&gt;This solution assumes that all the user names in the passed &lt;code&gt;users&lt;/code&gt; list argument will be unique. But names can be duplicate in real world and in case of a duplicate name, values for the same key would be overwritten.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Developers often want to solve problems and impulsively make assumptions to go through the problem at hand.&lt;/strong&gt; Be aware of this in your Python code reviews and you will be able to provide important feedbacks and prevent untested assumptions sneaking into production code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Performance is also an important topic to review. Depending on the scope of the project, performance can be critical. Even when it's not so, it is good to not let non-performant code go through.&lt;/p&gt;

&lt;p&gt;For example, if you see nested &lt;code&gt;for&lt;/code&gt; loops, ask why the author wrote the code this way and suggest an alternative approach if one exists.&lt;/p&gt;

&lt;p&gt;Using profiling to test the performance of the code may also uncover insights into performance issues. These may be more applicable to api responses and complex queries.&lt;/p&gt;

&lt;h3&gt;
  
  
  General Technical Considerations
&lt;/h3&gt;

&lt;p&gt;There are some general issues to consider as well that are not necessarily related to Python but are important in terms of code reviews.&lt;/p&gt;

&lt;p&gt;Keep the following in the back of your mind when doing a Python code review:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A Pull Request Should Do a Single Atomic Thing:&lt;/strong&gt; Code reviews are mainly done on pull requests. So, the number of commits in a pull request or the scope of the pull request is important for review. Ideally, it should be a unit of functionality that can be tested in isolation. This makes reviews easier and reduces the probability of bugs sneaking into production. If you see a pull request with 30 commits and 50 files changed, then it is a good idea to suggest that the pull request be broken into several smaller pull requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit Messages Should be Relevant and Meaningful:&lt;/strong&gt; Commit messages should be reviewed as well. Commit messages preserve the history of the project. So,  if you see a lot of work in progress commits, then you can request squashing the commits to keep the history clean and coherent. If you see meaningless commit messages like &lt;code&gt;bug fix&lt;/code&gt; or &lt;code&gt;wip&lt;/code&gt; and so on, then you should ask to modify the messages to something more meaningful. It is good to know &lt;a href="https://chris.beams.io/posts/git-commit/"&gt;How to Write a Git Commit Message&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typos and Grammatical Mistakes Should Not be Overlooked:&lt;/strong&gt; Developers can code from all parts of the world and that means grammar issues in variable names, code comments, documentation and git commits are a common occurrence. Typos are frequent as well. It is important to point these out in a friendly manner but not hold back important features that need to get through.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's a good idea to start your review with these items. That way, you get a good overview of the pull request under review and can dive deep into the details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python Code Review: The Organizational Aspect
&lt;/h2&gt;

&lt;p&gt;Code reviews happen in a collaborative environment and successful collaboration needs careful organization. Setting up clearly defined processes around code review can speed up the development workflow and increase productivity and quality.&lt;/p&gt;

&lt;p&gt;If you've read this far, then you may have already noticed that there is a pattern. &lt;strong&gt;It is possible to automate and standardize parts of the Python code review process to raise the level of productivity as a team.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Standards and guidelines can help align all the team members to produce coherent code and reviews. You can further raise the bar of reviews by incorporating checks like &lt;strong&gt;continuous integration&lt;/strong&gt;, code coverage, linters and so on.&lt;/p&gt;

&lt;p&gt;For example, style guides are mostly static. So, style checks can be automated using bots like &lt;a href="https://github.com/grantmcconnaughey/Lintly"&gt;Lintly&lt;/a&gt;, &lt;a href="https://github.com/features/actions"&gt;GitHub actions&lt;/a&gt; or &lt;a href="https://pre-commit.com/"&gt;pre-commit hooks&lt;/a&gt;. These checks will automate parts of the things you need to review and allow you to focus on the code more.&lt;/p&gt;

&lt;p&gt;Developing a pull request description template is also very useful for Python code reviews. A description template helps the author to present his pull request in a systematic fashion. It also helps the reviewer to learn the overall scope of the pull request before delving into the code. An example pull request template can be like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Problem&lt;/span&gt;
Small description of the problem

&lt;span class="gu"&gt;## Accepted Solution&lt;/span&gt;
A small summary of the approach taken to solve the problem

&lt;span class="gu"&gt;## Instructions to Test&lt;/span&gt;
Some step by step instructions or automated commands to test out the solution

&lt;span class="gu"&gt;## Links to related work&lt;/span&gt;
Links to dependent pull requests, user stories, bug reports,
support tickets and so on
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository"&gt;Creating a pull request template for your repository&lt;/a&gt; is very helpful. This way, everyone creating PRs on the repo will automatically get the template in their PR body to fill in the sections.&lt;/p&gt;

&lt;p&gt;You have been introduced to a number of aspects to consider during your Python code review. Remembering all of this can be hard initially. Using checklists for reviews can help you approach your Python code review tasks more systematically.&lt;/p&gt;

&lt;p&gt;You can prepare a personal checklist to go through during your reviews. Here's an example of what it can look like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are tests for new code being added.&lt;/li&gt;
&lt;li&gt;There are no typos, grammar issues.&lt;/li&gt;
&lt;li&gt;Code is readable and variables and functions have meaningful names.&lt;/li&gt;
&lt;li&gt;There is documentation for public methods.&lt;/li&gt;
&lt;li&gt;The solution handles errors properly.&lt;/li&gt;
&lt;li&gt;Overall, the code conforms to the &lt;em&gt;Zen of Python&lt;/em&gt; and best practices.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aspects are organizational because these make the most impact when adopted across the whole team. Knowing about this also provides you an opportunity to suggest organizational processes to the team. This can optimize overall Python code review workflow and enable you to contribute more to the team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hopefully, you've come across a lot of new concepts in this article. Learning and applying it well can help you become a better reviewer and in the process a better technical leader.&lt;/p&gt;

&lt;p&gt;To summarize, this article expanded on how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Analyze the process of Python code review&lt;/li&gt;
&lt;li&gt;Approach each part of the process accordingly&lt;/li&gt;
&lt;li&gt;Look back at the whole process to optimize it for you and the team&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is easy to get bogged down into the details and lose focus on the bigger picture. So, let's revisit the proper scope for Python code reviews one last time. &lt;strong&gt;Gratitude multiplies, so does frustration&lt;/strong&gt;. So, be generous, kind and empathetic in your reviews.&lt;/p&gt;

&lt;p&gt;Don't overcomplicate things, rather keep it simple and encourage others to write more Pythonic code. Be receptive to feedback when you're on the receiving end and consciously iterate on feedback to improve. Lastly, remember that the goal is to come out of the Python code review process a bit better, for all the 3 entities involved: the author, the reviewer and the codebase. Now, go perform Python code reviews like a pro!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Acknowledgements: I have drawn a lot of inspirations for this article from my time at BriteCore. Some ideas are directly from Lennart Regebro and Daniel and Audrey Feldroy. Thanks to all my colleagues there, past and present, who have put in place wonderful processes and standards for code review.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The article was originally published &lt;a href="https://modasserbillah.ml/2020/04/11/python-code-review/"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>codereview</category>
      <category>bestpractices</category>
    </item>
    <item>
      <title>Shell Function for Pulling PRs</title>
      <dc:creator>Modasser Billah</dc:creator>
      <pubDate>Thu, 18 Apr 2019 09:18:51 +0000</pubDate>
      <link>https://dev.to/billah_tishad/shell-function-for-pulling-prs-156</link>
      <guid>https://dev.to/billah_tishad/shell-function-for-pulling-prs-156</guid>
      <description>&lt;p&gt;Fetching PRs opened by others for reviewing or testing new functionalities is a common task. Generally, you'd do the following for this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git fetch upstream pull/&amp;lt;PR_NUMBER&amp;gt;/head:&amp;lt;BRANCH&amp;gt; &amp;amp;&amp;amp; git checkout &amp;lt;BRANCH&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Typing this everytime can soon become irritating and you can't have an alias for it because PR number and branch name will vary.&lt;/p&gt;

&lt;p&gt;So, shell function comes to the rescue! Functions can take parameters, so it makes our lives easier in this case.&lt;/p&gt;

&lt;p&gt;So, if you want a shorthand for the above commands, try the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Put this in your shell configuration file like, .bashrc or .zshrc :&lt;/li&gt;
&lt;/ul&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Source the config file with &lt;code&gt;source ~/&amp;lt;Shell_Config_File_Name&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fetch and checkout a PR branch with: &lt;code&gt;pr &amp;lt;PR_NUMBER&amp;gt; &amp;lt;USER:BRANCH&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The shell function is a bit opinionated. I prefer to name branches as originally named by the author in their fork. This helps keep track when you have a lot of branches.&lt;/p&gt;

&lt;p&gt;GitHub has recently introduced a copy button beside the branch name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lYsMGynx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://modasserbillah.ml/img/github_copy_button.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lYsMGynx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://modasserbillah.ml/img/github_copy_button.png" alt="copy_button"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, it makes it easier just to click that button to copy the branch name but it comes with a user name as well. But you don't have to worry about it, just copy it as it is with the button and use that as the second variable to call the shell function. The first line of the function splits and takes only the branch name to use it as the new branch name.&lt;/p&gt;

&lt;p&gt;Happy hacking!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Initially published at: &lt;a href="http://modasserbillah.ml"&gt;http://modasserbillah.ml&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>shell</category>
      <category>github</category>
      <category>git</category>
    </item>
  </channel>
</rss>
