<?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>Forem: RUBICON</title>
    <description>The latest articles on Forem by RUBICON (@rubicon_dev).</description>
    <link>https://forem.com/rubicon_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%2F478856%2F69d869a6-2a1f-4192-b530-9f8ace62975e.png</url>
      <title>Forem: RUBICON</title>
      <link>https://forem.com/rubicon_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rubicon_dev"/>
    <language>en</language>
    <item>
      <title>2021 is the Year for Digital Transformation</title>
      <dc:creator>RUBICON</dc:creator>
      <pubDate>Tue, 31 Aug 2021 15:02:08 +0000</pubDate>
      <link>https://forem.com/rubicon_dev/2021-is-the-year-for-digital-transformation-1hfg</link>
      <guid>https://forem.com/rubicon_dev/2021-is-the-year-for-digital-transformation-1hfg</guid>
      <description>&lt;p&gt;Although consumers want valuable solutions to their problems fast, the adoption of digital transformation has still been slow. However, in the wake of the pandemic, the digital age seems like it is just around the corner.&lt;/p&gt;

&lt;p&gt;Digital transformation, as the process of utilizing digital technologies to drastically improve business models, has become one of the hottest topics for companies around the globe. Executives in all industries are going digital to replace or improve their existing traditional technologies and processes. Moreover, digital transformation is a cultural change through which companies continually challenge the status quo. The recent pandemic has put many companies in ‘’survival mode’’ where an organization’s ability to adapt quickly to disruption has become of critical importance.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Framework
&lt;/h3&gt;

&lt;p&gt;Digital transformation varies based on the organization's specific challenges and demands, but there is a common framework that companies should consider as they embark on the digital transformation journey. The common digital transformation framework assumes digitization of 4 main areas: customer experience, products and services, operations and organizations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Digitizing Customer Experience
&lt;/h4&gt;

&lt;p&gt;Customers have always been the most important stakeholders of any organization. It is essential for every company to know its customers and serve them in the best possible way. CRM systems greatly help companies identify their customers’ needs and demands. The digital footprints that customers leave behind daily through social media platforms enable companies to link preferences to habits and accommodate to them accordingly.&lt;/p&gt;

&lt;p&gt;These insights are invaluable for digital marketing as well because to be competitive in today’s world, companies must engage with their customers online and personalize their product and service promotions in order to increase customer loyalty.&lt;/p&gt;

&lt;h4&gt;
  
  
  Digitizing Products and Services
&lt;/h4&gt;

&lt;p&gt;Selling the experience rather than products has become paramount for companies to stay competitive in today’s saturated market. To create such experiences, companies need to think about how to take customers on a journey and stay in touch with them throughout the process.&lt;/p&gt;

&lt;p&gt;Analysis of customer behavior on social media helps organizations predict the usage of products and level of satisfaction, enabling organizations to anticipate customer needs before problems arise.&lt;/p&gt;

&lt;h4&gt;
  
  
  Digitizing Operations
&lt;/h4&gt;

&lt;p&gt;Advanced digital technology can improve business processes in a number of ways. By automating, standardizing and globally sourcing processes, organizations can become more agile, more responsive to rapid changes, and better able to increase and sustain profitability. Ever since RUBICON adopted Agile practices, we’ve been able to develop high-quality products quicker, and transform operations to adapt quickly to rapid changes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Digitizing the Organization
&lt;/h4&gt;

&lt;p&gt;Digital solutions support the creation of ecosystems by the members of the value chains enabling them to work more closely together. However, to have the full advantage of effectively working together in an integrated ecosystem, employees have to break down silos and collaborate across different departments. This requires them to respond quickly and consistently to changes in the market and within their organizations. Moving towards the digital mindset means rewarding innovation and allowing customers’ opinions and suggestions to positively influence product development.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Types of Digital Transformation
&lt;/h3&gt;

&lt;p&gt;New digital technologies create significant opportunities for organizations if effectively embraced and pursued. There are 4 commonly differentiated types of digital transformation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Business Process Transformation&lt;/strong&gt;&lt;br&gt;
Business Process Transformation entails utilizing digital technology (data analytics, APIs, machine learning, AI, etc.) to reinvent business processes with the goals of lowering costs, reducing cycle times, and increasing quality and productivity. These transformations can create significant value for organizations because they focus on specific areas of business.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Business Model Transformation&lt;/strong&gt;&lt;br&gt;
The most common reason companies embrace digital technologies is to transform their traditional business models. Business model transformation refers to improving fundamental building blocks of how value is delivered in an industry. Corporations that achieve business model transformation open significant new opportunities for growth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Domain Transformation&lt;/strong&gt;&lt;br&gt;
Domain transformation is an area with little focus but vast opportunities. The new technologies offer executives options for unlocking new business opportunities for companies beyond their target market. This type of transformation often provides the greatest value and leveraging it efficiently can reap the benefits of new growth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cultural Transformation&lt;/strong&gt;&lt;br&gt;
Long-term digital transformation requires companies to redefine organizational mindsets, processes, and capabilities. In the digital age, companies have to recognize the importance of agile workflows, decentralized decision-making, and a greater reliance on business ecosystems. As technology changes, industries will continue to be forced to take active steps to adapt to changes successfully. Corporations that pursue digital transformation in a multi-dimensional way will find greater success than those that don’t.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Embracing Digital Transformation
&lt;/h3&gt;

&lt;p&gt;Embracing digital technology has never been more necessary for sustained growth. Here are some concepts to consider in order to adopt them successfully:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Switching from product-focused mindset to customer-focused;&lt;/li&gt;
&lt;li&gt;Creating innovative digital experiences;&lt;/li&gt;
&lt;li&gt;Customizing customer journeys;&lt;/li&gt;
&lt;li&gt;Enabling remote work and automation;&lt;/li&gt;
&lt;li&gt;Utilizing AI and machine learning;&lt;/li&gt;
&lt;li&gt;Prioritizing long-term value of digital initiatives.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Digitally transforming your business can be quite a complex project, so here are a few pieces of advice from RUBICON:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Think cloud.&lt;/strong&gt; Replace on-site solutions with cloud solutions to be more agile and meet customer demands quickly. Additionally, with cloud solutions, the latest features are automatically updated so you are never behind.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Personalize.&lt;/strong&gt; In today’s world customers have come to expect personalized experiences. Companies can provide that by using the data in their CRM software to evaluate buying behaviors and purchase history.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tie the digital channels.&lt;/strong&gt; Customers want a seamless experience regardless of the channel. Consider tying all the digital channels together to provide a user-friendly customer experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By focusing on these three factors, organizations can start embracing the new digital landscape, exceed customer expectations and improve the overall customer experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Can RUBICON Help
&lt;/h3&gt;

&lt;p&gt;RUBICON helps companies transform their business processes with digital transformation solutions. Our dedicated agile teams help our clients digitize their businesses by successfully improving performance, efficiency and customer experience. To find out more about the software solutions we design and develop, take a look at our recent &lt;a href="https://www.rubicon-world.com/case-studies/cloud-native-development-chemical-consumer-goods-company/"&gt;case study&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Are you ready to start your digital transformation journey? &lt;a href="https://www.rubicon-world.com/contact/"&gt;Contact us&lt;/a&gt; to take the first step and we will lead you through it.&lt;/p&gt;




&lt;p&gt;Original blog post: &lt;a href="https://www.rubicon-world.com/blog/2021/02/2021-is-the-year-for-digital-transformation/"&gt;2021 is the Year for Digital Transformation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>agile</category>
      <category>digital</category>
      <category>transformation</category>
    </item>
    <item>
      <title>5 Effective Ways to Encourage Knowledge Sharing in the Workplace</title>
      <dc:creator>RUBICON</dc:creator>
      <pubDate>Tue, 31 Aug 2021 14:28:42 +0000</pubDate>
      <link>https://forem.com/rubicon_dev/5-effective-ways-to-encourage-knowledge-sharing-in-the-workplace-2nl</link>
      <guid>https://forem.com/rubicon_dev/5-effective-ways-to-encourage-knowledge-sharing-in-the-workplace-2nl</guid>
      <description>&lt;p&gt;Organizations are constantly looking for ways to enhance their culture with ideas such as flexible working hours, a collaborative environment, team building activities, and recognition awards for employees. But oftentimes one of the most important elements of company culture is overlooked - knowledge sharing.&lt;/p&gt;

&lt;p&gt;Knowledge sharing is vital for a company’s growth and development and should be prioritized. So, without further ado, let’s discuss why knowledge sharing is an important part of workplace culture and take a look at some ways that you or your organization can implement it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is a Knowledge Sharing Culture Important?
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Shows your team members that they are valued
&lt;/h4&gt;

&lt;p&gt;Everyone wants to feel a part of the organization and to know that their ideas matter. Team members can contribute significantly more to a company apart from the daily tasks encompassed within their job roles by showcasing their unique experience and expertise.&lt;/p&gt;

&lt;h4&gt;
  
  
  Provides transparency across the organizatio
&lt;/h4&gt;

&lt;p&gt;Is everybody on your team in the loop and familiar with what’s going on in the company aside from their own projects? Knowledge sharing is the perfect opportunity for new team members to share their roles and responsibilities giving the entire team a better understanding of the business as a whole.&lt;/p&gt;

&lt;h4&gt;
  
  
  Helps team members find efficient ways to solve problems
&lt;/h4&gt;

&lt;p&gt;A knowledge sharing culture can remove the stigma of turning to others for help and thinking that you must have all the answers yourself. How often have you sat mulling over a problem for hours, only to solve it through a discussion with someone else? Team members sharing their own experiences can help you quickly and easily find optimal solutions to problems.&lt;/p&gt;

&lt;h4&gt;
  
  
  Promotes socializing in the workplace
&lt;/h4&gt;

&lt;p&gt;By having a time and place where team members are able to share information and learn from one another, you provide an opportunity for everyone in the organization to socialize. Building relationships within a company fosters friendships, drives employee engagement, and creates a positive work culture.&lt;/p&gt;

&lt;h4&gt;
  
  
  Improves communication skills
&lt;/h4&gt;

&lt;p&gt;Whether your team engages in open discussions, publishes written content, or organizes presentations, you are vastly improving your communication skills.&lt;/p&gt;

&lt;h4&gt;
  
  
  Builds a sea of knowledge
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;An organization’s most valuable asset is its people.&lt;/em&gt; Team members bring their knowledge, skills, experience, and proactiveness to the workplace. New skills and ways of critical thinking are always welcome and can only motivate and inspire your team. Your customers will be more than happy to work with a team that possesses a diverse set of skills and loves taking on exciting challenges and learning new things.&lt;/p&gt;

&lt;h3&gt;
  
  
  5 Effective Ways to Encourage Knowledge Sharing in the Workplace
&lt;/h3&gt;

&lt;p&gt;From executives to interns, everyone in an organization is responsible for contributing to a company’s culture. You can either be the person that brings the ideas to the table or executes them yourself. Let's discuss a few examples of how knowledge sharing can be implemented in your workplace.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Build a knowledge library
&lt;/h4&gt;

&lt;p&gt;A knowledge library is an efficient way for team members to easily access the information they are looking for.&lt;/p&gt;

&lt;p&gt;In order to create your knowledge library, you need to choose a platform where you can organize and store information. At RUBICON, we use &lt;a href="https://www.notion.so/desktop"&gt;Notion&lt;/a&gt; - an all-in-one workspace where you can organize notes, boards, calendars, and databases. By using Notion or a similar platform, you can create a space to store and organize information making it available to everyone in the company.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Planning, researching, and organizing&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sift through your already existing content (articles, books, videos, PDFs, etc) to find out what is helpful and worth sharing and what is ready for the trash bin. After you’ve reviewed your content, you need to consider how you’re going to organize your knowledge library to make it easily accessible. By category, by alphabetical order? Take a look at what works best for your organization. Make it user-friendly and easy for your team to navigate so they don’t spend too much time searching for what they are looking for.&lt;/p&gt;

&lt;p&gt;Once you’ve created your knowledge library, share it with everyone. Don’t just publish it and forget about it because it’s important for you to frequently update it and maintain it making sure all content is fresh and up to date. Lastly, encourage all team members to add valuable resources to keep the knowledge library growing.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Share interesting reads with your team
&lt;/h4&gt;

&lt;p&gt;My mornings usually consist of me getting ready for the workday by reading interesting articles or watching short informational videos. Whenever I run across something I think would be insightful to the rest of my team, I share it on our Slack channel &lt;strong&gt;#learning&lt;/strong&gt;. Our &lt;strong&gt;#learning&lt;/strong&gt; channel is a place where tons and tons of articles, books, and videos are shared throughout the day. This is an easy option to share information and start an engaging discussion.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Give everyone the opportunity to attend events
&lt;/h4&gt;

&lt;p&gt;There are plenty of industry events available worldwide that offer valuable knowledge, professional speakers, exciting activities, and fun networking opportunities. Unfortunately, most, if not all, events have been shifted online but still made available to anyone willing to attend. Encourage team members to participate in these events and share a recap with the rest of the team. From programming to project management to marketing, everyone and anyone on your team can find something that appeals to them.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Make online courses accessible
&lt;/h4&gt;

&lt;p&gt;Online courses are a great way to motivate team members to learn new skills or hone their already-existing ones. Platforms such as &lt;a href="https://www.udemy.com/"&gt;Udemy&lt;/a&gt; or &lt;a href="https://www.pluralsight.com/"&gt;PluralSight&lt;/a&gt; provide users with a large selection of reputable courses. From courses in react.js to photoshop tutorials - there is something available for everyone. At RUBICON, we have company accounts on both platforms where all team members are able to choose courses that they would like to explore.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Create a space for sharing
&lt;/h4&gt;

&lt;p&gt;The easiest and best way to uphold knowledge sharing within your company is to find a time and place for it. You can schedule an event, once a month, where team members present interesting topics in front of the company.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RUBICON Sync&lt;/strong&gt; is the name of the event where we present, engage in discussions, and most importantly learn from each other.&lt;/p&gt;

&lt;p&gt;Every third Friday of the month, one or two team members sign up to steal the spotlight and present a specific topic. &lt;em&gt;Before the pandemic&lt;/em&gt;, developers, designers, product owners, and yes even marketers would gather at 3 PM in our office lounge waiting for the presenter to start. Fast forward to &lt;em&gt;life during the pandemic&lt;/em&gt; and not much has changed regarding RUBICON Sync, other than the fact that the presentations are held on Google Meet and that it’s more difficult to see a presenter’s face flush red at times (because let’s get real - &lt;em&gt;developers don’t really present that often&lt;/em&gt;.) From tech-savvy presentations to presentations on how to write a tech blog, a variety of valuable topics are shared and each team member is given a chance to contribute.&lt;/p&gt;

&lt;p&gt;Organize your very own company event so that every expert on your team has a chance to present their knowledge. It can be once a week or once a month, whatever your team feels works best for them. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remember: sharing is caring.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HYP3rMs1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9y3zcz943d07gsojnnsm.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HYP3rMs1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9y3zcz943d07gsojnnsm.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Start Sharing Your Knowledge
&lt;/h3&gt;

