<?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: JeffD</title>
    <description>The latest articles on DEV Community by JeffD (@cotcotcoder).</description>
    <link>https://dev.to/cotcotcoder</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%2F37490%2Fe43a3fdf-fedc-4031-9415-4a80ad9f7473.png</url>
      <title>DEV Community: JeffD</title>
      <link>https://dev.to/cotcotcoder</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cotcotcoder"/>
    <language>en</language>
    <item>
      <title>Testing: the hidden side</title>
      <dc:creator>JeffD</dc:creator>
      <pubDate>Mon, 20 Mar 2023 07:59:36 +0000</pubDate>
      <link>https://dev.to/cotcotcoder/testing-the-hidden-side-29a7</link>
      <guid>https://dev.to/cotcotcoder/testing-the-hidden-side-29a7</guid>
      <description>&lt;p&gt;Testing is an activity with a very wide scope. We should test all critical components of our project, and it goes much further than the software features.&lt;/p&gt;

&lt;p&gt;Let's remove two misconceptions about test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All tests are not code (unit or functional test) and automated. Test may be a simple script started on demand or a visual check.&lt;/li&gt;
&lt;li&gt;Tests have different frequencies: some may be run once a day only or for each release according to the risk. The &lt;em&gt;test flow&lt;/em&gt; follows the development flow, it starts from developer workspace (pre-commit, git hook) and ends in production so some test may be outside the continuous integration tool and not be run for each commit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's focus on the target of our tests: &lt;strong&gt;WHAT&lt;/strong&gt; to test ?&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Input and Output
&lt;/h2&gt;

&lt;p&gt;In our project, you should test all input and output of your system, user input is generally well tested, but some internal features are not. It may be hidden code provided by an external library or written in a different language. Let's analyze the code to find code-related critical features.&lt;/p&gt;

&lt;p&gt;Here are some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Telemetry (logs, metrics and traces): do we really want a new release that doesn't write any logs ? If no, then we should probably find a way to get alerted if the telemetry brutally stop (Prometheus endpoint unavailable or empty record)&lt;/li&gt;
&lt;li&gt;Alert: we can raise alert to a warning level to ensure production outage will be reported. This kind of test may be done in a QA or staging environment.&lt;/li&gt;
&lt;li&gt;Automated process (scheduled job or database stored procedure): all critical job's execution must be tracked, any lack of the launch should raise an alert.&lt;/li&gt;
&lt;li&gt;Package: ensure the package contain the right content (config files for all environment) and doesn't contain sensitive data. For this kind of test the best place is in a pre-commit rule to avoid these secret were versioned.&lt;/li&gt;
&lt;li&gt;Release: &lt;a href="https://en.wikipedia.org/wiki/Smoke_testing_(software)"&gt;smoke test&lt;/a&gt; ensure the release is valid, but we can add test to ensure retro-compatibility; for example checking the new application works with the old version of the database (if this case may happen). This test is more complex than a simple unit-test, but it was greatly simplified by containers.&lt;/li&gt;
&lt;li&gt;Resource's policy: ensure your service can access to all required resource (storage, database, message queue...) and read/write data. These cases are probably already present in the functional test suite.&lt;/li&gt;
&lt;li&gt;Security procedure: this document list all the steps to be taken in response to an incident. To ensure all the step are correct and everyone in the team understand it, you should simulate commons incident and test your process.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code tests
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Back-to-back testing
&lt;/h3&gt;

&lt;p&gt;This vocabulary term is used when we run the same test launched on two different versions of the code, for example when we use &lt;em&gt;git bisect&lt;/em&gt; - To learn more about this Git feature, read &lt;a href="https://dev.to/mokkapps/use-git-bisect-to-find-the-commit-that-introduced-a-bug-2j3b"&gt;this short but efficient introduction&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Canary test
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Health check&lt;/strong&gt; is a constant call to a production service to ensure the service is up. This kind of test must be quick, it uses specific endpoint with basic response and it cannot guarantee that all is OK (such as the database).&lt;/p&gt;

&lt;p&gt;A canary test is a sequence of actions that simulates a real user behavior of the service. In return for its longer duration, this test guarantees that all major components are alright. We can furthermore use the metrics of this test to follow reliability and detect problems (duration, latency).&lt;/p&gt;

&lt;h3&gt;
  
  
  Hypothesis testing
&lt;/h3&gt;

&lt;p&gt;A new kind of testing framework (like &lt;a href="https://hypothesis.readthedocs.io/en/latest/index.html"&gt;Hypothesys&lt;/a&gt; for Python) allow defining the type of the input instead of defined a fixed value. At run, values used in the test will be randomly generated. These tests are not repeatable, it means the same test run twice will not use the same input data. &lt;/p&gt;

&lt;p&gt;It's a good way to find edge case, but you should use hypothesis tests in addition to classic unit tests to ensure nominal and specific data are well tested. Furthermore, for some complex and specific cases, this kind of test may rise some false-negative.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fault seeding
&lt;/h3&gt;

&lt;p&gt;Deliberately adding a new bug in the code and monitor the detection by the test suite. This can be done with a &lt;a href="https://en.wikipedia.org/wiki/Mutation_testing"&gt;&lt;strong&gt;Mutation testing&lt;/strong&gt;&lt;/a&gt; tool which modify your code (for example the value in a conditional statement) and run all tests to ensure this modification (called &lt;em&gt;mutant&lt;/em&gt;) is found. &lt;/p&gt;

&lt;p&gt;This kind of test consume a lot of resource, use it only for small and critical algorithm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security testing
&lt;/h3&gt;

&lt;p&gt;Security is a big topic, let's review the main points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consider &lt;a href="https://owasp.org/www-project-top-ten"&gt;OWASP Top 10 security issues&lt;/a&gt; and tools like BURG or &lt;a href="https://owasp.org/www-project-zap/"&gt;OWASP ZAP&lt;/a&gt; to test your code.&lt;/li&gt;
&lt;li&gt;Take a look at &lt;strong&gt;S&lt;/strong&gt;tatic &lt;strong&gt;A&lt;/strong&gt;pplication &lt;strong&gt;S&lt;/strong&gt;ecurity &lt;strong&gt;T&lt;/strong&gt;esting or &lt;strong&gt;D&lt;/strong&gt;ynamic &lt;strong&gt;A&lt;/strong&gt;pplication &lt;strong&gt;S&lt;/strong&gt;ecurity &lt;strong&gt;T&lt;/strong&gt;esting tool like &lt;a href="https://www.arachni-scanner.com"&gt;Arachni&lt;/a&gt; to find vulnerabilities.&lt;/li&gt;
&lt;li&gt;See &lt;a href="https://owaspsamm.org"&gt;OWASP SAMM&lt;/a&gt; to find unsecure practices beyond source code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Privacy testing
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Privacy is related to security but because this topic is often forgotten, I put it in a dedicated section.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the case who some features are implemented to mitigate data leaks (hashing, database encryption or column level security) these features must be periodically tested. See OWASP's recommendations to &lt;a href="https://owasp.org/www-project-proactive-controls/v3/en/c8-protect-data-everywhere"&gt;protect data everywhere&lt;/a&gt; and add a test for each countermeasure present in the project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain-specific test
&lt;/h3&gt;

