<?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: Walter Alleyz</title>
    <description>The latest articles on DEV Community by Walter Alleyz (@walteralleyz).</description>
    <link>https://dev.to/walteralleyz</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%2F719371%2Fd34f3a03-fd18-4c3d-a797-87c1fe84aedb.jpeg</url>
      <title>DEV Community: Walter Alleyz</title>
      <link>https://dev.to/walteralleyz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/walteralleyz"/>
    <language>en</language>
    <item>
      <title>Why Portugal Can Be Your Next Career Step</title>
      <dc:creator>Walter Alleyz</dc:creator>
      <pubDate>Sun, 11 Jan 2026 14:00:34 +0000</pubDate>
      <link>https://dev.to/walteralleyz/why-portugal-can-be-your-next-career-step-4h38</link>
      <guid>https://dev.to/walteralleyz/why-portugal-can-be-your-next-career-step-4h38</guid>
      <description>&lt;p&gt;Moving abroad can be a challenging career decision. Beyond that, there are many factors to consider: culture, people, convenience, quality of life, and what a new place can offer.&lt;/p&gt;

&lt;p&gt;Every detail can make a significant difference when deciding to take such a step.&lt;/p&gt;

&lt;p&gt;In this article, we will discuss the benefits of moving to Portugal in terms of career growth and professional potential.&lt;/p&gt;

&lt;p&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%2Fc3pdq9rhx50cvfwzfd2h.png" 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%2Fc3pdq9rhx50cvfwzfd2h.png" alt="lisbon" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  When You Hit a Career Plateau
&lt;/h3&gt;

&lt;p&gt;It is a common experience for almost every IT professional to face the question of how to continue evolving in their career. Many of us have already been through this phase and managed to move forward by learning new tools, studying and implementing new technologies, expanding our network, building connections, and attending workshops, among other strategies.&lt;br&gt;
However, there comes a point when our career hits a plateau. This often happens when you can no longer identify what to study next, how to increase your potential, or what steps to take to improve your salary.&lt;/p&gt;

&lt;p&gt;If this sounds familiar, it may be time to look abroad and seek opportunities to grow beyond the boundaries of technology itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Moving to Portugal Is More Than a Lifestyle Choice
&lt;/h3&gt;

&lt;p&gt;The official language of Portugal is Portuguese, but you can hear many different languages spoken across the country. This is because Portugal is a popular tourist destination in Europe.&lt;/p&gt;

&lt;p&gt;You can easily find people who speak English. In addition, Portuguese people are known for their strong English skills, so you are unlikely to face communication barriers—especially if your goal is to improve your own communication skills.&lt;/p&gt;

&lt;p&gt;Beyond improving communication skills, you will be exposed to a wide range of cultures, including Portuguese culture itself—and this is an important factor to consider.&lt;/p&gt;

&lt;p&gt;Understanding different cultures is essential, as it helps you navigate diverse environments, collaborate more effectively with people from different backgrounds, and build stronger, more meaningful connections over time.&lt;/p&gt;

&lt;p&gt;Portugal also offers a wide variety of culinary options, with natural and healthy food easily found in any grocery store.&lt;/p&gt;

&lt;p&gt;People are warm and welcoming, and you will find yourself busy exploring natural parks and beautiful architecture throughout the country.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimizing Your Social Profile to Attract International Companies
&lt;/h3&gt;

&lt;p&gt;“If you’re not visible, you won’t be found.”&lt;br&gt;
Preparing your social profile is the best choice when your goal is to move abroad.&lt;/p&gt;

&lt;p&gt;If you are using LinkedIn, the first step is to create a clear and meaningful title for your profession. For example, if you are a Business Analyst specializing in AI and BI, make that explicit. If you are a Java Developer with Cloud Computing experience, a title like Cloud Java Developer might be more effective. Choosing the right title makes it easier for headhunters to find you.&lt;/p&gt;

&lt;p&gt;The About section on LinkedIn is one of the most important parts of your profile. A strong About section should be concise, clear, and focused on your skills, achievements, and career goals. Start with a hook that grabs attention, then describe your experience, key accomplishments, and what you are passionate about.&lt;/p&gt;

&lt;p&gt;Take a look at a good example of an About section:&lt;br&gt;
“I am a Software Engineer specializing in Java and Python, with 5 years of experience building scalable web applications and cloud-based solutions. I have led teams of up to 4 developers and implemented projects that improved system performance by 30%. Currently, I am seeking opportunities abroad where I can leverage my technical expertise and leadership skills to drive impactful projects. Feel free to connect to discuss potential collaborations.”&lt;/p&gt;

&lt;p&gt;Organize experiences in reverse chronological order, starting with the most recent. Use bullet points to make it easy to read. A well-written About and Experience section significantly increases your chances of being discovered by headhunters and potential employers.&lt;/p&gt;

&lt;p&gt;Remember to write everything in English, since you are targeting the international market. Most importantly, focus on building meaningful connections: engage with people, show genuine interest in topics that matter, and make your objectives clear.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Feeling stuck in your career is a common experience for many IT professionals. It often occurs when you’re unsure of the next step, when acquiring more technical knowledge alone isn’t enough, and when it becomes necessary to seek new experiences beyond the tech bubble.&lt;/p&gt;

&lt;p&gt;In this article, I aimed to explain why Portugal is a great option for starting your international career, the benefits of living abroad, and the real impact it can have - both in terms of career growth and personal development.&lt;/p&gt;

</description>
      <category>career</category>
      <category>international</category>
      <category>workplace</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>How to Prepare for a Certification in any Tech Career</title>
      <dc:creator>Walter Alleyz</dc:creator>
      <pubDate>Sun, 04 Jan 2026 18:38:41 +0000</pubDate>
      <link>https://dev.to/walteralleyz/how-to-prepare-for-a-certification-in-any-tech-career-5g74</link>
      <guid>https://dev.to/walteralleyz/how-to-prepare-for-a-certification-in-any-tech-career-5g74</guid>
      <description>&lt;p&gt;As AI evolves, programmers must understand how to improve themselves and how to raise their values. Certifications are an effective way to acquire new skills while studying and to gain recognition in the job market. While certifications from platform like Udemy are useful for learning new skills, there are many certifications that significantly enhance professional capabilities.&lt;br&gt;
In this article, I will outline the most essential certifications and explain how to prepare for them.&lt;/p&gt;

&lt;p&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%2Fipm7xe19ksrlk5c9gf5c.png" 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%2Fipm7xe19ksrlk5c9gf5c.png" alt="person_studying_books_laptop" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Role and Importance of Certifications
&lt;/h3&gt;

&lt;p&gt;There are many AI tools available to help developers with debugging, problem-solving, planning, and learning new technologies. However, these tools tend to level the playing field, bringing many developers to the same baseline. What was once considered essential to be a developer has changed, and now more than ever, proving your value is a necessity.&lt;br&gt;
Heres a few reasons why choose a certification:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Competitive Advantage&lt;/em&gt;: Candidates with certifications have an edge when applying for jobs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Salary Increase&lt;/em&gt;: Certified professionals often earn more than non-certified professionals.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Up-to-Date Knowledge&lt;/em&gt;: While preparing for a certification, professionals learn new skills or improve existing ones.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Skill Validation&lt;/em&gt;: Certifications serve as proof of acquired knowledge and mastered skills.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Best Certifications to Boost Your Tech Career
&lt;/h3&gt;

&lt;p&gt;Choosing the right certification depends on your career direction and the technologies you currently work with. Professionals who use Java might choose the Java SE Associate if it is their first certification, or the Professional version for more advanced validation. Programmers who frequently work with cloud computing can pursue AWS certifications such as Solutions Architect, AI Practitioner, Developer, Practitioner, or CloudOps, as well as Google Cloud certifications like Cloud Engineer or Data Practitioner.&lt;br&gt;
There are many other certifications that can be considered complementary. The HashiCorp Certified Terraform Associate is the most suitable certification for those who work with Terraform or other infrastructure management tools. The GitHub Foundations certification is essential for mastering Git, while GitHub Actions is the best choice for learning how to manage triggers and pipeline integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where to Find Free Learning Resources
&lt;/h3&gt;