&lt;p&gt;I hope that you have found this information valuable and now understand the importance of prioritizing knowledge sharing at your own organization. I encourage you to run away with my ideas and either implement them yourself or pitch them to your team.&lt;/p&gt;

&lt;p&gt;If you have any ideas or suggestions, you can &lt;a href="https://www.rubicon-world.com/contact/"&gt;reach out&lt;/a&gt; to us as RUBICON is always looking for ways to boost our company culture.&lt;/p&gt;

&lt;p&gt;Have fun knowledge sharing!&lt;/p&gt;




&lt;p&gt;Original blog post: &lt;a href="https://www.rubicon-world.com/blog/2020/11/5-effective-ways-to-encourage-knowledge-sharing-in-the-workplace/"&gt;5 Effective Ways to Encourage Knowledge Sharing in the Workplace&lt;/a&gt;&lt;/p&gt;

</description>
      <category>culture</category>
      <category>knowledge</category>
      <category>collaboration</category>
      <category>advice</category>
    </item>
    <item>
      <title>Automating Flutter App Versioning Using Fastlane Plugin</title>
      <dc:creator>RUBICON</dc:creator>
      <pubDate>Tue, 31 Aug 2021 13:23:26 +0000</pubDate>
      <link>https://forem.com/rubicon_dev/automating-flutter-app-versioning-using-fastlane-plugin-1d6</link>
      <guid>https://forem.com/rubicon_dev/automating-flutter-app-versioning-using-fastlane-plugin-1d6</guid>
      <description>&lt;p&gt;If you’ve ever developed mobile applications and published them to their stores, then you are aware of the specific rules of versioning an app. Those rules revolve around two properties: App versioning and incrementing build number.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting our Facts Right
&lt;/h3&gt;

&lt;h4&gt;
  
  
  App Versioning
&lt;/h4&gt;

&lt;p&gt;Versioning is a critical component of an app upgrade and maintenance strategy.&lt;/p&gt;

&lt;p&gt;On iOS, the app version is presented by the CFBundleShortVersionString key that must correspond to &lt;a href="https://semver.org/"&gt;semantic versioning&lt;/a&gt;. This key is a machine-readable string composed of one to three period-separated integers, such as 10.14.1. The string can only contain numeric characters (0-9) and periods.&lt;br&gt;
Each integer provides information about the build version in the format [Major].[Minor].[Patch]:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Major: A major revision number.&lt;/li&gt;
&lt;li&gt;Minor: A minor revision number.&lt;/li&gt;
&lt;li&gt;Patch: A maintenance release number.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleversion"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On Android, the app version is presented by the versionName inside of the build.gradle file. Android doesn’t enforce any rules when it comes to specifying the name.&lt;/p&gt;

&lt;h4&gt;
  
  
  Build number
&lt;/h4&gt;

&lt;p&gt;Build number (CFBundleVersion on iOS, versionCode on Android) is an identificator that is used only to determine whether one version of an app is more recent than the other, with the higher number indicating a more recent version. Both Google Play Store and Apple AppStore use the build number to protect against downgrades by preventing users from installing an app with a lower build number than the version currently installed on their device. On Android, that number is an integer, but on iOS, that number can be presented both as an integer or as a semantic version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flutter's Way of Handling Stuff
&lt;/h3&gt;

&lt;p&gt;The Flutter team has decided to handle this very neatly; they have a property in pubspec.yaml called version that follows this pattern: {major}.{minor}.{patch}+{version}. Therefore, in order to publish our app with the app version of 1.2.4 and build number of 5, our pubspec.yaml would have a version property that looks like this: version: 1.2.4+5. The next time the application goes through the build process, those values are applied. However, the question is, how we can automate this whole process of versioning?&lt;/p&gt;

&lt;h4&gt;
  
  
  flutter_version_manager plugin for Fastlane - The Fun Part!
&lt;/h4&gt;

&lt;p&gt;Fastlane is the easiest way to build and release mobile apps. It has been used widely by the mobile application developers community. It’s written in Ruby, is open source and it has great support for developing your own custom plugins. That being said, I present to you the flutter_version_manager plugin for Fastlane:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rubiconba/fastlane-plugin-flutter-version-manager"&gt;https://github.com/rubiconba/fastlane-plugin-flutter-version-manager&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;em&gt;This approach is very subjective as this is the method I use to handle versioning of an app.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This plugin heavily resides on having a git repository and at least one commit as build number is applied through timestamp of HEAD commit. By leveraging the power of git, we no longer have to worry about incrementing versionCode/CFBundleVersion. As for the app version, version.yml file that we had to create manually should be used as a single source of truth. Now, there are a couple of ways of handling an app version using this plugin:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Increment a version manually and call -apply on the fastlane plugin. -applycommand will automatically apply all the changes to pubspec.yaml&lt;/li&gt;
&lt;li&gt;Use -major, -minor, or -patch to bump semantic version. It automatically calls -apply and updates the pubspec.yaml.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That being said, a DevOps engineer has power over versioning. For example, he may create a patch pipe that runs on patch branch that will call deploy_as_patch lane which automatically bumps patch version and deploys the latest version. You can find an example of Fastfile &lt;a href="https://github.com/rubiconba/fastlane-plugin-flutter-version-manager/blob/master/fastlane/Fastfile"&gt;here&lt;/a&gt;. Full documentation is available in a &lt;a href="https://github.com/rubiconba/fastlane-plugin-flutter-version-manager"&gt;git repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This plugin is open-source and any contributions to it are more than welcome. Happy DevOpsing! ^^&lt;/p&gt;




&lt;p&gt;Original blog post: &lt;a href="https://www.rubicon-world.com/blog/2020/09/automating-flutter-app-versioning-using-fastlane-plugin/"&gt;Automating Flutter App Versioning Using Fastlane Plugin&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>flutter</category>
      <category>devops</category>
      <category>fastlane</category>
    </item>
    <item>
      <title>A Developer's Guide to CQRS Using .NET Core and MediatR</title>
      <dc:creator>RUBICON</dc:creator>
      <pubDate>Tue, 31 Aug 2021 13:13:32 +0000</pubDate>
      <link>https://forem.com/rubicon_dev/a-developer-s-guide-to-cqrs-using-net-core-and-mediatr-1ae6</link>
      <guid>https://forem.com/rubicon_dev/a-developer-s-guide-to-cqrs-using-net-core-and-mediatr-1ae6</guid>
      <description>&lt;p&gt;&lt;strong&gt;“What is CQRS?”&lt;/strong&gt; you might ask. I hope you didn’t think you were going to get a definition because that’s what Wikipedia is for. Instead, what I’m hoping to achieve with this blog post is to help you understand CQRS through some practical examples.&lt;/p&gt;

&lt;p&gt;I will assume you’re either a beginner or someone who is unfamiliar with this topic, so maybe you get scared whenever you run into these big programming acronyms and concepts. I myself have been there so I’m here to help you figure it out in the easiest way possible.&lt;/p&gt;

&lt;p&gt;Before we get talking about CQRS, we need to understand a few concepts such as Clean Architecture for a better understanding. If you are already familiar with Clean Architecture, then feel free to skip onto the next section. If you are one of those people reading this blog who dislikes theory and just want to get your hands on the code, I encourage you to be patient and try and grasp these concepts and patterns as they will prove to be helpful in the end.&lt;/p&gt;

&lt;p&gt;In this blog, I’ll lead you through a step-by-step tutorial so you learn both about CQRS and also end up with a beautiful project structure that you can brag to your friends about. You may also learn an additional trick or two. At the end of the blog, I’ve provided a link to the entire solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clean Architecture
&lt;/h3&gt;

&lt;p&gt;Before tackling the concept of CQRS let’s learn a bit about Clean Architecture.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why?
&lt;/h4&gt;

&lt;p&gt;Because combining this duo gives us a pretty nice base for further development. Clean Architecture is all about layers and boundaries and creating a clean project structure just as the name itself implies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwsj642qpw6n9eoboqscf.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwsj642qpw6n9eoboqscf.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see how these layers form one solution. &lt;strong&gt;It is important to know that the outer layers depend upon the inner layers and not vice versa.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Domain
&lt;/h4&gt;

&lt;p&gt;In a perfect world, this layer wouldn’t have any dependencies and it would only contain entities, value objects, and maybe some Domain level custom exceptions and entity logic. This layer can be shaped by following the Domain-Driven Design guidelines. I would recommend that you explore these guidelines in-depth and since it’s a broad subject I’ll leave it up to you.&lt;/p&gt;

&lt;h4&gt;
  
  
  Application
&lt;/h4&gt;

&lt;p&gt;Together with the Domain layer, the Application layer forms up a Core of the solution which should be able to operate and provide business logic independently from outer layers and depend solely upon the Domain layer. It contains all of the good stuff such as the business logic (use cases), DTO’s, interfaces, and all of the CQRS stuff that we will be discussing later.&lt;/p&gt;

&lt;h4&gt;
  
  
  Infrastructure
&lt;/h4&gt;

&lt;p&gt;This is the layer where all of the communication logic with the outside systems should be implemented such as sending emails, communication with 3rd party API, etc. It only depends on the Application layer. It can also contain persistence logic if it’s not overly massive and/or complex.&lt;/p&gt;

&lt;h4&gt;
  
  
  Persistence
&lt;/h4&gt;

&lt;p&gt;Compared to the Infrastructure layer, this layer also holds the logic for communication with outside systems, but its specific purpose is to communicate with databases. All of this logic can also be placed under the Infrastructure layer. This layer only depends on the Application layer.&lt;/p&gt;

&lt;h4&gt;
  
  
  Presentation
&lt;/h4&gt;

&lt;p&gt;This is the interactable layer (by the outside world) which allows clients to get visible results after requesting data. This layer can be in the form of an API, console application, GUI client application, etc. Like Persistence, it also depends only on the Application layer.&lt;/p&gt;

&lt;p&gt;Now since you have this quick overview of the architecture, we can move forward to explore what CQRS is all about.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's dive in
&lt;/h3&gt;

&lt;p&gt;Have you ever experienced having to tweak some part of the logic or models and upon finishing that task you realize that you blew up half of the app? Or have you ever had to fix some bug (created by some other developer of course) and then you go strolling through the codebase searching for some specific part of logic but it’s hard to find because it’s all spaghetti code? Or maybe a load of users on your application has drastically increased and your current machine can’t handle it anymore and the “scale up” button is greyed out because it was so long ago that you already reached a top-level machine and then you think of balancing load with microservices but you do a facepalm because you know how much effort and time it will take to refactor all of that spaghetti?&lt;/p&gt;

&lt;p&gt;That’s what CQRS strives to solve!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ndyiy3lltgpnlq6jp18.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ndyiy3lltgpnlq6jp18.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CQRS stands for &lt;strong&gt;Command Query Responsibility Segregation&lt;/strong&gt; and my initial thought when I was learning this for the first time was: “Well this name doesn’t help very much in understanding this” even though it does when you start understanding the concept behind the name. So the name basically is all there is: &lt;strong&gt;Let’s separate responsibilities of commands &amp;amp; queries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then the next question arises, &lt;strong&gt;“What are commands and queries?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Well, it’s rather simple and I will use CRUD operations as an example.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CREATE, UPDATE,&lt;/strong&gt; and &lt;strong&gt;DELETE&lt;/strong&gt; are methods used to tell the system to insert, change, or remove something. As you’ve probably already figured out, you are giving out &lt;strong&gt;commands&lt;/strong&gt;. While with the &lt;strong&gt;READ&lt;/strong&gt; method you just want to get some data, and yes that’s a &lt;strong&gt;query&lt;/strong&gt;, just like when you query the database.&lt;/p&gt;

&lt;p&gt;Now that we have some basic idea of what CQRS should do, we come to the following question: &lt;em&gt;but how can we use all of this in practice?&lt;/em&gt; Which then brings us to a more specific question - &lt;em&gt;How do I separate these responsibilities?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That’s the next thing we are about to tackle.&lt;/p&gt;

&lt;h3&gt;
  
  
  CQRS in practice
&lt;/h3&gt;

&lt;p&gt;Let’s take a look at how CQRS looks in practice.&lt;/p&gt;

&lt;p&gt;For now, let’s say we have an Application layer with the business logic separated into use cases or rather services. Perhaps you would have a service for forum posts that would contain all of the logic regarding forum posts and may be dependent upon other services. In addition, this service could possibly be reused somewhere else.&lt;/p&gt;

&lt;p&gt;It would look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyl1im1xwp9n9pdvs8gug.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyl1im1xwp9n9pdvs8gug.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There may be issues with this approach down the line when you need to adjust a method in some service to adhere for a second service which could break logic in some other third service where the first service is used. You’ll end up with a headache since you need to adhere to multiple cases and then figure out the way to adjust logic for all these edge cases.&lt;/p&gt;

&lt;p&gt;Or maybe you want to separate the application into microservices until you realize how hard it will be because of the intertwined logic?&lt;/p&gt;

&lt;p&gt;The CQRS pattern solves these problems and has many pros. Of course, nothing is perfect, so the CQRS pattern also has its cons such as not being totally DRY &lt;strong&gt;(Don’t Repeat Yourself)&lt;/strong&gt; and managing it would take a bit more time for some global changes.&lt;/p&gt;

&lt;p&gt;Now let’s see how and why.&lt;/p&gt;

&lt;p&gt;The CQRS structure would look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3fxptsnsjj5cdqyx4deh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3fxptsnsjj5cdqyx4deh.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, every one of these classes has only one responsibility and they aren’t reused. Every single one of them has its own models, even though they might be alike or exact copies of other models. However, programming and project architecture are subjective things so you can combine approaches by having some reusable common things. All of this separation makes it easy for us to find issues and not ruin the rest of the codebase by fiddling with something. As well, it makes it easy to extract microservices from code eventually.&lt;/p&gt;

&lt;h4&gt;
  
  
  Additional Nuggets Used
&lt;/h4&gt;

&lt;p&gt;Check out some additional nuggets I used:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jbogard/MediatR" rel="noopener noreferrer"&gt;MediatR&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Before getting hooked on MediatR, I was really missing out. MediatR is such a handy addition to CQRS and Clean Architecture which makes a developer’s life much easier with how everything is handled independently from each other which you will see later on in this blog. &lt;/p&gt;

&lt;p&gt;I highly recommend checking it out since we are going to use it for our little project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AutoMapper/AutoMapper" rel="noopener noreferrer"&gt;AutoMapper&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;AutoMapper is a tool that makes it easy to do mapping between two objects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/domaindrivendev/Swashbuckle.AspNetCore" rel="noopener noreferrer"&gt;Swashbuckle Swagger&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;No backend application is whole without Swagger. It’s documentation GUI for endpoints and all of its details which are necessary for it to be consumed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enough theory already!
&lt;/h3&gt;

&lt;p&gt;Now before we get into the code, it’s important to keep in mind that even though we could create a Domain layer and some entities, we won’t be using them in this example project.&lt;/p&gt;