&lt;p&gt;Depending on your application you may add some tests for &lt;strong&gt;usability&lt;/strong&gt;, localization, accessibility or performance for web application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture tests
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Endurance test
&lt;/h3&gt;

&lt;p&gt;Endurance test is a &lt;strong&gt;load test&lt;/strong&gt; during a long time because if the load test duration is shorter than some cache or TTL specified in your system, maybe you'll miss something. Using real-life context and usage, you will increase tests quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stress test
&lt;/h3&gt;

&lt;p&gt;Unavailability (full or partial) of one or more resource (application server, database, LDAP...) to ensure queues or high-availability is working.&lt;br&gt;
These target may be randomly disconnected like for &lt;a href="https://en.wikipedia.org/wiki/Chaos_engineering"&gt;&lt;strong&gt;chaos engineering&lt;/strong&gt;&lt;/a&gt; or we can only add latency (partial unavailability) in some server to see application behavior and check degraded mode.&lt;/p&gt;

&lt;p&gt;To learn more you can look at &lt;a href="http://principlesofchaos.org/"&gt;the principles of chaos engineering&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incident-proof testing
&lt;/h3&gt;

&lt;p&gt;Because ransomware or disk crash sometimes happens, you can do &lt;strong&gt;recoverability test&lt;/strong&gt; to check your service can restart after incident or data corruption.&lt;/p&gt;

&lt;p&gt;We can also mention &lt;strong&gt;spike test&lt;/strong&gt; which ensure ability of the service to work after peak loads and &lt;strong&gt;scalability test&lt;/strong&gt; which check the system can get more worker to deal with increasing load. This work is usually done by an orchestration tool like Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  API
&lt;/h3&gt;

&lt;p&gt;A lot of tools have an API. For example, to check monitoring, we can use CURL and call Grafana and Prometheus APIs. Remember, learning about these APIs is a great way to automate things later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cause-effect diagram
&lt;/h3&gt;

&lt;p&gt;Writing a good test require to find the right problem you want to avoid. &lt;/p&gt;

&lt;p&gt;When you're stuck with a production problem, an interesting methodology to find the root causes is &lt;a href="https://untools.co/ishikawa-diagram"&gt;fishbone diagram or Ishikawa diagram&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can browse and look at the other "problem-solving" methodologies explained by &lt;a href="https://untools.co"&gt;Untools&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ISTQB Glossary
&lt;/h3&gt;

&lt;p&gt;On this testing certification website you can find &lt;a href="https://glossary.istqb.org/en_US/search"&gt;terms used in software testing&lt;/a&gt;. The full list of terms is no longer available.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exploratory testing
&lt;/h3&gt;

&lt;p&gt;This methodology provide good resources to find edge case for some tests. You can find some &lt;a href="https://www.ministryoftesting.com/articles/ab1cd85c"&gt;Test Heuristics Cheat Sheet&lt;/a&gt; to extend your test cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conferences
&lt;/h3&gt;

&lt;p&gt;To learn more about this fast-growing topic, I warmly recommend watching the conferences on the subject. FOSDEM has &lt;a href="https://fosdem.org/2023/schedule/track/testing_and_automation/"&gt;a Testing track&lt;/a&gt; and this subject is present in &lt;a href="https://www.youtube.com/@DevoxxForever"&gt;Devoxx&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>devops</category>
      <category>webdev</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Stop coding to improve your code and soft-skills</title>
      <dc:creator>JeffD</dc:creator>
      <pubDate>Tue, 07 Mar 2023 09:30:00 +0000</pubDate>
      <link>https://dev.to/cotcotcoder/stop-coding-to-improve-your-code-and-soft-skills-33da</link>
      <guid>https://dev.to/cotcotcoder/stop-coding-to-improve-your-code-and-soft-skills-33da</guid>
      <description>&lt;p&gt;Building software is a great activity, a passion for a lot of us. Practice is a great way to mastering subject. I love discovering new software, programming langages and platforms however spending time on another activity helps a lot for our work. This is a little list to get some soft-skill.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read History books
&lt;/h2&gt;

&lt;p&gt;Horse Troyan, Enigma, penicilin discovery, or &lt;a href="https://dev.to/raygun/11-of-the-most-costly-software-errors-in-history-gbi"&gt;worst technology failures&lt;/a&gt;. History is a fun way to learn how humanity solved problems, or how little problem caused big failure. Cryptography history learn us how people try to find failure, first in the cryptographic system, and then in our "language" itself (letter occurrence, word probability). &lt;em&gt;Code book&lt;/em&gt; from Simon Singh is a great read on this subject and you can do it away from a blue light screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hackathon
&lt;/h2&gt;

&lt;p&gt;Close your IDE, take a pen, a paper and listen. Ask questions, formulate a solution, debate, try to understand your interlocutors, the context, the problem, the constraint. And you can talk friendly, without fear, it's very different from the usual crazy customer. Hackathon put you out of your confort zone, to be free and build a very helpful solution, it's something really pleasant. I enjoy &lt;a href="https://hacking-health.org"&gt;Hacking-Health&lt;/a&gt; but "Code for &lt;em&gt;YourContry&lt;/em&gt;"  may be very interesting (feel free to list other initiative in the comments).&lt;/p&gt;

&lt;h2&gt;
  
  
  Visit industrial museum
&lt;/h2&gt;

&lt;p&gt;It's very interesting to discover how people dealed with information without computers: presence of employees, production results, wages... Sometimes a good organization can be done with only paper and pen. We can learn from Ford and Taylor but we can learn from before because industry started in antiquity, and old recipes can still works for our problems. Moreover you can discover fun facts, like this one: in Glenturret Scotland distillery, you can find a statue to honor a cat, Towser, because cat is a easy way to prevent mice from eating cereals used for wisky.&lt;/p&gt;

&lt;h2&gt;
  
  
  Talks &amp;amp; write
&lt;/h2&gt;

&lt;p&gt;You have to write, search deeply, resume complex subjects for junior and be interesting for experts. Talks are a great way to share knowledge and try to find another point of view to explains things. People will ask you questions so you have to search about problems or usages you've never had. Your audience will add some usefull comments, this is always interesting. And this is a way to present a tool, or a language, with a very original approch (like "Docker as fast-food restaurant" or "Scrum as a MMORPG game"). If you're affraid about speaking in public, blogging is a great alternative.&lt;/p&gt;

&lt;h2&gt;
  
  
  Translating documentation
&lt;/h2&gt;