&lt;p&gt;It is important to know what kind of certification you are about to pursue. Before investing in any advanced materials, using free resources can be a great strategy to understand the certification or to serve as a complementary study resource.&lt;br&gt;
As free resources we can list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.freecodecamp.org/" rel="noopener noreferrer"&gt;FreeCodeCamp&lt;/a&gt;: It is a platform with many free courses and a wealth of videos, making it a valuable resource both for certification preparation and for general learning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://medium.com/" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;: A blog-style site where people of any knowledge level can write articles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to"&gt;DEV-TO&lt;/a&gt;: It serves the same purpose as Medium but does not require an account to read articles. Additionally, there is a large number of high-quality technical articles covering a wide range of topics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.w3schools.com/" rel="noopener noreferrer"&gt;W3Schools&lt;/a&gt;: W3 is not only a learning platform, despite being well-known for its tutorials and testing environment, but it also offers AWS quizzes that you should try. W3 provides a large amount of high-quality, free materials.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are other resources where you can learn or test your knowledge. &lt;a href="https://skillbuilder.aws/" rel="noopener noreferrer"&gt;AWS SkillBuilder&lt;/a&gt; is an excellent tool for learning AWS-related topics. Google also provides a &lt;a href="https://cloud.google.com/learn/training" rel="noopener noreferrer"&gt;learning platform&lt;/a&gt; that can be used to prepare for certifications. For learn more about Git you can use the &lt;a href="https://learn.github.com/learning" rel="noopener noreferrer"&gt;Github Learn&lt;/a&gt; platform, which offers a wealth of free content and many instructional videos. To test the knowledge you have gained before the certification exam, you can take a practice test on &lt;a href="https://www.examprepper.co/exams" rel="noopener noreferrer"&gt;Examprepper&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Choose the Certification That Best Fits You
&lt;/h3&gt;

&lt;p&gt;Choosing the right certification should be a strategic decision, not a random one. The first step is to clearly define your career goals and understand your current role or the role you want to move into.&lt;/p&gt;

&lt;p&gt;If you work primarily with Java, certifications such as Java SE Associate or Java SE Professional make sense, depending on your experience level. For professionals dealing with cloud computing, certifications from AWS or Google Cloud are a natural fit.&lt;/p&gt;

&lt;p&gt;Use free resources to explore the certification scope. Platforms like AWS SkillBuilder, Google Cloud Training, GitHub Learn, and other free learning resources help you understand the exam objectives, difficulty level, and relevance to your career.&lt;/p&gt;

&lt;p&gt;Certifications should support long-term growth, not just add another badge to your CV.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Certifications remain a powerful way to stand out in an increasingly competitive and AI-driven market. They can help boost your career, develop new skills, and provide a competitive advantage.&lt;br&gt;
There are many free resources available, so even if you cannot afford advanced materials or mentoring, you can easily find free courses and practice tests.&lt;/p&gt;

</description>
      <category>certification</category>
      <category>aws</category>
      <category>cloud</category>
      <category>programming</category>
    </item>
    <item>
      <title>Debugging with AI: A Pratical Approach for Modern Developers</title>
      <dc:creator>Walter Alleyz</dc:creator>
      <pubDate>Mon, 24 Nov 2025 16:21:37 +0000</pubDate>
      <link>https://dev.to/walteralleyz/debugging-with-ai-a-pratical-approach-for-modern-developers-3hb</link>
      <guid>https://dev.to/walteralleyz/debugging-with-ai-a-pratical-approach-for-modern-developers-3hb</guid>
      <description>&lt;p&gt;Debugging is the backbone of software development. Learn how to handle it properly and how to use AI to help you, can be a great opportunity to boost your productivity and speed up your performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why use AI to Debug&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Debugging is the backbone of software development. When it goes wrong, productivity and motivation drop. Many developers rush the fixing process by trying to write more code without fully understanding the root cause. This strategy - or the lack of some - can lead to more issues and even creating more complex bugs. Debugging isn't just about eliminating errors, it's about building reliable software, prevent chaos in production and fixing the chaos created by the poor design and lack of good debugging practices.&lt;/p&gt;

&lt;p&gt;AI has become a great and powerful ally in this process. Instead of digging in endless lines of code or unclear stack traces, developers can use smart tools that help analyze problems and spot unusual patterns, either during debugging or even before deploying code to production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security and Data-Sharing Considerations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before we get further in this discution, is important to highlight the responsible use of AI.&lt;br&gt;
Even when integrating your favorite tool, we cannot rely on it blindly, especially when dealing with sensitive or confidential information.&lt;br&gt;
So, ask yourself:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Does this code contains API keys, passwords, user data or secrets?&lt;/li&gt;
&lt;li&gt;Would I be violating an NDA or company policy by sharing this?&lt;/li&gt;
&lt;li&gt;Does this code expose business logic or proprietary information?
If the answer for all these questions is NO, then you're probably using your AI assistant safely.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can discover more about this topic in my other article &lt;a href="https://kwan.com/blog/prompt-engineering-boost-your-productivity-with-ai/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How AI Enhances the Debugging Process&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;AI never gets tired&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;AI can scan logs, read code, generate explanations, analyze stack traces, and comes up with a solution faster than any human. It is useful not only in debugging process, but also beforehand, helping you scan the development code to find common pitfalls, flaws, missing validations, security breaches in libraries, and suggesting known fixes.&lt;br&gt;
The other benefit of AI, is its impact on the way developers think. When we have to explain the bug to AI, we can think clearly, isolating the context, and in many cases, they can reveal the issue more easely.&lt;br&gt;
AI can also help you understanding configuration errors and infraestructure-related problems.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Eliminating repetitive checks&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Bugs arise from missing validations, misconfigured files, or security vulnerabilities. AI assistance is ideal to deal with it, as it can scan flaw patterns, generate input validations and create unit tests. What would be a pain for the developer, now can be automated.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Targeted Tests&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Another strong suit of AI is the test generation. However, the AI can go further by memorizing the context. With this feature, the assistant can generate missing tests for methods, classes, API endpoints, even for edge cases and invalid inputs. AI can empowers developers to prevent errors in the future.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Prevent future Issues&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When dealing with the application context, AI can prevent future bugs by suggesting missing behaviors, validations or by elucidating the bugs created by the code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Using AI as a learning tool&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;AI can function not only as an assistant, but also, helping developers understand how to fix a bug and how it occurred. AI can also suggest best practices in the architecture, explain it and highlight the differences between architectures. AI can make simple to understand hard concepts related to software development and project patterns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debugging scenario - AI in action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine an undesired NullPointerException is thrown, the old fashion way is to speculate, investigate the stack trace, search on the web for documentation or ask on forums. It still works, of course, but with AI we can speed up this process.&lt;br&gt;
Now, we can let AI analyze our code, validate some snippets, analyze the context, point out where a variable might be uninitialized, suggest potential fixes such as adding null checks or refactoring the logic.&lt;br&gt;
By explaining the error and work together with the Assistant, we can fully understand the root cause, speed up the fixing and prevent similar problems in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best AI tools for Debugging&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ChatGPT&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ChatGPT is a LLM (Large Language Model) AI, designed for general-purpose use. It can help you understanding issues, debug context, review the application flow and identify architecture flaws. However, it's not made for code developing, test automation, or discovery. Its primary use it is more oriented toward learning. That said, it's still a great tool.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Github Copilot&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now we're talking about a powerful tool design for code assistance. Github can come up with inline code solutions, fix code while the developer is writing it. Copilot is supported by many IDEs, can hold the application context and works in the cloud. Can also integrate with pipelines and can generate high-quality boilerplate code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tabnine&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Tabnine is another AI-powered code assistant that provides code completions while maintaining context and prioritizing privacy, helping prevent data leaks. Although it is not as strong as Copilot when working with ecosystems or pipelines, Tabnine can boost developer productivity by offering clear explanations and assisting with unfamiliar libraries or frameworks.&lt;/p&gt;

