<?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: amabe_dev</title>
    <description>The latest articles on DEV Community by amabe_dev (@amabe_dev).</description>
    <link>https://dev.to/amabe_dev</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%2F882273%2F9b02bd11-d67d-47d1-8b07-9dfbd6a551cb.png</url>
      <title>DEV Community: amabe_dev</title>
      <link>https://dev.to/amabe_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amabe_dev"/>
    <language>en</language>
    <item>
      <title>How to Make Pull Requests Easier</title>
      <dc:creator>amabe_dev</dc:creator>
      <pubDate>Mon, 09 Jan 2023 19:24:36 +0000</pubDate>
      <link>https://dev.to/amabe_dev/how-to-make-pull-requests-easier-348k</link>
      <guid>https://dev.to/amabe_dev/how-to-make-pull-requests-easier-348k</guid>
      <description>&lt;p&gt;Pull Requests are a powerful tool for code review and knowledge sharing.&lt;/p&gt;

&lt;p&gt;And, as developers, reviewing Pull Requests represent a big amount of time every week.&lt;/p&gt;

&lt;p&gt;We will talk about "Pull Requests" in this article. But you can read it as "Merge Request" or whatever term you are used to. These ideas are not directly linked to any tooling.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  But we might not want to do Pull Request
&lt;/h2&gt;

&lt;p&gt;Some really knowledgeable people advise against doing Pull Requests inside a team. So, here are some reasons why we might not want to do Pull Requests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They introduce a blocking step in the dev process. And this step might take time.&lt;/li&gt;
&lt;li&gt;We do not often catch problems during these reviews.&lt;/li&gt;
&lt;li&gt;And when we find something to say, the feedback comes really late, and it might be too late to make changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can do pair or mob programming to keep the benefits of Pull Requests without their drawbacks. Pair or mob programming put the discussion and feedback during the development of a feature instead of when it is already done. This makes for a better design and implementation on the first time.&lt;/p&gt;

&lt;p&gt;By doing so, there should be nothing to say once the feature is done. And the team can go to another feature directly because there is no longer the need for this blocking Pull Request step in the process.&lt;/p&gt;

&lt;p&gt;But leaving Pull Requests or doing pair programming might not be an option. So we better know how to do effective Pull Requests. And here are thoughts to try to make them easier.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pull Requests as a team
&lt;/h2&gt;

&lt;p&gt;Pull requests do not have much sense outside a team because nobody would be able to review our changes. So it starts by asking ourselves why we use this tool inside our team.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Define what you expect from Pull Request
&lt;/h3&gt;

&lt;p&gt;It is not enough to create a branch, doing multiple things on it, create a Pull Request and wait while spamming our teammates from time to time so they don't forget to review it.&lt;/p&gt;

&lt;p&gt;Well. In fact, it can be enough. And it is sometimes what is done in teams. But it is definitively not the best experience for anyone.&lt;/p&gt;

&lt;p&gt;Instead, everybody on the team should be aligned on how to handle the Pull Requests. This means answering questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When should Pull Requests be used? Are they required for any new development? Or are they only for new features? What about documentation, styles or build changes?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Are they used for everyone or only for contributions from people outside the team?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What are their goal? Is it to share knowledge between team members? Is it just a tool for code review? Is it okay to suggest big changes or start discussions on a Pull Request?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Are Pull Request a way to transfer the ownership from the author to the whole team? Meaning that, once merged, every member of the team is as responsible for the code as the original author.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When are they reviewed? Each day? Each Friday? Each March 2nd?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Who can validate a Pull Request? Can every developer give his approval or only senior developers? &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And how the reviewers know that they should review the Pull Request? Are they mentioned on it? Do they watch for a given label? Does the Pull Request link need to be sent in a channel in team's chat?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When can we consider a Pull Request approved? Does it need to be approved by only one person? Or do multiple developers need to approve it before merging.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And how to know that someone approved the Pull Request? Does the person approve it by using an "Approve" feature of the tool? By adding an emoji? (If so, which emoji?) Or by leaving a comment that says "all good for me"?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Who resolve the comments on the Pull Request? Is it the author of the Pull Request or the author of the comment? Or is it the author of the comment if he has not yet approved it and the author of the Pull Request otherwise?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Making sure that everybody in the team is aligned with why we do Pull Requests is important. Otherwise, it could be the cause of conflicts between team members that have different expectations.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Automate everything you can
&lt;/h3&gt;

&lt;p&gt;A review by a peer takes time and is often quite exhausting for the reviewer.&lt;/p&gt;

&lt;p&gt;To make it easier on the reviewers, everything that can be automated should be automated.&lt;/p&gt;

&lt;p&gt;This includes, if possible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running the tests automatically, so the reviewers don't have to do it manually.&lt;/li&gt;
&lt;li&gt;Running code formatters to have consistent formatting everywhere and not letting the formatting be a distraction.&lt;/li&gt;
&lt;li&gt;Running linters and code quality tools for common problems and team conventions to avoid manual checking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Automating everything that can be lets the reviewers focus on what is important. They are free from checking every whitespace and variable declaration and can focus on the big picture.&lt;/p&gt;

&lt;p&gt;Another benefit is that the automation gives feedback earlier. The earlier the feedback, the better. Ideally we should even be able to run these automated checks locally to have the feedback during the development.&lt;/p&gt;

&lt;p&gt;And when automated, there are way less comments to handle. The fewer comments there are, the easier it is for everyone. The author doesn't have to handle them. And the reviewers don't have to come and check later to see if they are resolved.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Find what works for you
&lt;/h3&gt;

&lt;p&gt;There is no single solution that work for every team. Pull Requests are easier when everyone is aligned on why we do Pull Requests and there is automated feedback. But we still need to review the Pull Requests.&lt;/p&gt;