&lt;p&gt;A more technical activity: you will learn a lot of things translating the documentation of your stack. You can discover specific modules, unknow arguments, useful functions and awesome community. Moreover we use organization and tools similar to write documentation and code (versionning system is included in a wiki-like solution...) so it's easy to start and very helpful for non-english native people.&lt;/p&gt;

&lt;h2&gt;
  
  
  Volunteering
&lt;/h2&gt;

&lt;p&gt;When you work in event organization you'll need a tool to organize tasks, a tool to communicate in real-time, a tool to make feedback and so on. You'll deal with problems, you'll need to communicate a lot, with speakers, with public, with your team. You'll deal with urgency, think about diversity and people with disabilities, and theses ones are useful for empathy. You'll learn a lot outside of your technical domain.  Be volunteer encourage organization to continue year after year, it sometimes makes it possible to make the event free, so this is a good action (and there is always a good mood).&lt;/p&gt;

&lt;h2&gt;
  
  
  Sport (or manual activities)
&lt;/h2&gt;

&lt;p&gt;Physical activity is great for health, but it's great for spirit too. Doing sport helps you to forget your problems, bugs, deadlines. You will have a better sleep, it's a good break enabling to restart studying your problem from zero and finally find the bug. Some exercices are great to break our to many hours sitting position, see &lt;a href="https://dev.to/daraghjbyrne/5-yoga-poses-every-coder-should-try-102"&gt;this post&lt;/a&gt;. Physical and manual activities are great to get away from stress and pressure. You can do it in solo or in a team, the last one is good to become humble about our knowledge and abilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meditation
&lt;/h2&gt;

&lt;p&gt;Meditation helps you to work in a noisy environment and reduces stress. It's a great activity and a lot of ressources exists on this subject. &lt;a href="https://dev.to/daraghjbyrne/why-i-think-meditation-makes-you-a-better-programmer-4b0m"&gt;Ask Daragh if you need some help&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another major benefit: meditation help you to stay calm and to distance onself from something and this is very helpful to communicate softly with people. It's a good activity to avoid conflict and improve teamwork.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cooking
&lt;/h2&gt;

&lt;p&gt;Interruptions are hell, but because we can't delete them completely at work we have to deal with it. We have to learn to list our work in progress, treat one point after the other, finish them completely before starting another one, had to be concise and precise, so we have to learn to stop and resume work. &lt;/p&gt;

&lt;p&gt;So a good exercice is coding while preparing a meal: you put timer for the cooking of your meal and start to code. When it's riging you have to stop your work directly, put a status-note somewhere and go treat your meal before it burns. When you'll come back at work you sould read this status-note, remember all and restart coding. This is a trick I like but be aware of your personnal and professionnal time balance, this may become a bad habit and can develop burn-out. Take care of yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improve your existing tools
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"Give me six hours to chop down a tree and I will spend the first four sharpening the axe."&lt;br&gt;
Abraham Lincoln&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some tools helps you to do more with less code. Sometimes it's a library (as a ORM), sometimes it's a little CLI tips (like &lt;code&gt;!$&lt;/code&gt;) or a tool to search security issue, format code, prevent missing documentation. It's always interesting to look at how other developer works and which tools they uses. For this task you can browse on dev-to posts, or looking at Github, in big projects README, which process and tools are used to be efficient. Another way is to ask about it when you meet new people in any technical event.&lt;/p&gt;

&lt;p&gt;Thanks for reading, It's hard to cut this post and keep it short, I hope to deeply write about all all theses activities later.&lt;br&gt;
What's your favorite non-coding activity which helps you in your life ? Feel free to leave a comment ⌨️&lt;/p&gt;

</description>
      <category>afk</category>
      <category>life</category>
      <category>softskill</category>
    </item>
    <item>
      <title>Python: code a Flake8 plugin to check your own rule</title>
      <dc:creator>JeffD</dc:creator>
      <pubDate>Sat, 04 Mar 2023 11:00:00 +0000</pubDate>
      <link>https://dev.to/cotcotcoder/python-code-a-flake8-plugin-to-check-your-own-rule-56ah</link>
      <guid>https://dev.to/cotcotcoder/python-code-a-flake8-plugin-to-check-your-own-rule-56ah</guid>
      <description>&lt;p&gt;Conventions is not only a code style guide. If you include some rules to ensure security then you add some work for the reviewer. It may be interesting to  automate this check with some code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pypi.org/project/flake8/"&gt;Flake8&lt;/a&gt; is a tool to ensure your code follow some rules. You can add plugins and it's easy to create your own. This post is the textual version of &lt;a href="https://www.youtube.com/watch?v=ot5Z4KQPBL8"&gt;this very good Youtube tutorial&lt;/a&gt; by anthonywritescode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Non-syntax conventions
&lt;/h2&gt;

&lt;p&gt;You can use pylint or Black to reformat and uniformize your code but conventions may contains some other rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Security: your company may ban some function like &lt;code&gt;os.popen()&lt;/code&gt; or forbid a call to &lt;code&gt;request.get()&lt;/code&gt; without the &lt;code&gt;cert&lt;/code&gt; attribute.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Log message: you may have some rule to have explicit and descriptive log entry, for example &lt;code&gt;logger.critical()&lt;/code&gt; must contains some specific keywords (error uid, tracing span...).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Automate your conventions checks
&lt;/h2&gt;

&lt;p&gt;Building a flake8 has two major advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the review checklist is getting thinner because the continious integration tool take this job.&lt;/li&gt;
&lt;li&gt;the developer can be alerted by this noncompliance and fix-it himself instead of waiting pair-review.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to forbid the add of a controler class without documentation, you only have to ensure the docsting is set: It's easier for the reviewer to detect empty docstring than looking at each controler class if they contains documentation.&lt;/p&gt;

&lt;p&gt;Automate the first part of the checks (the existence) to help the reviewer to focus on validating the content. So some rules can only be partially automated but it still reduce the mental load of the reviewer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow your technical debt
&lt;/h2&gt;

&lt;p&gt;If you have many projects and you decide to migrate from library A to library B you can use flake8 to alert you about remaining library A usage.&lt;/p&gt;

&lt;p&gt;Once your &lt;em&gt;internal_conventions&lt;/em&gt; plugin is set and running it's easy to add some rules with some new error-code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Flake8 plugin
&lt;/h2&gt;

&lt;p&gt;It's very easy to check your own rules with a Flake8 plugin (not only because we don't have to use regex), the bootstrap is small.&lt;/p&gt;

&lt;p&gt;In this example I write a plugin to check every call to &lt;code&gt;logger.info()&lt;/code&gt; contains &lt;code&gt;mandatory_arg&lt;/code&gt;. So &lt;code&gt;logger.info("abc", mandatory_arg=1)&lt;/code&gt; is valid while &lt;code&gt;logger.info("abc")&lt;/code&gt; is invalid.&lt;/p&gt;