&lt;p&gt;However, Tabnine’s IDE integration is less seamless. When using GitHub Copilot or Tabnine, developers should remain aware that AI suggestions are not always correct. It is important to test thoroughly and verify sources before deploying any code generated with AI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Assistant Should You Choose Next?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Choosing the right AI assistant depends on your goals, and the type of code you're working with.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ChatGPT&lt;/em&gt; is the best for learning, understanding complex issues and getting explanations about code or architecture. But it's not designed for production-ready code generation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Copilot&lt;/em&gt; excels at generating code inline while you write, integrating seamlessly with IDEs, and producing boilerplate or pipeline-friendly solutions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tabnine&lt;/em&gt; prioritizes privacy and context, offers strong suggestions for unfamiliar libraries or frameworks, and works well in multi-language projects, though its IDE integration is less smooth and it is not as tightly connected to pipelines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI will not replace developers, but developers who learn how to use AI effectively will absolutely outperform those who ignore it. AI is not a threat, instead we should look at it as an opportunity, a tool and an assistant. Debugging shouldn't be a painful ritual of guesswork and frustation, bringing us hours of blind investigation and making us waste hours of work. With the right precautions, understanding the pros and cons, knowing what we can share and what not, AI can reduce time spent fixing issues, improve code quality, and help developers understand their applications more deeply.&lt;br&gt;
AI is not a magic wand and should not be fully relied upon. It won’t solve every problem in your application, nor will it deploy code for you. AI cannot think independently. As developers, we must understand how to use it effectively. Like any tool, we need to learn how to work with it, what suggestions to accept, and what to filter.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>coding</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>Using AI to Boost Your Productivity by Asking the Right Questions</title>
      <dc:creator>Walter Alleyz</dc:creator>
      <pubDate>Mon, 21 Jul 2025 14:35:30 +0000</pubDate>
      <link>https://dev.to/walteralleyz/using-ai-to-boost-your-productivity-by-asking-the-right-questions-5ao5</link>
      <guid>https://dev.to/walteralleyz/using-ai-to-boost-your-productivity-by-asking-the-right-questions-5ao5</guid>
      <description>&lt;p&gt;&lt;em&gt;If you don't know how to ask, now is the time to learn&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;AI is the new hype, and we all know it. Several companies are using AI to offer a better experience, either by making the interface more user-friendly or by creating new features that better meet user needs.&lt;br&gt;
With all the hype surrounding it, people are diving into AI tools, and when it comes to coding, relying solely on AI is not the safest option. Relying is the word we can use, because in most cases, developers (especially entry-level ones) are using AI tools without thinking, generating code, and sending it directly to the repository (or any version control system).&lt;br&gt;
Such blind reliance will create more problems than solutions, so we may need to rethink the way we're handling AI.&lt;/p&gt;

&lt;p&gt;There are two main problems associated with using AI in coding: "blind reliance" and the "don't know how to ask" problem. We will dive into the details of these issues in the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blind Reliance:
&lt;/h3&gt;

&lt;p&gt;Imagine we're building an application for food delivery, and the manager asks us to introduce a new feature called "weekend discount." To create this feature, we need to check if today is a weekend day. The app was built with Kotlin, so we need to use the language to achieve this. The goal is to get the day's name and compare it, checking if it's Saturday or Sunday to determine if it's a weekend.&lt;br&gt;
Now, let’s assume the programmer is not familiar with Kotlin. In this case, they might rely on the AI tool to complete the task.&lt;/p&gt;

&lt;p&gt;"How can I get today's name and compare it to see if it's a weekend day?" he asks.&lt;/p&gt;

&lt;p&gt;The LLM (Large Language Model), without knowing the context, will return anything except what the programmer needs to know. So, he asks again, providing the context (Kotlin), and the AI gives a response—but not necessarily the one he needs. This happens because the developer didn't read the response carefully. But it works, anyway. As the developer delivers the feature, the manager asks him to verify if the day number is not between 10 and 17. If it is, the app can't generate the discount.&lt;br&gt;
Once again, the developer turns to AI, expecting it to deliver the best possible code. But here's the problem: the AI has no context about the application. In many cases, this leads developers to copy and paste large portions of code—including core business logic—into the prompt, unintentionally exposing sensitive or proprietary information. This blind reliance isn't just a sign of limited coding knowledge; it's also a poor decision from an information security standpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't know how to ask:
&lt;/h3&gt;

&lt;p&gt;"How do I calculate the average in javascript?";&lt;br&gt;
"Today's day name in javascript";&lt;br&gt;
"Create a simple HTML portfolio page that uses my name".&lt;/p&gt;

&lt;p&gt;These kinds of questions clearly demonstrate a common issue: lack of context. Vague prompts not only waste your time—because the AI can't fully understand what you're asking and you'll have to keep refining and adding details—but they’re also inefficient in terms of token usage. To make things worse, not every AI tool has context memory. This means you’ll likely need to repeat the same information multiple times with each new prompt.&lt;/p&gt;

&lt;p&gt;To address this and reduce token waste, many companies are adopting a technique known as Prompt Engineering—a structured way to design prompts that give AI enough context to generate useful and accurate responses from the start.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prompt Engineering:
&lt;/h3&gt;

&lt;p&gt;"Write a JavaScript function that takes an array of numbers and returns their average. Include input validation and a usage example.";&lt;br&gt;
"Using JavaScript, how can I get the current weekday name (like 'Monday' or 'Tuesday') based on the user's local time?";&lt;br&gt;
"Generate a responsive HTML portfolio page featuring my name 'Fred', including sections for About Me, Projects, and Contact. Use modern semantic HTML and simple CSS".&lt;/p&gt;

&lt;p&gt;Above, we saw examples of how better inputs—crafted through Prompt Engineering—can significantly improve AI responses. The key idea is to isolate each request within its own clear context. This is the core of Prompt Engineering: designing effective and precise instructions that minimize hallucinations and maximize the accuracy of the output.&lt;/p&gt;

&lt;p&gt;When we give the AI proper context and write prompts with clarity, we unlock a series of benefits, such as:&lt;br&gt;
✅ Higher-Quality Outputs – More relevant, coherent, and accurate answers;&lt;br&gt;
✅ Reduced Token Waste – Saves time and lowers costs, especially important for teams using commercial APIs;&lt;br&gt;
✅ Improved Security &amp;amp; Privacy – Learn how to ask the right questions without exposing proprietary or sensitive information;&lt;br&gt;
✅ Reusability – Create structured templates that can be reused across different questions or use cases;&lt;br&gt;
✅ Adaptability – Prompts can be fine-tuned to fit different scenarios, users, or environments with minimal changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thought:
&lt;/h3&gt;

&lt;p&gt;As developers, we’re constantly looking for ways to be more efficient, solve problems faster, and deliver better code. AI is a powerful ally in that mission—but only when used wisely. Asking vague or incomplete questions leads to wasted time, increased costs, and even potential security risks.&lt;/p&gt;

&lt;p&gt;That’s where Prompt Engineering comes in. It’s not just a buzzword—it’s a necessary skill in the era of AI-assisted development. By isolating requests, providing clear context, and thinking carefully about how we phrase our prompts, we can turn generic AI outputs into high-value, production-ready solutions.&lt;/p&gt;

&lt;p&gt;Whether you're calculating an average, building a portfolio page, or trying to automate part of your workflow, remember: good prompts lead to great results. Treat your prompt like an interface—be specific, be intentional, and always consider the security and reusability of what you're asking.&lt;/p&gt;

&lt;p&gt;The future of development isn't about replacing developers with AI. It’s about empowering developers who know how to use AI intelligently.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>coding</category>
    </item>
    <item>
      <title>Meu primeiro projeto com AWS Cloudformation - Automatizando a criação da arquitetura</title>
      <dc:creator>Walter Alleyz</dc:creator>
      <pubDate>Sun, 26 Jun 2022 17:53:47 +0000</pubDate>
      <link>https://dev.to/walteralleyz/meu-primeiro-projeto-com-aws-cloudformation-automatizando-a-criacao-da-arquitetura-1k65</link>
      <guid>https://dev.to/walteralleyz/meu-primeiro-projeto-com-aws-cloudformation-automatizando-a-criacao-da-arquitetura-1k65</guid>
      <description>&lt;p&gt;0. Objetivo do projeto&lt;br&gt;