&lt;p&gt;As an alternative to creating everything from scratch, you may want to check out this repo before you start reading so you can follow along with all the examples. It’s based on &lt;a href="https://dotnet.microsoft.com/download" rel="noopener noreferrer"&gt;.NET Core 3.1.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first step would be to prepare the project structure by layers as defined per Clean Architecture and then add the additional Nuggets and make sure everything is running properly.&lt;/p&gt;

&lt;p&gt;For the theme of the project, we are going to make a CQRS backend for a forum-like app, but it’s not important because the business logic is not what matters. As well, I used the &lt;a href="https://jsonplaceholder.typicode.com/" rel="noopener noreferrer"&gt;JSONPlaceholder&lt;/a&gt; for obtaining data as a replacement for the database. In addition, the way I decided to go is to create it as an API backend solution.&lt;/p&gt;

&lt;h4&gt;
  
  
  Presentation
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Necessary Nuggets:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Swashbuckle.AspNetCore&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our case, the Presentation layer is the entry point of the application and the two main entry files are &lt;strong&gt;Program.cs&lt;/strong&gt; and &lt;strong&gt;Startup.cs&lt;/strong&gt;. For what we are trying to learn here, we will just need to modify Startup since we define our services there, dependency injection, and request pipeline. Also, in this layer, we have &lt;strong&gt;controllers&lt;/strong&gt; with the primary function to obtain some inputs and trigger our &lt;strong&gt;MediatR&lt;/strong&gt; request pipelines.&lt;/p&gt;

&lt;h4&gt;
  
  
  Startup.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Application;
using Infrastructure;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;

namespace Presentation
{
   public class Startup
   {
       public Startup(IConfiguration configuration)
       {
           Configuration = configuration;
       }

       private IConfiguration Configuration { get; }

       public void ConfigureServices(IServiceCollection services)
       {
           services.AddApplication();
           services.AddInfrastructure(Configuration);
           services.AddControllers();

           services.AddSwaggerGen(config =&amp;gt;
           {
               config.SwaggerDoc("v1", new OpenApiInfo() {Title = "CQRS Forum", Version = "v1"});
           });

           // Make routes globally lowercase.
           services.AddRouting(options =&amp;gt;
           {
               options.LowercaseUrls = true;
               options.LowercaseQueryStrings = true;
           });
       }

       public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
       {
           if (env.IsDevelopment())
           {
               app.UseDeveloperExceptionPage();
           }

           app.UseHttpsRedirection();

           app.UseRouting();

           app.UseAuthorization();

           app.UseEndpoints(endpoints =&amp;gt; { endpoints.MapControllers(); });

           app.UseSwagger();

           app.UseSwaggerUI(config =&amp;gt; config.SwaggerEndpoint("/swagger/v1/swagger.json", "CQRS Forum v1"));
       }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;strong&gt;Startup&lt;/strong&gt;, an important part is adding those dependency injection container methods from the Application and Infrastructure layer named AddApplication() and AddInfrastructure(). I also added the basic Swagger configurations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Controllers/BaseController.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;

namespace Presentation.Controllers
{
   [ApiController]
   [Route("api/[controller]")]
   public class BaseController : ControllerBase
   {
       private IMediator _mediator;

       protected IMediator Mediator =&amp;gt; _mediator ??= HttpContext.RequestServices.GetService&amp;lt;IMediator&amp;gt;();
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The base controller has been created using new C# 8 features so that we follow the DRY principle and keep our controllers as clean as possible.&lt;/p&gt;

&lt;h4&gt;
  
  
  Controllers/PostsController.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.Collections.Generic;
using System.Threading.Tasks;
using Application.Posts.Commands.CreatePost;
using Application.Posts.Queries.GetAllPosts;
using Microsoft.AspNetCore.Mvc;

namespace Presentation.Controllers
{
   public class PostsController : BaseController
   {
       [HttpGet]
       public async Task&amp;lt;ActionResult&amp;lt;IEnumerable&amp;lt;GetAllPostsDto&amp;gt;&amp;gt;&amp;gt; GetAllPosts()
       {
           var response = await Mediator.Send(new GetAllPostsQuery());

           return Ok(response);
       }

       [HttpPost]
       public async Task&amp;lt;ActionResult&amp;lt;CreatePostDto&amp;gt;&amp;gt; CreatePost(CreatePostCommand command)
       {
           var response = await Mediator.Send(command);

           return CreatedAtAction(nameof(CreatePost), response);
       }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we created the base controller with all of its perks we can use it to keep the rest of our controllers simple. As you can see, the traditional way would be to inject some PostsService here and to call its methods. But you can see the difference is that we only send commands or queries as objects to &lt;strong&gt;MediatR&lt;/strong&gt; and it will take care of handling the rest through its pipelines.&lt;/p&gt;

&lt;h4&gt;
  
  
  Application
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Necessary Nuggets:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AutoMapper&lt;/li&gt;
&lt;li&gt;AutoMapper.Extensions.Microsoft.DependencyInjection&lt;/li&gt;
&lt;li&gt;MediatR&lt;/li&gt;
&lt;li&gt;MediatR.Extensions.DependencyInjection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just like on the Infrastructure, the root of the layer contains a DI container and the rest of the folders.This is the place where the &lt;strong&gt;CQRS&lt;/strong&gt; magic happens.&lt;/p&gt;

&lt;p&gt;First, let’s talk about the &lt;strong&gt;Common&lt;/strong&gt; folder. As the name itself says, it is supposed to contain some commonly used stuff. In this particular case, I used it to add helpers for AutoMapper which will help to keep our code clean and located at proper places (for rebinding models) so it would be easier to maintain later down the line.&lt;/p&gt;

&lt;h4&gt;
  
  
  Common/Mappings/IMapFrom.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using AutoMapper;

namespace Application.Common.Mappings
{
   public interface IMapFrom&amp;lt;T&amp;gt;
   {
       void Mapping(Profile profile) =&amp;gt; profile.CreateMap(typeof(T), GetType());
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By inheriting IMapFrom on model we get access to this Mapping function which we can then use to set our transformations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Common/Mappings/MappingProfile.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using System.Linq;
using System.Reflection;
using AutoMapper;

namespace Application.Common.Mappings
{
   public class MappingProfile : Profile
   {
       public MappingProfile()
       {
           ApplyMappingsFromAssembly(Assembly.GetExecutingAssembly());
       }

       private void ApplyMappingsFromAssembly(Assembly assembly)
       {
           var types = assembly.GetExportedTypes()
               .Where(t =&amp;gt; t.GetInterfaces().Any(i =&amp;gt;
                   i.IsGenericType &amp;amp;&amp;amp; i.GetGenericTypeDefinition() == typeof(IMapFrom&amp;lt;&amp;gt;)))
               .ToList();

           foreach (var type in types)
           {
               var instance = Activator.CreateInstance(type);
               var methodInfo = type.GetMethod("Mapping");
               methodInfo?.Invoke(instance, new object[] { this });
           }
       }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now for the main part, the Posts folder. The root contains the interface for PostsApi with the &lt;strong&gt;Commands&lt;/strong&gt; and &lt;strong&gt;Queries&lt;/strong&gt; folders.&lt;/p&gt;

&lt;p&gt;In the next part, we will focus on querying posts.&lt;/p&gt;

&lt;h4&gt;
  
  
  Posts/IPostsApi.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.Collections.Generic;
using System.Threading.Tasks;
using Application.Posts.Commands.CreatePost;
using Application.Posts.Queries.GetAllPosts;

namespace Application.Posts
{
   public interface IPostsApi
   {
       Task&amp;lt;IEnumerable&amp;lt;GetAllPostsResponse&amp;gt;&amp;gt; GetAllPosts();
       Task&amp;lt;CreatePostResponse&amp;gt; CreatePost(CreatePostRequest request);
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Posts/Queries/GetAllPosts/GetAllPostsQuery.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using MediatR;

namespace Application.Posts.Queries.GetAllPosts
{
   public class GetAllPostsQuery : IRequest&amp;lt;IEnumerable&amp;lt;GetAllPostsVm&amp;gt;&amp;gt;
   {
       public class GetAllPostsQueryHandler : IRequestHandler&amp;lt;GetAllPostsQuery, IEnumerable&amp;lt;GetAllPostsVm&amp;gt;&amp;gt;
       {
           private readonly IPostsApi _postsApi;
           private readonly IMapper _mapper;

           public GetAllPostsQueryHandler(IPostsApi postsApi, IMapper mapper)
           {
               _postsApi = postsApi;
               _mapper = mapper;
           }

           public async Task&amp;lt;IEnumerable&amp;lt;GetAllPostsVm&amp;gt;&amp;gt; Handle(GetAllPostsQuery request, CancellationToken cancellationToken)
           {
               var posts = await _postsApi.GetAllPosts();
               return _mapper.Map&amp;lt;IEnumerable&amp;lt;GetAllPostsVm&amp;gt;&amp;gt;(posts);
           }
       }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So as you can see above, there are three main parts when using MediatR. We have a &lt;strong&gt;query&lt;/strong&gt; class, &lt;strong&gt;query handler&lt;/strong&gt; class and &lt;strong&gt;handler&lt;/strong&gt; method. If we were doing a &lt;strong&gt;CREATE&lt;/strong&gt;method, our &lt;strong&gt;query&lt;/strong&gt; class which in that case would be called &lt;strong&gt;command&lt;/strong&gt; would hold all necessary &lt;strong&gt;input properties&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It’s defined as a MediatR class by inheriting the IRequest interface and since it’s of generic nature we have to add a response type to it. If your method is void, then don’t add any return type, but the return type of your handle method would have to be of Task type.&lt;/p&gt;

&lt;p&gt;Handler class is defined by inheriting IRequestHandler and if you return void just omit returnType.&lt;/p&gt;

&lt;p&gt;And finally, we have a &lt;strong&gt;handler method&lt;/strong&gt; which holds the business logic and if it’s supposed to return void it’s &lt;strong&gt;signature&lt;/strong&gt; return type should be defined as Task as said previously and it should be returning Unit.Value.&lt;/p&gt;

&lt;h4&gt;
  
  
  Posts/Queries/GetAllPosts/GetAllPostsResponse.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.Text.Json.Serialization;

namespace Application.Posts.Queries.GetAllPosts
{
   public class GetAllPostsResponse
   {
       [JsonPropertyName("id")]
       public int Id { get; set; }
       [JsonPropertyName("title")]
       public string Title { get; set; }
       [JsonPropertyName("body")]
       public string Body { get; set; }
       [JsonPropertyName("userId")]
       public int UserId { get; set; }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have defined a class that will be serialized as a response from a 3rd party API. We also added data annotations to serve as a guide for System.Text.Json on how it should bind properties.&lt;/p&gt;

&lt;h4&gt;
  
  
  Posts/Queries/GetAllPosts/GetAllPostsDto.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Application.Common.Mappings;
using AutoMapper;

namespace Application.Posts.Queries.GetAllPosts
{
   public class GetAllPostsDto : IMapFrom&amp;lt;GetAllPostsResponse&amp;gt;
   {
       public int UserId { get; set; }
       public int Id { get; set; }
       public string Title { get; set; }
       public string Body { get; set; }