&lt;p&gt;My project name is &lt;code&gt;flake8_check_logger&lt;/code&gt;, &lt;code&gt;flake8_&lt;/code&gt; is a prefix for flake8 plugin (this good naming convention help us to discover plugin on Github). We use the error code &lt;strong&gt;LOG042&lt;/strong&gt; with message "Invalid logger". By the way use a prefix not already used by your flake8 plugins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;setup.py:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from setuptools import setup
setup()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;setup.cfg:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[metadata]
name = flake8_check_logger
version = 0.1.0

[options]
py_modules = flake8_check_logger
install_requires = 
    flake8&amp;gt;=3.7

[options.entry_points]
flake8.extension =  
    LOG=flake8_check_logger:Plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;flake8_check_logger.py&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;import&lt;/span&gt; &lt;span class="nn"&gt;importlib.metadata&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;ast&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Generator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NodeVisitor&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="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;problems&lt;/span&gt; &lt;span class="o"&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;visit_Call&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;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# TODO we write our test here
&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;generic_visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Plugin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;
    &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;importlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&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;tree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AST&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;_tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Generator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&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;Type&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;visitor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Visitor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visit&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;_tree&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;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;problems&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;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"LOG&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
   Discover AST (and astpretty)
&lt;/h3&gt;

&lt;p&gt;Instead of using regex we will use Abstract Syntax Trees. AST transform any python source code to an object representation.&lt;/p&gt;

&lt;p&gt;We will install &lt;a href="https://pypi.org/project/astpretty"&gt;astpretty&lt;/a&gt; with pip for development purpose only, it's not a requirement to add in our plugin.&lt;/p&gt;

&lt;p&gt;Then you can use it on your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;astpretty /dev/stdin &amp;lt;&amp;lt;&amp;lt; "logger.info('msg', mandatory_arg=1)"&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;And we obtain some information like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Expr(
            value=Call(
                func=Attribute(
                    value=Name(id='logger', ctx=Load()),
                    attr='info',
                    ctx=Load(),
                ),
                args=[Constant(value='msg', kind=None)],
                keywords=[
                    keyword(
                        arg='mandatory_arg',
                        value=Constant(value=1, kind=None),
                    ),
                ],
            ),
        ),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Write the test
&lt;/h3&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="nn"&gt;flake8_check_logger&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Plugin&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;ast&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Set&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_results&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Set&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;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&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;test_valid_logger_call&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;_results&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"logger.info('msg', mandatory_arg=1)"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;set&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;test_invalid_logger_call_no_mandatory_arg&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_results&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"logger.info('msg')"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'1:0 LOG042 Invalid Logger'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can add more testcases: &lt;code&gt;logger.something_else()&lt;/code&gt; or a local function with similar name &lt;code&gt;info()&lt;/code&gt; should not require this argument, test an empty line, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write the check
&lt;/h3&gt;

&lt;p&gt;I split my test in two parts for lisibility, this code could be refactored but I prefer to use very basic syntax for this tutorial.&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;visit_Call&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;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;mandatory_arg_found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="n"&gt;is_right_function&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"logger"&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;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attr&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"info"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;is_right_function&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_right_function&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;keyword&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keywords&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;keyword&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"mandatory_arg"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;mandatory_arg_found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;mandatory_arg_found&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;problems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;
                    &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lineno&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;col_offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                    &lt;span class="mi"&gt;042&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;"Invalid logger"&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;generic_visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Local test
&lt;/h3&gt;

&lt;p&gt;We install our plugin with:&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;pip install -e .&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
.&lt;/p&gt;

&lt;p&gt;And you can check flake load this plugin with&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;flake8 --version&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go further
&lt;/h2&gt;

&lt;p&gt;Your can find more information on the &lt;a href="https://flake8.pycqa.org/en/latest/plugin-development/index.html"&gt;flake8 documentation&lt;/a&gt; with a link to the very helpful video tutorial (30 minutes).&lt;/p&gt;

&lt;p&gt;With python you can access to something with code: &lt;code&gt;__doc__&lt;/code&gt; for documentation or &lt;code&gt;__bases__&lt;/code&gt; for parent class. Theses dunder function can help you to write some specific rules.&lt;/p&gt;

&lt;p&gt;You can learn more about existing flake8 plugin thanks to &lt;a href="https://dev.to/bowmanjd/some-flake8-plugins-for-python-linting-107h"&gt;Jonathan Bowman article&lt;/a&gt; and read the source-code of theses plugins to help you if you are blocked by a complex case.&lt;/p&gt;

</description>
      <category>python</category>
      <category>automation</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Backup Essentials (Additional informations)</title>
      <dc:creator>JeffD</dc:creator>
      <pubDate>Thu, 16 Sep 2021 19:52:26 +0000</pubDate>
      <link>https://dev.to/cotcotcoder/backup-essentials-additional-informations-4hjj</link>
      <guid>https://dev.to/cotcotcoder/backup-essentials-additional-informations-4hjj</guid>
      <description>&lt;p&gt;I read a lot about backup but the most important points that I noticed throughout my life as a developer are rarely listed. &lt;br&gt;
Backup is a mix between security, automation and low-level understanding of your application (and OS). It's a good exercise for every developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why ?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;It help to learn how your applications and system works. For each application you should find where is the data, which format is used (and why) and which tool you can use to get plain-text version of the data. You can learn a lot about your OS, web browser and games.&lt;/li&gt;
&lt;li&gt;You can &lt;strong&gt;duplicate your dev workstation&lt;/strong&gt; easily: save your developer setup on a USB key allow you to access your Linux alias, IDE  configuration, bookmarks, notes and snippets everywhere. It's an easy way to share you tips with your peers and work on someone else computer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hardware and Software failure&lt;/strong&gt;: your SSD is not invulnerable and despite all the tests, any application or OS can corrupt data during update or running. If you are developer maybe you know that unit test covers application functionality and rarely data consistency after migration.&lt;/li&gt;
&lt;li&gt;And the most famous: ransomware, thief, revenge, house in fire or under water, emergency evacuation, small child, fall of a magnet on your HDD, accidental &lt;em&gt;"rm -rf"&lt;/em&gt; etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The solution requirements
&lt;/h2&gt;