1. Desenho da arquitetura&lt;br&gt;
2. Código e explicação&lt;br&gt;
3. Conclusão&lt;/p&gt;
&lt;h3&gt;
  
  
  Objetivo do projeto
&lt;/h3&gt;

&lt;p&gt;A motivação por trás desse projeto foi me capacitar em AWS, principalmente nos serviços Cloudformation, S3, Lambda, VPC, RDS e IG e nos conhecimentos de políticas de acesso para crescer profissionalmente. O objetivo do projeto é ser um registrador de arquivos excluídos, sempre que um arquivo for deletado manualmente, ou por meio de políticas de um bucket, o S3 deverá alertar um Lambda para realizar um registro no RDS (MySQL). Pode ser uma boa solução para quem pretende sincronizar arquivos de um bucket com seu conteúdo em um banco RDS.&lt;br&gt;
Todo o projeto pode ser encontrado nesse &lt;a href="https://github.com/walteralleyz/myf_proj_cloudformation" rel="noopener noreferrer"&gt;repositorio.&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Desenho da arquitetura
&lt;/h3&gt;

&lt;p&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%2F0qp3ktfigk0c06oht5zl.png" 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%2F0qp3ktfigk0c06oht5zl.png" alt="Arquitetura Simples" width="564" height="183"&gt;&lt;/a&gt;&lt;br&gt;
A arquitetura é autoexplicativa: Vamos precisar de um S3 para enviar notificações à um Lambda que vai se comunicar com um RDS. Mas nada é tão simples, já que a comunicação entre esses serviços depende de rede e permissões. Por isso vamos precisar de uma VPC, duas subnets (que serão associadas ao RDS e ao Lambda) e uma Role com permissão do evento do bucket para o Lambda.&lt;/p&gt;
&lt;h3&gt;
  
  
  Código e explicação
&lt;/h3&gt;

&lt;p&gt;Inicialmente vamos criar uma VPC para proteger o acesso ao nosso RDS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SimpleVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      Tags:
        - Key: stack
          Value: des
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Começamos definindo o tipo de recurso com a palavra-chave "Type" e associamos ao valor "AWS::EC2::VPC", pois a VPC se encontra dentro do grupo EC2. Também precisamos definir o CidrBlock que é o conjunto de IP disponível dentro da VPC.&lt;br&gt;
Agora precisamos criar duas subnets, associadas a nossa VPC e um grupo de subnets que será usado pelo RDS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SimpleSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId:
        Ref: SimpleVPC
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: "us-east-1a"
      Tags:
        - Key: stack
          Value: des

  SimpleSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId:
        Ref: SimpleVPC
      CidrBlock: 10.0.2.0/24
      AvailabilityZone: "us-east-1b"
      Tags:
        - Key: stack
          Value: des

  SimpleDBSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      SubnetIds:
        - Ref: SimpleSubnet1
        - Ref: SimpleSubnet2
      DBSubnetGroupDescription: Subnet para o RDS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos criar o nosso RDS com uma máquina micro, que será suficiente para o nosso projeto pessoal, 4 GB de storage (mais do que o suficiente), com uma engine MySQL, e utilizando do nosso grupo de subnets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SQLDemoDbInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      DBName: !Ref pDbName
      MasterUsername: !Ref pDbUser
      MasterUserPassword: !Ref pDbPass
      Engine: MySQL
      DBInstanceClass: db.t2.micro
      StorageType: gp2
      PubliclyAccessible: False
      DBSubnetGroupName:
        Ref: SimpleDBSubnetGroup
      AllocatedStorage: "4"
      DBInstanceIdentifier: !Join ["-", [ "SQLDemoDbInstance", !Ref "AWS::Region" ]]
      AvailabilityZone: !Select [1, !GetAZs ""]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, vamos criar nosso bucket com uma política de notificação. Nesse caso, eu quero que meu bucket notifique o Lambda sempre que um objeto for removido, independente de seu estado anterior (versionado, taggeado, etc).&lt;br&gt;
É importante definir que o bucket terá uma dependência com a criação do Lambda e apontar a propriedade "Function" para o Arn do nosso Lambda, usando a função !GetAtt.&lt;br&gt;
Perceba que eu estou definindo um filtro no S3 para notificar somente arquivos terminados em ".txt".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MyBucket:
    Type: AWS::S3::Bucket
    DependsOn: LambdaS3Permissao
    Properties:
      BucketName: !Ref BucketName
      NotificationConfiguration:
        LambdaConfigurations:
          - Event: s3:ObjectRemoved:*
            Function: !GetAtt LambdaS3Processamento.Arn
            Filter:
              S3Key:
                Rules:
                  - Name: suffix
                    Value: .txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por fim, vamos criar a Lambda com um código simples que pode ser atualizado depois no console. Você também poderia apontar o seu código para um arquivo zip dentro de um bucket S3, mas vamos deixar mais simples para o nosso caso.&lt;br&gt;
O nosso Lambda terá a simples tarefa de receber o evento de notificação, extrair o nome do arquivo e salvar na base RDS com um timestamp associado. É importante lembrar de utilizar as mesmas subnets e o security group da nossa VPC.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LambdaS3Processamento:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.execute
      Role: !GetAtt LambdaS3Role.Arn
      Runtime: nodejs12.x
      MemorySize: 128
      Timeout: 45
      VpcConfig:
        SecurityGroupIds:
          - sg-0c094b8e5f85ae4b3
        SubnetIds:
          - !Ref SimpleSubnet1
          - !Ref SimpleSubnet2
      Code:
        ZipFile: &amp;gt;
          exports.execute = (event, context) =&amp;gt; {
            console.log(event);
          }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você pode, facilmente, criar a sua infraestrutura por meio do console AWS, no serviço cloudformation, importando o template que a gente acabou de criar.&lt;/p&gt;

&lt;p&gt;Depois de criado com sucesso, precisamos alterar o código da nossa Lambda com o nosso projeto do github. Para isso, precisamos baixar o projeto e compactar no formato zip. No serviço de Lambda do console AWS, escolha upload e o formato zip. Depois de atualizar o código, podemos testar enviando um arquivo ao nosso bucket e apagando logo em seguida.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;O AWS Cloudformation nos permitiu construir uma estrutura simples, de fácil deploy utilizando apenas um arquivo. Sempre que for necessário replicar a mesma estrutura, podemos usar o mesmo arquivo alterando poucos parâmetros.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>node</category>
      <category>cloud</category>
      <category>cloudformation</category>
    </item>
    <item>
      <title>Monitoração: O terror da falta de rastreabilidade em sistemas distribuídos</title>
      <dc:creator>Walter Alleyz</dc:creator>
      <pubDate>Mon, 02 May 2022 22:37:43 +0000</pubDate>
      <link>https://dev.to/walteralleyz/monitoracao-o-terror-da-falta-de-rastreabilidade-em-sistemas-distribuidos-4g35</link>
      <guid>https://dev.to/walteralleyz/monitoracao-o-terror-da-falta-de-rastreabilidade-em-sistemas-distribuidos-4g35</guid>
      <description>&lt;p&gt;1. Apresentação&lt;br&gt;
2. Contexto&lt;br&gt;
3. Arquitetura Exemplo&lt;br&gt;
4. O problema&lt;br&gt;
5. A solução é rastrear&lt;br&gt;
6. Algumas ferramentas muito úteis&lt;br&gt;
7. Conclusão&lt;/p&gt;

&lt;h3&gt;
  
  
  Apresentação
&lt;/h3&gt;

&lt;p&gt;Quando se fala em arquiteturas e aplicações modernas, a primeira opção em mente são os microsserviços. A estratégia de dividir os contextos de um monólito em demais aplicações também traz problemas "modernos". A monitoração (e mais especificamente a rastreabilidade) é o problema que vamos tratar nesse artigo, esclarecendo a sua importância e seus desafios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contexto
&lt;/h3&gt;