       public void Mapping(Profile profile)
       {
           profile.CreateMap&amp;lt;GetAllPostsResponse, GetAllPostsDto&amp;gt;();
       }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, we see a DTO model that will serve as a view model and in it, we can see the example of using auto mapping from response class.&lt;/p&gt;

&lt;h4&gt;
  
  
  Infrastructure
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Necessary Nuggets:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Microsoft.Extensions.Configuration&lt;/li&gt;
&lt;li&gt;Microsoft.Extensions.DependencyInjection&lt;/li&gt;
&lt;li&gt;Microsoft.Extensions.DependencyInjection.Abstractions&lt;/li&gt;
&lt;li&gt;Microsoft.Extensions.Http&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have created a typed base &lt;strong&gt;HttpClient&lt;/strong&gt; which is inherited by a specific client made for JSONPlaceholder API and did an abstraction of forum posts logic as PostsApi.cs. All of it is added through a DI container which is located on the root of the layer. I tried to keep it as simple as possible while using some best practices. You may wonder, &lt;em&gt;"Why are there so many abstractions for the HTTP client?"&lt;/em&gt; The answer is simple - I’m a .NET developer and I love my abstractions. It also makes code cleaner and more understanding about what it's doing.&lt;/p&gt;

&lt;h4&gt;
  
  
  BaseHttpClient.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace Infrastructure
{
   public class BaseHttpClient
   {
       private readonly HttpClient _httpClient;

       protected BaseHttpClient(HttpClient httpClient)
       {
           _httpClient = httpClient;
       }

       protected async Task&amp;lt;T&amp;gt; Get&amp;lt;T&amp;gt;(string uri)
       {
           var request = CreateRequest(HttpMethod.Get, uri);

           return await ExecuteRequest&amp;lt;T&amp;gt;(request);
       }

       protected async Task&amp;lt;T&amp;gt; Post&amp;lt;T&amp;gt;(string uri, object content)
       {
           var request = CreateRequest(HttpMethod.Post, uri, content);

           return await ExecuteRequest&amp;lt;T&amp;gt;(request);
       }

       private static HttpRequestMessage CreateRequest(HttpMethod httpMethod, string uri, object content = null)
       {
           var request = new HttpRequestMessage(httpMethod, uri);
           if (content == null) return request;

           // Serialize content
           var json = JsonSerializer.Serialize(content);
           request.Content = new StringContent(json, Encoding.UTF8, "application/json");

           return request;
       }

       private async Task&amp;lt;T&amp;gt; ExecuteRequest&amp;lt;T&amp;gt;(HttpRequestMessage request)
       {
           try
           {
               var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
                   .ConfigureAwait(false);
               var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

               response.EnsureSuccessStatusCode();

               return string.IsNullOrEmpty(responseContent) ? default : JsonSerializer.Deserialize&amp;lt;T&amp;gt;(responseContent);
           }
           catch (Exception ex) when (ex is ArgumentNullException ||
                                      ex is InvalidOperationException ||
                                      ex is HttpRequestException ||
                                      ex is JsonException)
           {
               throw new Exception("HttpClient exception", ex);
           }
       }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have implemented a generic base &lt;strong&gt;HttpClient&lt;/strong&gt; which can be further extended with more methods, I will leave it up to you to make the decision of whether you’d like to further extend it or not. The reason why I have decided to do it this way is because of making it simpler to use, making it reusable, and keeping it DRY.&lt;/p&gt;

&lt;h4&gt;
  
  
  JsonPlaceholderApi/JsonPlaceholderClient.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Application.Posts.Commands.CreatePost;
using Application.Posts.Queries.GetAllPosts;

namespace Infrastructure.JsonPlaceholderApi
{
   public class JsonPlaceholderClient : BaseHttpClient
   {
       public JsonPlaceholderClient(HttpClient httpClient) : base(httpClient)
       {

       }

       public async Task&amp;lt;IEnumerable&amp;lt;GetAllPostsResponse&amp;gt;&amp;gt; GetAllPosts()
       {
           return await Get&amp;lt;IEnumerable&amp;lt;GetAllPostsResponse&amp;gt;&amp;gt;(Endpoints.Posts.GetAllPosts);
       }

       public async Task&amp;lt;CreatePostResponse&amp;gt; CreatePost(CreatePostRequest request)
       {
           return await Post&amp;lt;CreatePostResponse&amp;gt;(Endpoints.Posts.CreatePost, request);
       }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the implementation of base HttpClient, we can use it for specific tasks like in our case communicating with JsonPlaceholder API for obtaining a list of posts. Again, since we created the base HttpClient the way we did we can create more of these specific type clients for communication with more than one 3rd party API.&lt;/p&gt;

&lt;h4&gt;
  
  
  JsonPlaceholderApi/PostsApi.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.Collections.Generic;
using System.Threading.Tasks;
using Application.Posts;
using Application.Posts.Commands.CreatePost;
using Application.Posts.Queries.GetAllPosts;

namespace Infrastructure.JsonPlaceholderApi
{
   public class PostsApi : IPostsApi
   {
       private readonly JsonPlaceholderClient _client;

       public PostsApi(JsonPlaceholderClient client)
       {
           _client = client;
       }

       public async Task&amp;lt;IEnumerable&amp;lt;GetAllPostsResponse&amp;gt;&amp;gt; GetAllPosts()
       {
           return await _client.GetAllPosts();
       }

       public async Task&amp;lt;CreatePostResponse&amp;gt; CreatePost(CreatePostRequest request)
       {
           return await _client.CreatePost(request);
       }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have one more abstraction on our way to the HttpClient. &lt;strong&gt;Why?&lt;/strong&gt; Why not combine JsonPlaceholderClient and PostsApi into one class?&lt;/p&gt;

&lt;p&gt;The reason is the instancing of HttpClient primarily and separation. Most of us are used to repository patterns so by somewhat following them we know what this class is about.&lt;/p&gt;

&lt;p&gt;If you want to learn more about issues with instancing HttpClient I suggest you read &lt;a href="https://josef.codes/you-are-probably-still-using-httpclient-wrong-and-it-is-destabilizing-your-software/" rel="noopener noreferrer"&gt;this&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  DependencyInjection.cs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using Application.Posts;
using Infrastructure.JsonPlaceholderApi;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Infrastructure
{
   public static class DependencyInjection
   {
       public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
       {
           services.AddHttpClient&amp;lt;JsonPlaceholderClient&amp;gt;("JsonPlaceholderClient", config =&amp;gt;
           {
               config.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
               config.Timeout = TimeSpan.FromSeconds(30);
           });

           services.AddTransient&amp;lt;IPostsApi, PostsApi&amp;gt;();

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  GitHub Codebase
&lt;/h3&gt;

&lt;p&gt;The entire project can be found &lt;a href="https://github.com/rubiconba/cqrs-with-net-core-mediatr" rel="noopener noreferrer"&gt;HERE&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;After reading this blog, I hope that you’ve gained a better understanding of CQRS and are excited to take on new challenges. Personally, for me, CQRS is the way to go and there is no better way to organize your project, subjectively speaking, until the next new big programming acronym comes around to do bigger and better things. &lt;/p&gt;

&lt;p&gt;Thank you for your patience for going through this with me and I wish you good luck and happy coding!&lt;/p&gt;




&lt;p&gt;Original blog post: &lt;a href="https://www.rubicon-world.com/blog/2020/06/a-developers-guide-to-cqrs-using-net-core-and-mediatr/" rel="noopener noreferrer"&gt;A Developer's Guide to CQRS Using .NET Core and MediatR&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>architecture</category>
      <category>cqrs</category>
      <category>mediatr</category>
    </item>
    <item>
      <title>A Beginner's Guide to Progressive Web Apps (PWA)</title>
      <dc:creator>RUBICON</dc:creator>
      <pubDate>Tue, 31 Aug 2021 10:19:06 +0000</pubDate>
      <link>https://forem.com/rubicon_dev/a-beginner-s-guide-to-progressive-web-apps-pwa-3cf1</link>
      <guid>https://forem.com/rubicon_dev/a-beginner-s-guide-to-progressive-web-apps-pwa-3cf1</guid>
      <description>&lt;p&gt;More and more businesses are realizing the value behind building apps for their products or services. When it comes to developing an app, businesses need to make a choice: do they develop a responsive web app, a native mobile app, a cross-platform, or a hybrid app? Progressive Web Apps are here to save the day and make your decision a lot easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Progressive Web App?
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Progressive Web App (PWA)&lt;/strong&gt; is a web app that uses modern web browser capabilities but looks and behaves like a mobile app across different platforms. Progressive web apps combine the best features of both web and native apps as they are fast, reliable, and engaging.&lt;/p&gt;

&lt;p&gt;In simpler terms, just as Frances Berriman (Designer) and Alex Russell (Engineer) from Google said:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“A PWA is just a website that took all the right vitamins.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;PWAs are a set of principles that make a web app work in a way that allows users to feel like they are using a seamless mobile app. The ultimate goal is for end-users not to be able to differentiate a web app from a mobile app. PWAs bring considerable benefits to both software engineers and businesses as they provide fairly easy development and effective user engagement.&lt;/p&gt;

&lt;h4&gt;
  
  
  Characteristics of a PWA
&lt;/h4&gt;

&lt;p&gt;Progressive web apps are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Progressive - PWAs work on any device and take advantage of any available feature on the user's device and browser.&lt;/li&gt;
&lt;li&gt;Responsive - A PWA’s UI must adapt to any device screen (tablets, laptops, mobile phones, etc.)&lt;/li&gt;
&lt;li&gt;Connectivity Independent - PWAs work in areas of low connectivity or offline.&lt;/li&gt;
&lt;li&gt;App-like - UX design interface that looks/feels like a native app.&lt;/li&gt;
&lt;li&gt;Fresh - When new content is available and the user is connected to the Internet that content will be updated in the app.&lt;/li&gt;
&lt;li&gt;Safe - PWAs are hosted over HTTPS.&lt;/li&gt;
&lt;li&gt;Engaging - Provide available push notifications in the app to encourage users to take action.&lt;/li&gt;
&lt;li&gt;Discoverable - Easily found by typing in the URL or through search engines.&lt;/li&gt;
&lt;li&gt;Installable - Can be easily installed through the browser and behave like a native app afterward.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  How do PWAs work?
&lt;/h4&gt;

&lt;p&gt;Users can visit the PWA like any normal web page. As the user is surfing the web page, they will be greeted with a pop-up, &lt;strong&gt;“Add to Home Screen.”&lt;/strong&gt; The user can also install the PWA directly bookmarking on the browser and adding the app to their home screen with a few taps.&lt;/p&gt;

&lt;p&gt;For example, here is how the platform Pinterest works as a PWA:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3racncohfkffbd3tfhxp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3racncohfkffbd3tfhxp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the user confirms the installation prompt, the “app” will install itself in the background. Once the PWA installs, it is automatically added to the user’s home screen. One single click and it’s now on the user’s phone, no need to enter any sort of App Store to download the app. Once the user opens their app, it looks just like a regular native app:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faaplfdaihxv0k8qmbol0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faaplfdaihxv0k8qmbol0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There you have it, a PWA!&lt;/p&gt;

&lt;p&gt;Now the user is able to use various PWA features such as offline mode, push notifications, open in full-screen mode, self-updates, camera, microphone, and other app-like features.&lt;/p&gt;

&lt;p&gt;One of the most beneficial features of PWAs is that users are able to browse the app offline and the content will still appear on their mobile phones. On the other hand, if the user rejects to install the PWA or clicks to install at a later time, then the web app is still reachable through the browser.&lt;/p&gt;

&lt;p&gt;Now that we’ve covered the basics, let’s move onto the fun stuff - setting up your PWA app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up a PWA
&lt;/h3&gt;

&lt;p&gt;In this blog, we will create a basic PWA that works offline and is installable on the device home screen. Let’s take a look at what it takes to create a basic PWA.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Create a basic web app with create-react-app&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will create a basic web app using create-react-app, which has built-in support for making PWAs. First, enter this command in the console:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx create-react-app simple-react-pwa&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Now you have created a basic react app. You can run it locally using:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd simple-react-pwa&lt;br&gt;
npm start&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Turn your app into a PWA&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To turn your app into a PWA, you need to register the &lt;strong&gt;service worker&lt;/strong&gt; and your app should have a &lt;strong&gt;manifest.json file&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  What is a Service Worker?
&lt;/h4&gt;

&lt;p&gt;A &lt;strong&gt;Service Worker&lt;/strong&gt; is a JavaScript worker that ‘sits’ between your app and the network. Whenever your app talks to the network it will pass through the service worker. On the first app load, the service worker stores the required resources in the browser cache. The next time the user visits your app, the service workers will check the cache and return the response to the user before even checking the network so the user can see the previous fetched content even if they are offline. A Service worker manages the push notifications and helps to build the offline-first web app using the browser’s cache API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open up the index.tsx file in your newly created project, at the bottom of the file you will find this code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// If you want your app to work offline and load faster you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https//bit.ly//CRA-PWA
serviceWorker.unregister().
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make our app a PWA, we need to change the unregister() call to register().&lt;/p&gt;

&lt;h4&gt;
  
  
  What does this mean? What have we achieved?
&lt;/h4&gt;

&lt;p&gt;The official documentation states the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your app will work regardless of network state, even if offline. This means your users will be able to use your app at 10,000 feet (even on the subway).&lt;/li&gt;
&lt;li&gt;On mobile devices, your app can be added directly to the user's home screen with the app’s icon. This eliminates the need for the app store.&lt;/li&gt;
&lt;li&gt;All static site assets are cached so that your page loads fast on subsequent visits, regardless of network connectivity (such as 2G or 3G). Updates are downloaded in the background.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find more information &lt;a href="https://create-react-app.dev/docs/making-a-progressive-web-app/#why-opt-in" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;h4&gt;
  
  
  Manifest.json
&lt;/h4&gt;

&lt;p&gt;What is manifest.json? Why do we need this?&lt;/p&gt;

&lt;p&gt;The manifest.json file is a simple JSON containing some basic information about our PWA like its name, starting URL, icons, etc. In create-react-app, a default manifest file public/manifest.json is automatically included when a new app is built. The HTML file public/index.html, also contains a  element to load the manifest:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;link rel="manifest" href="%PUBLIC_URL%/manifest.json" /&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Having a manifest is required by the browser to show the Add to Home Screen (A2HS) prompt. When a user adds a web app to their home screen using either Chrome or Firefox on Android, the metadata in manifest.json determine what icons, names, and branding colors to use when the web app is displayed.&lt;/p&gt;

&lt;p&gt;Your manifest.json should look 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;{
 "short_name": "React App",
 "name": "Create React Simple",
 "icons": [
   {
     "src": "logo192.png",
     "type": "image/png",
     "sizes": "192x192"
   },
   {
     "src": "logo512.png",
     "type": "image/png",
     "sizes": "512x512"
   }
 ],
 "start_url": ".",
 "display": "standalone",
 "theme_color": "#000000",
 "background_color": "#ffffff"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To verify that our properties are working correctly in this example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a production build with:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;npm run build&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;and run your production build with:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;npx serve build&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open up your dev tools and select Application tab. In the application panel, select the manifest tab and you'll be able to see your PWA information:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkvsvc5z6mbkyt0smd4y.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkvsvc5z6mbkyt0smd4y.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Give your app a name and declare multiple icons.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once we verify that everything is set up, it is time to name your PWA and declare some icons.&lt;/p&gt;

&lt;p&gt;In your manifest.json located in the public folder replace "short_name":"React App" with "short_name":"Simple PWA" and "name":"Create React Simple" with "name":"Simple PWA".&lt;/p&gt;

&lt;p&gt;Also, change your app name in your &lt;strong&gt;index.html&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;title&amp;gt;React App&amp;lt;/title&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;with&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;title&amp;gt;Simple PWA&amp;lt;/title&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Now we should define a set of icons for the browser to use on the home screen, app launcher, splash screen and so on. To do this, first, create a new images folder in the public folder &lt;strong&gt;(public/images)&lt;/strong&gt; and update references to them in &lt;strong&gt;manifest.json&lt;/strong&gt; file.&lt;/p&gt;

&lt;p&gt;After we change our app name and define multiple icons, our manifest.json should look 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;{
 "short_name": "Simple PWA",
 "name": "Simple PWA",
 "icons": [
   {
     "src": "images/simplePwaLogo72.png",
     "type": "image/png",
     "sizes": "72x72"
   },
   {
     "src": "images/simplePwaLogo96.png",
     "type": "image/png",
     "sizes": "96x96"
   },
   {
     "src": "images/simplePwaLogo192.png",
     "type": "image/png",
     "sizes": "192x192"
   },
   {
     "src": "images/simplePwaLogo512.png",
     "type": "image/png",
     "sizes": "512x512"
   }
 ],
 "start_url": ".",
 "display": "standalone",
 "theme_color": "#000000",
 "background_color": "#ffffff"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila! You now have a basic PWA configuration.&lt;/p&gt;

&lt;p&gt;For more information to help you get started with your PWA, check out this &lt;a href="https://create-react-app.dev/docs/making-a-progressive-web-app/" rel="noopener noreferrer"&gt;link&lt;/a&gt;. Good luck building your PWA app!&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Should You Build a PWA?
&lt;/h3&gt;

&lt;p&gt;You’ve learned a bit about PWA, how to build your app and now you may be asking yourself:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Why should I even build a PWA?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here are a few reasons why building a PWA for your business or your client’s business may be the ideal solution:&lt;/p&gt;

&lt;p&gt;Progressive web apps are faster to develop and update&lt;br&gt;
You can have one single codebase for various platforms, not just the two popular platforms (Android &amp;amp; iOS).&lt;/p&gt;

&lt;h4&gt;
  
  
  Cost-Effective
&lt;/h4&gt;

&lt;p&gt;Choosing to build a PWA saves your business money because you get that two-for-one deal. You no longer have to invest in both a native app and a web app, instead, you can just develop a PWA.&lt;/p&gt;

&lt;h4&gt;
  
  
  Uses less data and works offline
&lt;/h4&gt;

&lt;p&gt;PWAs cut data usage which seriously benefits users. They help users save on their data usage (purchasing data can be pricey), save storage on their mobile devices and even access the app when offline. How convenient? All of this is possible due to PWAs being equipped with service workers.&lt;/p&gt;

&lt;h4&gt;
  
  
  Ability to send push notifications
&lt;/h4&gt;

&lt;p&gt;This is another way businesses are able to increase their overall engagement. PWAs allow you to engage with your users by sending them push notifications even when they’re offline. A little reminder can go a long way to encourage users to log into the app or check out a specific feature.&lt;/p&gt;

&lt;h4&gt;
  
  
  Easy installation without download
&lt;/h4&gt;

&lt;p&gt;Progressive web apps require no App Store or installation. From the browser, visitors can bookmark and add the app to their home screen with a few taps. The PWA will show up on the home screen, in their app directory, send notifications, and integrate into system settings.&lt;/p&gt;

&lt;h4&gt;
  
  
  An overall better user experience
&lt;/h4&gt;

&lt;p&gt;A PWA is sure to offer your users a great experience starting with automatically adjusting to the screen size and resolution of any mobile device with the addition of a super-fast loading time. Afterwards, users are offered the option of adding the app to their mobile phone home page and not having to go through a tedious installation process. PWAs offer many favourable perks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;To summarize, here are the things we explored in this blog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What PWAs are&lt;/li&gt;
&lt;li&gt;Characteristics of a PWA
*How PWAs work&lt;/li&gt;
&lt;li&gt;Setting up a PWA&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope you enjoyed this beginner's guide and learned something new about PWAs!&lt;/p&gt;




&lt;p&gt;Original blog post: &lt;a href="https://www.rubicon-world.com/blog/2020/05/a-beginners-guide-to-progressive-web-apps-pwa/" rel="noopener noreferrer"&gt;A Beginner's Guide to Progressive Web Apps (PWA)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webapp</category>
      <category>webdev</category>
      <category>guide</category>
    </item>
    <item>
      <title>Remote Workshop 101</title>
      <dc:creator>RUBICON</dc:creator>
      <pubDate>Tue, 31 Aug 2021 09:42:27 +0000</pubDate>
      <link>https://forem.com/rubicon_dev/remote-workshop-101-2524</link>
      <guid>https://forem.com/rubicon_dev/remote-workshop-101-2524</guid>
      <description>&lt;p&gt;Our team coordinates lean inception workshops and in mid-March, we were supposed to travel and organize one. So as the facilitator, I re-read all the books, made the schedule for 3 days (yes, you can do it in 3), packed the felt pens, post-its, papers, posters, the whole shebang. And then COVID-19 took the world by storm. So we decided to have a remote workshop, with two co-located teams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gkco0mNN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cjquxrofelly02iho9ek.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gkco0mNN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cjquxrofelly02iho9ek.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few days later, half of RUBICON’s team was in self-isolation. The day before the workshop, our clients were in #stayhome mode as well. So the final plan was for everyone to check in from home. That meant 11 participants in a 7-hour call for 3 days, each with their own set of special circumstances due to the pandemic. So not quite as planned.&lt;/p&gt;

&lt;p&gt;For those of you unfamiliar with the process behind lean inception, it heavily relies on individual and group exercises. They involve writing, walking, presenting - a lot of things that are generally connected with being physically present in a room. So there were quite a few things that could go wrong if you decide to apply the same recipe in a virtual environment. The thing is, our team already knows the recipe is never the same, even in fully co-located workshops. There is always improvisation. So we adapt. We remove some of the activities and add others based on the type of issue we’re facing.&lt;/p&gt;

&lt;p&gt;Since most of us around the world are in #stayhome mode during COVID-19 and will be left with no choice but to work remotely, here are some tips for facilitating, regardless of the type of workshop:&lt;/p&gt;

&lt;h3&gt;
  
  
  Before the Workshop
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Adopt a digital-first mindset
&lt;/h4&gt;

&lt;p&gt;This guide to facilitating remote workshops by the MURAL team is excellent, which is why I will not go into a lot of detail - they say it all. Read it and then read it again. It might seem overwhelming, but keep in mind that not everything will be applicable to your workshop. You need to adjust your activities depending on the type of your workshop. For example, for lean inception, you want to abandon all activities that break into small groups. Make them an individual effort instead.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pay attention to the audio setup
&lt;/h4&gt;

&lt;p&gt;All the participants need to have a quality headset and/or microphone. &lt;strong&gt;Keep in mind that if your audio fails, everything fails - we cannot stress this enough.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Choose your means of communication
&lt;/h4&gt;

&lt;p&gt;Some companies have strict rules about the communication tools they use. You need to check with your clients and find one that suits everyone. Pro tip? Try to choose one that offers live captions. Google Hangouts Meet, Skype, and Microsoft Teams all have that option. We tested them on Google Meet and they work like a charm. Even if a participant’s audio comes back scrambled, the captions have a high degree of accuracy. It decreases the amount of times you need to say “I’m sorry, could you repeat that?”&lt;/p&gt;

&lt;h4&gt;
  
  
  Record the sessions
&lt;/h4&gt;

&lt;p&gt;This has proven to be very useful for us in the past. Sometimes the discussions get very technical and it is difficult to keep track of everything. Later on, you can go back to the recording and check. Most of the communication tools have a built-in option to record the session. If yours doesn’t, you can always use an external app to do it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Choose a visual collaboration tool
&lt;/h4&gt;

&lt;p&gt;In a co-located meeting, you use a wall, a flipchart and post-its to visualize your progress. Visual output is powerful and there is no replacing it - so how do we do it digitally?&lt;/p&gt;

&lt;p&gt;Tool overload is a real issue. We use so many tools on a daily basis that having to learn how to use a new one can be overwhelming, especially for your clients. Our choice? Miro - online whiteboard for visual collaboration. We chose it because it has a short learning curve, a simple UX/UI, and a set of powerful features to help you facilitate. You can integrate it with a lot of the tools you’re already using (Google Drive, Jira, Slack, InVision etc.). And it’s actually fun to use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QoHK6P19--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vs2c8jajdlldbm5t850l.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QoHK6P19--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vs2c8jajdlldbm5t850l.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feel free to check out our Miro board &lt;a href="https://miro.com/miroverse/profile/rubicon"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Test, test, test
&lt;/h4&gt;

&lt;p&gt;Before you begin with the workshop, you need to test everything. Set up a call with your team to test how the collaboration will work and see if there are any unknowns. You cannot start your workshop without being aware of how your tools work and interact. Make sure you’ve given access to all tools for all participants.&lt;/p&gt;

&lt;h4&gt;
  
  
  Explain
&lt;/h4&gt;

&lt;p&gt;Once you have chosen all your tools, you need to walk your participants through the ins and outs. Send them an email a couple of days before the workshop with all the necessary information:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Schedule&lt;/strong&gt; - incorporate hour lunch breaks as you would in a co-located meeting. Send invites for all the days of the workshop to all participants with links to join the conversation. &lt;strong&gt;Additional tip:&lt;/strong&gt; have two schedules. One with general morning-afternoon time slots for everyone, and a very detailed one just for you. People tend to worry if they see you’re breaking the schedule, but you always have to have space for improvisation and unexpected time management.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.Audio directions&lt;/strong&gt; - tell everyone they need to have quality devices in place. Ask participants if it is OK to record the workshop, as those recordings will be useful later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.Doodling&lt;/strong&gt; - tell your participants they should have paper and pens with them. Even in digital form, you can always benefit from this. You might not end up using them, but keep them as a backup option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.Tools&lt;/strong&gt; - explain all the tools you will be using and send necessary tutorials. Tell your participants that you, the facilitator, are responsible for the visual board, but they should familiarize themselves with how it works. It will improve the flow of your workshop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.Reassurance&lt;/strong&gt; - let everyone know that you will go through the basic communication rules and the workflow first thing when you start your workshop. You cannot explain everything in an email. It is a lot better to set these ground rules at the beginning of the workshop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Starting the Workshop
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Set the rules
&lt;/h4&gt;

&lt;p&gt;Let everyone know that respectful communication is key. There will be interruptions because of a lack of visual cues. You all need to accept that without being annoyed. Body language accounts for a lot in co-located meetings. Work together to bridge that impediment.&lt;/p&gt;

&lt;p&gt;Some basic rules are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;If you are not speaking, you should keep your microphone muted to avoid excess noise. This will take a bit of getting used to and a lot of reminders during the first day.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you need to leave the meeting room, please let everyone know through chat when you leave and when you will be back.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the live captions feature (if offered by your communication tool of choice).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remind the participants that you will be recording the session. Also, don’t forget to click the record button.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go through the schedule and give a brief explanation of all the activities and what the end result will be.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Get to know each other
&lt;/h4&gt;

&lt;p&gt;I’m not a fan of ice breakers. It’s a subjective attitude, but they all seem to be designed to make people uncomfortable. That being said, it is necessary for everyone to turn on their camera and introduce themselves. It creates a connection between participants and puts a face to a voice. It would be great to keep the cameras on during the workshop, but sometimes it creates technical issues. You can try to turn them on and decide whether to keep them on when you see how it works.&lt;/p&gt;

&lt;h3&gt;
  
  
  During the Workshop
&lt;/h3&gt;

&lt;p&gt;This is where you start with the first activity. Regardless of the type of workshop you’re running, here are some things to keep in mind during remote facilitating:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Keep track of time as you normally would. You still have a number of activities to go through, so use your timer and make sure everyone knows how much time they have.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As your workshop progresses, do a small recap of the previous day in the morning, just to warm everybody up and get them to focus on the task at hand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s important for all your participants to contribute, but it might be difficult for some of them to share in a remote setting. If you feel that you haven’t heard from someone in a while, call on them giving them some space to be heard.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep track of the conversation and if it sounds as if you’re getting off track, feel free to politely interrupt and say “Maybe we can park this discussion for now and get back to it later?” Don’t be embarrassed if you have to do this often - it’s a normal part of the process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explain all your activities in detail, possibly with examples of how they should be done. If necessary explain things again and again, until all the participants understand the goal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;...and finally, as COVID-19 is a special circumstance and your participants are probably very worried and under a lot of stress, check in with them. Ask them how they’re doing, and give them space to voice their concerns. Be supportive and understanding if they need to drop out of the conversation because their kids or their pets need them. When they come back, send them a message to explain your progress and where you are now.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hopefully, this gives you some idea about all the bases you need to cover. The process is demanding, but you can get excellent results as long as everyone is respectful - and as long as your audio works. Cannot stress that enough.&lt;/p&gt;

&lt;p&gt;Best of luck!&lt;/p&gt;




&lt;p&gt;Original blog post: &lt;a href="https://www.rubicon-world.com/blog/2020/04/remote-workshop-101/"&gt;Remote Workshop 101&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>leaninception</category>
      <category>collaboration</category>
      <category>workshop</category>
    </item>
    <item>
      <title>7 Tips for Working From Home</title>
      <dc:creator>RUBICON</dc:creator>
      <pubDate>Tue, 31 Aug 2021 09:25:22 +0000</pubDate>
      <link>https://forem.com/rubicon_dev/7-tips-for-working-from-home-4oe6</link>
      <guid>https://forem.com/rubicon_dev/7-tips-for-working-from-home-4oe6</guid>
      <description>&lt;p&gt;During this time, it is important for all of us, no matter where we live to stay at home in order to keep ourselves and our loved ones safe. Like many companies worldwide, our team has decided to indefinitely switch to remote work so we can &lt;a href="https://twitter.com/hashtag/FlattenTheCurve?src=hashtag_click"&gt;#flattenthecurve&lt;/a&gt; and &lt;a href="https://twitter.com/hashtag/stayhome"&gt;#stayhome&lt;/a&gt; meanwhile continuing to offer our clients the best service possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  How can you make WFH manageable and productive?
&lt;/h3&gt;

&lt;p&gt;Since our team is already experienced in working from home a few times a month, we would like to share a few tips with you to help you get through this difficult period:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Prepare for your productive workday.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Start off your day with your usual morning routine. Wake up early, shower, get your coffee brewing, and breakfast ready. Consider getting some fresh air and taking a walk outside to boost your mood. Take the time you would usually spend commuting to work and make your morning enjoyable.&lt;/p&gt;

&lt;p&gt;Afterward, you can start planning the rest of your day. Build a schedule around the times you know when you’re most productive and fill out the rest with breaks. Having a to-do list also makes sure you always have something to work on and helps you keep organized.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“After almost two weeks from home, I now understand that it is really important to have the same routine of getting ready for work. Continue doing the same morning activities like drinking coffee, working out, or meditating before work”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Always make sure you have enough coffee on the table.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“I get up from bed, stretch, grab some water, prepare my breakfast (usually fruit, oatmeal, vitamins, and coffee), and check out my to-do list for the day.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Create your own home office.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Get your ideal set-up ready to make yourself feel comfortable. Find a quiet area in your home away from distractions, preferably close to a window with some natural light where you can set up your table, work chair, laptop, and possibly monitor. Adjust your chair and desk to the proper height, and organize the rest of your equipment so you can have your own &lt;a href="https://www.rubicon-world.com/blog/2019/06/a-developers-guide-to-proper-desk-sitting/"&gt;ergonomic environment&lt;/a&gt; at home. By having a proper home office area, you’ll create a place where you’ll keep both productive and healthy.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“I’ve created my own workroom equipped with a desk, chair, lamp, pinboard, sticky notes, markers and pens, and of course my laptop.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“I like switching between my comfortable couch and the kitchen table.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aO58CzAT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l8kkvpio21v1f37o8l0i.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aO58CzAT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l8kkvpio21v1f37o8l0i.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Communicate more than ever.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Thanks to great technology, there are many ways to keep our communication clear and effective when working remotely. Tools such as &lt;a href="https://slack.com/intl/en-ba/lp/three?utm_medium=ppc&amp;amp;utm_source=google&amp;amp;utm_campaign=d_ppc_google_western-europe_en_brand-hv&amp;amp;utm_term=slack&amp;amp;ds_rl=1249094&amp;amp;gclid=EAIaIQobChMI4YO28Ku16AIVjRnTCh3uOwQjEAAYASAAEgKqdPD_BwE&amp;amp;gclsrc=aw.ds"&gt;Slack&lt;/a&gt; and &lt;a href="https://gsuite.google.com/products/chat/"&gt;Google Hangouts&lt;/a&gt; allow us the opportunity to instant message and call so we can easily run demos, daily stand-ups, and stay in touch with our team members. Aside from being able to call and message, Slack also offers the option of setting employee statuses. Heading out to run an errand? Or in a meeting? No problem, set your status to let the rest of the team know what you’re up to.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“I keep my Slack notifications on. And I always begin my morning by having a remote coffee with my team.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Be available all the time (except when in meetings), on multiple communication tools. Sync regularly. Secure a strong internet connection.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Most of the time it's easier to video call someone and explain the issue than to go back and forth through chat.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Establish new rules for meetings.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It can get a bit challenging being a part of a meeting with more than two people as it becomes difficult to control who is speaking. In addition, not everyone will always have a stable internet connection or be working in a quiet environment. That’s why it’s a good idea to put speaking rules in place, keep your meetings small, and regularly check your equipment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“The most important part is that everyone needs to be very respectful. People should turn their mics off when they're not talking so they don’t cause excessive noise. They need to be prepared to be interrupted as it is sometimes difficult to get visual cues from other participants when they want to speak. Meetings need to have a moderator to keep things under control and going in the proper direction. Everyone needs to use quality headsets and/or microphones to get their message across, these devices are very important. Certain activities need to be timed and everything collaborative has to be properly explained.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Somebody taking charge of the meeting helps keep things on point.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"A strong internet connection, audio support and/or equipment, focus, and empathy."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Take breaks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Breaks are essential for refreshing your mind and body. Go for a walk outside, take a nap, do an at-home workout or really anything that makes you feel better when you stay away from your work. We suggest you take a 10-minute break every hour instead of taking one long break for utmost productivity.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“I do some sort of workout challenge. Plank challenge is the choice of the month.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Go for a walk, do some laundry. If it is a meal break there is always a meal time video in the background. Also, if you don't know what to watch while you eat, there is even a subreddit for that: &lt;a href="https://www.reddit.com/r/mealtimevideos/"&gt;r/mealtimevideos&lt;/a&gt;”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Preparing food, taking a nap and playing video games. It is important to go into another area or room so you actually feel like you’re on a break and away from your work.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Eat healthier.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that you’re at home and you have full access to your kitchen, you may as well make good use of it. Take the opportunity to make healthy meals and snacks to promote good health and productivity.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Making a meal really makes me excited these days, it is something I look forward to. I try to get creative with everything I already have in my fridge so that I don't go out on a whim. I try to eat balanced meals. Every meal should have some vegetables, carbs, protein, and most importantly be very tasty. Taste is definitely a priority. For easy and fast meals, there is the &lt;a href="https://www.instagram.com/buzzfeedtasty/"&gt;Tasty Instagram account&lt;/a&gt; with lots of short video recipes, you don't have to follow them to a T as you can always improvise.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Lots of Vitamin D!”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ujUndn7B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4bru6hccdtik070hbaai.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ujUndn7B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4bru6hccdtik070hbaai.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Stay connected and laugh.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Maintain those fun moments and close relationships you’ve developed inside the office. Take the time to message or call your colleagues to catch up and see how they are doing and take part in non-work banter because trust me, you’ll miss working closely with your colleagues after a few days.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“I miss the feeling of being a part of a community and having the team physically there.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“I miss hanging out in person with my co-workers, exchanging stories and making jokes.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;RUBICON wishes you a happy WFH experience! &lt;a href="https://twitter.com/hashtag/staysafe?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Ehashtag"&gt;#staysafe&lt;/a&gt; and &lt;a href="https://twitter.com/hashtag/staystrong?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Ehashtag"&gt;#staystrong&lt;/a&gt; !&lt;/p&gt;




&lt;p&gt;Original blog post: &lt;a href="https://www.rubicon-world.com/blog/2020/03/rubicons-7-tips-for-working-from-home/"&gt;RUBICON's 7 Tips for Working From Home&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>culture</category>
      <category>workstations</category>
      <category>wfh</category>
    </item>
    <item>
      <title>How to Work Well Together: Designer and Developer Collaboration</title>
      <dc:creator>RUBICON</dc:creator>
      <pubDate>Mon, 30 Aug 2021 14:33:12 +0000</pubDate>
      <link>https://forem.com/rubicon_dev/how-to-work-well-together-designer-and-developer-collaboration-4ab</link>
      <guid>https://forem.com/rubicon_dev/how-to-work-well-together-designer-and-developer-collaboration-4ab</guid>
      <description>&lt;p&gt;A healthy designer-developer collaboration is one of the key ingredients in a software development recipe. A UX/UI designer’s job is to create the visual look and feel concept of the product and for the developer to bring the design to life. Even though the two of them come from rather different domains, they both love to analyze and creatively solve problems. When this cross-functional duo collaborates effectively, they can achieve the impossible and build awesome products in the sphere of software development!&lt;/p&gt;

&lt;h3&gt;
  
  
  Software Project Roles
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Software Developer’s&lt;/strong&gt; responsibility is to write and implement efficient code needed for the end product. Developers write and test the code, which is later used to assemble the software application.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;UX/UI Designer&lt;/strong&gt; creates a user experience by focusing on both the UX and UI of the product. &lt;strong&gt;UX&lt;/strong&gt; is how something works and how a person interacts with it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UI (User Interface)&lt;/strong&gt; focuses on the look and layout of the product. The role of the designer is to create a guided path for the person making the product both user-friendly and visually appealing.&lt;/p&gt;

&lt;p&gt;When the two co-create, the developer takes care of the core structure of the product while the designer creates the look and feel. It sounds simple, but in many instances, the team encounters challenges when trying to set up an &lt;strong&gt;effective workflow&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1mWiJsaD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/61roy0ymn6y2pr82l2ve.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1mWiJsaD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/61roy0ymn6y2pr82l2ve.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At RUBICON, we've experienced many challenges when developing our effective workflow. Luckily, we're here to openly share our challenges and offer some firsthand tips on how to build effective collaboration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Designer-Developer Collaboration Challenges
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Lack of domain knowledge&lt;/strong&gt;&lt;br&gt;
Designers spend their workday coming up with ideas and playing around with pixels; while, developers solve problems, explore new technology and write lines of code. Often, there is a bridge between the two domains as one lacks tech knowledge and the other doesn't have much knowledge about design and UX. But what about when the designer and developer need to cross paths?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Communication&lt;/strong&gt;&lt;br&gt;
In most software development teams, miscommunication is the most frequent challenge. For example, many teams experience poor communication during the design to development phase. A designer will create a design handoff and pass it onto the developer to implement it into the product. In the end, once the developer is finished implementing the design, it sometimes may not look the exact same way the designer imagined it to be. This can be frustrating for the entire team.&lt;/p&gt;

&lt;p&gt;When situations like this happen, the workflow gets slower, products do not reach their intended or full potential, sprint goals are not met and even sprints end up failing - all of this can happen due to poor communication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nG3_sLWr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/okhagda6cekbzks6299l.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nG3_sLWr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/okhagda6cekbzks6299l.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Framework restrictions&lt;/strong&gt;&lt;br&gt;
Sometimes the designer will create a fancy, cool design, but unfortunately, they may not be aware of some aspects which simply can’t be done due to framework limitations. One thing that designers should be aware of is that every framework, every OS and every piece of hardware has a software developer behind it. That being said, the possibilities of what a certain framework is capable of hardly relies on what framework the developer decides to implement and provide to the designer. The following reasons may cause restrictions on what a framework can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security issues&lt;/li&gt;
&lt;li&gt;Performance issues&lt;/li&gt;
&lt;li&gt;Insufficient time to plan a feature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we take Android OS for an example, before the API21 (framework version), users weren't able to change the status bar's background colour. It is believed that the reason behind this was due to a performance issue as the hardware at that point was considerably slow. In the API21 version, developers have been granted the ability to change the background colour of the status bar but are still prevented from doing the same for Pre-API21 devices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. UI design often suffers&lt;/strong&gt;&lt;br&gt;
When designers encounter technical barriers and deadlines, it becomes difficult for them to bring their ideas to life, and often they have to compromise with developers. Of course, this has to do with the project and the entire team itself, but as far as the design-development process is concerned, it is not unusual that developers have an aversion to complex UI solutions and custom components. Most developers aren’t as passionate about UX and design as designers. Therefore, an initial fancy idea for a design will oftentimes need to become simplified to meet product needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Differences in time estimation&lt;/strong&gt;&lt;br&gt;
Designing something stunning truly does take time and many elements need to be considered: user experience, layout, user interface, aesthetics and more. Designers will take their time creating the design but sometimes they will underestimate how long it will take the developer to implement their design into the final product. As a result, it will take longer than intended for the design to be engineered and the team may miss a deadline.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;On the other hand, a small change may not be that small.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The team might even overlook the amount of time it takes a developer to implement a feature or a designer to make a change in design. When something needs to be changed, it might take longer than expected. A small change isn’t just pasting a code, or changing the colour of a feature, there are more steps required to make some of these changes. Communication is key when making changes in the product or design so the timeline of the development project doesn’t suffer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Individual goals&lt;/strong&gt;&lt;br&gt;
When it comes to creating a successful end product, the two domains have different goals. For a designer, the main goal is to create a visually appealing product and a smooth &lt;strong&gt;user experience&lt;/strong&gt;. While developers think about the technical aspects and using the latest technologies to make a fast and secure product.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips for A Successful Designer-Developer Collaboration
&lt;/h3&gt;

&lt;p&gt;You’re better off together. Check out some tips on how any organization can create a harmonious work setting between developers and designers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E5Yyjv2i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uzdzxbu2s9sljikw7b37.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E5Yyjv2i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uzdzxbu2s9sljikw7b37.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Learn and Educate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don't be afraid to blur the lines between the two fields.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you’re a designer, spend some time learning a programming language or understanding the basic principles behind a framework such as iOS, Android, React or Vue. If you’re a programmer, become familiar with basic design principles and explore the tools the designer is using. Be open to helping each other learn about your expertise and sharing information. Growing familiar with both technology and design principles can really benefit workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. User is #1&lt;/strong&gt;&lt;br&gt;
Place the user you’re building the product for on a pedestal. Remember, the product is being built for the user. A better user experience should be the primary goal for both developers and designers and that’s what each team member should focus on when building the product. Questions such as “How will the user use this product?” should be asked. All development and design decisions should revolve around the user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Use the right tools&lt;/strong&gt;&lt;br&gt;
Using the right tools can take your team a long way and make everyone’s life a whole lot easier. These tools can help you maintain seamless communication and a product workflow making everything more productive. Using tools such as &lt;a href="https://slack.com/intl/en-ba/"&gt;Slack&lt;/a&gt; for instant messaging, &lt;a href="https://www.atlassian.com/software/jira"&gt;Jira&lt;/a&gt; or &lt;a href="https://azure.microsoft.com/en-us/services/devops/"&gt;Azure&lt;/a&gt; for tracking tickets and keeping organised, and &lt;a href="https://www.figma.com/"&gt;Figma&lt;/a&gt; for prototyping design are recommended to help your team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Blank paper and whiteboards may not be as exciting but they certainly do help people communicate their ideas clearly and visually.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Communicate, communicate, and communicate&lt;/strong&gt;&lt;br&gt;
The two roles should communicate effectively from the start of the project to the finish. Clearly explaining ideas, handing over easy-to-understand instructions and always being on the same page ensures effective communication. Attending daily scrum meetings, sprint plannings, and sprint retrospective meetings keeps the entire team in the loop and gives everyone the opportunity for a time and place to communicate their thoughts.&lt;/p&gt;

&lt;p&gt;Creating a work environment for your team where everyone is able to freely express their opinions and ideas allows for a place where new ideas can come to life and the best possible products can be made. This is especially true for teams that use Agile where constant changes are implemented and feedback is always welcome in order to build the best product possible. Behind open-communication lies fairness, trust and respect where all ideas are equally valued and open for discussion. Developers and designers need to build trust and feel comfortable when working with one another. This is the most important factor for healthy collaboration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Designer + Developer = The Ultimate Product
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Iv3EBc9P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eqcjksnuqg9fhfqad2gi.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Iv3EBc9P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eqcjksnuqg9fhfqad2gi.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your team can add these helpful tips to your software development recipe in order to establish a successful designer-developer team and build a great product for your customer. Communicate clearly, be willing to compromise, value your team members and put yourself in the other person's shoes.&lt;/p&gt;

&lt;p&gt;It all comes down to these key messages for a healthy collaboration, you’ll not only gain a steady workflow but you’ll also build better products for your clients.&lt;/p&gt;




&lt;p&gt;Original blog post: &lt;a href="https://www.rubicon-world.com/blog/2020/02/how-to-work-well-together-designer-and-developer-collaboration/"&gt;How to Work Well Together: Designer and Developer Collaboration&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ux</category>
      <category>design</category>
      <category>culture</category>
    </item>
    <item>
      <title>A Journey Through Quality Assurance Testing</title>
      <dc:creator>RUBICON</dc:creator>
      <pubDate>Mon, 30 Aug 2021 11:10:43 +0000</pubDate>
      <link>https://forem.com/rubicon_dev/a-journey-through-quality-assurance-testing-4fin</link>
      <guid>https://forem.com/rubicon_dev/a-journey-through-quality-assurance-testing-4fin</guid>
      <description>&lt;p&gt;A while ago, I found myself roaming the new and strange waters of Quality Assurance. Writing tests is a part of the development process, so no matter what technologies are used, sooner or later you learn that testing your code is necessary. While working on Front End, I had to learn really quickly that, &lt;strong&gt;“Testing shows the presence, not the absence of bugs.”&lt;/strong&gt; This really got me wondering just how important my role as a QA is in assuring quality and does it rely solely upon me and the QA team to make sure everything works?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Quality is achieved by putting development and testing into a blender and mixing them until one is indistinguishable from the other.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;-&lt;em&gt;How Google Tests Software&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Developers vs Testers
&lt;/h3&gt;

&lt;p&gt;Let us start by introducing our key players in the game called &lt;strong&gt;“The Software Development Process.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For this game, we will be focusing on two players of the game (the developer and the tester), even though the roles and responsibilities behind each software development project range far and wide and there are many more key stakeholders than just two. Meet the two players:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YtGTcShb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h3rr6c1nsc5vv5docy6v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YtGTcShb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h3rr6c1nsc5vv5docy6v.png" alt="Alt Text" title="Players"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Player #1:&lt;/strong&gt; The Developer aka the Problem Solver. Developers are the ones building things, putting the pieces together and working out the logic that connects everything and drives the software in the background.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Player #2:&lt;/strong&gt; The Tester aka The Critical Thinker. Testers are all about analysis. Once the developers build the product, the tester takes it apart and inspects it piece by piece.&lt;/p&gt;

&lt;p&gt;The fundamental difference between testers and developers is in the process. The developer synthesizes the code into a product and the tester analyses it. Both testers and developers like figuring out how things work, but the difference is where the developer is focused on putting things together to make them work in a certain way and the tester is focused on taking things apart to find out all those unintended consequences. Testers and developers are the yin and yang of the development world.&lt;/p&gt;

&lt;h4&gt;
  
  
  Set-Up: Quality and the Importance of Testing
&lt;/h4&gt;

&lt;p&gt;The goal behind software testing is to check whether or not the tested software system is defect-free. It is a process that evaluates the functionality of the software and it matches the expected result or behaviour with the actual one. Software testing is used as an objective source of information about the quality of developed software. In software project management, the process of checking whether a software system meets its required specifications and that it fulfils its intended purpose is called &lt;strong&gt;verification and validation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Verification and validation, or simply software quality control, is a part of the software development lifecycle. We use verification to ask the following questions: &lt;strong&gt;"Are we building the software in the right way?"&lt;/strong&gt; and &lt;strong&gt;"Are we correctly implementing specifications in our system?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Validation, on the other hand, asks questions such as: &lt;strong&gt;"Is the right software being built?"&lt;/strong&gt; and &lt;strong&gt;"Does the system that we are building match users' needs?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To verify and validate software we use &lt;strong&gt;test cases&lt;/strong&gt;. A test case is a detailed test instruction that defines the inputs, procedures, execution conditions and the expected result of a test. A collection of test cases intended to be used to test the software system is called a &lt;strong&gt;test suite&lt;/strong&gt;. A test suite groups together similar test cases as they grow and expand according to an already determined &lt;strong&gt;test plan&lt;/strong&gt;. A test plan is a detailed understanding of objectives, resources, and processes needed to test the system, therefore a good test plan is crucial to the development process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level up: Unit and Integration Testing
&lt;/h3&gt;

&lt;p&gt;When defining testing, we must acknowledge that there are different levels of testing. Tests are grouped into levels depending on what is the focus of the test case and the specificity that the test case covers. They are also defined by when the particular test is added to the SDLC. There are four levels of testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unit testing&lt;/li&gt;
&lt;li&gt;Integration testing&lt;/li&gt;
&lt;li&gt;System testing&lt;/li&gt;
&lt;li&gt;Acceptance testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Unit testing&lt;/strong&gt; focuses on the smallest testable part of any software, such as modules, classes, and components. Unit testing isolates units of code from the rest of the application and tests them individually and independently. Unit testing is done by developers as they work on the app.&lt;/p&gt;

&lt;p&gt;The goal behind &lt;strong&gt;integration testing&lt;/strong&gt; is to find defects in the interaction between two or more integrated components. Integration testing makes sure that units work together in cohesion forming whatever functionalities we need. Integration testing is mainly done by quality assurance engineers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System testing&lt;/strong&gt; is performed on a complete and fully integrated system. It is a black-box testing technique which means it doesn’t concern itself with the inner workings of the system, just that it is compliant with its specified requirements.&lt;/p&gt;

&lt;p&gt;The purpose behind &lt;strong&gt;acceptance testing&lt;/strong&gt; is to evaluate that the system does not differ from the business requirements and assess whether it is acceptable for delivery. It is done pre-release and sometimes it is called Operational acceptance testing (OAT). OAT tests security vulnerabilities, recovery procedures, functional stability, supportability and reliability of the app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Press Play for TDD aka Test Driven Development
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Test-Driven Development&lt;/strong&gt; is a methodology of developing software in a manner that expects you to first consider the requirements for the code that you are about to write. Also, instead of writing the logic right away, the developer would first write the tests. TDD starts with writing a unit test before writing any code. This test would first fail and then the developer would write just enough code so that the tests would pass. Next comes refactoring and improving the code. To explain TDD, we often use the &lt;strong&gt;Red-Green-Refactor&lt;/strong&gt; scheme that indicates that the purpose of TDD isn’t only in test coverage but also in safely refactoring your code, not fearing change and merge. The following diagram displays the Red-Green-Refactor pattern:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--23FyrLCN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2tev4fo6cj6mtdvuzyqp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--23FyrLCN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2tev4fo6cj6mtdvuzyqp.png" alt="Alt Text" title="Red-Green-Refactor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most developers find TDD unnecessary and a waste of time but what “Red, Green, Refactor” means is that at any randomly chosen time in the development process, unit tests are there to make sure that all of your code works. Unit tests increase code coverage but most importantly ensure that the software is tested in-depth since they serve as a guarantee that all of the pieces that make your code tick are doing what they are supposed to be doing.&lt;/p&gt;

&lt;p&gt;In a continuous integration environment, unit tests should run every time you commit a change to the source code repository and they should also be run on the development machine as well. Let’s take for example an app component like email input. This input should adhere to certain rules. Maybe it should display an error message if the input was left empty, or if the string was not a valid email address. These would be two test cases that the unit test should cover. Using the TDD approach, the developer would first write these unit tests, run them so they fail, then write the component code to satisfy the test expectations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Press Play for BDD aka Behaviour Driven Development
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Behaviour Driven Development&lt;/strong&gt; has the goal of bridging the gap between business and IT. BDD puts the development focus on the behaviour of the app, or the feature that you are making. In BDD, assertions and making sure that something exists or that two values are equal are merely one aspect of behaviour testing. Scenarios for these tests, on the other hand, are full software specifications and can also serve as living documentation for the application. Behaviour scenarios show how the app is supposed to function in a humanly readable manner, thanks to Gherkin.&lt;/p&gt;

&lt;p&gt;What is &lt;strong&gt;Gherkin&lt;/strong&gt;? Gherkin is a business readable, domain-specific language used specifically for behaviour descriptions of app features. Using abstractions, it removes logic details from behaviour tests. Gherkin is designed to be easy to read by non-programmers and uses the &lt;strong&gt;Given-When-Then&lt;/strong&gt; step structure to illustrate how a feature should behave once it is presented to the end-user.&lt;/p&gt;

&lt;p&gt;While TDD focuses on how a single functionality or unit is implemented, BDD focuses on integrating these functionalities into behavior from the end-users perspective. Similar to the email input unit test example, the BDD approach would expand the test case to define a complete feature scenario, for example, an entire log in check.&lt;/p&gt;

&lt;p&gt;Gherkin scenario for log in behaviour:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Given user is on the log in page 
When user enters “email@gmail.com” as email address
And user enters “password” as password
And user click on the "Login" button
Then user should login successfully.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or to add even more abstraction since whoever is reading it shouldn’t be concerned with what the login steps entail, just that they are executed successfully:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Given user is on the log in page 
When user logs in
Then user should login successfully.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Final Score
&lt;/h3&gt;

&lt;p&gt;Among testing trends, there seems to be a crucial shift towards the beginning of the software development cycle. This allows us to find issues earlier in the process and to fix them. Shifting testing towards the beginning relies heavily on making developers responsible for testing and practices like continuous integration and delivery which in turn require automated tests that can be run quickly and reliably. This shift also recognizes that making testers the only ones responsible for creating an automation framework and writing tests is going to slow down the development process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GbfJLJfK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.prismic.io/rubicon-worldcom/c885adbc-4254-4f28-a2ac-6f80944c8224_high-score-0-5x.png%3Fauto%3Dcompress%252Cformat%26w%3D1400%26h%3D687" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GbfJLJfK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.prismic.io/rubicon-worldcom/c885adbc-4254-4f28-a2ac-6f80944c8224_high-score-0-5x.png%3Fauto%3Dcompress%252Cformat%26w%3D1400%26h%3D687" alt="alt text" title="New High Score"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the book, “How Google tests software," a similar inquiry was made:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“At Google, this is exactly our goal: to merge development and testing so that you cannot do one without the other. Build a little and then test it. Build some more and test some more. The key here is who is doing the testing.“&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The text continues to answer the question, &lt;strong&gt;"Who better to do all that testing than the people doing the actual coding?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Behavior-driven development practices and the test-first development approach help split the testing into layers. Before the code is written for a new feature, the developers should have the solution planned out with automation in mind. Using both BDD and TDD would test the quality of the code the developer writes and test the behavior of the system defined by the product owner.&lt;/p&gt;

&lt;p&gt;Software products should always be made with testability in mind. From the product owner to designers, everybody should be critical of the software they are in the process of producing. Every bug, visual bug, and grammar mistake should not go unnoticed when aiming to ensure software quality. Testing shouldn't be an activity that is done only at the end of a sprint by a designated tester.&lt;/p&gt;




&lt;p&gt;Original blog post: &lt;a href="https://www.rubicon-world.com/blog/2020/01/a-journey-through-quality-assurance-testing/"&gt;A Journey Through Quality Assurance Testing&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>testing</category>
      <category>testdev</category>
      <category>qa</category>
    </item>
    <item>
      <title>Writing Automated Acceptance Tests Using Serenity and the Screenplay Pattern</title>
      <dc:creator>RUBICON</dc:creator>
      <pubDate>Thu, 27 May 2021 09:39:25 +0000</pubDate>
      <link>https://forem.com/rubicon_dev/writing-automated-acceptance-tests-using-serenity-and-the-screenplay-pattern-1eck</link>
      <guid>https://forem.com/rubicon_dev/writing-automated-acceptance-tests-using-serenity-and-the-screenplay-pattern-1eck</guid>
      <description>&lt;p&gt;Serenity is a powerful library for writing automated user acceptance tests. It uses test results to generate world-class test reports that document and describe what your application does and how it works. &lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Serenity BDD
&lt;/h3&gt;

&lt;p&gt;To better understand Serenity, let's write an example test for RUBICON's homepage.&lt;/p&gt;

&lt;p&gt;For this tutorial, we are going to use JUnit. Serenity can also be used with BDD tools such as JBehave or Cucumber. The complete source code for this tutorial can be found here or you can tag along by downloading the Serenity jUnit startup project here.&lt;/p&gt;

&lt;p&gt;For this tutorial, we'll be using the browser Firefox. To begin, let's import the project into IntelliJ.&lt;/p&gt;

&lt;p&gt;Let's follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select Import Project in IntelliJ, then find the downloaded project and select the folder with the build.gradle file and click Open. &lt;/li&gt;
&lt;li&gt;Select Import project from external model and select Gradle, click Next.&lt;/li&gt;
&lt;li&gt;On the next window select Only Use default Gradle wrapper and click Finish.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now we will need to wait for Gradle to build the project. To confirm that everything works, we can find the TestStory file and run the TestExample test. The test should display Google's homepage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In the Screenplay pattern, tests are presented from the perspective of the user. A user that interacts with the web app is called an actor. Everything revolves around actors in the Screenplay pattern. Actors have special abilities such as being able to open web pages. They can also perform tasks and ask questions about the state of the web app.&lt;/p&gt;

&lt;p&gt;Now let’s move onto the next steps.&lt;/p&gt;

&lt;p&gt;The outline for the test we are going to write is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Given that Nermin can see the Rubicon home page&lt;br&gt;
When Nermin opens the Development link&lt;br&gt;
Then Nermin should see the Development page&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we are using Gherkin to describe the test case. Using the given-when-then structure for test scenarios is helpful because it clearly separates what the pre-condition (given), the action performed (when) and the expected postcondition (then) is.&lt;/p&gt;

&lt;p&gt;Now in our features package, let’s create a new test class called Navigation and add the following code:&lt;br&gt;
package features;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import net.serenitybdd.junit.runners.SerenityRunner;
import org.junit.runner.RunWith;

@RunWith(SerenityRunner.class)
public class Navigation {
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Opening a web page
&lt;/h3&gt;

&lt;p&gt;To open a web page we will need to use a web browser. We can do that by declaring a web driver field called webBrowser. The @Managed annotation will let Serenity manage our web driver.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Managed
WebDriver webBrowser;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we can do anything in Serenity, we will need an actor. We will name our actor Nermin and give Nermin the ability to use a web browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private Actor nermin;

@Before
public void userCanBrowseTheWeb() {
    this.nermin = Actor.named(“Nermin”);
    nermin.can(BrowseTheWeb.with(webBrowser));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The @Before and @After annotations are used in JUnit to mark those methods as set up and tear down methods respectively.&lt;/p&gt;

&lt;p&gt;To write our test, the first thing we are going to do is to open RUBICON’s homepage. Our actor Nermin will have to perform a task to open RUBICON's homepage. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In the Screenplay pattern, tasks represent the high-level steps the user needs to perform in order to achieve a goal.&lt;/p&gt;

&lt;p&gt;To write the OpenTheRubiconHomePage task, we will create a new package called tasks. Inside tasks, we will create another file called OpenTheRubiconHomePage.java. To make this class a Serenity task, it needs to implement the Task interface which has one method performAs.&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 OpenTheRubiconHomePage implements Task {
    @Override
    @Step("{0} opens the rubicon home page")        
    public &amp;lt;T extends Actor&amp;gt; void performAs(T actor) {
        actor.attemptsTo(Open.url("https://www.rubicon-world.com"));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To open a web page, we will use the Open action class that Serenity provides for us.&lt;/p&gt;

&lt;p&gt;To make the actor call the Open task, we will need to use the attemptsTo method.&lt;/p&gt;

&lt;p&gt;The string in the @Step annotation is used to modify the Serenity report. The {0} will be replaced by the name of the actor that calls this task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Actions are similar to tasks, but the difference is that actions perform low- level interactions on the web page such as clicking on an element or moving the mouse cursor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XhHYGgkg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/at7lr4inf7qxf7cypjgu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XhHYGgkg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/at7lr4inf7qxf7cypjgu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what the task will look like in the Serenity report.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The reports Serenity generates can be found in the target/site/serenity folder located in the project folder.&lt;/p&gt;

&lt;p&gt;Now we are going to declare it in our Navigation class with the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Steps
OpenTheRubiconHomePage openTheRubiconHomePage;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding the @Steps annotation will allow Serenity to initialize the openTheRubiconHomePage task. This will only work for simple tasks that take no parameters. Later on in the blog, we’ll take a look at how to create tasks that accept parameters.&lt;/p&gt;

&lt;p&gt;Since we now have our task for opening the RUBICON web page, we will call it in our test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
public void shouldBeAbleToOpenTheDevelopmentService() {
    givenThat(nermin).wasAbleTo(openTheRubiconHomePage);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is actually possible to call this task without the givenThat method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nermin.wasAbleTo(openTheRubiconHomePage);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if we use static methods like this, we can increase the readability of the code. Some other methods of the GivenWhenThen class are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;andThat()
when()
then()
and()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Interacting with the Web Page
&lt;/h3&gt;

&lt;p&gt;The next thing we need to do is to create a task that will both open the services dropdown and click on the Development service link.&lt;/p&gt;

&lt;p&gt;To do that, we will need to find the web elements for the Service menu and links.&lt;/p&gt;

&lt;p&gt;Now we can create a new package called targets and within it, a new class called RubiconHomePage where the following code can be added:&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 RubiconPage {
    public static Target SERVICES = Target.the("services dropdown")
        .locatedBy(".nav-services");
    public static Target SERVICE_ITEM = Target.the("service item")
        .locatedBy("//li[contains(@class,'dropdown-item')]//a[contains(text(),'{0}')]");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Target class is used to associate CSS selectors and XPaths with meaningful labels that will be used in the Serenity report. By separating the web elements in their own files, we will reduce duplication that can result from using hardcoded strings.&lt;/p&gt;

&lt;p&gt;To open the Development service, we will first need to hover over the Services dropdown and then click on the Development service. This task will require the name of the service passed in as a parameter. This task will be created by calling the named method.&lt;/p&gt;

&lt;p&gt;The complete code for our OpenServicePage will look 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;public class OpenServicePage implements Task {

    private final String service;

    public OpenServicePage(String service) {
        this.service = service;
    }

    public static OpenServicePage named(String service) {
        return Instrumented.instanceOf(OpenServicePage.class).withProperties(service);
    }

    @Override
    @Step("{0} opens the service named #service") 
    public &amp;lt;T extends Actor&amp;gt; void performAs(T actor) {
        actor.attemptsTo(
            MoveMouse.to(SERVICES),
            Click.on(SERVICE_ITEM.of(service))
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we are calling two actions in the attemptsTo method, which can take one or more tasks. The first one is the MoveMouse action that will move the mouse cursor to the Services dropdown and the Click action will click on the service with the name passed in. Using the “of” method on the service item will pass into the target the parameter service, which will be replaced with {0} in the XPath string.&lt;/p&gt;

&lt;p&gt;To type values into input fields, we can use the Enter action class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;actor.attemptsTo(Enter.theValue("Hello World").into(TARGET));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To enter only a single key, we can use the Hit class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;actor.attemptsTo(Hit.the(Keys.ENTER).into(TARGET));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To select values either by visible text, index or value from a dropdown we can use the SelectFromOptions action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;actor.attemptsTo(SelectFromOptions.byVisibleText("Hello World").from(DROPDOWN));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have our new task we need to call it in our test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
public void shouldBeAbleToOpenTheDevelopmentService() {
    givenThat(nermin).wasAbleTo(openTheRubiconHomePage);

when(nermin).attemptsTo(OpenServicePage.named("Development"));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Asking About the State of the Web Page
&lt;/h4&gt;

&lt;p&gt;For the final part of this test, we will write our then part or the postcondition of the test.&lt;/p&gt;

&lt;p&gt;In the Screenplay Pattern, actors can ask questions about the state of the web page. The purpose of the questions is to answer a precise question about the state of the web application, from an actor’s point of view.&lt;/p&gt;

&lt;p&gt;To confirm that we are on the right web page, we are going to write a question that will return the heading of the current page.&lt;/p&gt;

&lt;p&gt;This is what the question will look like:&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 CurrentPage implements Question&amp;lt;String&amp;gt; {
    public static Question&amp;lt;String&amp;gt; heading() {
        return new CurrentPage();
    }

    @Override
    public String answeredBy(Actor actor) {
        return Text.of(HEADING).viewedBy(actor).asString();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Questions need to implement the Question interface where T is the return type of the question. That interface has one method called answeredBy that needs to be implemented.&lt;/p&gt;

&lt;p&gt;HEADING is just a new target we added to the RubiconHomePage class:&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 Target HEADING = Target.the("Heading").located(By.tagName("h1"));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Text class is used to read text values in a more fluent way. Another way to read the text would be to call the resolveFor method on the target to get the web element. This is a type of WebElementFacade and it has a method called getText() that will return the text on it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public String answeredBy(Actor actor) {
    return HEADING.resolveFor(actor).getText();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assertions in Serenity Screenplay look 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;then(nermin).should(seeThat(CurrentPage.heading(), equalTo("Software engineering.")));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can begin an assertion by calling the should method on the actor. Then we can pass a question into it and a hamcrest matcher.&lt;/p&gt;

&lt;p&gt;Now that we have our question, we can finally complete our test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
public void shouldBeAbleToOpenTheDevelopmentService() {
    givenThat(nermin).wasAbleTo(openTheRubiconHomePage);

    when(nermin).attemptsTo(OpenServicePage.named("Development"));

    then(nermin).should(seeThat(CurrentPage.heading(), equalTo("Software engineering.")));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes there will be situations in which we have to wait for a web page to load, in that case, we can retry the assertion by using the static method eventually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;then(nermin).should(eventually(seeThat(CurrentPage.heading(), 
        equalTo("Software engineering."))));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After we run the test, Serenity will generate the following report for us:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fpR6-Rsd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o59b8gjirefda4ob8txb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fpR6-Rsd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o59b8gjirefda4ob8txb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Words
&lt;/h3&gt;

&lt;p&gt;As you can see, tests in Serenity are written from the perspective of the user or actor. Tests coded in this way are far more readable and follow good engineering principles, such as the single responsibility principle. By splitting up our tests into tasks, questions, abilities, and actions we avoid duplication and create reusable parts that will speed up the development process of the test.&lt;/p&gt;

&lt;p&gt;But that is not biggest advantage of using serenity over other frameworks. The strength of serenity lies in its great reports. Serenity is not just a library that generates test reports, the real goal is to produce living documentation for your product. That is a concept that comes from the world of Behavior Driven Development. Why living documentation, because it documents how the application works and what the business rules are in a way anyone can understand it, and it is living because it is generated by the automated test suite and it is always up to date. With that all said I encourage you to give Serenity BDD a try.&lt;/p&gt;

&lt;p&gt;For more information about Serenity, you can check out the official &lt;a href="http://www.thucydides.info/#/"&gt;Serenity website&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Original blog post: &lt;a href="https://www.rubicon-world.com/blog/2019/09/writing-automated-acceptance-tests-using-serenity-and-the-screenplay-pattern/"&gt;Writing Automated Acceptance Tests Using Serenity and the Screenplay Pattern&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>testing</category>
      <category>qa</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>10 Tips for Becoming a Better Developer</title>
      <dc:creator>RUBICON</dc:creator>
      <pubDate>Tue, 25 May 2021 10:45:28 +0000</pubDate>
      <link>https://forem.com/rubicon_dev/10-tips-for-becoming-a-better-developer-31p6</link>
      <guid>https://forem.com/rubicon_dev/10-tips-for-becoming-a-better-developer-31p6</guid>
      <description>&lt;p&gt;Why settle for good when you can be great? We all want to become the best developers out there, but how do we achieve this? What are some things we can do to improve ourselves?&lt;/p&gt;

&lt;p&gt;RUBICON’s talented and experienced developers teamed up to discuss what helps them succeed in the world of IT. Follow these tips in order to become a rockstar developer!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don’t be afraid to ask for help.&lt;/strong&gt; No one expects you to know everything. One of the most important parts of learning is to recognize you don't know everything and that you’re willing to learn something new. Accepting that you need help and simply saying to your colleagues “I don’t know this, can you help me?” will lead you to find out the answer quickly and move onto the path of learning something new. FYI the developers around you are great resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Patience and persistence.&lt;/strong&gt; The two Ps in programming are patience and persistence. Patience is a virtue especially when it comes to programming and persistence is what helps you get it right. Learning takes time and if you keep trying you’ll eventually get it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learn from your code reviews.&lt;/strong&gt; Code reviews are an essential step in the development process for producing high-quality codes. Code reviews ensure that every line of your code is up to standard and is approved by at least two team members. For further direction, you can check out this guide. Take the opportunity to discuss alternative solutions during code reviews, it not only improves the code base but has also a learning effect for all involved.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code and learn after 5 P.M.&lt;/strong&gt; Coding and learning shouldn’t come to an end when you leave your office. Learn outside of the workplace to gain new skills and come to work ready and full of new information. Luckily in today’s world, the internet provides us with many great learning tools such as &lt;a href="https://www.udemy.com"&gt;Udemy&lt;/a&gt; .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Read, read and read some more.&lt;/strong&gt; Read programming books. Choose good quality, general programming books and you’ll soon distinguish yourself from nearly every developer around you. Here are some of our favourites:&lt;br&gt;
The Pragmatic Programmer - Andy Hunt &amp;amp; Dave Thomas&lt;br&gt;
Clean Code - Robert Cecil Martin&lt;br&gt;
Head First Design Patterns - Elisabeth Freeman &amp;amp; Kathy Sierra&lt;br&gt;
Code Complete - Steve McConnell&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practice writing clean code.&lt;/strong&gt; Clean code is readable and easily understood by everyone on your team. Implementing clean coding practices will benefit you down the line so you should practice making it a habit from the first line of code to the last.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shortcuts don’t lead to success.&lt;/strong&gt; Avoid taking shortcuts when writing code. We all know that time is precious but shortcuts will end up taking up more of your time if you make mistakes, therefore take your time in order to provide the best work possible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Focus on learning principles instead of frameworks.&lt;/strong&gt; Programming languages, frameworks and tools come and go but the principles behind them are here to stay. If you are able to understand the architecture behind the frameworks, then it will make it easier for you to learn new and upcoming things. The world of IT is always changing so being able to understand the core principles will help you adapt to change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pay attention to the bigger picture.&lt;/strong&gt; Often times developers get lost in their code and focus mainly on programming a specific feature. Instead, take a different approach and look at the bigger picture (the product). Focus on optimizing and making the best product possible for users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Take a break.&lt;/strong&gt; Not only does your body and mind deserve a break but you’ll also be boosting your own productivity. Work in time splits and allow your brain to recharge. Take a walk, exercise, grab lunch or socialize. Often times we forget that we’re human and we need to do things other than work.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Follow these steps in order to be the best developer you can be. Happy coding!&lt;/p&gt;




&lt;p&gt;Original blog post: &lt;a href="https://www.rubicon-world.com/blog/2019/06/10-tips-for-becoming-a-better-developer/"&gt;10 Tips for Becoming a Better Developer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>culture</category>
      <category>career</category>
    </item>
    <item>
      <title>A Developer's Guide to Proper Desk Sitting</title>
      <dc:creator>RUBICON</dc:creator>
      <pubDate>Tue, 25 May 2021 10:40:36 +0000</pubDate>
      <link>https://forem.com/rubicon_dev/a-developer-s-guide-to-proper-desk-sitting-3gga</link>
      <guid>https://forem.com/rubicon_dev/a-developer-s-guide-to-proper-desk-sitting-3gga</guid>
      <description>&lt;p&gt;We spend countless hours hunched over at our desks, typing away and squinting at our screens while working on a code. And naturally, we focus on getting the job done instead of paying attention to our posture and the length of time we spend sitting in the same position.&lt;/p&gt;

&lt;h3&gt;
  
  
  Poor Work Habits Lead to Health Issues
&lt;/h3&gt;

&lt;p&gt;You may already have some poor habits outside of the workplace that damage your health such as smoking, not exercising, a poor diet and spending a lot of time sitting. What about your poor habits IN the workplace?&lt;/p&gt;

&lt;p&gt;After all, on average we spend about 40 hours a week working and most of that time is spent sitting. The longer you sit, the worse your posture becomes.&lt;/p&gt;

&lt;p&gt;Some say that sitting is the new smoking. A bad posture and sitting for a long time can lead to many health risks such as back &amp;amp; neck pain, muscle stiffness, an increased risk of cardiovascular disease and a variety of other issues.&lt;/p&gt;

&lt;p&gt;If you catch yourself taking part in any of the following habits, then you’re putting yourself at risk:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sitting with knees, ankles or arms crossed.&lt;/li&gt;
&lt;li&gt;Sitting slumped to one side.&lt;/li&gt;
&lt;li&gt;Not properly supporting the feet.&lt;/li&gt;
&lt;li&gt;Not fully supporting the back (especially the lower back).&lt;/li&gt;
&lt;li&gt;Sitting with your spine in a 'C Shape.' &lt;/li&gt;
&lt;li&gt;Sitting in one position for a long time.&lt;/li&gt;
&lt;li&gt;Straining the neck for long periods of time while staring at a screen.&lt;/li&gt;
&lt;li&gt;Sitting for an extended period of time without taking a break.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Correct Sitting Posture
&lt;/h3&gt;

&lt;p&gt;There are a few steps you can take in order to ensure healthy habits at work. Firstly, let’s take a look at sitting properly in a comfortable chair, it may sound super simple but most of us don't follow proper sitting.&lt;/p&gt;

&lt;p&gt;Follow these simple steps in order to sit properly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Take a seat in your chair and plant your feet on the floor or on a footrest.&lt;/li&gt;
&lt;li&gt;Push your hips as far back as they can go in the chair. 
Keep your shoulders and back straight and focus on keeping your lower back supported on the back of the chair. &lt;/li&gt;
&lt;li&gt;Leave a small gap between the back of your knees and the chair.&lt;/li&gt;
&lt;li&gt;Position your knees at the same height or slightly lower than your hips and place your ankles in front of your knees.&lt;/li&gt;
&lt;li&gt;Recline the back of the chair to a 100 to 110-degree angle.&lt;/li&gt;
&lt;li&gt;Adjust your armrests so that your shoulders are relaxed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Tc8Wy7O5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0hl4z0oyn00978ufntws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Tc8Wy7O5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0hl4z0oyn00978ufntws.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There you have it, you’re sitting properly in your chair. Now that’s only one part to proper desk sitting. Let’s set up your desk for the ideal work environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Your Workspace for Success
&lt;/h3&gt;

&lt;p&gt;Setting up your workplace is as important as sitting properly for your health. Check out how to set up your workspace:&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting up your desk:
&lt;/h4&gt;

&lt;p&gt;Adjust the height of your chair so you are able to roll up to your desk and fit both of your feet and the chair’s armrests comfortably underneath. Adjust your chair so that your arms are bent to 90 degrees.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting up your monitor:
&lt;/h4&gt;

&lt;p&gt;It is very important to adjust your monitor to the correct height since constantly looking up or down can make you tired and eventually lead to eye strain. Place your monitor in front of you, arms length away and at eye level height since this will ensure that your neck will be straight and relaxed.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting up your mouse &amp;amp; keyboard:
&lt;/h4&gt;

&lt;p&gt;Place the mouse and keyboard directly in front of you and as central to your body as possible. Position both the mouse and keyboard at about elbow height. If you’re using a keyboard tray, place it just above your thighs for the ideal position.&lt;/p&gt;

&lt;p&gt;If you want to find out the ideal height to adjust your chair, monitor and keyboard, you can check out this site where you’re able to place your height &amp;amp; it will give you the proper dimensions. &lt;/p&gt;

&lt;h3&gt;
  
  
  A Few Additional Tips to Staying Healthy at Work
&lt;/h3&gt;

&lt;p&gt;Here are a few additional tips you can follow to achieve the ideal healthy workday:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Avoid sitting for long periods of time&lt;/strong&gt; - It is recommended that you take stretch breaks every 20 to 30 minutes so you’re not constantly sitting. Get up on your feet, even if you’re standing beside your desk and not moving around it is still better than sitting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give a standing desk a try&lt;/strong&gt; - If your desk is adjustable, you are able to work in a standing position just make sure to adjust it properly to your height. Working while standing can be just as effective as sitting!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eating healthy &amp;amp; drinking plenty of water&lt;/strong&gt; - Don’t let your work completely consume you, remember to keep hydrated and always have healthy food available in your workspace.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  RUBICON: An Ergonomic Workplace
&lt;/h3&gt;

&lt;p&gt;RUBICON’s office space is an ideal work environment offering ergonomic materials to help you get comfortable in your desk space.&lt;/p&gt;

&lt;p&gt;Each team member has their own office space that is accompanied by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A heigh adjustable standing desk.&lt;/li&gt;
&lt;li&gt;A soft cushioned adjustable chair with lower back support.&lt;/li&gt;
&lt;li&gt;An ergonomic keyboard &amp;amp; monitor.&lt;/li&gt;
&lt;li&gt;Space around the office to walk, stretch and take a break whenever needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using these appliances, I’m able to create my own workspace in which I feel both comfortable and productive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create your own healthy workspace
&lt;/h3&gt;

&lt;p&gt;The average person spends around 90,000 hours at work, therefore healthy habits are very important. You too can create your own ideal workspace and be mindful to how you’re sitting at your desk to avoid health issues. I challenge you to make a change in your work environment!&lt;/p&gt;




&lt;p&gt;Original blog post: &lt;a href="https://www.rubicon-world.com/blog/2019/06/a-developers-guide-to-proper-desk-sitting/"&gt;A Developer's Guide to Proper Desk Sitting&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>advice</category>
      <category>ergonomics</category>
      <category>culture</category>
    </item>
  </channel>
</rss>