&lt;p&gt;There is requirements you should keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You must be able to restore/access the data with any other computer (and/or another OS). The perfect solution is a backup file you can restore with &lt;em&gt;Live OS&lt;/em&gt; (boot on USB key).&lt;/li&gt;
&lt;li&gt;Software should be easy to install on your host (computer/smartphone) and easy to use.&lt;/li&gt;
&lt;li&gt;The output file format should be common: so you can write an automated test on your backup pipeline: backup folder containing one text file, verify the file is present and the content of this file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many tools may be good for this job and by the way you can build your own backup script with Python (or any shell language), rsync and cron jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check the job is well done
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Set up alert when backup fail. A good way is to configure a independent CRON job to verify the most recent backup file is not older than 2 days.&lt;/li&gt;
&lt;li&gt;Test your data restoration frequently in real condition (using VM or container).&lt;/li&gt;
&lt;li&gt;Cryptography is essential for personal data but remember to ensure you can restore data easily in any context (another OS/platform and version).&lt;/li&gt;
&lt;li&gt;Automation is the key (cron) but beware this automation doesn't silently delete data. One of your duplicated should only add new files and never repeat (on the remote) the local deletion of a file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3-2-1 rule&lt;/strong&gt;: see &lt;a href="https://dev.to/rjjsoftware/backups-backups-backups-4ff1"&gt;this post&lt;/a&gt; - Remember something like 4-3-2 is better :)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Personal advice
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I often use USB key and SD card: they are compact (portable), waterproof, shockproof and easy to put in a little fireproof vault. Moreover it can be full-time connected to your computer as simple RAID1 solution against hardware and software failure.&lt;/li&gt;
&lt;li&gt;Ransomware infects all device connected to network so NAS and RAID1 solution, it's why an off-site and offline storage is important. Cloud storage is a good alternative if your hosting company pass your privacy requirements :)&lt;/li&gt;
&lt;li&gt;My backup strategy is divided into 2 &lt;em&gt;channels&lt;/em&gt;: personal data (rarely updated and encrypted) and work data (modified everyday but doesn't need crypto). So I have two distinct process and allocated storage to avoid my every-day backup doesn't raise problem to my important.&lt;/li&gt;
&lt;li&gt;Install and test recover software (for example &lt;a href="https://www.cgsecurity.org/wiki/PhotoRec"&gt;PhotoRec&lt;/a&gt;) it may be helpful.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bonus: Data checklist example
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Personal data: pictures, phone-numbers, scanned files &lt;/li&gt;
&lt;li&gt;Internet data (browser relative data): bookmarks, passwords, important e-mails and/or downloaded files&lt;/li&gt;
&lt;li&gt;Online services: a copy of everything you create directly online (without copy on your local host) like blog post.&lt;/li&gt;
&lt;li&gt;Game level backup ;)&lt;/li&gt;
&lt;li&gt;Development stuff: projects, IDE configuration, gitconfig, Linux alias (bashrc), git hooks, API keys, docker-compose files, paid resources (icons, libs, ...)&lt;/li&gt;
&lt;li&gt;External data: data stored in databases&lt;/li&gt;
&lt;li&gt;External support: backup is necessary for your 2AF solutions like Yubikey, or have a fallback for Android application without degrading security level.&lt;/li&gt;
&lt;li&gt;OS configuration: firewall rules, SSH keys ...&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>backup</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Better applications with Unix Philosophy</title>
      <dc:creator>JeffD</dc:creator>
      <pubDate>Tue, 14 Apr 2020 16:41:55 +0000</pubDate>
      <link>https://dev.to/cotcotcoder/better-applications-with-unix-philosophy-547g</link>
      <guid>https://dev.to/cotcotcoder/better-applications-with-unix-philosophy-547g</guid>
      <description>&lt;p&gt;Unix system works with command, a small program with a lot of possibilities, and we will take a closer look at their use.&lt;br&gt;
Because this ecosystem is based on a philosophy very useful for any software and web application.&lt;br&gt;
Note: 5 and 6 are not directly related to Unix philosophy :)&lt;/p&gt;

&lt;h2&gt;
  
  
  1. One tool do one job done 🔬
&lt;/h2&gt;

&lt;p&gt;It's sound like &lt;a href="https://dev.to/trekhleb/s-o-l-i-d-principles-around-you-1o17"&gt;Single Responsability&lt;/a&gt; and it is, &lt;br&gt;
in Unix system you find &lt;em&gt;chown&lt;/em&gt; to change owner of a file, but if you want to create a new user, you should use &lt;em&gt;useradd&lt;/em&gt;.&lt;br&gt;
So, rights management is divised into many commands.&lt;/p&gt;

&lt;p&gt;In his book Rework, Jason Fried regrets that the applications became heavy, with so many features:&lt;br&gt;
it's difficult to maintain, and the user is lost. &lt;br&gt;
We have plugin architecture, we use it in our browser (and IDE and it helped them get their groove on).&lt;/p&gt;

&lt;p&gt;So start with &lt;strong&gt;minimal functionality&lt;/strong&gt; and add feature with &lt;strong&gt;plugin&lt;/strong&gt;. &lt;br&gt;
A good example is &lt;a href="https://app.super-productivity.com"&gt;this todo app&lt;/a&gt; by johannesjo.&lt;br&gt;
You can read &lt;a href="https://dev.to/arcanis/plugin-systems-when-why-58pp"&gt;this article&lt;/a&gt; by arcanis (Javascript).&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Tools are cumulative 🔗
&lt;/h2&gt;

&lt;p&gt;In Unix this is &lt;em&gt;pipe&lt;/em&gt;: result of the first command go in the second command.&lt;br&gt;
For example &lt;em&gt;grep&lt;/em&gt; to search a keyword: &lt;em&gt;history | grep keyword&lt;/em&gt;: data returned by &lt;em&gt;history&lt;/em&gt; are filtered by &lt;em&gt;grep&lt;/em&gt;.&lt;br&gt;
This compatibility allow a command to be used with another.&lt;/p&gt;

&lt;p&gt;To make this, input or output of &lt;strong&gt;your application must be compatible with another application&lt;/strong&gt;, &lt;br&gt;
this is why so many application allow to export (or import) in a &lt;strong&gt;standard format&lt;/strong&gt; (csv, xml, json etc) and it's great, we can export data, treat them with another software, re-import them, you should always give this possibility to your user.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Norms and conventions 🌐
&lt;/h2&gt;

&lt;p&gt;In Unix they're some conventions (not always respected):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;return code (0 for ok, 1 for minor erreur, 2 for fail)&lt;/li&gt;
&lt;li&gt;arguments (-h for help, -v for verbose...)&lt;/li&gt;
&lt;li&gt;paths (config, binary, logs, user profile files)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's helpful for debug, for integration, backup, and to learn and understand application. For example, command and keywords in docker are similar to Unix ones (ls, ps, commit, env), it's easy to remember them. If your user already know keywords (from another application) for the same usage, it will facilitate learning curve to use the same.&lt;/p&gt;

&lt;p&gt;Another example: IDE allow to use keyboard shortcuts of another IDE, it's perfect, your user can keep his habits.&lt;/p&gt;

&lt;p&gt;And if your system recommand some rules, please respect them, and your user won't be looking during hours where is the log file :)&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Extendable with configuration 🎲
&lt;/h2&gt;