&lt;p&gt;Sistemas distribuídos são compostos por outros microsserviços que trabalham em contextos específicos consumindo e produzindo mensagens que alterar o estado de um objeto principal. Essas mensagens são eventos que são enviados para um barramento de eventos de forma assíncrona produzindo uma arquitetura de mensageria. Muito complexo? De forma resumida, em uma arquitetura baseada em eventos, as aplicações geram mensagens que serão enviadas para um centralizador, e essas mensagens serão consumidas por outras aplicações de forma desacoplada.&lt;br&gt;
No entanto, esse desacoplamento tem um custo que é o rastreamento dos objetos fonte dos eventos. Quanto maior o número de eventos e operações maior a complexidade em monitorar o resultado das operações.&lt;/p&gt;

&lt;h3&gt;
  
  
  Arquitetura Exemplo
&lt;/h3&gt;

&lt;p&gt;Vamos imaginar um ecommerce com uma arquitetura distribuída, onde cada estado da experiência do cliente seja um microsserviço. O nosso fluxo será composto de: consultar estoque do produto, gerenciamento de produtos no carrinho, cadastro do cliente, serviço de cotação de frete, verificação de segurança dos dados, verificação de pagamento e processo logístico. Cada etapa desse fluxo será um microsserviço gerando evento por operação executada no objeto pedido - que é o objeto criado pela nossa aplicação principal.&lt;/p&gt;

&lt;h3&gt;
  
  
  O problema
&lt;/h3&gt;

&lt;p&gt;A nossa aplicação principal produz um evento que será consumido pelos demais serviços. O nosso objeto pedido possui um campo de estado, indicando a sua posição no fluxo. Os microsserviços não alteram o estado do objeto, mas retornam um evento de resposta em que o único interessado é a nossa aplicação principal. Quando o nosso evento pedido é enviado para o barramento (&lt;em&gt;centralizador&lt;/em&gt;) a nossa aplicação principal perde o controle do estado da operação. Nesse ponto, o que acontece caso um serviço ocorra em falha durante a sua funcionalidade? E se outros fluxos também quebrarem enquanto processam outros eventos, de que maneira poderemos identificar cada evento e a sua fonte de falha?&lt;/p&gt;

&lt;h3&gt;
  
  
  A solução é rastrear
&lt;/h3&gt;

&lt;p&gt;Em um cenário indesejado e catastrófico, nossos eventos se perdem e não teremos resposta do estado da operação. Isso seria terrível!&lt;br&gt;
No mundo ideal cada evento seria uma mensagem composta por id associativo, estado da operação, fonte do evento e a data e hora. Sendo essa mensagem enviada para um log central. Em caso de falha em algum ponto do processo, poderíamos ter uma resposta de erro associado ao id do evento de pedido e tudo suportado por logs, dashboards e métricas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Algumas ferramentas muito úteis
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Splunk&lt;/strong&gt;: é uma ferramenta para centralizar logs de forma bem estruturada, e com um serviço de pesquisa orientado ao código. Também fornece gráficos para comparar métricas e macros para segmentar eventos, com tipos definidos pelo programador.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloudwatch&lt;/strong&gt;: muito semelhante ao Splunk mas totalmente vinculado à plataforma da AWS, fornecendo facilidade para aplicações que utilizam o ambiente da cloud AWS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graphana&lt;/strong&gt;: é uma ferramenta que fornece gráficos e tabelas para análise de métricas, além da possibilidade de configurar dashboards personalizados e alarmes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jaeger&lt;/strong&gt;: ferramenta para fazer tracing (&lt;em&gt;rastreamento&lt;/em&gt;) de todo o fluxo de uma requisição. O Jaeger consegue fazer análise de dependência, causa raiz de falhas, problemas com latência e otimização e monitoramento da propagação do evento.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Uma arquitetura de sistemas distribuídos que opera direcionado a eventos (&lt;em&gt;eventdriven&lt;/em&gt;), possui um fluxo muito intenso de troca de mensagens e depende da resposta entre os microsserviços para continuar o fluxo de execução das suas operações. É muito comum encontrar pontos de falha que quebrem o fluxo e abandonem o objeto da finalidade da operação. Sabendo disso é importante ter ferramentas para mitigar os problemas e reduzir a sua incidência no ambiente de produção.&lt;br&gt;
Mensagens bem formatadas, logs centralizados, Ids únicos associativos, métricas, alertas e dashboards são algumas ferramentas que podem nos ajudar com rastreabilidade.&lt;/p&gt;

</description>
      <category>monitoring</category>
      <category>devops</category>
      <category>distributedsystems</category>
      <category>eventdriven</category>
    </item>
    <item>
      <title>Exemplo em código dos padrões de projeto</title>
      <dc:creator>Walter Alleyz</dc:creator>
      <pubDate>Wed, 12 Jan 2022 14:01:15 +0000</pubDate>
      <link>https://dev.to/walteralleyz/exemplo-em-codigo-dos-padroes-de-projeto-1p3k</link>
      <guid>https://dev.to/walteralleyz/exemplo-em-codigo-dos-padroes-de-projeto-1p3k</guid>
      <description>&lt;p&gt;Design Patterns (comumente relacionados na literatura de TI como “Padrões de Projeto”) são soluções para problemas comuns que encontramos no desenvolvimento ou manutenção de um software orientado a objetos (não são tão bem aplicáveis em outros paradigmas).&lt;/p&gt;

&lt;p&gt;Os padrões GoF foram divididos e categorizados de acordo com a natureza do problema que eles resolvem (ou ao menos tentam, uma vez que software, como bem você sabe, é algo com “vida própria” haha):&lt;/p&gt;

&lt;p&gt;Padrões de Criação: Tem como objetivo abstrair a instanciação de objetos. Com eles, o sistema vai solicitar um objeto de um determinado tipo e o terá prontinho, sob demanda, sem nem se preocupar com as nuances da criação. Fazendo um paralelo com o mundo real, uma empresa automobilística quando precisa de amortecedores, ela terceiriza (solicita-os) e então os instala em seus carros, sem se preocupar com o todo envolvido na criação desse componente.&lt;/p&gt;

&lt;p&gt;Padrões estruturais: Os padrões dessa categoria se preocupam em melhor organizar a estrutura das classes e os relacionamentos entre classes e objetos.&lt;/p&gt;

&lt;p&gt;Padrões comportamentais: Os padrões dessa categoria atuam diretamente na delegação de responsabilidades, definindo como os objetos devem se comportar e se comunicar.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Texto retirado da Treinaweb&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A seguir é possível encontrar os padrões com detalhes e um exemplo de código, divididos por sua aplicação.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Padrões de Criação&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O Abstract Factory é usado para criarmos diferentes famílias de objetos sem precisar especificar a classe concreta. Assim, definimos uma classe abstrata que cria os recursos e as classes concretas criam as classes de cada família. Este padrão tem relação com os padrões Factory Method, Prototype e Singleton.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/2004ec5a8ccc246002ea0a5ae2ef74dc" rel="noopener noreferrer"&gt;&lt;em&gt;Abstract Factory&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O padrão Factory Method utiliza um método de uma classe que cria objetos de outro tipo. Em outras palavras, este padrão fornece uma interface para criar objetos em uma classe mãe e permite que seus filhos alterem o tipo de objeto que será criado.  Os padrões Factories costumam ter vários Factory Methods dentro deles.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/53ec860cba1346f5235267fbb64f8b47" rel="noopener noreferrer"&gt;&lt;em&gt;Factory Method&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este padrão de criação é usado quando temos um “modelo” de um objeto que queremos criar e para criar novos objetos clonamos este objeto. Em uma Factory podemos ter vários Prototypes e a criação de objetos irá gerar cópias deste objeto.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/6b32fc7680c1d2f19f1e3f454a6f5b58" rel="noopener noreferrer"&gt;&lt;em&gt;Prototype&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O Singleton é utilizado quando queremos que exista só uma única instância de uma classe e que ela possa ser facilmente acessível de qualquer ponto do programa. É uma boa alternativa às variáveis globais e as classes que só possuem métodos estáticos. Em um Singleton, a própria classe é responsável por gerenciar sua única instância.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/2952a7322fe2f499f2f2d9a62fa6c2ee" rel="noopener noreferrer"&gt;&lt;em&gt;Singleton&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A definição do padrão Builder é bem clara. Ele separa a construção de um objeto complexo de sua representação de modo que o mesmo processo de construção possa criar diferentes representações. Em outras palavras, você tem a estrutura da classe e consegue criar os objetos como se fossem um passo a passo.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/733632239fe7ce2b2b61e70eae66d6db" rel="noopener noreferrer"&gt;&lt;em&gt;Builder&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Padrões de Estrutura&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Um uso comum do Façade é quando temos que fazer a comunicação com um subsistema complexo. Para isso, o padrão fornece uma interface única para um conjunto de interfaces de um subsistema. O objetivo é diminuir o acoplamento no sistema ao concentrar o uso do subsistema em uma fachada, ou seja, em uma interface de nível mais elevado que torna o subsistema mais fácil de usar.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/776584c0a187035ce2bcea0eedaa789c" rel="noopener noreferrer"&gt;&lt;em&gt;Facade&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O objetivo do Composite é compor objetos em estruturas de árvore, de um modo que possamos tratar um objeto da mesma maneira que uma única instância do mesmo tipo de objeto. Existe também uma estrutura todo-parte em um Composite: um nó na hierarquia de um Composite tem como partes integrantes de si todos os seus filhos.&lt;/p&gt;