&lt;p&gt;To make the review process easier, the team may choose to use its own conventions. Here are some ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everybody can add an emoji while reviewing to communicate that he's still doing the review. This can help avoid getting comments after the Pull Request is merged. And it helps to avoid spamming someone for a review if he is already reviewing the Pull Request.&lt;/li&gt;
&lt;li&gt;A tool that can be useful is the use of &lt;a href="https://conventionalcomments.org/" rel="noopener noreferrer"&gt;conventional comments&lt;/a&gt;. This helps to give context about the comment, its intent and what is expected. It can make it easier for everyone to know what is needed. (More on that later.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's now move on into the life of a Pull Request. And its starts by the author creating the Pull Request for review.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  As the author
&lt;/h2&gt;

&lt;p&gt;As the author of the Pull Request, we are proposing changes to our team. It is often expected that we will make the changes necessary until the Pull Request is merged.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Remember that it is the code that is reviewed
&lt;/h3&gt;

&lt;p&gt;Comments on the Pull Request are comments about the code we produced and the solution we thought of. It is easy to take them personally.&lt;/p&gt;

&lt;p&gt;But we shouldn't. One of the most important thing we can do is to remember that the comments are about the code and not about ourselves. We should put our ego aside to discuss the choices we made and search for the best solution.&lt;/p&gt;

&lt;p&gt;It's possible that we made bad choices. There are a lot of good reasons to be wrong, including not being aware of some information, or just making mistakes. Or our solution can be a good solution but not the best possible. We should try our best to stay open to find better solutions instead of defending what we did first.&lt;/p&gt;

&lt;p&gt;This does not mean that the reviewers are always right. Sometimes we already thought about or tried what is suggested and rejected the solution. We should explain why we chose the solution if it's relevant. We just shouldn't hold to a bad solution just because of our ego.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Break changes down
&lt;/h3&gt;

&lt;p&gt;Big Pull Requests are exhausting both for us and for the reviewers. And the reviewers will not be able to do a good review if the Pull Request is too long.&lt;/p&gt;

&lt;p&gt;To make Pull Requests easier, we should try to make them as small as possible. This means splitting big tasks in smaller tasks and doing one Pull Request for each.&lt;/p&gt;

&lt;p&gt;If the task is big and multiple Pull Requests are necessary, it may take time to continue. To address this problem, we can stack Pull Requests. (The first points to the branch we want to merge on. The second point on the branch of the first. And we will merge the first before merging the second.)&lt;/p&gt;

&lt;p&gt;Smaller Pull Requests make it possible for the reviewers to focus on what changed, leading to better feedback. And since they are faster to review and result in less comments, they are usually merged faster. And, since smaller Pull Requests are less of a chore, this can help team members to review them more frequently.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Explain what the change is intended to do
&lt;/h3&gt;

&lt;p&gt;To make it easier for reviewers, we should explain what the changes are intended to do. It can be as easy as giving the context that made the change necessary.&lt;/p&gt;

&lt;p&gt;Since we try to make small Pull Request, the changes should only focus on one behavior change. That makes them easier to explain.&lt;/p&gt;

&lt;p&gt;The reviewers were most likely working on other subjects. Giving them the context of the change is a gift we give to them. This information makes the switch of context easier for them.&lt;/p&gt;

&lt;p&gt;If the change is linked to an issue, it is interesting to put a link to that issue in the description. It gives an easy way for reviewers to get more context if they need. (For what it's worth, you might also want to put it in the commit. It can help a lot to find why something was done when debugging in the future.)&lt;/p&gt;

&lt;p&gt;And we can add comments on our Pull Request if there are some changes where we think more context is needed. (In this case it makes sense to ask ourselves if the best place is a comment on the Pull Request or a comment in the code.)&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Be your first reviewer
&lt;/h3&gt;

&lt;p&gt;Reviewing our Pull Request ourselves can help catch errors, forgotten TODOs or bad structure. And finding these ourselves saves times for everyone by avoiding back and forth comments.&lt;/p&gt;

&lt;p&gt;Reviewing our code is easier that reviewing a Pull Request from someone else because we already have the context and the big picture view of what is done. There is no good reason not to do it. (Except that we might have already done it before typing "git commit" two minutes ago.)&lt;/p&gt;

&lt;p&gt;And it is an opportunity to add comments to explain a choice we made for the reviewers. Or even to ask for thoughts about a piece of code we are unsure of.&lt;/p&gt;

&lt;p&gt;Then we just have to wait for the reviewers to review our newly created Pull Request and answer them or apply their suggestions.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  As a reviewer
&lt;/h2&gt;

&lt;p&gt;This is the hardest role in the Pull Request process. It requires us to switch context and understand what someone else did. But it is the whole point of the Pull Requests. They would serve no purpose without reviewers.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Remember that it is the code that is reviewed
&lt;/h3&gt;

&lt;p&gt;The authors should remember that it is their code that is reviewed and that the comments are not about themselves. But for that to work, we have to ensure that the comments are about the code and not the authors when writing them.&lt;/p&gt;

&lt;p&gt;We should always be discussing solutions and how to make the code better. And there should never have comments on the author. If we find ourselves using "you" in a comment, we should take time to think again if this is really what we are wanting to write. Pull Requests are usually not fun. Let's try to not make them harder than necessary for anyone.&lt;/p&gt;

&lt;p&gt;If you see something that seem strange, it is better to ask for details about the choice. And more often than not we should not suggest that something is wrong without all the context necessary. There are chances that the authors thought about it and made a decision based on information we do not have. So prefer asking for details instead of pointing something as wrong.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Share your thoughts
&lt;/h3&gt;

&lt;p&gt;Pull Requests are a communication tool. This is not an evaluation of the code someone else produced. We can do more than just saying what could be better.&lt;/p&gt;

&lt;p&gt;It can be asking questions to better understand a choice or why the change was necessary. After all, once the Pull Request is merged, we will likely have to maintain this code. It is a good moment to go get information to understand it.&lt;/p&gt;

&lt;p&gt;It can also be thoughts of potential issues we think of when reviewing the code. Maybe the changes may have impacts that the authors did not think about that would be interesting to check. If so, tell them. It will be easier to check it and make changes when the Pull Request is still being reviewed.&lt;/p&gt;

&lt;p&gt;And it can even be unrelated thoughts. For example, sharing a pattern that we think might be appropriate but do not make the code a lot better. It can help to gather opinions or start a discussion to finish elsewhere later.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Be clear about what you expect
&lt;/h3&gt;

&lt;p&gt;We put comments on Pull Requests for different reasons. We should be clear about the intent behind every comment so the author and other reviewers know what we are expecting.&lt;/p&gt;

&lt;p&gt;The context of a comment includes: if it is blocking the Pull Request, whether it is a question, a thought or an issue, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://conventionalcomments.org/" rel="noopener noreferrer"&gt;Conventional comments&lt;/a&gt; are a great tool for this. It consists of prefixing the comment with context. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prefixing with "&lt;strong&gt;question:&lt;/strong&gt;" if we are asking for more details&lt;/li&gt;
&lt;li&gt;prefixing with "&lt;strong&gt;thought:&lt;/strong&gt;" if we are sharing a thought and not making a suggestion&lt;/li&gt;
&lt;li&gt;prefixing with "&lt;strong&gt;suggestion:&lt;/strong&gt;" if we are suggesting changes&lt;/li&gt;
&lt;li&gt;prefixing with "&lt;strong&gt;nitpick:&lt;/strong&gt;" if what is done works, but we found something to nitpick about&lt;/li&gt;
&lt;li&gt;adding "&lt;strong&gt;(blocking)&lt;/strong&gt;" or "&lt;strong&gt;(non-blocking)&lt;/strong&gt;" to add context about if it has to be taken into account if the author wants our approval&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See &lt;a href="https://conventionalcomments.org/" rel="noopener noreferrer"&gt;the Conventional Comments' website&lt;/a&gt; for more details. And, even if they thought of a lot of cases, we can add our own keywords if we need to. Or even take inspiration from it and do it our way with different keywords. Or with emojis.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Let the author know of what is done well
&lt;/h3&gt;

&lt;p&gt;Last, it is nice to the authors know if we find something that is well done.&lt;/p&gt;

&lt;p&gt;It can be hard to receive only feedback on what to change. Getting feedback on what is good can help the authors feel better about the review and his skills. Especially if the author is new in the team, a junior or lacks confidence.&lt;/p&gt;

&lt;p&gt;The review is not a punishment, we should try to make it easier for everyone.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

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

&lt;p&gt;There are tips that I think can help make Pull Requests easier for everyone in a team.&lt;/p&gt;

&lt;p&gt;These are my current opinions about Pull Requests. It may change in the future, it surely did since I started doing them. And I will try to keep this article updated if I change my mind.&lt;/p&gt;

&lt;p&gt;I hope it can help you to make better Pull Requests. And, if you think of things that are missing, please reach out. I would be grateful for the feedback and would love to try new ideas.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>github</category>
      <category>git</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Interesting resources</title>
      <dc:creator>amabe_dev</dc:creator>
      <pubDate>Sat, 19 Nov 2022 15:50:31 +0000</pubDate>
      <link>https://dev.to/amabe_dev/interesting-resources-entry-point-ia9</link>
      <guid>https://dev.to/amabe_dev/interesting-resources-entry-point-ia9</guid>
      <description>&lt;p&gt;This post is intended as an entry point to resources I find interesting.&lt;/p&gt;

&lt;p&gt;These were in my Twitter bookmarks. But it does not seem the best place to keep these resources anymore.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;General&lt;/li&gt;
&lt;li&gt;Architecture&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Tooling&lt;/li&gt;
&lt;li&gt;Design&lt;/li&gt;
&lt;li&gt;Management&lt;/li&gt;
&lt;li&gt;Misc&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  General
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Clean Code rules summary with JavaScript examples:&lt;br&gt;
&lt;a href="https://github.com/ryanmcdermott/clean-code-javascript" rel="noopener noreferrer"&gt;https://github.com/ryanmcdermott/clean-code-javascript&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Programming principles summary: &lt;a href="https://github.com/webpro/programming-principles" rel="noopener noreferrer"&gt;https://github.com/webpro/programming-principles&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Using an hexagonal architecture to limit coupling of the business logic with the framework: &lt;a href="https://dev.to/drouianm/hexagonal-architecture-as-a-solution-to-the-obsolescence-of-ui-frameworks-ej2"&gt;https://dev.to/drouianm/hexagonal-architecture-as-a-solution-to-the-obsolescence-of-ui-frameworks-ej2&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Guide for JavaScript library build: &lt;a href="https://github.com/frehner/modern-guide-to-packaging-js-library" rel="noopener noreferrer"&gt;https://github.com/frehner/modern-guide-to-packaging-js-library&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Thoughts about microservices vs monolith: &lt;a href="https://dev.to/semaphore/when-microservices-are-a-bad-idea-2p7h"&gt;https://dev.to/semaphore/when-microservices-are-a-bad-idea-2p7h&lt;/a&gt; %}&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Testing best practices (for JavaScript app): &lt;a href="https://github.com/goldbergyoni/javascript-testing-best-practices" rel="noopener noreferrer"&gt;https://github.com/goldbergyoni/javascript-testing-best-practices&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Tooling
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A great articles about using the devtools: &lt;a href="https://dev.to/lissy93/awesome-dev-tool-tips-32oo"&gt;https://dev.to/lissy93/awesome-dev-tool-tips-32oo&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Design
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Checklist for interface design: &lt;a href="https://www.smashingmagazine.com/2022/09/ux-checklists-for-interface-designers/" rel="noopener noreferrer"&gt;https://www.smashingmagazine.com/2022/09/ux-checklists-for-interface-designers/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Management
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A framework for evaluation: &lt;a href="https://github.com/jorgef/engineeringladders" rel="noopener noreferrer"&gt;https://github.com/jorgef/engineeringladders&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Misc
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Privacy and security focused softwares: &lt;a href="https://github.com/lissy93/awesome-privacy" rel="noopener noreferrer"&gt;https://github.com/lissy93/awesome-privacy&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Personal security best practices: &lt;a href="https://security-list.js.org/#/" rel="noopener noreferrer"&gt;https://security-list.js.org/#/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Article about knowledge sharing in teams: &lt;a href="https://leaddev.com/communication-relationships/want-promote-knowledge-sharing-your-teams-standardize-way-you-take" rel="noopener noreferrer"&gt;https://leaddev.com/communication-relationships/want-promote-knowledge-sharing-your-teams-standardize-way-you-take&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tips to promote knowledge sharing: &lt;a href="https://dev.to/codingchili/tips-for-boosting-knowledge-sharing-1f93"&gt;https://dev.to/codingchili/tips-for-boosting-knowledge-sharing-1f93&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>career</category>
    </item>
    <item>
      <title>How do you promote knowledge sharing?</title>
      <dc:creator>amabe_dev</dc:creator>
      <pubDate>Thu, 06 Oct 2022 17:28:51 +0000</pubDate>
      <link>https://dev.to/amabe_dev/how-do-you-share-knowledge-inside-your-team-1p16</link>
      <guid>https://dev.to/amabe_dev/how-do-you-share-knowledge-inside-your-team-1p16</guid>
      <description>&lt;p&gt;Knowledge sharing seem to be a hard challenge.&lt;/p&gt;

&lt;p&gt;So, here is the question: How do you promote knowledge sharing inside your team and/or organization?&lt;/p&gt;

&lt;p&gt;Please share your awesome tips and resources to go deeper on the subject!&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Unit testing AngularJS components with ng-model</title>
      <dc:creator>amabe_dev</dc:creator>
      <pubDate>Wed, 31 Aug 2022 18:10:22 +0000</pubDate>
      <link>https://dev.to/amabe_dev/angularjs-unit-testing-ng-model-4ic1</link>
      <guid>https://dev.to/amabe_dev/angularjs-unit-testing-ng-model-4ic1</guid>
      <description>&lt;p&gt;I wanted to test a component using the UI elements to avoid testing to much implementation details.&lt;/p&gt;

&lt;p&gt;When doing that, I faced was faced with an input and did not find easily how to trigger its change events to trigger the &lt;code&gt;ng-model&lt;/code&gt; change and the &lt;code&gt;ng-change&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;Here is how I did it. (This come late given that AngularJS is deprecated. But I guess I will not be the only one lucky enough to still work with it sometime.)&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  The test base
&lt;/h2&gt;

&lt;p&gt;For these tests, we will use the &lt;code&gt;angular-mocks&lt;/code&gt; library.&lt;/p&gt;

&lt;p&gt;We will use le &lt;code&gt;$compile&lt;/code&gt; to instanciate the component. And then interact with the component by using the compiled elements.&lt;/p&gt;

&lt;p&gt;We will compile the &lt;code&gt;input&lt;/code&gt; directly to make the tests easier. We could compile a component that have inputs and retrieve them by calling the JQuery &lt;code&gt;.find(&amp;lt;selector&amp;gt;)&lt;/code&gt; on the compiled element.&lt;/p&gt;

&lt;p&gt;We will use the Jest syntax for the test declaration and assertions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;angular-mocks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;$rootScope&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;$compile&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;$timeout&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_$rootScope_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_$compile_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_$timeout_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;$rootScope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_$rootScope_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;$compile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_$compile_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;$timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_$timeout_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Simple ng-model test
&lt;/h2&gt;

&lt;p&gt;In this test, we will use a simple &lt;code&gt;input&lt;/code&gt; without &lt;code&gt;ng-model-options&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To update the &lt;code&gt;ng-model&lt;/code&gt; update and &lt;code&gt;ng-change&lt;/code&gt; update we will use the following JQuery operations:&lt;br&gt;
    - &lt;code&gt;.val(&amp;lt;value&amp;gt;)&lt;/code&gt; to update the value&lt;br&gt;
    - &lt;code&gt;.triggerHandler('change')&lt;/code&gt; to send the &lt;code&gt;change&lt;/code&gt; event of the input&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Should trigger change ng-model value and trigger ng-change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$rootScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;input ng-model="value" ng-change="onChange()"&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$digest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;triggerHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  ng-model with update on blur
&lt;/h2&gt;

&lt;p&gt;In this test, we will use a simple &lt;code&gt;input&lt;/code&gt; with &lt;code&gt;ng-model-options&lt;/code&gt; to update only when the input &lt;code&gt;blur&lt;/code&gt; event is triggered.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;blur&lt;/code&gt; event is triggered when the field looses focus.&lt;/p&gt;

&lt;p&gt;This may be used to avoid updating every time the value changes if we know that we will only use the value when the input will be filled.&lt;/p&gt;

&lt;p&gt;To update the &lt;code&gt;ng-model&lt;/code&gt; update and &lt;code&gt;ng-change&lt;/code&gt; update we will use the following JQuery operations:&lt;br&gt;
    - &lt;code&gt;.val(&amp;lt;value&amp;gt;)&lt;/code&gt; to update the value&lt;br&gt;
    - &lt;code&gt;.triggerHandler('change')&lt;/code&gt; to send the &lt;code&gt;change&lt;/code&gt; event of the input&lt;br&gt;
    - &lt;code&gt;.triggerHandler('blur')&lt;/code&gt; to send the &lt;code&gt;blur&lt;/code&gt; event of the input&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Should trigger change ng-model value and trigger ng-change (update on blur)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$rootScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;input ng-model="value" ng-model-options="{ updateOn: &lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;blur&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt; }" ng-change="onChange()"&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$digest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;triggerHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;triggerHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blur&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  ng-model with debounce
&lt;/h2&gt;

&lt;p&gt;In this test, we will use a simple &lt;code&gt;input&lt;/code&gt; without &lt;code&gt;ng-model-options&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The debounce option can be used to update the value only when the if it does not change for a given time.&lt;/p&gt;

&lt;p&gt;This make it possible to keep up to date even if the input does not loose focus while avoiding getting too much events.&lt;/p&gt;

&lt;p&gt;It can be useful for elements like search inputs where we want to show suggestions while the user types. But we do not want to do the computation on every change because it can be quite heavy.&lt;/p&gt;

&lt;p&gt;To update the &lt;code&gt;ng-model&lt;/code&gt; update and &lt;code&gt;ng-change&lt;/code&gt; update we will use the following JQuery operations:&lt;br&gt;
    - &lt;code&gt;.val(&amp;lt;value&amp;gt;)&lt;/code&gt; to update the value&lt;br&gt;
    - &lt;code&gt;.triggerHandler('change')&lt;/code&gt; to send the &lt;code&gt;change&lt;/code&gt; event of the input&lt;/p&gt;

&lt;p&gt;Then we will use &lt;code&gt;$timeout.flush()&lt;/code&gt; for the code to act like if the debounce time has passed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Should trigger change ng-model value and trigger ng-change (debounce)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$rootScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;input ng-model="value" ng-model-options="{ debounce: 200 }" ng-change="onChange()"&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$digest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;triggerHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;$timeout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>angular</category>
      <category>testing</category>
    </item>
    <item>
      <title>Interesting Things in Tech lately (2022 week 33)</title>
      <dc:creator>amabe_dev</dc:creator>
      <pubDate>Mon, 22 Aug 2022 16:28:00 +0000</pubDate>
      <link>https://dev.to/amabe_dev/interesting-things-in-tech-lately-2022-week-33-210d</link>
      <guid>https://dev.to/amabe_dev/interesting-things-in-tech-lately-2022-week-33-210d</guid>
      <description>&lt;p&gt;It takes quite a lot of time to keep updated on what is happening in the tech world. So I thought it would be interesting to share what we found interesting.&lt;/p&gt;

&lt;p&gt;Here is what I found interesting last week. If you have found interesting things that I didn't put here, please add them in the comments, it will help to share the efforts.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Big changes for Deno
&lt;/h2&gt;

&lt;p&gt;Deno will make it easier to work with NPM packages. It will be possible to import them like this: &lt;code&gt;import express from "npm:express@5";&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And they have the goal to make it the fastest of JavaScript runtimes.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://deno.com/blog/changes" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--r_KgTWst--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://deno.com/blog/changes/og.png" height="419" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://deno.com/blog/changes" rel="noopener noreferrer" class="c-link"&gt;
          Big Changes Ahead for Deno
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Learnings from our recent survey and feedback from across our community. We'll discuss how we're addressing this feedback and the features to expect from Deno in the coming months.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--1H83jcKN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://deno.com/favicon.ico" width="256" height="256"&gt;
        deno.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;
  
  
  The job interview process for senior roles
&lt;/h2&gt;

&lt;p&gt;A very complete article on the interview process for senior engineer roles.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/errietta" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fpCsJRPO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--c4lCwhQE--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/49539/54372f98-bb09-4199-ab2e-036ccbbfcc0b.jpg" alt="errietta"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/errietta/how-to-get-the-best-job-offer-for-senior-software-engineer-roles-4pdf" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to get the best job offer for senior+ software engineer roles&lt;/h2&gt;
      &lt;h3&gt;Erry Kostala ・ Aug 15 '22&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#interview&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#career&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#jobs&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;
  
  
  Thoughts about the tech lead role
&lt;/h2&gt;

&lt;p&gt;An interesting thread to read on the teach lead role.&lt;/p&gt;

&lt;p&gt;(TL;DR: Be there to improve the team as a whole, not just have badass skills.)&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1559213234992947202-528" src="https://platform.twitter.com/embed/Tweet.html?id=1559213234992947202"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1559213234992947202-528');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1559213234992947202&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Tips for giving feedback
&lt;/h2&gt;

&lt;p&gt;Very nice thoughts about giving feedback.&lt;/p&gt;

&lt;p&gt;Remember to also include feedback on what we like and not only negative feedback.&lt;/p&gt;

&lt;p&gt;And remember that the person might also receive feedback from others.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://charity.wtf/2022/08/15/giving-good-feedback-consider-the-ratio/" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--gSuH-ho9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i0.wp.com/charity.wtf/wp-content/uploads/2021/01/mepurp-15.jpg%3Ffit%3D902%252C1200%26ssl%3D1" height="1064" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://charity.wtf/2022/08/15/giving-good-feedback-consider-the-ratio/" rel="noopener noreferrer" class="c-link"&gt;
          Giving Good Feedback: Consider the Ratio – charity.wtf
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Consider the ratio. You work with someone great. If someone asked, you’d say they are brilliant, inspired and dedicated. They care deeply about their work, they are timely and reliable (for the mos…
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--MjWuUMLq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://s0.wp.com/i/webclip.png" width="512" height="512"&gt;
        charity.wtf
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;
  
  
  Thoughts about taking notes as a team
&lt;/h2&gt;

&lt;p&gt;Nice thoughts about taking notes as a team to share knowledge.&lt;/p&gt;

&lt;p&gt;Taking (good) notes as a person is a very powerful tool. Taking them as a team may be even more powerful. (If people in the team are interested in taking notes this way.)&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://leaddev.com/communication-relationships/want-promote-knowledge-sharing-your-teams-standardize-way-you-take" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--2otqvEyg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://leaddev.com/sites/default/files/styles/linkedin_card/public/2022-08/Want%2520to%2520promote%2520knowledge-sharing%2520in%2520your%2520teams%253F%2520Standardize%2520the%2520way%2520you%2520take%2520notes..png%3Fitok%3DYo8BBG10" height="457" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://leaddev.com/communication-relationships/want-promote-knowledge-sharing-your-teams-standardize-way-you-take" rel="noopener noreferrer" class="c-link"&gt;
          Want to promote knowledge-sharing in your teams? Standardize the way you take notes. | LeadDev
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          How to manage and document the collective knowledge across your teams
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--aECTTNKI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://leaddev.com/themes/custom/leaddev/favicon.ico" width="48" height="48"&gt;
        leaddev.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Good (quick) Resources to Become a Better Developer</title>
      <dc:creator>amabe_dev</dc:creator>
      <pubDate>Mon, 15 Aug 2022 15:18:00 +0000</pubDate>
      <link>https://dev.to/amabe_dev/good-quick-resources-to-be-a-better-developer-288n</link>
      <guid>https://dev.to/amabe_dev/good-quick-resources-to-be-a-better-developer-288n</guid>
      <description>&lt;p&gt;In this article I will share some resources that I find great to become a better developer.&lt;/p&gt;

&lt;p&gt;There will be no books or other time consuming resources in this article. I will only include resources that are relatively quick to consume.&lt;/p&gt;

&lt;p&gt;If you can think of other good resources that are not included here, feel free to share them in the comments. I am always looking for good resources and would love to see them.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean Code
&lt;/h2&gt;



&lt;h3&gt;
  
  
  clean-code-javascript by Ryan McDermott
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/ryanmcdermott/clean-code-javascript" rel="noopener noreferrer"&gt;clean-code-javascript&lt;/a&gt;, by Ryan McDermott, is a GitHub repository. It shows examples of the Clean Code principles of Uncle Bob written in JavaScript.&lt;/p&gt;

&lt;p&gt;It is a sort of overview of what is in the book. It is a really good read for people that are not familiar with the book or who want a refresher.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Programming Principles
&lt;/h2&gt;



&lt;h3&gt;
  
  
  Programming Principles by Lars Kappert
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/webpro/programming-principles" rel="noopener noreferrer"&gt;Programming Principles&lt;/a&gt;, by Lars Kappert, is a GitHub repository. It lists programming principles with a brief description and links to dig deeper.&lt;/p&gt;

&lt;p&gt;It is a good introduction to programming principles. Or a good refresher for those who already know about them.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  patterns.dev website
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.patterns.dev/" rel="noopener noreferrer"&gt;patterns.dev&lt;/a&gt; website lists design patterns for the web. It is both a free book and a set pages by design pattern on the website.&lt;/p&gt;

&lt;p&gt;It also includes links to other resources, like the clean-code-javascript above.&lt;/p&gt;

&lt;p&gt;It is a good place filled with interesting resources.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Best Practices
&lt;/h2&gt;



&lt;h3&gt;
  
  
  JavaScript Testing Best Practices by Yoni Goldberg
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/goldbergyoni/javascript-testing-best-practices" rel="noopener noreferrer"&gt;JavaScript Testing Best Practices&lt;/a&gt;, by Yoni Goldberg is a GitHub repository. It gives good practices about testing.&lt;/p&gt;

&lt;p&gt;I would recommend it for everyone because it is really complete. There are good chances that everyone will either learn or remember some good practices while reading it.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Interesting Things in Tech (2022w32)</title>
      <dc:creator>amabe_dev</dc:creator>
      <pubDate>Mon, 15 Aug 2022 12:25:40 +0000</pubDate>
      <link>https://dev.to/amabe_dev/interesting-things-in-tech-2022w32-54a7</link>
      <guid>https://dev.to/amabe_dev/interesting-things-in-tech-2022w32-54a7</guid>
      <description>&lt;p&gt;It takes quite a lot of time to keep updated on what is happening in the tech world. So I thought it would be interesting to share what we found interesting.&lt;/p&gt;

&lt;p&gt;Here is what I found interesting last week. If you have found interesting things that I didn't put here, please add them in the comments, it will help to share the efforts.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  A reflection on SOLID principle
&lt;/h2&gt;

&lt;p&gt;Martin Fowler said it all in this tweet. It is an interesting read with openings to other principles.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1558085694127489025-414" src="https://platform.twitter.com/embed/Tweet.html?id=1558085694127489025"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1558085694127489025-414');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1558085694127489025&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Checklists for accessibility
&lt;/h2&gt;

&lt;p&gt;These checklists are quite simple but have a lot of value to make sure that we looked at everything.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1557704990822731779-589" src="https://platform.twitter.com/embed/Tweet.html?id=1557704990822731779"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1557704990822731779-589');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1557704990822731779&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Using native modals
&lt;/h2&gt;

&lt;p&gt;A nice article from &lt;a class="mentioned-user" href="https://dev.to/dailydevtips1"&gt;@dailydevtips1&lt;/a&gt; about using native modals. There seems that we have no need for modal plugins anymore. It even takes care about the accessibility issues with focus.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/dailydevtips1" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F370165%2F083a25f4-e79b-42c4-9e5f-0332b834ca5e.png" alt="dailydevtips1"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/dailydevtips1/trying-out-native-dialog-modals-20md" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Trying out native dialog modals&lt;/h2&gt;
      &lt;h3&gt;Chris Bongers ・ Aug 8 '22&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#html&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;
  
  
  The changes on GitLab free plan
&lt;/h2&gt;

&lt;p&gt;Last week they announced that inactive projects will be archived. They will still be accessible but it will take longer to access.&lt;/p&gt;

&lt;p&gt;They will also apply a storage limit on free namespaces: &lt;a href="https://docs.gitlab.com/ee/user/usage_quotas.html#namespace-storage-limit-enforcement-schedule" rel="noopener noreferrer"&gt;https://docs.gitlab.com/ee/user/usage_quotas.html#namespace-storage-limit-enforcement-schedule&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here are thoughts about these changes and the reaction we see. The complaints come from the user perspective to whom we remove things they could use for free before. This gives a wider perspective:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1558172218751963136-729" src="https://platform.twitter.com/embed/Tweet.html?id=1558172218751963136"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1558172218751963136-729');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1558172218751963136&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  NPM and security
&lt;/h2&gt;

&lt;p&gt;A big problem with NPM is that we have to download the packages to see their code. There is often a link to a GitHub repository but we cannot be sure that it is the same code.&lt;/p&gt;

&lt;p&gt;NPM has opened a RFC to address this problem.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1556706813944504320-766" src="https://platform.twitter.com/embed/Tweet.html?id=1556706813944504320"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1556706813944504320-766');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1556706813944504320&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The impact of translations on the design
&lt;/h2&gt;

&lt;p&gt;Interesting thoughts about the impact of translations on the design.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1556531974604455937-973" src="https://platform.twitter.com/embed/Tweet.html?id=1556531974604455937"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1556531974604455937-973');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1556531974604455937&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Teasing on Preact performance
&lt;/h2&gt;

&lt;p&gt;Jason Miller continues teasing about his latests achievements while trying to make Preact more performant.&lt;/p&gt;

&lt;p&gt;It will be a new library to replace hooks with a similar interface. More details in these threads:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1549001036802625536-221" src="https://platform.twitter.com/embed/Tweet.html?id=1549001036802625536"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1549001036802625536-221');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1549001036802625536&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1557163907340443648-280" src="https://platform.twitter.com/embed/Tweet.html?id=1557163907340443648"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1557163907340443648-280');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1557163907340443648&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Astro 1.0
&lt;/h2&gt;

&lt;p&gt;Astro has reached the 1.0. It is a framework for optimization worth checking out.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1557049466401632256-50" src="https://platform.twitter.com/embed/Tweet.html?id=1557049466401632256"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1557049466401632256-50');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1557049466401632256&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  What you learn when hacking your car
&lt;/h3&gt;

&lt;p&gt;An interesting article about the steps it takes to hack a car and the findings he did: &lt;a href="https://programmingwithstyle.com/posts/howihackedmycar/" rel="noopener noreferrer"&gt;https://programmingwithstyle.com/posts/howihackedmycar/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1558309810801631233-996" src="https://platform.twitter.com/embed/Tweet.html?id=1558309810801631233"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1558309810801631233-996');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1558309810801631233&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  A benchmark on Bun
&lt;/h2&gt;

&lt;p&gt;Another interesting benchmark on Bun by &lt;a class="mentioned-user" href="https://dev.to/tomfern"&gt;@tomfern&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;TL;DR: It is not yet fully compatible with Node.js API but it is faster on the things tested.&lt;/p&gt;

&lt;p&gt;I am still curious to see if it faster than Node.js on more complex programs. v8 has a lot of optimizations that JavaScriptCore (base of WebKit) might not have.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/semaphore" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&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%2Forganization%2Fprofile_image%2F1183%2Fc8d02a31-85ba-4528-b043-30ee19b6db2f.png" alt="Semaphore" width="500" height="500"&gt;
      &lt;div class="ltag__link__user__pic"&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%2Fuser%2Fprofile_image%2F246163%2Fd3e35cfd-7503-407d-a461-cccb8657c26f.jpg" alt="" width="800" height="599"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/semaphore/a-first-look-at-bun-will-it-take-nodes-crown-4hpd" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;A First Look at Bun: Will It Take Node’s Crown?&lt;/h2&gt;
      &lt;h3&gt;Tomas Fernandez for Semaphore ・ Aug 12 '22&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#deno&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#typescript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;
  
  
  Experienced developers struggle as well
&lt;/h2&gt;

&lt;p&gt;An article by &lt;a class="mentioned-user" href="https://dev.to/jkettmann"&gt;@jkettmann&lt;/a&gt; that I found interesting, reminding that everyone struggles at times. I think the conclusion has good advice for new developers.&lt;/p&gt;

&lt;p&gt;It makes a good point on pair-programming for onboarding new developers. It makes them see experienced developers struggle and it may help to ease the impostor syndrome. (On top of all other advantages of pair-programming.)&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/profydev" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&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%2Forganization%2Fprofile_image%2F3338%2F43691f8f-0edd-4c5e-bbc3-584d46d5f3c6.png" alt="Profy.dev" width="168" height="168"&gt;
      &lt;div class="ltag__link__user__pic"&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%2Fuser%2Fprofile_image%2F140139%2F5881453b-c3cb-4812-a9e8-4c41db313b70.jpg" alt="" width="400" height="400"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/profydev/experienced-programmers-struggle-as-well-ease-your-imposter-syndrome-as-a-junior-developer-36ad" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Experienced Programmers Struggle As Well: Ease Your Imposter Syndrome As A Junior Developer&lt;/h2&gt;
      &lt;h3&gt;Johannes Kettmann for Profy.dev ・ Aug 12 '22&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#frontend&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Interesting Things in Tech (2022w31)</title>
      <dc:creator>amabe_dev</dc:creator>
      <pubDate>Mon, 08 Aug 2022 09:48:00 +0000</pubDate>
      <link>https://dev.to/amabe_dev/tech-things-i-found-interesting-last-week-2022-08-01-2022-08-07-1fil</link>
      <guid>https://dev.to/amabe_dev/tech-things-i-found-interesting-last-week-2022-08-01-2022-08-07-1fil</guid>
      <description>&lt;p&gt;It takes quite a lot of time to watch what is happening in the tech sphere. So I thought it would be interesting to share what we found interesting.&lt;/p&gt;

&lt;p&gt;Here is what I found interesting last week. If you have found interesting things that I didn't put here, please add them in the comments.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Funny
&lt;/h2&gt;

&lt;p&gt;Think about this next time you do infinite scrolling:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1554130332420476929-574" src="https://platform.twitter.com/embed/Tweet.html?id=1554130332420476929"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1554130332420476929-574');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1554130332420476929&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Articles
&lt;/h2&gt;
&lt;h3&gt;
  
  
  2.1. Tips for creating buttons
&lt;/h3&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1554443986974253057-370" src="https://platform.twitter.com/embed/Tweet.html?id=1554443986974253057"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1554443986974253057-370');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1554443986974253057&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2. Thoughts on microservices and monoliths
&lt;/h3&gt;

&lt;p&gt;An interesting read about why starting directly with microservices may not be a good idea.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/semaphore" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&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%2Forganization%2Fprofile_image%2F1183%2Fc8d02a31-85ba-4528-b043-30ee19b6db2f.png" alt="Semaphore" width="500" height="500"&gt;
      &lt;div class="ltag__link__user__pic"&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%2Fuser%2Fprofile_image%2F246163%2Fd3e35cfd-7503-407d-a461-cccb8657c26f.jpg" alt="" width="800" height="599"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/semaphore/when-microservices-are-a-bad-idea-2p7h" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;When Microservices Are a Bad Idea&lt;/h2&gt;
      &lt;h3&gt;Tomas Fernandez for Semaphore ・ Aug 1 '22&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#microservices&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opinion&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;
  
  
  3. Security
&lt;/h2&gt;
&lt;h3&gt;
  
  
  3.1. A reminder to take care about our credentials when coding
&lt;/h3&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1554108071492079616-598" src="https://platform.twitter.com/embed/Tweet.html?id=1554108071492079616"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1554108071492079616-598');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1554108071492079616&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Dev tooling
&lt;/h2&gt;
&lt;h3&gt;
  
  
  4.1. GitLab will archive inactive repositories
&lt;/h3&gt;

&lt;p&gt;GitLab will archive inactive making them slower to access. It made a lot of noise earlier when they announced they would be deleted.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1555325376687226883-620" src="https://platform.twitter.com/embed/Tweet.html?id=1555325376687226883"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1555325376687226883-620');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1555325376687226883&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;And a discussion thread here:&lt;/p&gt;

&lt;p&gt;(The title has not been update yet to reflect the change that projects will not be deleted but archived.)&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/ben" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F1%2Ff451a206-11c8-4e3d-8936-143d0a7e65bb.png" alt="ben"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/ben/gitlab-will-be-deleting-dormant-projects-53jm" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;GitLab will be deleting dormant projects&lt;/h2&gt;
      &lt;h3&gt;Ben Halpern ・ Aug 4 '22&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#news&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#discuss&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#gitlab&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cloud&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  4.2. A new version of VSCode is here
&lt;/h3&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1555252452722675712-807" src="https://platform.twitter.com/embed/Tweet.html?id=1555252452722675712"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1555252452722675712-807');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1555252452722675712&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;And it has a new interesting experimental feature:&lt;/p&gt;

&lt;p&gt;(The title has not been updated to reflect the change yet.)&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1555466217774882818-898" src="https://platform.twitter.com/embed/Tweet.html?id=1555466217774882818"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1555466217774882818-898');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1555466217774882818&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3. StackBlitz announced collections
&lt;/h3&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1555238114574082048-735" src="https://platform.twitter.com/embed/Tweet.html?id=1555238114574082048"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1555238114574082048-735');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1555238114574082048&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;It may become a good place to find tips, like with &lt;a href="https://stackblitz.com/@waterplea/collections/angular-tips-and-tricks" rel="noopener noreferrer"&gt;this collection&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Misc
&lt;/h2&gt;
&lt;h3&gt;
  
  
  5.1. A framework for engineering managers
&lt;/h3&gt;

&lt;p&gt;An interesting read even for people who are not managers.&lt;/p&gt;

&lt;p&gt;I found it interesting to see where I think I am on this graph and what I can do to do better. And there is example graphs for different roles.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1553019018298138625-89" src="https://platform.twitter.com/embed/Tweet.html?id=1553019018298138625"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1553019018298138625-89');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1553019018298138625&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  5.2. A survey about CSS nesting
&lt;/h3&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1552034604550279168-717" src="https://platform.twitter.com/embed/Tweet.html?id=1552034604550279168"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1552034604550279168-717');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1552034604550279168&amp;amp;theme=dark"
  }



&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to run GUI apps in LXD containers</title>
      <dc:creator>amabe_dev</dc:creator>
      <pubDate>Thu, 04 Aug 2022 13:42:43 +0000</pubDate>
      <link>https://dev.to/amabe_dev/how-to-run-gui-apps-in-lxd-containers-882</link>
      <guid>https://dev.to/amabe_dev/how-to-run-gui-apps-in-lxd-containers-882</guid>
      <description>&lt;p&gt;I recently tried to run GUI apps in LXD containers and had a hard time doing it. Here is the solution I found and the problems I encountered.&lt;/p&gt;

&lt;p&gt;We will assume a basic knowledge of LXD. It is possible to follow this article with a very limited knowledge of it. But we will not start from scratch by explaining what it is and how to use it.&lt;/p&gt;

&lt;p&gt;I will explain how I did it on a Ubuntu host, by using the host Xorg socket in containers that use the &lt;code&gt;ubuntu:22.04&lt;/code&gt; image.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why use GUI apps in a LXD container
&lt;/h2&gt;

&lt;p&gt;Before doing anything, we should probably discuss why we may want to do that. Here is why I did it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Running apps in a container is more secure. They still have access to other windows because we use the host Xorg socket. But they run in a separated filesystem and have only access to what we give them.&lt;/li&gt;
&lt;li&gt;It is easier to make backup by using the snapshots and backups features provided by LXD.&lt;/li&gt;
&lt;li&gt;We can use them for temporary tests without polluting the host machine. And then delete them as if they had never been there.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My main goal was testing applications I don't fully trust while staying the most secure I can. And I then found that it is really nice to have the ability to make snapshots and clone containers, especially for dev environments.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  A way to run GUI apps in a LXD container
&lt;/h2&gt;

&lt;p&gt;Here begins the journey!&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Creating a profile and forwarding the Xorg socket
&lt;/h3&gt;

&lt;p&gt;First we need to forward the host Xorg socket. It will allow the container to display GUI without having to install its own window system.&lt;/p&gt;

&lt;p&gt;To make it easier, we can create a profile. We will then be able to start multiple containers without having to write everything again.&lt;/p&gt;

&lt;p&gt;To create a profile, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lxc profile create &amp;lt;profile name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And edit it to add the following config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;config:
  environment.DISPLAY: :0
description: ""
devices:
  X0:
    bind: container
    connect: unix:/tmp/.X11-unix/X1
    listen: unix:/mnt/X0
    security.gid: "1000"
    security.uid: "1000"
    type: proxy
name: &amp;lt;profile name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What it does is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;set the &lt;code&gt;DISPLAY&lt;/code&gt; environment variable with the value &lt;code&gt;:0&lt;/code&gt; (used to know which socket to use)&lt;/li&gt;
&lt;li&gt;proxy the host Xorg socket located at &lt;code&gt;/tmp/.X11-unix/X1&lt;/code&gt; to the container at &lt;code&gt;/mnt/X0&lt;/code&gt; (you might need to replace the &lt;code&gt;X1&lt;/code&gt; by something else)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Warning&lt;/em&gt;: We do not want to proxy the socket to &lt;code&gt;/tmp/.X11-unix/X0&lt;/code&gt; in the container. Otherwise it will be deleted on reboot because it is located on the &lt;code&gt;/tmp&lt;/code&gt; folder. See below how to do it.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Starting a container
&lt;/h3&gt;

&lt;p&gt;Now that we have our profile, we are able to create new containers with it.&lt;/p&gt;

&lt;p&gt;To start a new container, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lxc launch --profile default --profile &amp;lt;profile name&amp;gt; &amp;lt;image&amp;gt; &amp;lt;container name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are using the official &lt;code&gt;ubuntu:22.04&lt;/code&gt; image, so run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lxc launch --profile default --profile &amp;lt;profile name&amp;gt; ubuntu:22.04 &amp;lt;container name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can then enter the container by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lxc exec &amp;lt;container name&amp;gt; -- bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is our dear terminal where we can do almost anything!&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Creating a symlink for the Xorg socket
&lt;/h3&gt;

&lt;p&gt;We created a proxy for the host Xorg socket. But it is located at &lt;code&gt;/mnt/X0&lt;/code&gt;. Not in &lt;code&gt;/tmp/.X11-unix/X0&lt;/code&gt; were it needs to be.&lt;/p&gt;

&lt;p&gt;We did that to avoid the socket being deleted when the system starts. Because the &lt;code&gt;/tmp&lt;/code&gt; would be emptied on boot.&lt;/p&gt;

&lt;p&gt;To make it work, we are going to create a symlink from &lt;code&gt;/mnt/X0&lt;/code&gt; to &lt;code&gt;/tmp/.X11-unix/X0&lt;/code&gt; by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ln -s /mnt/X0 /tmp/.X11-unix/X0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can use GUI apps inside our container. But it is not really user friendly.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Make the symlink automatic on startup
&lt;/h3&gt;

&lt;p&gt;Until now, we are able to use GUI apps in out container. But we have to create the symlink manually everytime we start the container. We will make it automatic to avoid this pain.&lt;/p&gt;

&lt;p&gt;To do that we can use multiple solutions. Here, we will use CRON jobs.&lt;/p&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;crontab -e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add this in the editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@reboot ln -s /mnt/X0 /tmp/.X11-unix/X0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to be able to run GUI apps from other users, we can also change the socket permissions by adding this CRON job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@reboot chmod a+wx /tmp/.X11-unix/X0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we can restart our container as much as we cant without having anything manual to do anymore!&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Install GUI apps and run them
&lt;/h3&gt;

&lt;p&gt;This step is just the fun part!&lt;/p&gt;

&lt;p&gt;Just install any GUI app in your container and start it. Everything should work as a charm. (If you are as lucky as me.)&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

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

&lt;p&gt;Running GUI apps in LXD containers is not that simple. And some guides that we can find on the Internet even make it harder by guiding us in the wrong direction.&lt;/p&gt;

&lt;p&gt;The main challenges I found were not documented enough were:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The need to proxy the Xorg socket to anywhere else than the &lt;code&gt;/tmp&lt;/code&gt; folder. Otherwise it would work. But only before we restart the container.&lt;/li&gt;
&lt;li&gt;Setting the permissions on the socket to allow other users to run GUI apps. Because even in containers we may not want to use them as root. And Electron apps do not like to be run as root.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope this article helped. (And "Hi!" to my future self 😁️)&lt;/p&gt;

&lt;p&gt;Feedback and tips are more than welcome, don't hesitate to reach out!&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>linux</category>
      <category>tooling</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Why we use layered architectures</title>
      <dc:creator>amabe_dev</dc:creator>
      <pubDate>Mon, 25 Jul 2022 16:45:00 +0000</pubDate>
      <link>https://dev.to/amabe_dev/why-are-we-using-layered-architectures-1n1l</link>
      <guid>https://dev.to/amabe_dev/why-are-we-using-layered-architectures-1n1l</guid>
      <description>&lt;p&gt;I recently looked for articles that I could forward to explain why we use often choose a layered architecture when creating a new service. &lt;/p&gt;

&lt;p&gt;And I found none. The articles I found either did not try to explain the why or, in my opinion, missed the point by just stating that "this is easy". So, here is my attempt to explain the why of the layered architecture.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer&lt;/em&gt;: I am not an architect. This is only my understanding as a software developer. If you see anything wrong or missing, please reach out, I will happily update the article (and my knowledge).&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a layered architecture
&lt;/h2&gt;

&lt;p&gt;A layered architecture is a way to design a service by dividing its logic in layers. Each layer is only allowed to call the layer directly below.&lt;/p&gt;

&lt;p&gt;We usually use these 3 layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;em&gt;API/UI&lt;/em&gt; layer: exposes the API or the UI and is responsible for authentication and requests handling.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;business logic&lt;/em&gt; layer: everything that is business logic, data validation and processing.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;data access&lt;/em&gt; layer: responsible for the interactions with the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is usually represented like this:&lt;br&gt;
&lt;a href="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%2Ft2d7ynxhkpz2igevb4xl.jpg" class="article-body-image-wrapper"&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%2Ft2d7ynxhkpz2igevb4xl.jpg" alt="Layered architecture drawing (the layers on top of each other with arrows to the below layer)" width="351" height="234"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we are using a layered architecture
&lt;/h2&gt;

&lt;p&gt;There are many reasons why we may want to use a layered architecture. Even the reason "because I was told to" is valid.&lt;/p&gt;

&lt;p&gt;The following reasons are the reasons that I think have the most valuable impact.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  It tends to remove surprises
&lt;/h3&gt;

&lt;p&gt;The layers separation forces us to separate the logic in a given way. One of the consequences is that it make it easier to find what we are looking for. Everything is where it should be.&lt;/p&gt;

&lt;p&gt;If we are looking for an API route, we know that it will be in the API layer. The same is true if we are looking for a specific request to the database, it will be in the data access layer.&lt;/p&gt;

&lt;p&gt;It also make it easier to navigate in the code. We know that a request is starting at the API layer and we can drill down the layers if we want to know the implementation details.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  It helps reuse the logic
&lt;/h3&gt;

&lt;p&gt;One of the direct results of the separation of the API logic, the business logic and the data access logic is that it is way easier to reuse the logic without duplicating it.&lt;/p&gt;

&lt;p&gt;It is easier to reuse the business logic in multiple API routes because it is not mixed with a specific route logic. It is also easier to reuse the data access logic because it is not mixed with a specific business logic part.&lt;/p&gt;

&lt;p&gt;For example, instead of duplicating the query to retrieve an entity everywhere, it can - and probably should - be a single function in the data access layer.&lt;/p&gt;

&lt;p&gt;(Yes. It could and should be the case even without using the layered architecture. But we see things we can never unsee in this world.)&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  It makes it easier to change
&lt;/h3&gt;

&lt;p&gt;The consequence of separating the logic is that is it way easier to change any part of it.&lt;/p&gt;

&lt;p&gt;For example, if we have a single function to retrieve an entity, we have only one place to change when the filter has to change.&lt;/p&gt;

&lt;p&gt;We can also go a step further. It is way easier to replace a whole layer if we need it. (Even if we probably would never want to replace the business logic layer. It makes more sense for the other layers.)&lt;/p&gt;

&lt;p&gt;For example, we can replace the data access layer with limited to no impact on the other layers. It may happen if we want to switch the database engine that we use.&lt;/p&gt;

&lt;p&gt;To make this even easier, the layers should know each other only by interface and avoid exposing their implementation details. Dependency injection can help for that.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Throwing big principles names
&lt;/h3&gt;

&lt;p&gt;Since we love to name things, I thought I would try to throw big principle names that apply there:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Because it gives a structure and define where things are expected to be, it contributes to the principle of least surprise.&lt;/li&gt;
&lt;li&gt;Because each layer has a well defined role, it contributes to the separation of concerns principle.&lt;/li&gt;
&lt;li&gt;Because it helps to avoid duplication of the logic, it contributes to the "don't repeat yourself" principle.&lt;/li&gt;
&lt;li&gt;To make it easier to change, we can use the inversion of control principle with dependency injection.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;We use the layered architecture because it is quite simple to implement and helps a lot to maintain a project.&lt;/p&gt;

&lt;p&gt;It is of course possible to make a mess while implementing it. But the structure it gives guide us in the right direction.&lt;/p&gt;

&lt;p&gt;If you see something wrong or something that I might have missed, please reach out. I would love to learn more. And I would like this article to be as complete as possible to be able to share it next time.&lt;/p&gt;

&lt;p&gt;Hope it helped!&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>webdev</category>
      <category>api</category>
      <category>microservices</category>
    </item>
    <item>
      <title>How to have multiple Git configs for the same user</title>
      <dc:creator>amabe_dev</dc:creator>
      <pubDate>Thu, 14 Jul 2022 17:56:00 +0000</pubDate>
      <link>https://dev.to/amabe_dev/how-to-have-multiple-git-configs-for-the-same-user-3ahn</link>
      <guid>https://dev.to/amabe_dev/how-to-have-multiple-git-configs-for-the-same-user-3ahn</guid>
      <description>&lt;h1&gt;
  
  
  How to have multiple Git configs for the same user?
&lt;/h1&gt;

&lt;p&gt;In this article, we will see how to have different Git configs depending on the folder in which is the project we are working on.&lt;/p&gt;

&lt;p&gt;It is quite easy to change the config for a single project. But it means we have to do it for every project on which we want the change to be made. And we need to keep it in mind to do it on every new project that we clone.&lt;/p&gt;

&lt;p&gt;The goal here is to set it up once and be able to forget it. We will then be able to clone any new project and it will use our custom config without us doing anything.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why have multiple Git configs?
&lt;/h2&gt;

&lt;p&gt;There are multiple reasons why we may want to have multiple Git configs. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To have a different commit name and email on different projects. For example, for work projects and for personal projects.&lt;/li&gt;
&lt;li&gt;To have different aliases depending on projects. For example, if some aliases are tied to a context shared by only some projects.&lt;/li&gt;
&lt;li&gt;To have different behavior on different projects. For example, having &lt;code&gt;git pull&lt;/code&gt; perform a merge on some project and a rebase on others.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I can go on and on. But I might end up reciting everything that can be configured in Git. So, I won't.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What we will do
&lt;/h2&gt;

&lt;p&gt;To have different configs depending on projects, we will use a Git option to include config files conditionally.&lt;/p&gt;

&lt;p&gt;For the example, we are going to use a different name depending if we are on a work project or a personal project.&lt;/p&gt;

&lt;p&gt;We will assume that we have a workspace structure like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/
    work/
        project1/
        project2/
    perso/
        project3/
        project4/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  Diving into Git configs
&lt;/h2&gt;

&lt;p&gt;First, we need to create config files with the config that we want to override. For example &lt;code&gt;~/work/gitconfig&lt;/code&gt; and &lt;code&gt;~/perso/gitconfig&lt;/code&gt; and add the custom config in each.&lt;/p&gt;

&lt;p&gt;For example, in &lt;code&gt;~/work/gitconfig&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[user]
    name = The name I use at work
    email = &amp;lt;myworkemail@example.com&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can conditionally include the config from the folder depending on the project on which we are working on. To do this, we will add a new option in out Git config (&lt;code&gt;~/.gitconfig&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[includeIf "gitdir:~/work/**"]
    path = ~/work/gitconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, each time we run a Git command in a directory inside &lt;code&gt;~/work/&lt;/code&gt; folder, the custom config from &lt;code&gt;~/work/gitconfig&lt;/code&gt; will override our default config. And, if we run a command anywhere else, it will not.&lt;/p&gt;

&lt;p&gt;Only the config that is present in the included file will be overridden. Anything else from the &lt;code&gt;~/.gitconfig&lt;/code&gt; will stay unchanged.&lt;/p&gt;

&lt;p&gt;This is helpful to have a common config for everything. With only small differences for some projects.&lt;/p&gt;

&lt;p&gt;(We can ever have aliases in the main config file and add new aliases in an included file.)&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Using different SSH keys
&lt;/h2&gt;

&lt;p&gt;When using different identities, we might want to also use different SSH keys. For example, to use different accounts on the same Git repo hosting platform (GitHub, GitLab, etc).&lt;/p&gt;

&lt;p&gt;To do this, we will use both the SSH config file and an option from Git to change the URL used on actions.&lt;/p&gt;

&lt;p&gt;To be able to use different SSH keys, we will update the SSH config (&lt;code&gt;~/.ssh/config&lt;/code&gt;) like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host github
    User git
    HostName github.com
    IdentityFile ~/.ssh/id_rsa # change the path to the key here
    IdentitiesOnly true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will use the SSH key at the given path when using &lt;code&gt;github&lt;/code&gt; as a remote (here &lt;code&gt;~/.ssh/id_rsa&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Then we need to replace the used remote from &lt;code&gt;git@github.com&lt;/code&gt; to &lt;code&gt;github&lt;/code&gt; to use our new SSH alias. We can either update the remote on each repository or add this in our Git config (&lt;code&gt;~/.gitconfig&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[url "github"]
    insteadOf = git@github.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





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

&lt;p&gt;By using this configs, we are able to have a flexible Git config. Some is common between projects because we want to use Git in the same way everywhere. And yet we are able to override some configs depending on the projects we are working on.&lt;/p&gt;

&lt;p&gt;I found it really helpful (and quite hard to find) when I needed to use a different commit email on some projects.&lt;/p&gt;

&lt;p&gt;If you have any feedback, please reach out either in the comments or in private. This is my first attempt at learning in public and writing about technical things. I will be grateful for any opportunity to improve.&lt;/p&gt;

&lt;p&gt;Hope it helped! And have a good config session :)&lt;/p&gt;

</description>
      <category>git</category>
      <category>tooling</category>
      <category>tutorial</category>
      <category>devjournal</category>
    </item>
  </channel>
</rss>