&lt;p&gt;In Debian system &lt;em&gt;apt&lt;/em&gt; is the tool to manage packages (softwares and os updates).&lt;br&gt;
You can create a Debian package for anything you want, for example a simple configuration file. &lt;br&gt;
So if you set up a personal package repository link in &lt;em&gt;apt&lt;/em&gt; configuration file you'll get theses packages.&lt;/p&gt;

&lt;p&gt;Application working with file don't care if theses file are local, on usb key, on a network or on web hosting.&lt;br&gt;
They expecting a file and don't care about the source.&lt;/p&gt;

&lt;p&gt;So if your application can read data from many sources without problem, allow a configuration for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Intuitive usage 🙂
&lt;/h2&gt;

&lt;p&gt;Unix an comand line interface are not so friendly but autocompletion helps a lot. &lt;br&gt;
If you can implement some helper or search query builder it's always appreciated.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Alias&lt;/em&gt; is a command to make a personnal shortcut:&lt;br&gt;
for example &lt;em&gt;alias cgst='clear &amp;amp;&amp;amp; git status'&lt;/em&gt;.&lt;br&gt;
It's a favorite shortcut, for example in a transportation app, user can choose a geographical point as favorite (home, work place, library, ...).&lt;/p&gt;

&lt;p&gt;In Unix system you can find the command &lt;em&gt;wereis&lt;/em&gt; to locate binary of another command, &lt;em&gt;whatis&lt;/em&gt; to explain a command, &lt;br&gt;
&lt;em&gt;man&lt;/em&gt; to show documentation, &lt;em&gt;whence&lt;/em&gt; to show if &lt;em&gt;alias&lt;/em&gt; is used, etc.&lt;br&gt;
This is great because it help user to have a fast overview of a software, where it is, what it do, how to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Attractive Documentation 🎠
&lt;/h2&gt;