&lt;p&gt;Um bom exemplo são as interfaces gráficas: cada componente da tela herda de Widget e pode ter vários filhos. Com isso podemos tratar tanto um simples botão como uma janela completa do mesmo modo.&lt;br&gt;
Este padrão se relaciona com o Visitor, que pode ser utilizado para realizar uma operação em um Composite e também com o Iterator, que pode ser utilizado para percorrer o Composite.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/d20644e136631282e5d15dcc17380315" rel="noopener noreferrer"&gt;&lt;em&gt;Composite&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O padrão Adapter serve como um adaptador. Ele converte a interface de um objeto para a interface esperada por um cliente. Permite que objetos com interfaces incompatíveis comuniquem-se efetivamente.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/e76e9d7f7ed6379259c5602748231ff1" rel="noopener noreferrer"&gt;&lt;em&gt;Adapter&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O padrão Bridge permite que possamos desacoplar uma abstração de sua implementação, gerando hierarquias gêmeas. É como se você  dividisse uma classe grande ou um conjunto de classes intimamente ligadas em duas hierarquias separadas. Literalmente cria-se uma “ponte” de ligação.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/d3b6fb3e8783839a08353c970d24bd62" rel="noopener noreferrer"&gt;&lt;em&gt;Bridge&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De forma jocosa, o padrão Decorator permite adicionar coisas a um objeto em tempo de execução. Ou seja, ele nos permite adicionarmos responsabilidades adicionais a um objeto dinamicamente. Com isso ganhamos mais flexibilidade em detrimento ao uso de herança.&lt;/p&gt;

&lt;p&gt;Um exemplo poderia ser em uma biblioteca de streams: um stream que pode escrever em arquivos pode ser decorado por outro que compacta os dados antes, que pode ser decorado por outro que criptografa os dados, e assim por diante.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/c747dbf4dc5a72ffbbfc6d8337299168" rel="noopener noreferrer"&gt;&lt;em&gt;Decorator&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um Proxy controla o acesso a um objeto, de modo a prover somente as funções permitidas a um objeto cliente. Um exemplo pode ser um proxy de proteção, que nega acesso a algumas partes de um objeto a um grupo de clientes.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/42425cc1ab9527b8263cad01fcb50c00" rel="noopener noreferrer"&gt;&lt;em&gt;Proxy&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um Flyweight pode ser utilizado quando temos muitos objetos que compartilham uma grande parte de seu estado. A solução é criar um Flyweight que guarda esse estado compartilhado e o estado que muda é guardado com cada objeto.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/52a0bd800ba37506346f6a29d1788bf7" rel="noopener noreferrer"&gt;&lt;em&gt;Flyweight&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Padrões Comportamentais&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Usamos o Strategy quando queremos ter uma família de algoritmos, de modo que possamos encapsular cada um deles , e torná-los intercambiáveis, permitindo assim que os algoritmos variem independentemente dos clientes que os utilizam.&lt;/p&gt;

&lt;p&gt;A ideia do Strategy é encapsular esses algoritmos em uma classe separada e assim podemos trocar entre eles apenas mudando uma referência.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/b1c4987ead7e7d487b85c00e89511a90" rel="noopener noreferrer"&gt;&lt;em&gt;Strategy&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um Template Method é um método concreto em uma classe abstrata que define os passos de um algoritmo a ser executado, porém cada passo deve ser implementado pelas subclasses concretas. Este padrão se relaciona com um Strategy. Enquanto o Template Method cria variações entre as partes de um algoritmo usando herança, o Strategy varia o algoritmo todo usando delegação.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/6f393320a68c0a36be489fb1e516a3dd" rel="noopener noreferrer"&gt;&lt;em&gt;Template Method&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Usar um State é necessário quando queremos que objeto altere seu comportamento quando seu estado interno muda. É como se o objeto mudasse de classe. Neste caso o estado é encapsulado em uma classe separada.&lt;/p&gt;

&lt;p&gt;Um exemplo poderia ser um inimigo inteligente em um jogo: dependendo da situação do ambiente, seu estado muda para agressivo ou defensivo (este estado pode ser uma classe separada que controla as ações do inimigo quando ele está naquele estado).&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/c2346a1393bfeb087f51c888a85beb68" rel="noopener noreferrer"&gt;&lt;em&gt;State&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Utilizamos um Mediator quando vários objetos relacionam-se bastante. Como estas relações geram muito acoplamento, concentramos este acoplamento em uma classe mediadora. Assim, cada classe fala somente com o mediador, que repassa as mensagens para as outras classes. O mediador também concentra as regras de negócio dos objetos que ele media.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/24dff6fdf20075f54a7821f917c3ca86" rel="noopener noreferrer"&gt;&lt;em&gt;Mediator&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um Iterator serve para dar acesso aos elementos de uma coleção ou agregado sem expor sua implementação interna. Exemplos desse padrão são encontrados em coleções que suportam a iteração usando o comando foreach presente em algumas linguagens de programação.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/159a61e7e48a9bcb460ab008cee02ca7" rel="noopener noreferrer"&gt;&lt;em&gt;Iterator&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O Memento é usado para externalizar o estado de um objeto sem violar o encapsulamento, de modo a poder restaurar este estado posteriormente.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/37e6e9e93ba22a8434a88525ff4665cc" rel="noopener noreferrer"&gt;&lt;em&gt;Memento&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com o uso do padrão Command, criamos uma maneira de encapsular requisições em classes, para que estas requisições possam ser ordenadas, enfileiradas, etc. Um uso muito comum é em logs e em distribuição de tarefas.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/315fcb1434abb225825de674f668d142" rel="noopener noreferrer"&gt;&lt;em&gt;Command&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Através da cadeia de responsabilidades, este padrão desacopla o receptor do emissor da mensagem, criando uma cadeia de objetos em que um objeto decide se vai processar a mensagem ou passar a responsabilidade para o próximo. Este padrão se relaciona com o Composite.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/2fbb04235b2ccd379f513a3a0f39cb1d" rel="noopener noreferrer"&gt;&lt;em&gt;Chain of Responsability&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ele define uma espécie de gramática. Um Interpreter define uma representação para esta gramática e um interpretador para interpretar sentenças nesta gramática. Utilizado principalmente em compiladores e interpretadores (de XML, de linguagens de programação).&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/63b5ea88f498ea9d68a953e38793b30b" rel="noopener noreferrer"&gt;&lt;em&gt;Interpreter&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um Visitor representa uma operação a ser executada em todos os elementos de uma estrutura de objetos. Este padrão se relaciona com o Composite (percorre os elementos do Composite) e Interpreter (neste caso o Visitor realiza a interpretação).&lt;/p&gt;

&lt;p&gt;Diferença com o Iterator: enquanto o Visitor representa uma operação executada em uma estrutura de elementos, o Iterator simplesmente fornece um meio de acessar os elementos da estrutura.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/c88033436cff97e6ab71b0b2d2f75267" rel="noopener noreferrer"&gt;&lt;em&gt;Visitor&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um Observer define uma relação de um para muitos tal que quando algo do primeiro objeto mudar, todos os outros objetos são avisados . Isso é feito de forma a não criar acoplamento entre os objetos.&lt;br&gt;
&lt;a href="https://gist.github.com/walteralleyz/769b397bde3b45f6c42463d63c5afe88" rel="noopener noreferrer"&gt;&lt;em&gt;Observer&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Atenção: Esse conteúdo é apenas um compilado de materiais da internet, na tentativa de fazer um resumo usando a linguagem Java. Espero que tenham gostado.&lt;/p&gt;

&lt;p&gt;Fontes:&lt;br&gt;
Growthdev&lt;br&gt;
RefactoringGuru&lt;br&gt;
DevMedia&lt;br&gt;
Medium&lt;br&gt;
USP&lt;/p&gt;

</description>
      <category>design</category>
      <category>patterns</category>
      <category>padroes</category>
      <category>projeto</category>
    </item>
    <item>
      <title>YAGNI: Solucionando um problema na implantação de pequenas funcionalidades</title>
      <dc:creator>Walter Alleyz</dc:creator>
      <pubDate>Sat, 23 Oct 2021 16:52:24 +0000</pubDate>
      <link>https://dev.to/walteralleyz/yagni-solucionando-um-problema-na-implantacao-de-pequenas-funcionalidades-4kp0</link>
      <guid>https://dev.to/walteralleyz/yagni-solucionando-um-problema-na-implantacao-de-pequenas-funcionalidades-4kp0</guid>
      <description>&lt;p&gt;O YAGNI (junto ao &lt;a href="https://www.interaction-design.org/literature/topics/keep-it-simple-stupid#:~:text=Keep%20it%20simple%2C%20stupid%20(KISS)%20is%20a%20design%20principle,of%20user%20acceptance%20and%20interaction." rel="noopener noreferrer"&gt;KISS&lt;/a&gt; e ao &lt;a href="https://en.m.wikipedia.org/wiki/Don%27t_repeat_yourself#:~:text=The%20DRY%20principle%20is%20stated,authoritative%20representation%20within%20a%20system%22.&amp;amp;text=When%20the%20DRY%20principle%20is,in%20other%20logically%20unrelated%20elements." rel="noopener noreferrer"&gt;DRY&lt;/a&gt;) é um princípio base muito importante na vida de um desenvolvedor. O conceito que explica o YAGNI, diz que devemos isolar as etapas da nossa aplicação em funcionalidades que realizem o seu objetivo da forma mais simples e direta possível, evitando criar coisas desnecessárias que fujam do escopo inicial.&lt;br&gt;
Vou dar um exemplo do mundo real, que é um aprendizado da minha carreira - motivo desse post - e que envolve projeto de software. Eu estava trabalhando em uma nova funcionalidade, e essa funcionalidade havia sido dividida e isolada em unidades menores que chamamos de histórias. Cada história contava uma etapa do processo, e os requisitos de completude. Por esse meio, nós temos uma noção do ponto de partida, as tecnologias necessárias, e o produto mínimo e viável para implantar a história.&lt;br&gt;
De início, o desenvolvimento parecia constante e equilibrado, focado na solução. Mas decidimos dividir a equipe em outras histórias, e eu me perdi no desenvolvimento. Como a equipe estava dividida, quando precisamos implantar a história (e ela apresentava problemas) passamos a unir outras funcionalidades nela, aumentando o escopo e gerando mais bugs que atrasaram a nossa entrega.&lt;br&gt;
Mas o que isso tem relação com o YAGNI? Tudo! Deixamos de focar no mínimo, quando tentamos adicionar mais código para corrigir os problemas. E o produto deixou de ser viável pois apresentou mais problemas do que funcionamento. Tornamos o desenvolvimento complexo, como que na tentativa de matar uma barata com um míssil.&lt;br&gt;
Em resumo desse artigo, estou escrevendo para que eu mesmo não me esqueça de que é preciso focar, no desenvolvimento, naquilo que é mais importante para entregar a funcionalidade sempre considerando que o produto é incremental e sua evolução é contínua.&lt;/p&gt;

</description>
      <category>yagni</category>
      <category>programming</category>
      <category>principles</category>
    </item>
    <item>
      <title>Reduzindo a quantidade de Branchs na criação de Objetos com uma estrutura plugável</title>
      <dc:creator>Walter Alleyz</dc:creator>
      <pubDate>Fri, 08 Oct 2021 17:30:30 +0000</pubDate>
      <link>https://dev.to/walteralleyz/reduzindo-a-quantidade-de-branchs-na-criacao-de-objetos-com-uma-estrutura-plugavel-4ic9</link>
      <guid>https://dev.to/walteralleyz/reduzindo-a-quantidade-de-branchs-na-criacao-de-objetos-com-uma-estrutura-plugavel-4ic9</guid>
      <description>&lt;p&gt;Você já se deparou com o cenário em que criar objetos, de forma dinâmica, usando algum parâmetro era necessário?&lt;br&gt;
Digamos que estejamos criando um sistema para academias, e para diferenciar os tipos de clientes nós vamos modelar classes diferentes. De início vamos ter os planos básico, avançado e de luxo e com o tempo podemos acrescentar novos planos a partir de novas atualizações.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Basico {}

public class Avcado {}