&lt;p&gt;Unix system has man pages and so many documentation online (great community).&lt;br&gt;
So manual, wiki and  FAQ or QA forum are some basics, but there is some idea for more attractive solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Readme: with common usage and frequent problem. See &lt;a href="https://dev.to/scottydocs/how-to-write-a-kickass-readme-5af9"&gt;How to write kickass Readme&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tutorial/Cookbook: advanced usage and usage categorized by needs/profile user/...&lt;/li&gt;
&lt;li&gt;cheat sheet: a list with all command or and annoted screenshot of the interface&lt;/li&gt;
&lt;li&gt;sandbox mode: allow user to dive into dangerous command without losing real data or web tool like &lt;a href="https://git-school.github.io/visualizing-git/"&gt;Git School&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;changelog with Gif: look at VSCode changelog or &lt;a href="https://vscodecandothat.com"&gt;vscodecandothat&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;alternative list: do a comparative listing concurrent alternative, 
because when we are looking for an alternative to Trello we type trello (rarely kanban).
so it's great for SEO (especially on Github).&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Start with minimal interface and add features in plugin&lt;/li&gt;
&lt;li&gt;Allow to export (and import) in standart format (json, csv, ...)&lt;/li&gt;
&lt;li&gt;Respect the OS norms, conventions, habits&lt;/li&gt;
&lt;li&gt;Allow configuration to extend your application usage&lt;/li&gt;
&lt;li&gt;Help user (autocompletion, favorite shortcut)&lt;/li&gt;
&lt;li&gt;Write attractive documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Learn more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://homepage.cs.uri.edu/~thenry/resources/unix_art/ch01s06.html"&gt;The (real) Unix philosophy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;You want to start working with Linux/MacOS command line: see &lt;a href="https://developer.ibm.com/technologies/linux/tutorials/l-lpic1-map"&gt;IBM free articles&lt;/a&gt; and the &lt;a href="https://explainshell.com"&gt;explainshell webtool&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading - Stay safe.&lt;br&gt;
Sorry for the typo and mistakes (&lt;em&gt;#french&lt;/em&gt; &lt;em&gt;#confinmentDay30&lt;/em&gt;)&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>linux</category>
      <category>programming</category>
    </item>
    <item>
      <title>Some free-time ? Some ideas !</title>
      <dc:creator>JeffD</dc:creator>
      <pubDate>Fri, 27 Mar 2020 19:36:37 +0000</pubDate>
      <link>https://dev.to/cotcotcoder/some-free-time-some-ideas-3kkd</link>
      <guid>https://dev.to/cotcotcoder/some-free-time-some-ideas-3kkd</guid>
      <description>&lt;p&gt;I live in France so my work were stopped during this Covid-19 crisis. I don't do remote work because you know, the book Remote (by 37signal) were not translated to french (or maybe here big company loves managers and physical employees). So I'm at home, with 8 hours per day available and a limited internet access. &lt;strong&gt;What can I do ?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hack-Covid 🦠
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://helpwithcovid.com/"&gt;lot of hackathons&lt;/a&gt; are emerging to help medical and emergency services. I can speak a lot about &lt;a href="https://hacking-health.org/"&gt;Hacking Health&lt;/a&gt; but there so many initiatives (from associations to companies and countries). It's great because you meet some people with various skills and you can work on a new technology.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start a long-time project 🔧
&lt;/h2&gt;

&lt;p&gt;Do you remember this awesome idea you got years ago ? &lt;strong&gt;Now you can try !&lt;/strong&gt; We regrets things we didn't try more than bad ideas.&lt;br&gt;
I have Arduino and Micropython board and I didn't do anything with it. So now I'll probably burn out some LEDS and write something about a dream: transform an old (1940) typewriter to an external keyboard for computer (it's an experience for an awesome gift for my sister).&lt;/p&gt;

&lt;h2&gt;
  
  
  Write 🖊️
&lt;/h2&gt;

&lt;p&gt;I will write a Jitsy tutorial for my family to promote visio-call and probably continue to translate some article on Mozilla Developper Network. Maybe I'll write here an simple introduction to web-certificate because there nothing on MDN. &lt;strong&gt;You can write that tutorial you wish you'd had in the past&lt;/strong&gt; (all the point of view are welcome on complex subject).&lt;br&gt;
It's very important to share knowledge and if you have no idea, you can write the best life lesson for your children or nephews and nieces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Boring stuff: backup and mails 🧹
&lt;/h2&gt;

&lt;p&gt;You know spending some time to automate today will make you gain some time later. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ransomwares are still dangerous&lt;/strong&gt;, so I decide to seriously work on automated backup and find a solution to simplify backup on temporary connected hard-disk (stored at different places outside my home).&lt;/li&gt;
&lt;li&gt;Delete spam, unsubscribe to some newsletters, remove all attachment... I really love to have a clean mail box. Clean workspace is a good thing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Learn (Read, talks, MOOCS) 📚
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I started to learn subjects more deeply, I'm very happy to discover &lt;a href="https://www.github.com/crypto101/book"&gt;this free ebook about cryptography&lt;/a&gt;. And I read other paper-book because you know, blue ligth...&lt;/li&gt;
&lt;li&gt;I'm volunteer to many conferences so I miss very interesting talks. &lt;a href="https://www.youtube.com/user/fosdemtalks"&gt;Fosdem&lt;/a&gt; and &lt;a href="https://pyvideo.org"&gt;Pycon&lt;/a&gt; contains so many interesting subjects (but you need a fast internet access and no data limitation). If you are french CNIL published a &lt;a href="https://atelier-rgpd.cnil.fr/"&gt;great MOOC about RGPD&lt;/a&gt;.
And next you can write a blog post about your new skill.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Starting new habits 🗓️
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When you have a lot of time you can easily allocate some time to a new activity and build an habit (I think it takes 20 occurrences). So I plan one to do Yoga, piano and meditation. And I love to start poping some blog post from my &lt;em&gt;to-read list&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can start contributing&lt;/strong&gt; to something like take one picture per day and publish it on Wikipedia or Unsplash, add content on openstreetmap, learn a new language, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Design (work without computer) 🧶
&lt;/h2&gt;

&lt;p&gt;I draw some sketches for my new desk (not really a desk, something very special). &lt;strong&gt;Doing something different from a software&lt;/strong&gt; is a very interesting task with new constraints and workflow, I definitively recommand it. You can conceive a new board-game, a new cook recipe, a new children activity, an infography on any subject, etc. &lt;/p&gt;

&lt;h2&gt;
  
  
  Think 🤔
&lt;/h2&gt;

&lt;p&gt;I finish with this point. Viruses are not new, but Covid19 is (sadly) very special. Many things have helped to spread it and we need to think on all problems we are meeting right now and take some time on the causes. We should anticipate remote work, massive usage, learn to be more forward-looking about health problems, find solutions to coordinate people all arround the world, both block viruses and respect privacy, educate people to avoid fake-news. Technology won't solve everything and logic we developped as engineer can be apply to food supply and medical problems, so &lt;strong&gt;don't stick to computers, development, AWS and blockchain&lt;/strong&gt;. &lt;em&gt;When we can help we must help&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spend time with your friends and family, call them, and take care.&lt;/strong&gt; 💜&lt;/p&gt;

&lt;p&gt;Thank you &lt;/p&gt;

</description>
      <category>confinment</category>
      <category>covid19</category>
      <category>remote</category>
      <category>development</category>
    </item>
    <item>
      <title>7 advices after 10 years of development</title>
      <dc:creator>JeffD</dc:creator>
      <pubDate>Wed, 11 Sep 2019 21:00:46 +0000</pubDate>
      <link>https://dev.to/cotcotcoder/7-advices-after-10-years-of-development-5bc0</link>
      <guid>https://dev.to/cotcotcoder/7-advices-after-10-years-of-development-5bc0</guid>
      <description>&lt;h2&gt;
  
  
  Write 🗒️
&lt;/h2&gt;

&lt;p&gt;This is the first and best way to communicate (persistant and remote-friendly). So &lt;strong&gt;write all the things&lt;/strong&gt; you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;meetings: decisions, questions and answers, work in progress and pending subjects...&lt;/li&gt;
&lt;li&gt;problems: hardware failures, bugs and their solution, software weakness, code to refactor...&lt;/li&gt;
&lt;li&gt;conferences: draw or write but keep trace to essential content, references, tools, books ...&lt;/li&gt;
&lt;li&gt;code snippets: CORS, http headers, dark options or regex...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find a tool you can easily &lt;strong&gt;share with your team&lt;/strong&gt;, accessible everywhere (if needed). This knowledge will be available for a new coworker, even if you are on holiday, even if you leave. This is a valuable practice.&lt;br&gt;
Notions, Wiki, Evernote there are many solutions, I use plain text files (with rsync and git).&lt;/p&gt;
&lt;h2&gt;
  
  
  Learn efficiently 📗
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Know yourself&lt;/strong&gt;: learn at morning, learn at evening, look schema, listen podcast, write and search that's work the best for you because you'll spend a lot of time to learn it's very important to find your best way to aquire knowledge.&lt;br&gt;
Learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;when in the day you can learn efficiently&lt;/li&gt;
&lt;li&gt;if graphics, illustrations helps you&lt;/li&gt;
&lt;li&gt;how long time you can be concentrated on reading articles or any technical book&lt;/li&gt;
&lt;li&gt;how long time you can be concentrated on writing code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Allocate time&lt;/strong&gt;: one hour once in a while (make a habits) to read blog posts.&lt;br&gt;
Use long period (2 or 3h) to practice and write code&lt;/p&gt;

&lt;p&gt;Read documentation before writing code (ideally the day before and a few hours before)&lt;br&gt;
when you'll be stuck you'll know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;where to search solution to any problem.&lt;/li&gt;
&lt;li&gt;if it's possible to do that you want (and if it's a good practice or not).&lt;/li&gt;
&lt;li&gt;better ... because it helps memory to read twice!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Don't try to learn all (really) ❌
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;List ten subjects you want to learn, split up to atomic objectives. Choose objective one by one, all interesting articles or tools should be put in a "later" list.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start with basics&lt;/strong&gt; (HTTP, SQL, security, design patterns, language internal ...) they are evolving more slowly than EcmaScript/JS.&lt;/li&gt;
&lt;li&gt;Learn the possibilities of your tools, starting with OS and IDE because many build-in tools are awesome.&lt;/li&gt;
&lt;li&gt;Stop learning deprecated lib, even if you made something with long time ago. Your mind should be clear and not overloaded (like your resume). Sorry JQuery.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Avoid boring stuff 🤖
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automate&lt;/strong&gt; your backup, bills payment, domain names renewal, OS updates, let computer do it alone, test that it's work fine and forget about it.&lt;/li&gt;
&lt;li&gt;Use RSS to get news, less ad, less distractions than in classical websites.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Newsletters&lt;/strong&gt; are awesome, you'll lose less time than looking at Twitter and content are very relevant.&lt;/li&gt;
&lt;li&gt;Want to try a new tool or language, look at &lt;a href="https://github.com/bayandin/awesome-awesomeness" rel="noopener noreferrer"&gt;awesome pages on Github&lt;/a&gt;, you'll find a lot of ressources about a lot of stuff.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Refactoring - Unit-test - Debug 🧩
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Refactoring: I'll write about this soon. 📝 &lt;/li&gt;
&lt;li&gt;Reading open-source code to get new way to write code.&lt;/li&gt;
&lt;li&gt;Learn about your debug tool and TDD.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a bug occurs ask you theses questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What: define the probleme with the more details you can find.&lt;/li&gt;
&lt;li&gt;Where: which server, which database, which microservice, which part of the code, are any external lib involved ?&lt;/li&gt;
&lt;li&gt;When: date (day saving time), version (app, software), server status (memory usage), duration of the transaction, it is just after any activity like cron ?&lt;/li&gt;
&lt;li&gt;How : how this state arrived here: what's happend before, are the previous data correct?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course subscribe to: &lt;/p&gt;
&lt;div class="ltag__tag ltag__tag__id__203"&gt;
    &lt;div class="ltag__tag__content"&gt;
      &lt;h2&gt;#&lt;a href="https://dev.to/t/testing" class="ltag__tag__link"&gt;testing&lt;/a&gt; Follow
&lt;/h2&gt;
      &lt;div class="ltag__tag__summary"&gt;
        Find those bugs before your users do! 🐛
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Learn security 🔒
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Security is not a feature, it should be the backbone of your app.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Because of privacy and because it can cost a lot of money:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with &lt;a href="https://dev.to/victoria/sql-injection-and-xss-what-white-hat-hackers-know-about-trusting-user-input-481b"&gt;Victoria's post&lt;/a&gt; then learn &lt;a href="https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project#Translation_Efforts_2" rel="noopener noreferrer"&gt;OWASP top ten threat&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Remember threat evolving all the time (&lt;a href="https://dev.to/logan/homographs-attack--5a1p"&gt;homographs attacks&lt;/a&gt;, JSON hacking, ransomware, *coin-mining).&lt;/li&gt;
&lt;li&gt;Ask your friend, teammates to hack your app in exchange for a beer or chocolate.&lt;/li&gt;
&lt;li&gt;Learn with vulnerableApp like &lt;a href="https://www.owasp.org/index.php/OWASP_Security_Shepherd" rel="noopener noreferrer"&gt;security shepherd&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Be open-minded 👥
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;To all domains because we can learn from processes used everywhere like medical team, restaurant or classical factories. Remember Kanban comes from traditionnal industries (car manufacturer Toyota).&lt;/li&gt;
&lt;li&gt;To people from another country, age, skill level because the way they learn or analyze a problem are very interesting.&lt;/li&gt;
&lt;li&gt;To other tools, OS's, programing languages because we are not ennemy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding your users will help you to build better apps. Get empathy will help you to be a better human.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks for reading - Have a nice day&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;PS: it is obvious that you should also read:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/missamarakay" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1330%2Fe4706a09-0796-4d76-a451-832c6897bda5.jpg" alt="missamarakay"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/missamarakay/following-cooking-recipes-makes-you-a-clearer-writer-460a" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Following Cooking Recipes Makes You a Clearer Writer&lt;/h2&gt;
      &lt;h3&gt;Amara Graham ・ Jul 17 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devrel&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#documentation&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#developerrelations&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;div class="ltag__link"&gt;
  &lt;div class="ltag__link__content"&gt;
    &lt;div class="missing"&gt;
      &lt;h2&gt;Article No Longer Available&lt;/h2&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>How do you imagine Joel Test 2019 ?</title>
      <dc:creator>JeffD</dc:creator>
      <pubDate>Mon, 18 Jun 2018 20:27:46 +0000</pubDate>
      <link>https://dev.to/cotcotcoder/how-do-you-imagine-joel-test-2019--50g9</link>
      <guid>https://dev.to/cotcotcoder/how-do-you-imagine-joel-test-2019--50g9</guid>
      <description>&lt;p&gt;One day, Joel Spolsky defined the "12 step to better code". &lt;a href="https://www.joelonsoftware.com/2000/08/09/the-joel-test-12-steps-to-better-code/"&gt;It's Joel Test&lt;/a&gt;. It was writted in August 2000, a long time ago when "CVS was fine" :) There is the list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do you use source control?&lt;/li&gt;
&lt;li&gt;Can you make a build in one step?&lt;/li&gt;
&lt;li&gt;Do you make daily builds?&lt;/li&gt;
&lt;li&gt;Do you have a bug database?&lt;/li&gt;
&lt;li&gt;Do you fix bugs before writing new code?&lt;/li&gt;
&lt;li&gt;Do you have an up-to-date schedule?&lt;/li&gt;
&lt;li&gt;Do you have a spec?&lt;/li&gt;
&lt;li&gt;Do programmers have quiet working conditions?&lt;/li&gt;
&lt;li&gt;Do you use the best tools money can buy?&lt;/li&gt;
&lt;li&gt;Do you have testers?&lt;/li&gt;
&lt;li&gt;Do new candidates write code during their interview?&lt;/li&gt;
&lt;li&gt;Do you do hallway usability testing?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, what do you suggest for the Joel Test 2019 edition ?&lt;/p&gt;

&lt;p&gt;Here is mine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do programmers have quiet working conditions?&lt;/li&gt;
&lt;li&gt;Do you make daily builds?&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can you make a build in one step? (include tests and deployment)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do you use decentralized source control?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do you have a wiki?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do you use tools chosen by the team? (include OS &amp;amp; IDE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do you have time allocated to improve internal tools or process?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do you have time allocated to learn something new? (Not just lunch &amp;amp; learn)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can you do remote-work one day in the week?/Can you choose your work-hours?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can you sleep or make sport during lunch time? (Quiet room/shower available)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can you meet or talk with your final users? (best feedback and empathy source :) )&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do you use any agile methodology?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(In my opinion the agile methodology is not something perfect, it could be something like "Can the team refuse the chief assignment/work/idea ?", something about hierarchy, humans interractions, democracy in the team, I'm a little bit fuzzy about this step).&lt;/p&gt;

&lt;p&gt;Please, feel free to share your "Must-have" ideas :)&lt;br&gt;
Thanks for reading, enjoy your day !&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>work</category>
    </item>
    <item>
      <title>Any rules, tips and tricks for commit message</title>
      <dc:creator>JeffD</dc:creator>
      <pubDate>Mon, 16 Oct 2017 19:18:35 +0000</pubDate>
      <link>https://dev.to/cotcotcoder/any-rules-tips-and-tricks-for-commit-message-22c</link>
      <guid>https://dev.to/cotcotcoder/any-rules-tips-and-tricks-for-commit-message-22c</guid>
      <description>&lt;p&gt;Reading commit messages is a great way to understand software evolution without reading all the code.&lt;/p&gt;

&lt;p&gt;I use the following rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;start with an action verb: Add, Fix, Remove, Update, Refactore...&lt;/li&gt;
&lt;li&gt;include the concerned domain (if != code): test, documentation, config, scripts... &lt;/li&gt;
&lt;li&gt;a description to explain the "Why?" or "How?"&lt;/li&gt;
&lt;li&gt;and a reference to ticket or bug&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To obtain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fix tests for Linux platform: filesystem was hardcoded - #123&lt;/li&gt;
&lt;li&gt;Add configuration: support article pagination - #345&lt;/li&gt;
&lt;li&gt;Refactore customer subscription service to improve performance - #898&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you, do you use any rules to write better commit message in your company or open source project ?  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://xkcd.com/1296/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33lx2fc7hrsm1bh1kgnp.png" width="439" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vcs</category>
      <category>git</category>
      <category>tips</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