public class DeLuxo {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Podemos perceber que se o nosso cliente estiver buscando um sistema em que ele possa definir os tipos de planos, ele vai sofrer com forte dependência do time de desenvolvimento, pois para adicionar um plano ele precisará esperar uma nova atualização. Não é o objetivo desse artigo solucionar esse problema.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Normalmente para instanciar essas classes de forma dinâmica, nós poderíamos criar uma função para receber um parâmetro e retornar o objeto selecionado. Mas para isso, nossas classes precisam adquirir um super tipo que as torne polimórficas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface UserPlan {
  void doSomething();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora podemos implementar essa interface em nossas classes e criar o nosso método.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public UserPlan criarPlano(String plan) {
  if(plan.equals("basico")) return new Basico();
  else if(plan.equals("avancado")) return new Avcado();
  else return new DeLuxo();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Muito fácil, não é mesmo? O problema que criamos utilizando desse padrão é que sempre que uma nova classe &lt;b&gt;plano&lt;/b&gt; for criada, precisaremos editar essa função e adicionar uma nova branch. Se esse método estiver contido dentro da própria classe cliente (a classe que dependeria dessa função), teremos um problema em dobro, sempre tendo de abrir a classe para dar manutenção e tendo de alterar todos os pontos em que a criação desses objetos atinge.&lt;/p&gt;

&lt;p&gt;Um exemplo simples de entender é que, se a classe cliente dependesse do nome do objeto criado para executar alguma ação, e a implementação dessa ação estivesse contida dentro da classe cliente, também precisaríamos editar esse código gerando um ciclo de retrabalho interminável.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Cliente {

  public void fazAlgoDeAcordoComObjeto(String plan) {
    UserPlan plan = criarPlano(plan);

    if(plan.getClass().getSimpleName().equals("Basico"))
    // implementa algo aqui

    else if(plan.getClass().getSimpleName().equals("Avcado"))
    // implementa algo aqui

    else
    // implementa algo aqui

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

&lt;/div&gt;



&lt;p&gt;Esse tipo de implementação cria uma dependência (ou acoplamento) terrivelmente abusiva, que nos traz um novo problema sempre que precisamos realizar alguma alteração.&lt;/p&gt;

&lt;p&gt;Para contornar esse contra padrão e eliminar as branchs, podemos nos aproveitar de uma estrutura de dados que já utiliza comparação de acordo com um parâmetro específico; uma estrutura de chave-valor.&lt;/p&gt;

&lt;p&gt;Vamos começar eliminando da classe cliente a implementação do método &lt;em&gt;fazAlgoDeAcordoComObjeto&lt;/em&gt;, e utilizar injeção de dependência para chamar o método &lt;em&gt;doSomething&lt;/em&gt; que as classes implementam por meio da interface &lt;b&gt;UserPlan&lt;/b&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Cliente {

  private final UserPlan userPlan;

  public Cliente(UserPlan userPlan) {
    this.userPlan = userPlan;
  }

  public void fazAlgoDeAcordoComObjeto() {
    userPlan.doSomething();
  }

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Eliminamos vários pontos de manutenção distribuindo a responsabilidade.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Agora podemos criar uma classe utilitária que vai cuidar da criação do objeto para nós.&lt;br&gt;
Essa classe vai possuir um HashMap (que recebe chave e valor) para guardar a chave de comparação e o método de criação do objeto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class UserPlanCreator {

  private static final Map&amp;lt;String, PlanCreator&amp;gt; plans = new HashMap&amp;lt;&amp;gt;();

  static {
    plans.put("basico", Basico::new);
    plans.put("avancado", Avcado::new);
    plans.put("luxo", DeLuxo::new);
  }

  private UserPlanCreator() {}

  public static UserPlan criarPlano(String plano) {
    return plans.get(plano).create();
  }

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Uma validação de nulo pode ser implementada no método criarPlano.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Você deve ter percebido que a nossa estrutura Map não retorna o super tipo e sim uma interface que a gente não implementou ainda. Eu fiz essa escolha de design, porque criar um objeto dentro de um iniciador estático iria tornar essa criação única, fazendo o método sempre retornar o mesmo objeto.&lt;br&gt;
Para evitar esse comportamento, precisamos retornar o método de criar e não o objeto instanciado e nesse momento as &lt;b&gt;interfaces funcionais&lt;/b&gt; podem nos ajudar.&lt;/p&gt;

&lt;p&gt;Uma interface funcional é uma estrutura que possui um único método abstrato e pode ser utilizada para implementar lambdas ou referências de métodos. Assim seria a nossa interface funcional:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@FuncionalInterface
public interface PlanCreator {

  UserPlan create();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto, agora a gente só precisa garantir que o lambda, ou referência de método, retorne o objeto do tipo UserPlan (e por isso estamos usando um super tipo nas classes de planos    😀).&lt;/p&gt;

&lt;p&gt;Apesar desse monte de código você vai perceber que as responsabilidades estão bem definidas, e a classe cliente só precisa chamar o método do objeto que ela vai receber, sem precisar lidar com a comparação e sem precisar conhecer os objetos que ela possui dependência. Ainda eliminamos vários pontos de manutenção, garantindo que quando uma nova classe for criada precisaremos alterar apenas uma estrutura do todo.&lt;/p&gt;

&lt;p&gt;Por fim, nosso código para criar um plano ficaria assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static void main(String[] args) {
  // geralmente a entrada do tipo do plano viria de algum input
  Client client = new Client(UserPlanCreator.criarPlano("basico"));
  client.doSomething();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>java</category>
      <category>factory</category>
      <category>inversion</category>
      <category>dependency</category>
    </item>
    <item>
      <title>Entendendo Encapsulamento</title>
      <dc:creator>Walter Alleyz</dc:creator>
      <pubDate>Tue, 05 Oct 2021 03:19:06 +0000</pubDate>
      <link>https://dev.to/walteralleyz/entendendo-encapsulamento-2j1p</link>
      <guid>https://dev.to/walteralleyz/entendendo-encapsulamento-2j1p</guid>
      <description>&lt;p&gt;Esse é um dos principais conceitos da programação orientada à objetos. O seu objetivo é proteger os dados internos de uma classe aos interesses externos.&lt;/p&gt;

&lt;p&gt;A primeira vez que nos deparamos com informações sobre os princípios da OOP, o encapsulamento (geralmente) como conceito, traz a ideia de que tornar atributos privados é a essência da proteção dos dados de uma classe. Dia após dia, os jovens programadores de Java, enchem os seus projetos de classes anêmicas recheadas de anotações (que com o uso de espelhamento) para gerar seus getters/setters por baixo dos panos e distribuem a lógica do negócio para longe do domínio, com a defesa de alguma arquitetura por aí.&lt;br&gt;
O que nem todo mundo sabe é que o sistema pode apresentar muita fragilidade (e inutilidade) com o overengeneering do desacoplamento da validação.&lt;/p&gt;

&lt;p&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%2Frxfdi61bha33glluydjf.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%2Frxfdi61bha33glluydjf.jpg" alt="Implementação frágil" width="800" height="764"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O exemplo do código mostra a implementação de um gerador como o Lombok, ou de uma classe anêmica comum. Como é possível perceber, o modificador de acesso é completamente inútil já que o setter não possui qualquer verificação de entrada. Qualquer valor (desde que do tipo esperado), inserido por meio do método, será aceito e isso pode representar uma falha de segurança, se alguém encontrar um jeito de instanciar essa classe diretamente.&lt;br&gt;
Esperar que colocar as regras de negócio nas bordas da arquitetura vai salvar toda a aplicação, pode representar um erro futuro de proteção à consistência da informação.&lt;br&gt;
Separar as regras de negócio do domínio também representa uma quebra de encapsulamento, já que estamos informando à outras entidades (e fornecendo o acesso) como atribuir valores e com isso, transferimos essa responsabilidade para outras classes, quebrando padrões de design.&lt;/p&gt;

&lt;p&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%2Fzdf7dop4as5ofd790wf4.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%2Fzdf7dop4as5ofd790wf4.jpg" alt="Uma lista fácil de modificar" width="800" height="575"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Analisando esse código, é possível perceber que continuamos cometendo o mesmo erro de confiar a propriedade da validação à outras classes, mas vamos além: estamos permitindo o acesso de modificação de uma lista para qualquer um que obtê-la.&lt;br&gt;
E não é exagero; ao chamar &lt;b&gt;getContas()&lt;/b&gt; recebemos o objeto List e toda possibilidade de ações que a classe implementa. Perigoso não?&lt;/p&gt;

&lt;p&gt;E então qual a solução para esses problemas?&lt;br&gt;
Trabalhar com classes anêmicas não é um problema, mas quando utilizamos elas para definir o modelo do nosso negócio, continuamos expondo nossa implementação e nossas regras mesmo utilizando modificadores de acesso.&lt;br&gt;
Martin Fowler traz um padrão de design, que propõe unir o comportamento aos dados, deixando de lado anemia e dando poder ao domínio.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This is often a good thing because this data and the behavior that manipulates them are tightly coupled: changes in one cause changes in the other, understanding one helps you understand the other." - Fowler, Martin.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nas palavras de Martin Fowler, esse padrão (também conhecido como &lt;a href="https://martinfowler.com/bliki/TellDontAsk.html" rel="noopener noreferrer"&gt;TellDontAsk&lt;/a&gt;) é frequentemente bom porque traz o comportamento para perto dos dados, facilitando a manutenção e o entendimento das regras de negócio.&lt;/p&gt;

&lt;p&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%2Fdb41ftsz1gc0qeb44z4y.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%2Fdb41ftsz1gc0qeb44z4y.jpg" alt="Um domínio com garantias" width="800" height="657"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora estamos garantindo que vamos entregar um objeto selado, além do acesso controlado de/para informações. Ainda, se precisarmos alterar alguma regra de negócio, ou adicionar comportamento ao domínio, está tudo bem próximo para dar manutenção e facilitar o entendimento.&lt;br&gt;
Em programação, nem sempre existe o certo ou errado, mas permanece o questionamento: o que é encapsulamento pra você?&lt;/p&gt;

</description>
      <category>encapsulamento</category>
      <category>security</category>
      <category>classes</category>
    </item>
  </channel>
</rss>
