<?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: Profil Software</title>
    <description>The latest articles on Forem by Profil Software (@profilsoftware).</description>
    <link>https://forem.com/profilsoftware</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%2F345739%2F9dc378c2-060b-43e9-a3ec-0c3af2691574.jpg</url>
      <title>Forem: Profil Software</title>
      <link>https://forem.com/profilsoftware</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/profilsoftware"/>
    <language>en</language>
    <item>
      <title>10 Aviation Industry Trends and Challenges. Future of Air Travel</title>
      <dc:creator>Profil Software</dc:creator>
      <pubDate>Thu, 06 Nov 2025 13:02:42 +0000</pubDate>
      <link>https://forem.com/profilsoftware/10-aviation-industry-trends-and-challenges-future-of-air-travel-4ii5</link>
      <guid>https://forem.com/profilsoftware/10-aviation-industry-trends-and-challenges-future-of-air-travel-4ii5</guid>
      <description>&lt;p&gt;The aviation industry is undergoing a significant transformation. It’s driven by advancements in technology, an increase in safety regulations, and the growing need for efficient operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technology is constantly changing the way people travel. **Just think, online check-in was first introduced only a little over two decades ago, and we bet most of you didn’t even consider booking your airplane ticket through your phone back then. But today, that’s no news. **We do everything online, and many of these operations happen right on our phones. Thanks to that, we no longer need to spend hours standing in long queues at the airport.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;However, travelers are not the only ones reaping the benefits of aviation technology. On the other side, there are aviation maintenance technicians and manufacturers, pilots, operators, and mechanics who ensure that planes run smoothly and that air travel is as easy and pleasurable as it gets. Technology helps those behind the curtain drive automation, enhance safety, reduce costs, and improve the customer experience, both at airports and during flights.&lt;/p&gt;

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

&lt;p&gt;Tools such as flight management systems, automated check-in systems and automated baggage handling systems already lessen the burden that lies on manual labour, leading to faster processing by aviation mechanics and less errors. But this is just the beginning of what technology is doing for us.&lt;/p&gt;

&lt;p&gt;Centralized communication platforms are revolutionizing coordination across the aviation ecosystem. These platforms integrate real-time updates between ground crews, air traffic controllers, maintenance teams, and airline operations, enabling faster response times to disruptions and minimizing costly delays. They ensure every stakeholder accesses the same data.&lt;/p&gt;

&lt;p&gt;Compliance and Safety Management Systems (SMS) are also critical. These tools help airlines and airports stay aligned with strict regulatory frameworks by automating documentation, tracking incidents, and managing safety audits. With data-driven insights, SMS platforms not only improve transparency and accountability but also help prevent accidents before they occur.&lt;/p&gt;

&lt;p&gt;**Predictive Maintenance Tools use IoT sensors and AI algorithms to anticipate mechanical failures before they happen. By analyzing trends in engine performance, hydraulic systems, and avionics, these tools enable timely interventions and reduce aircraft downtime. &lt;br&gt;
**This not only cuts maintenance costs but also enhances safety and reliability across fleets.&lt;/p&gt;

&lt;p&gt;These innovations, along with many new ones, such as Digital ID’s and facial matching technology, also call for stronger security measures.&lt;/p&gt;

&lt;p&gt;**All those transformative tools has brought about opportunities and challenges not only when it comes to cybersecurity but also safety and maintenance. &lt;br&gt;
**In this article we’d like to explore the key trends, challenges, and potential solutions shaping the aviation industry’s future.&lt;/p&gt;

&lt;p&gt;What can software solutions offer to the Aviation Industry? How can we bring the costs down, ensure aircraft safety and make aviation maintenance technician’s job more efficient and effective? Let’s dive into it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Trends in Aviation Software and Safety
&lt;/h2&gt;

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

&lt;h2&gt;
  
  
  1. Advanced Data Analytics and AI Integration in Aviation industry
&lt;/h2&gt;

&lt;p&gt;Modern aviation relies heavily on data generation and analysis to enhance decision-making on many different fronts. Real-time analytics, AI-driven data extraction, and predictive maintenance tools enable operators to optimise schedules, reduce costs, and minimise downtime.&lt;/p&gt;

&lt;p&gt;**By structuring unorganised maintenance data and analysing it, operators can ensure precise repair planning, improved aircraft reliability, and enhanced safety. &lt;br&gt;
**Maintenance logs and reports or aircraft sensors aren’t the only sources of information. AI can also be integrated to handle the passengers information, weather reports, flight operations data, airline operational data, regulatory and compliance data, security and cybersecurity data, and more. The diversity of usage is what makes it one of the most crucial trends in Aviation Software and Safety.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Interactive 3D Models for Maintenance
&lt;/h2&gt;

&lt;p&gt;Interactive 3D visualization is becoming a standard in aircraft maintenance systems.&lt;br&gt;
** These tools allow engineers and operators to identify repair needs visually, schedule grouped repairs, and reduce costs associated with repeated disassembly of components.**&lt;/p&gt;

&lt;p&gt;How? &lt;br&gt;
&lt;strong&gt;It shows the previous repairs and maintenance schedule for different parts, as well as reported issues on a 3D model, which makes it easier to plan the maintenance in the most efficient way.&lt;/strong&gt;&lt;br&gt;
 This way airlines and aircraft operators can also ensure better resource allocation. Interactive 3D Models are often used for training as well, ensuring stress free practice, which allows performing scenarios of repairs, fixing aircraft elements without risks or costs. The educational aspect of it only adds to an already crucial tool that makes maintenance more time and cost effective.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Seamless Communication and Role-Based Systems
&lt;/h2&gt;

&lt;p&gt;Effective communication between stakeholders, mechanics, safety authorities, and managers, is vital for operational success. Aviation software trends now focus on tools that provide centralized communication platforms, which ensure that relevant information reaches the right people while maintaining robust cybersecurity protocols.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Confidential information should only ever be shared with the people, who have the clearance to see it.&lt;/strong&gt; &lt;br&gt;
It’s just as crucial for the information to be shared in an efficient and easy manner, which calls for quick data collection and analysis services, as well as a user friendly dashboard and messaging or reporting systems that will not only ensure that data is shared with the right people, but that it’s available at any given moment.&lt;/p&gt;

&lt;p&gt;Thanks to report filing and analysis tools our software is able to identify the changes and repairs already done on the aircraft and those that still need to be taken care of, and relate this information to a manager and avionics technician.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Compliance and Safety Management Systems
&lt;/h2&gt;

&lt;p&gt;Adhering to international and national safety standards, such as those from FAA and EASA, is a fundamental requirement for aviation operators.&lt;/p&gt;

&lt;p&gt;Safety management systems equipped with features for hazard reporting, audit management, and risk assessment help operators achieve compliance while minimizing risks. Audit modules streamline the process by enabling efficient planning, scheduling, and oversight of quality control tasks, while findings are systematically addressed through structured resolution workflows.&lt;/p&gt;

&lt;p&gt;The insights generated are reintegrated into the safety management cycle, enhancing risk mitigation and ensuring continuous improvement in operational safety.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overcoming challenges of Aviation Software Development: Solutions and innovations
&lt;/h2&gt;

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

&lt;p&gt;The Aviation Industry is growing fast and with it, so do the challenges that it poses. Some of the major concerns include handling vast amounts of unstructured data and ensuring safe and efficient communication between staff managing the aircraft. &lt;strong&gt;Meeting compliance requirements and implementing secure access management features are also among the aspects that need a dedicated solution.&lt;/strong&gt; Introducing a reliable custom aviation software to airlines and aircraft management businesses is a guaranteed method for tackling all these obstacles all out once.&lt;/p&gt;

&lt;p&gt;For starters, the aviation industry generates a vast amount of unstructured data from maintenance reports, safety documents, and incident logs. &lt;br&gt;
**Extracting actionable insights from this data is a significant challenge. Operators require tools that can process diverse formats and present structured, analyzable information. &lt;br&gt;
**Thanks to the efficient document management, one can track repair histories and plan ahead more efficiently.&lt;/p&gt;

&lt;p&gt;**Software can also provide real-time cost comparisons and thanks to the 3D models that were mentioned above, one can track all these more easily. **Optimizing the maintenance costs while ensuring safety and compliance might be one of the challenges of this industry, but with the right software development team on board you can easily overcome them.&lt;/p&gt;

&lt;p&gt;Navigating complex and evolving safety regulations is another challenge. Operators must manage risk, change, and audits while keeping comprehensive documentation that aligns with regulatory requirements. Keeping up with the ever changing regulations in this demanding market, while also having in mind that **the aviation industry’s increasing reliance on interconnected systems makes it a prime target for cyberattacks **and being prepared for it, may seem overwhelming. However, it is a must. Ensuring robust cybersecurity measures, such as vulnerability management, API protection, and secure communication systems, is crucial to protecting sensitive operational data.&lt;/p&gt;

&lt;p&gt;Thanks to our experience in developing Aviation Software we know which tools and innovations will help you tackle these obstacles in the most time and cost efficient manner. Some of the solutions were already mentioned, because they are so effective, they made their way to the top of the functionalities wanted in Aviation Industry, so if you’re not implementing them, you’re already behind your competition. &lt;br&gt;
Of course, developing software like that it’s not an easy feat and it’s very probable that you don’t even know where to start. &lt;strong&gt;This is where offshoring software development can come in handy — for letting the experienced team of experts handle the processes will save you time and funds,&lt;/strong&gt; just like all the solutions and innovations we listed for you below. Let’s recap, how can outsourcing software development teams help your business grow and revenue increase with Aviation Software?&lt;/p&gt;

&lt;h2&gt;
  
  
  1. AI-Powered Data Structuring and Analysis
&lt;/h2&gt;

&lt;p&gt;As we mentioned, handling vast amounts of unstructured data is a hallmark challenge for aviation. AI technologies excel at converting diverse data formats, maintenance logs, incident reports, sensor outputs, into structured, actionable insights, which requires extensive training . These tools streamline operations by identifying trends, flagging anomalies, and presenting a comprehensive view of aircraft conditions.** AI-driven platforms enable operators to plan repairs effectively, reduce redundancies, and anticipate maintenance needs, ensuring both security and cost-efficiency.**&lt;/p&gt;

&lt;p&gt;Developing our interactive** 3D aircraft models &lt;strong&gt;was a multifaceted process that required the precise integration of numerous components.&lt;/strong&gt; Our work began with an in-depth analysis of aircraft parts documentation, followed by the implementation of custom mechanisms to import this data into a meticulously designed database.**&lt;/p&gt;

&lt;p&gt;A key challenge was the unpredictable structure of the source documentation, which necessitated a deep understanding of complex aircraft construction. To achieve this, we held in-depth sessions with aircraft mechanics to gain the necessary domain expertise.&lt;br&gt;
&lt;strong&gt;The final step involved mapping each aircraft element to its corresponding location on the 3D model, culminating in an impressive and highly engaging experience for the end-user.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Predictive Maintenance and Enhanced Visualization
&lt;/h2&gt;

&lt;p&gt;Combining predictive analytics with interactive 3D models revolutionizes how maintenance is approached. It’s a trend for a reason.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Predictive maintenance tools analyze historical data to forecast potential failures, enabling proactive intervention.&lt;/strong&gt; &lt;strong&gt;Interactive 3D models complement this by visualizing repair schedules, past interventions, and real-time damage reports.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Together, these technologies optimize maintenance workflows, reduce unnecessary downtime, and help operators allocate resources more effectively. Additionally, &lt;strong&gt;the use of 3D models in training scenarios offers hands-on experience in risk-free environments, equipping teams with the skills to address complex challenges.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The capabilities of AI models are advancing at an incredible pace. *&lt;em&gt;Problems we once projected would take months to solve — if they could be solved at all — can now be addressed in a matter of days. **Features that were previously narrowed down to meet budget constraints have become easily achievable for a fraction of the cost, thanks to the increasing power of AI integrated into application updates.&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
Nowadays, it’s more crucial than ever to stay current with the latest technologies, not just from the last year, but from the last few months or even weeks. **Our company’s flat structure and agile philosophy allow us to adapt to these new developments rapidly.&lt;/strong&gt; This agility provides a significant competitive advantage for our customers, especially in the fast-moving startup world.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Communication and Collaboration Tools
&lt;/h2&gt;

&lt;p&gt;How to facilitate good communication and collaboration between the members of your team?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integrated platforms with centralized messaging and role-based access control ensure that the right information reaches the right people at the right time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These systems enhance collaboration by providing secure, real-time access to essential data while safeguarding sensitive information. Features like automated incident reporting and structured repair updates keep teams informed, improving transparency and reducing delays in decision-making.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Holistic Safety and Risk Management Systems
&lt;/h2&gt;

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

&lt;p&gt;&lt;strong&gt;Modern Safety Management Systems (SMS)&lt;/strong&gt; are comprehensive platforms that address hazard reporting, risk assessment, and audit management. These systems are designed to meet stringent regulatory standards, ensuring complete compliance with regulations from agencies such as homeland security while simplifying compliance processes. By automating audit planning, integrating findings into safety workflows, and providing detailed analytics dashboards, &lt;a href="https://profil-software.com/case-studies/aviation-software/jumpseatsms/" rel="noopener noreferrer"&gt;SMS platforms&lt;/a&gt; enable operators to maintain a high standard of safety and continuously improve their operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Secure, Scalable, and Reliable Infrastructure
&lt;/h2&gt;

&lt;p&gt;Aviation technology must handle complex operations while ensuring scalability and security. Modern infrastructures built with robust technologies like AWS, PostgreSQL, and Redis offer unmatched reliability and performance. These solutions ensure that aviation operators can scale their operations without compromising speed or data integrity. Security measures, including API protection and real-time monitoring, safeguard sensitive data from cyberthreats, ensuring compliance with global cybersecurity standards.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Cost Optimization through Digital Transformation
&lt;/h2&gt;

&lt;p&gt;Digital transformation, powered by custom aviation software, is a game-changer for cost management. Automation of manual processes, integration of tools for cost comparison, and proactive maintenance scheduling regarding airframe all contribute to significant savings. Predictive analytics and 3D modeling further streamline aircraft maintenance expenses by identifying opportunities for grouped repairs and reducing operational disruptions.&lt;/p&gt;

&lt;p&gt;By embracing these innovations, aviation operators can effectively address current challenges and position themselves for long-term success.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Whether it’s through AI-powered insights, enhanced maintenance visualization, or robust safety management, customized aviation software provides the tools needed to navigate this demanding industry.&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
With experienced teams driving these solutions, operators can focus on achieving operational efficiency, safety, and scalability without compromising on quality or compliance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Navigating the Future of Aviation Sector with Technology
&lt;/h2&gt;

&lt;p&gt;The aviation industry stands at a crossroads where challenges meet opportunities, and innovation becomes the key to progress. From managing vast amounts of unstructured data to ensuring seamless communication and compliance with ever-evolving regulations, &lt;strong&gt;the complexities of modern aviation demand sophisticated, reliable, and **&lt;/strong&gt;adaptive software solutions**.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By capitalizing on AI-driven data management, predictive maintenance, and interactive 3D models, operators can not only enhance safety and efficiency but also significantly reduce costs.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Secure and scalable infrastructure ensures that these solutions remain robust in the face of growing demands, while advanced communication tools and comprehensive safety systems provide the transparency and control needed to navigate an increasingly interconnected aviation ecosystem.&lt;/p&gt;

&lt;p&gt;Digital transformation is no longer an option, it is a necessity. The integration of cutting-edge technologies into aviation operations not only optimizes processes but also helps businesses stay competitive in a rapidly evolving industry. With the right development team, these innovations can be seamlessly adapted to specific needs, creating solutions that address the unique challenges faced by airlines and operators today.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this era of rapid change, choosing to invest in innovative software solutions is choosing to invest in the future of aviation.&lt;/strong&gt; Whether it’s enhancing aircraft maintenance, strengthening cybersecurity, or streamlining safety compliance, custom aviation software offers the tools and insights necessary to thrive in a demanding and dynamic environment.&lt;/p&gt;

</description>
      <category>aviationsoftware</category>
      <category>airtravel</category>
      <category>aviation</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Tips on What Elements to Include in a Pitch Deck for a Startup</title>
      <dc:creator>Profil Software</dc:creator>
      <pubDate>Thu, 11 May 2023 11:26:16 +0000</pubDate>
      <link>https://forem.com/profilsoftware/tips-on-what-elements-to-include-in-a-pitch-deck-for-a-startup-1038</link>
      <guid>https://forem.com/profilsoftware/tips-on-what-elements-to-include-in-a-pitch-deck-for-a-startup-1038</guid>
      <description>&lt;h2&gt;
  
  
  How to start and which pitch deck elements are the most important?
&lt;/h2&gt;

&lt;p&gt;If you’re looking for investors to fund your business, &lt;strong&gt;what you need is a well-prepared Pitch Deck&lt;/strong&gt;. Most of you probably have at least a vague idea of what Pitch Deck is. It can be summed up as &lt;strong&gt;a short presentation that showcases your business, product, plans or services to potential investors&lt;/strong&gt;. The main goal of a pitch deck is to sell whatever it is you’re offering, to &lt;strong&gt;make potential investors interested and willing to invest&lt;/strong&gt;. However, it is worth mentioning that you probably won’t get funding right away.&lt;/p&gt;

&lt;p&gt;Be prepared to give out and send out a lot of Pitch Decks before somebody decides to fund your Startup or project, and remember that &lt;strong&gt;a great Pitch Deck is not about getting someone to invest right away&lt;/strong&gt;. It usually takes a few meetings for investors to make that decision, so &lt;strong&gt;what you want to achieve with your Pitch Deck is getting an invitation to another meeting&lt;/strong&gt;. Negotiations often start with a Pitch Deck, so you have to make sure that what you’re presenting in person or sending out by email ticks all of the boxes.&lt;/p&gt;

&lt;p&gt;Firstly, &lt;strong&gt;if you want your Pitch Deck to be successful, follow these three rules&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep it simple and easy to understand&lt;/li&gt;
&lt;li&gt;Be informative and captivating — make them feel like they will be missing out on something if they don’t invest&lt;/li&gt;
&lt;li&gt;Win their trust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, it sounds simple enough but once you start working on your first Pitch Deck you might realize that you don’t really know how to achieve this. Y*&lt;em&gt;ou can try coming up with your own structure for a Pitch Deck, but why would you do that when there’s already one that has worked for many startups and entrepreneurs before you?&lt;/em&gt;* It is believed that a great startup Pitch Deck includes the following information:&lt;/p&gt;

&lt;p&gt;**1. Cover&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Problem slide&lt;/li&gt;
&lt;li&gt;Solution slide&lt;/li&gt;
&lt;li&gt;Product Demo&lt;/li&gt;
&lt;li&gt;Target Market Size&lt;/li&gt;
&lt;li&gt;Business Model slide&lt;/li&gt;
&lt;li&gt;Competition**&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why? Simply, because all of this information is necessary if you want to give someone a reason to fund your business or project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you’re looking for help in creating a successful Pitch Deck, here you’ll find tips on how to do that and what to focus on, followed by startup pitch deck examples. And if you have a great idea for a product but you’re not sure where to start, a &lt;a href="https://profil-software.com/product-discovery-workshops/"&gt;Product Discovery Workshop&lt;/a&gt; might help you get there.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips on how to create a successful Pitch Deck
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Consider your audience&lt;/strong&gt;&lt;br&gt;
Each group of people has its own needs and you should take these needs into account. While preparing your Pitch Deck keep in mind to whom you are pitching your business, idea, or product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tailor Your Message to Your Target Audience&lt;/strong&gt;&lt;br&gt;
Investors need to know that the investment in your business or product will bring them some gain. That’s why showing them t*&lt;em&gt;he problem and the solution&lt;/em&gt;* or** the potential team **will be meaningless if you don’t show them a working business model as well.&lt;/p&gt;

&lt;p&gt;Proving to them that they will get some kind of &lt;strong&gt;return on their investment&lt;/strong&gt; might be just what they require to justify sharing their resources with you.&lt;/p&gt;

&lt;p&gt;For example, if you’d like to pitch the same business or project to potential employees, customers or partners, &lt;strong&gt;you should consider both what you need from them and how can you fulfill their wishes in order to get their approval.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keeping your audience in mind and reviewing your Pitch Deck from their perspective can help you achieve your goal — whether it’s to acquire funding or get the approval of the board or a business partner.&lt;/p&gt;

&lt;p&gt;So, what else do you need to add to your Pitch Deck to fulfill the specific requirements of the potential &lt;strong&gt;investors&lt;/strong&gt;? For starters, you might want to add information about &lt;strong&gt;the amount of money&lt;/strong&gt; you will need and when you will need it. Does your business require one big upfront investment or a number of smaller ones made over the years? Answer the question of &lt;strong&gt;how the money will be spent&lt;/strong&gt; and what kind of &lt;strong&gt;resources your business requires&lt;/strong&gt;. Bear in mind that resources don’t always mean money.&lt;/p&gt;

&lt;p&gt;The last thing that you should remember is to include in your Pitch multiple forms of &lt;strong&gt;contact information&lt;/strong&gt; in case someone wants to reach out to you to ask you more questions or get more information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introduce your company&lt;/strong&gt;&lt;br&gt;
It might seem obvious but before going into details, you should reserve &lt;strong&gt;a slide to present the fundamental principles of your company&lt;/strong&gt;, the evolution that it underwent, and its &lt;strong&gt;values and mission&lt;/strong&gt;. You want investors to have a full grasp of &lt;em&gt;what your company is standing for&lt;/em&gt;. This one is also important for you; knowing the purpose of your company will help you clarify the problem and the solution that you’ve introduced to it.&lt;/p&gt;

&lt;p&gt;However, you don’t want the introduction of your company and its purpose to take up more than one slide. In fact, you want to make it as short as you can; it can even be one sentence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiring Examples of Company Introductions in Successful Startup Pitch Decks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KbHTM7VC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9hlbsjlwu0i9tsf63jur.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KbHTM7VC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9hlbsjlwu0i9tsf63jur.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ux0ehJ98--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/24llyjjsjrnjs5y2tvly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ux0ehJ98--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/24llyjjsjrnjs5y2tvly.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6ncXBpC6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vtqr39zgi8agdym6l1ff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6ncXBpC6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vtqr39zgi8agdym6l1ff.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to make your company’s &lt;strong&gt;business model&lt;/strong&gt; clearer to your audience, you might try comparing it to some big company that is already well-known, such as Netflix or Youtube. However, if you’re comparing your company to another you have to know exactly what distinguishes your idea from the one that’s already popular to not create a feeling of copying something that’s working.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Showing that your idea is unique while making it seem like there’s a strong need for it on the market may get you a ticket to funding.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’re unable, to sum up, your company in one sentence, you can create an “overview”, like the one prepared by Slack:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GdZY5aJH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/31qje86igbyseuhn2fmm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GdZY5aJH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/31qje86igbyseuhn2fmm.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sometimes you can even use quotes to give people a better idea of what you believe is the mission or purpose of your company as Buffer did.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3m_8-o6z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1rumz9zn0y5dr4bygwy5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3m_8-o6z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1rumz9zn0y5dr4bygwy5.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think about the problem and its solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TBxG4t1h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wk4u21dpcg9w5f5pxeun.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TBxG4t1h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wk4u21dpcg9w5f5pxeun.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I3kqPp30--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uq1x8yar5pd308xjoi6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I3kqPp30--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uq1x8yar5pd308xjoi6c.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;br&gt;
Airbnb:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tKABxj4r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/32rjm1cf6mimcyeg5aru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tKABxj4r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/32rjm1cf6mimcyeg5aru.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZsRFSnnK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hpsty817l6d2y578ohn8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZsRFSnnK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hpsty817l6d2y578ohn8.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gather data and numbers&lt;/strong&gt;&lt;br&gt;
As was already mentioned, giving investors a reason to back your business is crucial for your investor Pitch Deck. Money is a strong motivator — &lt;strong&gt;if you prove that your business or project is beneficial, you will at the very least capture their attention.&lt;/strong&gt; That’s why it’s so important to undergo solid research and &lt;strong&gt;prepare as much data and numbers as you can&lt;/strong&gt; for your Pitch.&lt;/p&gt;

&lt;p&gt;Try illustrating your progress and growth, milestones, anticipated revenue, and the expenses and earnings of the companies with a similar business model with data and numbers. This will make your pitch more reliable and solid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KfJuymQi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3g9beoqsnovzvr6u7qp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KfJuymQi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3g9beoqsnovzvr6u7qp.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you show your progress in numbers you’ll give the potential investors &lt;strong&gt;a clearer view of your growth&lt;/strong&gt; and what can they expect in the future if they invest in your business or project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G4BHhNxM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zsqbwka57kgwp2wmwinh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G4BHhNxM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zsqbwka57kgwp2wmwinh.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Important questions to ask yourself
&lt;/h2&gt;

&lt;p&gt;Having in mind the tips we’ve just shared with you, you probably now have a vague idea of how to start creating your Pitch Deck. However, there are still some important questions that you will have to answer yourself and incorporate into your pitch deck. &lt;strong&gt;Questions that can be decisive for the potential investor.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Market Size: How Big Is Your Potential Market?&lt;/strong&gt;&lt;br&gt;
Let’s think back to one of the very first slides that Buffer introduced in their Pitch Deck — the one that we’ve already seen above. It states right away that social media are the most important trend and underlines the fact that the amount of social media users increases every year and the number of posts as well, and the importance of social media marketing. Airbnb chooses a little more direct approach, showing numbers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GnGbNa1u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vlp6d80n6rfaedfagzcg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GnGbNa1u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vlp6d80n6rfaedfagzcg.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Facebook which started as a student-dedicated portal went for the statistics as well:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LtMx6EMk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cnz8i08akfq83yrx0456.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LtMx6EMk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cnz8i08akfq83yrx0456.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In short, to create this part of your own Pitch Deck you’ll have to answer yourself: &lt;strong&gt;How many people are struggling with this problem and looking for a solution? How many customers exist for your product or service?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your Business Model: how do you plan to make money?&lt;/strong&gt;&lt;br&gt;
One of &lt;strong&gt;the most important questions&lt;/strong&gt; for potential investors is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you plan to make money?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As was already stated before, proving that they will see some return on their investment plays a crucial role in convincing them to fund your business or project. You have to show that &lt;strong&gt;you know exactly what you’re doing and how you’re going to earn money&lt;/strong&gt;, as well as what role will their money play in this plan of yours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Showcasing Your Business Model: Pitch Deck Examples to Learn From
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1Qx2BpyB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uemeedrosroshe8nzmq6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1Qx2BpyB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uemeedrosroshe8nzmq6.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gOKPJ_pq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u58z7trodby5lcb1mwt9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gOKPJ_pq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u58z7trodby5lcb1mwt9.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pnz9Sb00--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tivtkauagt7pifxmo7nn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pnz9Sb00--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tivtkauagt7pifxmo7nn.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What should you mention to highlight Your Unique Value? Proprietary Tech or Expertise&lt;/strong&gt;?&lt;br&gt;
Showing the potential investors that you have &lt;strong&gt;something unique to offer&lt;/strong&gt;, something that they won’t find somewhere else can heighten the feeling of &lt;strong&gt;FOMO&lt;/strong&gt;, thus making them more likely to invest. Think about your value, and come up with the things that only you can bring to the project or business. **Make it seem that there are certain things that you and your team can deliver in a way that no other team would. **You’re not only solving the problem — you’re also the only one that can solve this problem, because of your expertise or because of the tool, application or system that is only developed and used by your enterprise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can you outshine the Competition? Analyzing the Competitive Landscape and Emphasizing Your Advantages&lt;/strong&gt;&lt;br&gt;
If there are other companies that are solving your problem — &lt;strong&gt;make it seem that whatever they are doing, you’re going to do it better.&lt;/strong&gt; Your idea will make this problem smaller, will fix it quickly or the effects will last longer. &lt;strong&gt;You shouldn’t avoid talking about your competition, because you may end up being perceived as untrustworthy.&lt;/strong&gt; Being honest about it is a better idea. Not only because of the possible funding but also because &lt;strong&gt;you need to know what your competition is and how you are going to beat them if you want to succeed.&lt;/strong&gt; So answer yourself:_ Who else is solving this problem for your customers? Who are your main competitors, and how are their businesses performing?_&lt;/p&gt;

&lt;p&gt;Only after answering these will you be able to come up with what we’ve talked about above — &lt;strong&gt;why are you better than your competition, what differs your idea from theirs and why it’s you who should get the funding and not them&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is an example of a competition slide of a winning pitch deck from Canva’s Pitch Deck that was used to raise $9m series-D from River Cities Capital Funds:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TfRE3fkO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35x99nakoy130acujv8j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TfRE3fkO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35x99nakoy130acujv8j.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And from the “Castle”:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qIiVwDyq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8h3otf2q4skhuobmhh1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qIiVwDyq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8h3otf2q4skhuobmhh1.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tYDjdPi8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m1ixkpo92hzp55i3f2q6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tYDjdPi8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m1ixkpo92hzp55i3f2q6.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is choosing your Team the most profitable for potential investors?&lt;/strong&gt;&lt;br&gt;
While thinking about what sets you apart from your competition and makes your company the one worth investing in &lt;strong&gt;you may consider your expertise and proprietary tech but you might also bring up your team&lt;/strong&gt;. If you hire &lt;strong&gt;experienced, talented professionals&lt;/strong&gt;, you should definitely show them off in your Pitch Deck. &lt;strong&gt;In a team slide of your pitch introduce your team&lt;/strong&gt;, show their strengths, and talk about their experience.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Showcasing Your Stellar Team: Examples of Highlighting Talent and Experience&lt;br&gt;
*&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SmvUySRv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obd0crx1pq2zu7k45vav.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SmvUySRv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obd0crx1pq2zu7k45vav.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f0iYwBFi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kdwdezaxpok53ez429k3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f0iYwBFi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kdwdezaxpok53ez429k3.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Go-to-market Strategy
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What are the milestones and timeline to make your vision a reality?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zwibkhLE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zya6yjxqea5p1ke86m55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zwibkhLE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zya6yjxqea5p1ke86m55.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Financials
&lt;/h2&gt;

&lt;p&gt;While writing and then presenting your Pitch Deck you cannot forget what you’re doing it for. It’s not just to show off or get recognition — &lt;strong&gt;you’re doing it to get funding&lt;/strong&gt;. And even though it might take a few meetings and a lot more than just this one Pitch Presentation, you cannot lose your focus. &lt;strong&gt;Your mind should always be set on getting the funds that you need.&lt;/strong&gt; That’s why it’s important to talk about the financials, the real cost, and the expected earnings.&lt;/p&gt;

&lt;p&gt;If your business has already achieved some milestones and earned some money, you should definitely use that information to your advantage. Tell the potential investors &lt;strong&gt;how much your project has already secured.&lt;/strong&gt; This will give them a vague idea of what they can expect from your startup or project in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Investment: how much money do you need?&lt;/strong&gt;&lt;br&gt;
Finally, we’ve arrived at the most important of all of the crucial details you must talk about in your Pitch Deck. &lt;strong&gt;After introducing all the data, presenting your team, market strategy, business model, and so on, it’s time for you to ask the investors to take your business into consideration when it comes to investing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;More than that, you need to &lt;strong&gt;tell them how much money you would like for them to contribute to your project&lt;/strong&gt; or business and what you want to spend it on exactly. After going through all of the information that you need to put in your Pitch Deck and reviewing your numbers, it should be fairly easy to figure out how much money you need and for what. And don’t just throw numbers on the potential investors — &lt;strong&gt;it’s better to tell a story with your numbers, a story about your business, product and customers.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Start by visualizing simple data (such as sales, revenue, expenses, and user growth) and having an expert check it over,” says Epstein. “Once you’ve done that, work on contextualizing and explaining that information… You always want your commentary to corroborate and elucidate your data, showing investors that you have a complete understanding of how your business runs.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you can see, &lt;strong&gt;your Pitch Deck should be well-detailed and contain a lot of information on quite a few subjects that the potential investors might take an interest in.&lt;/strong&gt; Having said that, you should do everything in your power to make it as short as possible.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Investors reviewing pitch decks spend 23 percent of their time on the financial slides, so it can be tempting to fill them with every figure and projection imaginable. You’ll want to steer clear of this bait, however,” says Eli Epstein of CoFoundersLab. “Investors aren’t interested in a barrage of numbers that are really just broad estimates. Instead, they seek honest projections (even if it isn’t hockey stick growth) and a thoughtful analysis of how you calculated them and how you plan to achieve them.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you want to learn more about what to do to ensure that your Startup doesn’t fail, take a look at our article on &lt;a href="https://profil-software.com/blog/saas-build-and-grow/7-saas-startup-software-development-challenges-why-startups-fail/"&gt;7 SaaS Startup Software Development Challenges&lt;/a&gt; which includes tips from successful entrepreneurs.&lt;/p&gt;

</description>
      <category>pitch</category>
      <category>startup</category>
      <category>business</category>
      <category>saass</category>
    </item>
    <item>
      <title>Testing a React Application with React Hooks with Jest and Enzyme for newbies</title>
      <dc:creator>Profil Software</dc:creator>
      <pubDate>Thu, 02 Mar 2023 13:07:12 +0000</pubDate>
      <link>https://forem.com/profilsoftware/testing-a-react-application-with-react-hooks-with-jest-and-enzyme-for-newbies-37ji</link>
      <guid>https://forem.com/profilsoftware/testing-a-react-application-with-react-hooks-with-jest-and-enzyme-for-newbies-37ji</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://profil-software.com/services/javascript-app-development/" rel="noopener noreferrer"&gt;ReactJS application development&lt;/a&gt;leads to code base growth. Once a certain point is reached, an application becomes more complex. Tasks start to get more and more time consuming. &lt;strong&gt;Adding a new feature or even fixing a bug creates a real risk for your application&lt;/strong&gt;. If there is no testing at this point, it should be introduced immediately. Testing makes an app more robust and less prone to error. It’s the best way to ensure that your code works as expected in every possible scenario.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is nothing more frustrating than spotting an error that could have been found and removed during development&lt;/strong&gt; if only tests had been written. Everyone wants to &lt;strong&gt;create bug-free applications&lt;/strong&gt; that users will love. To achieve this goal, every front-end developer has to ensure that at least crucial parts of their application are tested and the risk of introducing badly working code is minimal.&lt;/p&gt;

&lt;p&gt;My goal is to share some practical knowledge about &lt;strong&gt;testing React applications using Jest and Enzyme&lt;/strong&gt;. It comes in handy when you're working for any &lt;a href="https://profil-software.com/services/react-native-app-development/" rel="noopener noreferrer"&gt;React Native Agency &lt;/a&gt;as well.&lt;/p&gt;

&lt;p&gt;This article contains code fragments from the following repository: &lt;a href="https://github.com/dybik08/github-browser" rel="noopener noreferrer"&gt;https://github.com/dybik08/github-browser&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Overview
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Modern React applications&lt;/strong&gt; are made by stateless functional components with hooks. It is the direction React is evolving towards. In this article I won’t focus on testing class-based components which are displaced by functional ones.&lt;/p&gt;

&lt;p&gt;We’ll learn how to test them starting with &lt;strong&gt;UI testing&lt;/strong&gt;. After that we’ll move to &lt;strong&gt;React Hooks testing&lt;/strong&gt;, then we’ll move to Redux Thunk asynchronous actions, and we’ll finish with Redux.&lt;/p&gt;

&lt;p&gt;For the purpose of this article, &lt;strong&gt;I’ve made a small application that displays searched GitHub repository info&lt;/strong&gt;. It uses Github v3 public API. For more info check the Github API docs &lt;a href="https://docs.github.com/en/rest/overview" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Project structure can be found in the image below. &lt;strong&gt;The project was bootstrapped by React CLI&lt;/strong&gt; which handled installation of all libraries and created a boilerplate project with a bunch of useful commands ready to use like npm run start or npm run test.&lt;/p&gt;

&lt;p&gt;Getting back to the project, users can search Github repositories by filling in the input and pressing the search button or enter key on the keyboard. Users can then press the details button to see detailed info of the selected repository or check other repositories of the selected repository owner.&lt;br&gt;
Project structure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4uvt8dscri03r4p54rn5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4uvt8dscri03r4p54rn5.jpg" alt=" " width="302" height="920"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Enzyme
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Enzyme is a JavaScript Testing utility built for React that makes it easier to test your React Components’ output&lt;/strong&gt;. Enzyme’s main role is to prepare React components for testing by mount, shallow, or render methods and to provide various methods for selecting desired components. It also provides a series of APIs used to examine the component’s properties. For more details please follow this link to check the Enzyme docs directly. Enzyme needs a testing library to provide a foundation for the tests it generates. It’s commonly used along with Jest.&lt;/p&gt;
&lt;h2&gt;
  
  
  Jest
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Jest is a fully-featured testing framework&lt;/strong&gt;. It provides a test runner and provides dozens of methods that can be used in testing along with an assertion library. &lt;a href="https://jestjs.io/docs/expect" rel="noopener noreferrer"&gt;Follow this link to check the assertion library API&lt;/a&gt; directly in Jest docs. Jest combined with Enzyme works great for React, but it’s not limited just to React. It’s very popular and widely used in the JavaScript ecosystem. For web applications built entirely in vanilla JavaScript, Jest allows you to test the whole application with one test library.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;a href="https://profil-software.com/estimate-project/" rel="noopener noreferrer"&gt;Enjoying this article? Need help? Talk to us!&lt;br&gt;
Receive a free consultation on your software project&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Enzyme render methods — what do they do and what are they for?
&lt;/h2&gt;

&lt;p&gt;Mount — Ideal for use cases when you have components that may interact with the DOM API or use React lifecycle methods in order to fully test the component. This is the default method when writing component tests.&lt;/p&gt;

&lt;p&gt;Shallow — Renders only a single component, not including its children. It is useful to isolate the component for pure unit testing. The biggest advantage is that it protects against changes or bugs in a child component.&lt;/p&gt;

&lt;p&gt;A summary of both methods can be found in the table below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnskfnjmkfiav675632gr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnskfnjmkfiav675632gr.jpg" alt=" " width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Testing stateful functional components — useState hook
&lt;/h2&gt;

&lt;p&gt;Mocking the useState hook&lt;/p&gt;

&lt;p&gt;To properly test stateful functional components, &lt;strong&gt;it would be good to start with mocking the useState hook along with the setState function&lt;/strong&gt;. The SearchReposInput component’s purpose is to handle text entered by the user and pass it to the Redux action on button press.&lt;/p&gt;

&lt;p&gt;The image below shows how to handle mocking. The Jest.fn() method in the setState function will be needed to ensure setState was called with the correct arguments or the correct number of times. There is an option to set the default useState value, but in this case it will be left untouched.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const setState = jest.fn();
    const useStateSpy = jest.spyOn(React, 'useState');
    useStateSpy.mockImplementation(initialState =&amp;gt; [initialState, setState]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the mock is correctly set up, it is time to write some tests. For this component, testing should start by finding an input. It can be done by CSS class name. It’s also a good practice to find input or any other interactive element by value seen by the user like placeholder text, button name, etc. An example of the test can be found in the image below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; it('should update state on input change', () =&amp;gt; {
        const newInputValue = 'React is Awesome';
        wrapper.find('.ant-input').simulate('change', { target: { value: newInputValue } });
        expect(setState).toHaveBeenCalledWith(newInputValue);
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Mocking Redux hooks
&lt;/h2&gt;

&lt;p&gt;The code below, taken from SearchReposInput.test, also &lt;strong&gt;shows how to mock the React-Redux useSelector and useDispatch hooks&lt;/strong&gt;. When writing tests for components using the Redux dispatch method to dispatch actions, there should be a spy assigned to the method.&lt;/p&gt;

&lt;p&gt;It can be done the same way as you see in the image below. It will provide an option to check which function is dispatched along with its arguments. Tests that run on Redux’s store values need to return a mock value from the useSelector method. It provides better control over the tested component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mockDispatch = jest.fn();
jest.mock('react-redux', () =&amp;gt; ({
    useSelector: jest.fn().mockReturnValue({
        // useSelector will return redux state object
        repositories: {
            loading: false,
            repos: [],
        },
    }),
    useDispatch: () =&amp;gt; mockDispatch,
}));

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

&lt;/div&gt;



&lt;p&gt;The code below, also taken from SearchReposInput.test, shows how to mock functions from external modules. It can be useful when a test needs specific conditions like a mocking response from a function calling an external API. In this example, along with Jest’s spy on a mocked function, it was necessary to mock function output. &lt;strong&gt;Mocked values should be close to the original response to make the testing case more realistic&lt;/strong&gt;. This was achieved by using mockReturnedValue. When the expected response is a promise, the mockResolvedValue method should be used instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jest.mock('../../actions/networkActions', () =&amp;gt; ({
    fetchRepos: jest.fn().mockResolvedValue({
        data: {
            name: 'name',
            description: 'some description',
            language: 'javascript',
            stargazers_count: 1,
            forks: 2,
            owner: {
                repos_url: '',
                type: '',
                avatar_url: '',
                login: '',
            },
            created_at: '2020:10:12',
            updated_at: '2020:10:14',
            license: {
                name: 'MIT',
            },
        },
    }),
}));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing logic inside the useEffect hook
&lt;/h2&gt;

&lt;p&gt;One of the most common use cases for the useEffect hook is to &lt;strong&gt;execute API calls after component mounts&lt;/strong&gt;. A good testing example of this feature is fetching data and further data processing in useEffect.&lt;/p&gt;

&lt;p&gt;Once the user presses the details button on one of the repositories in the repositories list, a modal opens, displaying the selected repository details. One of the sections displays other repositories linked to the selected repository owner. Those “extra” repositories are fetched after the modal mounts, to be ready when users press the additional user repositories dropdown panel. To test if components behave as expected, some preparations are required. First, &lt;strong&gt;mock the fetchAdditionalUserRepos function from the networkActions module along with its response, as shown in the image below.&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;const mockFetchAdditionalUserReposResponse = ['repo1', 'repo2', 'repo3'];
const mockFetchAdditionalUserRepos = jest.fn().mockResolvedValue(mockFetchAdditionalUserReposResponse);
networkActions.fetchAdditionalUserRepos = mockFetchAdditionalUserRepos;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since it's a promise, the mock will be handled by the mockResolved function.&lt;br&gt;
With everything prepared, we can write a test to ensure extra data is correctly fetched after the component mounts. The test code is presented in the image below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('fetch additional user repos on mount', () =&amp;gt; {      expect(mockFetchAdditionalUserRepos).toHaveBeenCalledWith('repos_url');     expect(setState).toHaveBeenCalledWith(mockFetchAdditionalUserReposResponse);
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Redux Thunk — testing async actions is easy!&lt;/strong&gt;&lt;br&gt;
In this section, I’d like to focus on testing &lt;strong&gt;asynchronous actions&lt;/strong&gt;. Those actions are handled by Redux thunk middleware. Testing them is more complicated, especially for the first time. I’ll also show you how to mock the axios library to return resolved or rejected values that are needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The main goal is to ensure that all expected actions are correctly executed when the fetchRepos function is called.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Testing preparation starts by mocking a Redux store via the configureMockStore function from Redux-mock-store library. An example of a Redux store mock is shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we have to &lt;strong&gt;mock the axios library&lt;/strong&gt; to imitate the correct network call. Since only the get method from the axios module is needed for this test, only this method will be mocked. The image below presents a mock get method from the axios library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mockedGet = jest.fn().mockResolvedValue({ data: { items: [mockedRepository, mockedRepository] } });
        axios.get = mockedGet;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to &lt;strong&gt;prepare a variable with expected actions and their payload&lt;/strong&gt;. The image below displays how the expected actions array should look for the given example — fetchRepos test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const expectedActions = [
            {
                type: NetworkActionNames.START_FETCHING_REPOS,
            },
            { type: NetworkActionNames.FETCHING_REPOS_DONE, payload: [mockedRepository, mockedRepository] },
        ];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once all mocks are prepared, it is time for a thunk action test. This test will check if all asynchronous actions were called in the correct order and carried an expected payload. It will also ensure that the axios get method was called before any Redux action. Example code for the thunk action is displayed in the image below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const store = mockStore([]);
        return store.dispatch(fetchRepos('React')).then(() =&amp;gt; {
            expect(mockedGet).toHaveBeenCalled();

            expect(store.getActions()).toEqual(expectedActions);
        });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Redux Testing — make your app state great again (and bug-free, of course)
&lt;/h2&gt;

&lt;p&gt;This section will focus on the reducers testing. Every Redux testing scenario should start with an initial state check. The image below displays an example test for checking the correct value of the reducer's initial state. Example code for an initial state test is shown in the image below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('should return initial state', () =&amp;gt; {
        expect(repositories(undefined, {})).toEqual(repositoriesReducerInitialState);
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reducer tests for all action cases are mandatory to ensure that every Redux action listener acts as expected and the action payload is correctly handled. A test’s job is to check if the returned, updated state value is the same as the one saved in the expected state variable. Those kinds of tests are very straightforward and help maintain app state management. An example of the reducer test code is shown in the image below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('should handle START_FETCHING_REPOS action', () =&amp;gt; {
        expect(
            repositories(repositoriesReducerInitialState, {
                type: NetworkActionNames.START_FETCHING_REPOS,
                payload: undefined,
            })
        ).toEqual({
            ...repositoriesReducerInitialState,
            loading: true,
        });
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;a href="https://profil-software.com/careers/" rel="noopener noreferrer"&gt;Interested in working for our software development company in Poland?&lt;br&gt;
Check out our current job offers now&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Snapshot testing — should we even care about it?
&lt;/h2&gt;

&lt;p&gt;Snapshot tests compare the JSON image of the rendered component with the JSON image created during the previous tests.&lt;/p&gt;

&lt;p&gt;As opposed to end-to-end tests, snapshot tests are run in a command line runner rather than a real browser. It is a good way to ensure our component looks exactly as we want. It’s useful especially when the look changes dynamically depending on passed props.&lt;/p&gt;

&lt;p&gt;Even if they’re not popular among the React community and often skipped, it’s good to know what they are, what they do, and of course how to write one.&lt;/p&gt;

&lt;p&gt;The image below displays code for a snapshot test. The renderer creates the method that returns a component snapshot which can be further transformed to a JSON object. The JSON object format is required by the toMatchSnapshot function which, under the hood, compares the current component tree to the historical snapshot saved in the snapshot file. An example of a snapshot file can be found &lt;a href="https://github.com/dybik08/github-browser/blob/master/src/__tests__/RepoDetailsModal/RepoInfoRow/__snapshots__/RepoInfoRow.test.tsx.snap" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('renders correctly', () =&amp;gt; {
        const tree = renderer.create(wrapper).toJSON();
        expect(tree).toMatchSnapshot();
    });

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion — receiving another bug report makes you mad? Consider testing!
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This knowledge should help you start code testing using React and Redux&lt;/strong&gt;. With your code test covered, you will get rid of struggles with the same bugs which reoccur from time to time. If you’ve ever been in a situation where you’re nervous to add new code to an existing codebase in the fear that you’ll break something in a completely different part of the code, &lt;strong&gt;make your and your teammates’ lives easier by diving into the testing world! When developing an application it's important to include&lt;/strong&gt; &lt;strong&gt;&lt;a href="https://profil-software.com/services/software-testing-and-quality-assurance/" rel="noopener noreferrer"&gt;QA testing &lt;/a&gt;&lt;/strong&gt;&lt;strong&gt;services as well.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Need to check something directly in the source code? Visit: &lt;a href="https://github.com/dybik08/github-browser" rel="noopener noreferrer"&gt;https://github.com/dybik08/github-browser&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you'd like to get more tips on programming and how to be a better programmer, our software development blog features many subjects that may interest you. Learn &lt;a href="https://profil-software.com/blog/development/4-non-coding-tips-on-how-to-improve-coding-skills/" rel="noopener noreferrer"&gt;how to improve your coding skills&lt;/a&gt;, how to Streamline Your Wagtail &lt;a href="https://profil-software.com/blog/development/5-tips-to-streamline-your-wagtail-cms-development/" rel="noopener noreferrer"&gt;CMS Development&lt;/a&gt;, and many more.&lt;/p&gt;

</description>
      <category>nuxt</category>
      <category>a11y</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Sentiment analysis on Twitter posts</title>
      <dc:creator>Profil Software</dc:creator>
      <pubDate>Tue, 14 Feb 2023 13:20:35 +0000</pubDate>
      <link>https://forem.com/profilsoftware/sentiment-analysis-on-twitter-posts-3j82</link>
      <guid>https://forem.com/profilsoftware/sentiment-analysis-on-twitter-posts-3j82</guid>
      <description>&lt;p&gt;Hi! I’m Przemysław from AI Development Company Profil Software. This will be my 2nd article connected with AI. If you want to answer the question of how can object classification be easily fooled you should refer to the first article of mine.&lt;/p&gt;

&lt;p&gt;This time I will try to present some hands-on examples of how to deal with simple NLP tasks like sentiment analysis. The solutions used in this article could be easily reused in other classification tasks. We will traverse the rough trails of AI starting with data cleaning and preprocessing, then move on to model definition and visualising the results. The solution was prepared using Google Colab and will be shared at the end. So are you ready? ;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;While using Google Colab no external packages are required to run the solution. Libraries like scikit-learn are already included. While moving to another environment you can easily grab dependencies using the !pip freeze command in a notebook cell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dataset
&lt;/h2&gt;

&lt;p&gt;In this article I will be using Twitter dataset from the kaggle competition . The dataset consists of 1.6M tweets written in English and extracted using the Twitter api. They are grouped into 2 classes (named targets):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;positive (target 0 in csv)&lt;/li&gt;
&lt;li&gt;negative (target 4 in csv)
The dataset also contains other columns like corresponding date or the user that posted the tweet. For the purpose of this article, we will be using text and target info only. What can be useful for further processing might be the data distribution over the 2 classes. Part of the code responsible for loading the dataset and counting target distribution is presented below:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import pandas as pd

df = pd.read_csv(
  filepath_or_buffer='data/training.1600000.processed.noemoticon.csv',
  encoding="ISO-8859-1",
  usecols=[0, 5],
  names=['target', 'text'],
  engine='python',
  error_bad_lines=False,
)

df['target'].value_counts().plot(kind='bar')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Sample rows of the raw dataset are displayed below:&lt;/p&gt;

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

&lt;p&gt;At first glance we can see that data is a bit dirty and can be cleaned to remove bogus parts like links and mentions. To briefly apply simple preprocessing, some pandas utils were used. You can see that part below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;remove all urls and user mentions, hashtags,&lt;/li&gt;
&lt;li&gt;accept only letters and digits&lt;/li&gt;
&lt;li&gt;remove extra spaces&lt;/li&gt;
&lt;li&gt;parse everything to lowercase&lt;/li&gt;
&lt;li&gt;rename target class 4 -&amp;gt; 1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Enjoying this article? Need help? Talk to us!&lt;/em&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://profil-software.com/estimate-project/" rel="noopener noreferrer"&gt;Receive a free consultation on your software project&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sample output of preprocessed data (can be compared with previous image):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwcxeg2019xpdup2nuno.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwcxeg2019xpdup2nuno.jpg" alt=" " width="727" height="542"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Data split
&lt;/h2&gt;

&lt;p&gt;To be able to train our AI model we need to first split the data into train and test sets. The code below shows how to do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
from sklearn.model_selection import train_test_split

TEST_SIZE = .1
RANDOM_STATE = 123

def split_data(test_size: float = TEST_SIZE, random_state: int = RANDOM_STATE):
  X = df['text']
  y = df['target']

  X_train, X_test, y_train, y_test = train_test_split(X, y, 
                                                      test_size=test_size, 
                                                      random_state=random_state,
                                                      stratify=y)
  return X_train, X_test, y_train, y_test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used therandom_state option to enable reproductivity between experiments, while the stratify option is responsible for enabling similar distribution of classes in both sets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model
&lt;/h2&gt;

&lt;p&gt;The first model that will be checked is a so-called Bag of words model. The bag-of-words model is a simplifying representation used in NLP. In this model, a text (such as a sentence or a document) is represented as the bag (multiset) of its words, disregarding grammar and even word order but keeping multiplicity. Its visualisation is presented below:&lt;/p&gt;

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

&lt;p&gt;I will implement it using CountVectorizer from sklearn which converts a collection of text documents to a matrix of token counts. This approach will then enable us to use preprocessed vectors as an input for the LogisticRegression model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression

NGRAM_RANGE = 2
MAX_ITER = 1000

vectorizer = CountVectorizer(ngram_range=(1, NGRAM_RANGE))
X_train = vectorizer.fit_transform(X_train)
X_test = vectorizer.transform(X_test)

log_reg = LogisticRegression(max_iter=MAX_ITER, random_state=RANDOM_STATE)
log_reg = log_reg.fit(X_train, y_train)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, with just a few lines of code we can prepare a fully working model. In the above code, NGRAM_RANGE describes how many coexisting words will be analysed as a feature. MAX_ITER enables us stop the algorithm after a certain amount of iteration; for such big datasets it is sometimes safe to limit that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;And voilà, that was it, we did it. Now let’s see what results we receive.&lt;/p&gt;

&lt;p&gt;For sklearn models, we can use visualisation functions that help with ad hoc prototyping.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;classification_report: grabs prediction and true labels and prepares printable report&lt;/li&gt;
&lt;li&gt;plot_confusion_matrix: plots a heat-map of classification; for binary classification it will have a structure of 4 squares
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from sklearn.metrics import classification_report, plot_confusion_matrix

print(classification_report(log_reg.predict(X_train), y_train))
print(classification_report(log_reg.predict(X_test), y_test))

plot_confusion_matrix(log_reg, X_train, y_train)
plot_confusion_matrix(log_reg, X_test, y_test)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outputs of both functions are presented below:&lt;/p&gt;

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

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

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

&lt;p&gt;As we can see, the model reaches above 80% accuracy for the unknown samples which is a great result compared to the amount of code that was used to achieve that.&lt;/p&gt;

&lt;p&gt;_&lt;br&gt;
Interested in working for our software development company in Poland?_&lt;br&gt;
&lt;em&gt;&lt;a href="https://profil-software.com/careers/" rel="noopener noreferrer"&gt;Check out our current job offers now&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Feature importance
&lt;/h2&gt;

&lt;p&gt;The logistic regression model enables us to use its features (in our case 1-word or 2-words pairs) and coefficients calculated during data fitting to obtain features that are influential for choosing a specific label. Below is a short snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import numpy as np

top_n = 10

features = vectorizer.get_feature_names()

# get features with lowest coeficients
positive = np.argsort(log_reg.coef_[0])[::-1][:top_n]

# get features with heighest coeficients
negative = np.argsort(log_reg.coef_[0])[:top_n]

print(f'\n Positive features: \n {[features[x] for x in positive]}')
print(f'\n Negative features: \n {[features[x] for x in negative]}')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Positive features: ['not sad', 'no problem', 'doesnt hurt', 'not bad', 'no problems', 'no prob', 'not problem', 'never too', 'no probs', 'cant miss'] Negative features: ['clean me', 'not happy', 'sad', 'passed away', 'rip', 'not looking', 'funeral', 'headache', 'disappointing', 'upsetting']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Here is the complete solution (&lt;a href="https://github.com/profilsoftware/sentiment-detection-article):" rel="noopener noreferrer"&gt;https://github.com/profilsoftware/sentiment-detection-article):&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;In the next article I will try to implement a model doing the same task but constructed with neural networks. Can’t wait for it and I hope that you cannot wait for it either!&lt;/p&gt;

&lt;p&gt;Source:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://colab.research.google.com/" rel="noopener noreferrer"&gt;https://colab.research.google.com/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.kaggle.com/kazanova/sentiment140" rel="noopener noreferrer"&gt;https://www.kaggle.com/kazanova/sentiment140&lt;/a&gt;&lt;br&gt;
Thanks to Katarzyna Latarska. &lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>discuss</category>
      <category>learning</category>
      <category>career</category>
    </item>
    <item>
      <title>Make your code more Pythonic with Magic Methods</title>
      <dc:creator>Profil Software</dc:creator>
      <pubDate>Mon, 16 Jan 2023 10:12:28 +0000</pubDate>
      <link>https://forem.com/profilsoftware/make-your-code-more-pythonic-with-magic-methods-23al</link>
      <guid>https://forem.com/profilsoftware/make-your-code-more-pythonic-with-magic-methods-23al</guid>
      <description>&lt;h2&gt;
  
  
  Dunders
&lt;/h2&gt;

&lt;p&gt;If you spend some time with Python you will eventually hear about something called “dunder”. Even if you haven’t and this name sounds odd to you I can bet that you’ve used it multiple times and just didn’t know what was called. To make it easier — dunder is an abbreviation of two words: “double under”, where “under” is yet another abbreviation, this time of the word “underscore”. Knowing this, you probably already know what I am talking about. Yes, the Python &lt;strong&gt;init&lt;/strong&gt; method is one of many dunders (also sometimes called “magic method”) that we can use in Python.&lt;/p&gt;

&lt;p&gt;Dunders are internal cogs that do work when on the surface we use built-in methods, operators and keywords that make Python so easy to read and write. For a good start, we can look at which dunders are provided with the base object that every other class inherits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
o = object()
dir(o)
[
    "__class__",
    "__delattr__",
    "__doc__",
    "__format__",
    "__getattribute__",
    "__hash__",
    "__init__",
    "__new__",
    "__reduce__",
    "__reduce_ex__",
    "__repr__",
    "__setattr__",
    "__sizeof__",
    "__str__",
    "__subclasshook__",
]

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

&lt;/div&gt;



&lt;p&gt;Straight off the bat we have 15 dunders. Let’s just take some of them and see what they do. If you’ve ever used Django you are probably familiar with the &lt;strong&gt;str&lt;/strong&gt; method, used often when declaring models. This is the one responsible for returning the string representation of… well, anything in Python. Whenever you use the built-in function str(), this dunder will be called and it will decide what string will be returned. Similarly, when you use print to log something in the console, the &lt;strong&gt;str&lt;/strong&gt; dunder will be called.&lt;/p&gt;

&lt;p&gt;Some dunders are called when you use specific keywords in Python. For example, &lt;strong&gt;delattr&lt;/strong&gt; is called when you use the keyword del, as when deleting dictionary entries for instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dictionary = { 'key': value }
del dictionary['key']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, these 15 dunders are just a small fraction of what can be used. Some of the more useful are ones that allow us to override operators. This is a concept known for a very long time in other programming languages. In C++ you can overload operators to have a special meaning when used with objects that provide the overload definition. In Python you can do the same by implementing, for example, the &lt;strong&gt;add&lt;/strong&gt; method that is responsible for handling the addition operator. To demonstrate, we can create a simple class that will allow us to “simplify” adding elements to a list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Appender:
    def __init__(self):
        self.array = []

    def __add__(self, other):
        self.array.append(other)
        return self

    def __str__(self):
        return str(self.array)


ap = Appender()
ap + 3 + 5 + 6 + 9 + 12

print(ap)
# output: [3, 5, 6, 9, 12]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, we implemented the Appender class that overrides the &lt;strong&gt;add&lt;/strong&gt; method to append a new element to a list it keeps inside every time we use a + operator. After that we return the Appender instance so we can do it many times over by chaining operators.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Enjoying this article? Need help? Talk to us!&lt;br&gt;
&lt;a href="https://profil-software.com/estimate-project/" rel="noopener noreferrer"&gt;Receive a free consultation on your software project&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How about something useful?
&lt;/h2&gt;

&lt;p&gt;Ok, so Appender shows that you can do some creative stuff with operators in Python to cause non-standard behavior of the code. Some of it is really useful and is even in the Python standard library. For example, have you ever wondered how you add timedelta to the datetime object? Yup, operator overload. Here is the example from the cpython repository, file &lt;a href="https://github.com/python/cpython/blob/main/Lib/datetime.py#L2067" rel="noopener noreferrer"&gt;datetime.py&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def __add__(self, other):
    "Add a datetime and a timedelta."
    if not isinstance(other, timedelta):
        return NotImplemented

    delta = timedelta(
        self.toordinal(),
        hours=self._hour,
        minutes=self._minute,
        seconds=self._second,
        microseconds=self._microsecond,
    )
    delta += other
    hour, rem = divmod(delta.seconds, 3600)
    minute, second = divmod(rem, 60)
    if 0 &amp;lt; delta.days &amp;lt;= _MAXORDINAL:
        return type(self).combine(
            date.fromordinal(delta.days),
            time(hour, minute, second, delta.microseconds, tzinfo=self._tzinfo),
        )
    raise OverflowError("result out of range")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of the interesting approaches of using dunders can also be found in pathlib. It is a library meant to help you work with filesystem. Before it was included in the standard library (it’s been there since Python 3.4) you would most likely have used os.path for creating path names and opening files. However, if you did it even once you know how cumbersome that was. Say you want to get the parent directory of the current code file. You can use os.path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import os
parent_dir = os.path.dirname(os.path.abspath(__file__))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not that bad, right? Well, this is just the directory of the file. Imagine you want to go a bit lower; you have to wrap that thing in another os.path.dirname invocation. Alternatively, you can use pathlib for a smoother approach.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from pathlib import Path
print(Path(__file__).resolve().parent)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Easier, right? But what does it have to do with dunders anyway? Well, pathlib also introduces one neat trick to help you create paths. Let’s say you want to create a path from your working directory to the directory foo that is in the directory bar. In pathlib you can do it 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;p = Path('/etc')
p / 'init.d' / 'redis-server'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dividing the Path object by a string will work similarly to our Appender class. It will join path and return a new Path object, ready to be joined again with another string. Thanks to the usage of the &lt;strong&gt;truediv&lt;/strong&gt; (or &lt;strong&gt;div&lt;/strong&gt; if you are still using Python 2.x) we can create paths in a way that is intuitive and similar to how paths are represented in string format. Here is how it looks in the source code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def __truediv__(self, key):
    try:
        return self._make_child((key,))
    except TypeError:
        return NotImplemented
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Interested in working for our software development company in Poland?&lt;br&gt;
&lt;a href="https://profil-software.com/careers/" rel="noopener noreferrer"&gt;Check out our current job offers now&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ORMs love dunders
&lt;/h2&gt;

&lt;p&gt;If you’ve ever used any Python web framework, you’ve probably also used ORM for easier database handling. During my work at Profil Software - Python Development Company I usually use Django as my backend web framework and with it - a built-in Django ORM. If you were using other, less feature-complete frameworks (like Flask or Pyramid) you would probably use SQLAlchemy. Both of these libraries heavily use Python magic methods to make database usage as painless as possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj47ddliwzugb7nw0uwt7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj47ddliwzugb7nw0uwt7.jpg" alt="Image description" width="592" height="206"&gt;&lt;/a&gt;&lt;br&gt;
For example, creating a connection between a model field and an actual database uses something called descriptors. The &lt;strong&gt;get&lt;/strong&gt;, &lt;strong&gt;set&lt;/strong&gt;, and &lt;strong&gt;delete&lt;/strong&gt; methods are, respectively, three of the dunders that control what happens when values are read, set or deleted. Overriding each of these magic methods controls what happens when you manipulate model fields.&lt;/p&gt;

&lt;p&gt;So, when you have a User object and you try to access a value of the related field, the code in the &lt;strong&gt;get&lt;/strong&gt; descriptor is fired, data is fetched from the database, and you get straight to the value. Behavior like this is possible because of descriptors. The entire descriptor function for Django models is quite long so I won’t place it here, but &lt;a href="https://github.com/django/django/blob/54ea290e5bbd19d87bd8dba807738eeeaf01a362/django/db/models/fields/related_descriptors.py#L155" rel="noopener noreferrer"&gt;you can see it directly on GitHub.&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is only one example. ORMs use these mechanics heavily. Let’s see how you would create a query using SQLAlchemy using a NOT statement. You actually have two options of doing that. If we want to get users that don’t start with “bob”, you can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from sqlalchemy.sql.expression import not_


User.query.filter(not_(User.username.startswith('bob')))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can skip the import of the NOT expression and use a bitwise NOT like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User.query.filter(~User.username.startswith('bob'))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both will produce the same outcome thanks to ColumnElement subclasses implementing their own &lt;strong&gt;invert&lt;/strong&gt; dunder that controls operator behavior. With this you can skip the import of the not_ expression and reduce the length of your code line while still preserving the general explicitness of what you want to achieve.&lt;/p&gt;

&lt;h2&gt;
  
  
  With great power comes great responsibility
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvs709sltriaef6cv00yn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvs709sltriaef6cv00yn.jpg" alt="Image description" width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is, of course, just a small sample of what can be done with dunder mechanisms. If you know of other interesting implementations of operator overriding, let me know in the comments section, and if you want to read more about Python and coding check out our articles on 2 Questions to Ask Before Choosing &lt;a href="https://profil-software.com/blog/development/2-questions-ask-choosing-python-framework/" rel="noopener noreferrer"&gt;Python Frameworks&lt;/a&gt; and 10 things you need to know to effectively use &lt;a href="https://profil-software.com/blog/development/10-things-you-need-know-effectively-use-django-rest-framework/" rel="noopener noreferrer"&gt;Django Rest Framework.&lt;/a&gt;&lt;br&gt;
Python is a language that gives you a lot of freedom in what you do with your code. Dunders allow you to get extremely creative with how you approach various problems and let you to write very intuitive frameworks, ORMs and libraries for you and others to use. It lets you write code that looks natural even for someone that doesn’t have a lot of experience in programming. It also allows you to write an ugly, obfuscated code if you want to be a bad person.&lt;/p&gt;

&lt;p&gt;Dunders are a feature that allow you to do both of these things at the same time and that’s why it is so important to keep in mind that readability, intelligibility and widely accepted good practices should be paramount in your code.&lt;/p&gt;

&lt;p&gt;Profil Software is not only a Python Development Company, we also offer &lt;a href="https://profil-software.com/services/react-native-app-development/" rel="noopener noreferrer"&gt;React Native Agency&lt;/a&gt; and &lt;a href="https://profil-software.com/services/devops-services/" rel="noopener noreferrer"&gt;DevOps Services&lt;/a&gt;, and we cover these subjects in our blog as well so feel free to check it out.&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Database Comparison - SQL vs. NoSQL (MySQL vs PostgreSQL vs Redis vs MongoDB)</title>
      <dc:creator>Profil Software</dc:creator>
      <pubDate>Wed, 04 Jan 2023 14:18:57 +0000</pubDate>
      <link>https://forem.com/profilsoftware/database-comparison-sql-vs-nosql-mysql-vs-postgresql-vs-redis-vs-mongodb-2e0l</link>
      <guid>https://forem.com/profilsoftware/database-comparison-sql-vs-nosql-mysql-vs-postgresql-vs-redis-vs-mongodb-2e0l</guid>
      <description>&lt;p&gt;Hey there! I’m Maciej from an &lt;a href="https://profil-software.com/services/python-app-development/" rel="noopener noreferrer"&gt;outsource python development company&lt;/a&gt; that works on &lt;a href="https://profil-software.com/industries/speech-recognition-software/" rel="noopener noreferrer"&gt;speech recognition software development&lt;/a&gt;, &lt;a href="https://profil-software.com/industries/shareholder-management-software/" rel="noopener noreferrer"&gt;shareholder management software&lt;/a&gt; and more. I recently performed many database operations which took hours to complete. Waiting for too long in this way may force you to search for a better alternative to your current database engine, so I started looking for something new. To help me in my search, I tried to find a comparison based on database performance, but couldn’t find anything which suited me. That’s when I decided to create my own small comparison.&lt;/p&gt;

&lt;h2&gt;
  
  
  Databases
&lt;/h2&gt;

&lt;p&gt;For my analysis I used 4 databases:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;li&gt;MongoDB
**&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here we have both &lt;strong&gt;SQL&lt;/strong&gt; and &lt;strong&gt;NoSQL&lt;/strong&gt; databases. The main difference between these two is that SQL databases, also called Relational Databases (RDBMS), have relational structure and NoSQL doesn’t use relations. SQL databases are vertically scalable, which means one ultimate machine will do the work for you. On the other hand, NoSQL databases are horizontally scalable, which means multiple smaller machines will do the work for you.&lt;/p&gt;

&lt;p&gt;Comparing NoSQL and SQL databases is hard to do, because of differences in build. User Euphoric made a good comment about this on StackExchange:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The thing you are missing about NoSQL is that NoSQl cannot be compared to SQL in any way. NoSQL is name of all persistence technologies that are not SQL. Document DBs, Key-Value DBs, Event DBs are all NoSQL. They are all different in almost all aspects, be it structure of saved data, querying, performance and available tools.&lt;br&gt;
But for this comparison I’m going to test only insert, select, update and remove operations which can be performed both in NoSQL and SQL.&lt;/p&gt;
&lt;/blockquote&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%2Fszaw8n05y7jrxf9ut4z4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fszaw8n05y7jrxf9ut4z4.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Google trends shows that MySQL is a true champ in searches, but does it come with great performance? Let’s check it out!&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%2Fsk58f1863iq31oikc9x8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsk58f1863iq31oikc9x8.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;MySQL&lt;/strong&gt; is a full-featured, relational database management system sponsored by the company MYSQL AB, but still the source code is open source. It’s written in C and C++ and works with most current operating systems. In this comparison I used version 5.7 which will be supported to October 2023.&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%2Fa1t82dub0r8qtg00m85w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1t82dub0r8qtg00m85w.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt; is also an open-source, relational database management system. It is not controlled by a single company but is developed through community effort. PostgreSQL provides support for advanced data types and optimization.&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%2Fypltjllo9z98pp741jat.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypltjllo9z98pp741jat.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Redis&lt;/strong&gt; is an open source (BSD), in-memory key-value data structure store, which can be used as a database, cache or message broker. It’s a NoSQL database used in GitHub, Pinterest and Snapchat. Redis performance and atomic manipulation of data structures solves problems which can often be found with relational databases.&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%2Fbt8fzyjfcmiod5zxe8c0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbt8fzyjfcmiod5zxe8c0.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;MongoDB&lt;/strong&gt; is a general purpose, document-based, distributed database. It is another example of a NoSQL database. Record in MongoDB is a document, which is a data structure composed of field and value pairs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Enjoying this article? Need help? Talk to us!&lt;br&gt;
&lt;a href="https://profil-software.com/estimate-project/" rel="noopener noreferrer"&gt;Receive a free consultation on your software project&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;p&gt;After gathering some databases for comparison, I needed to use a language which would have good drivers for them. I didn’t have to look much into that because my main language, Python, provides a number of good drivers for these databases.&lt;/p&gt;

&lt;p&gt;The drivers I used for the specified database are:&lt;/p&gt;

&lt;p&gt;MySQL -&amp;gt; &lt;strong&gt;MySQL Connector&lt;/strong&gt;&lt;br&gt;
Postgres -&amp;gt; &lt;strong&gt;psycopg2&lt;/strong&gt;&lt;br&gt;
Redis -&amp;gt; &lt;strong&gt;redis-py&lt;/strong&gt;&lt;br&gt;
MongoDB -&amp;gt; &lt;strong&gt;PyMongo&lt;/strong&gt;&lt;br&gt;
To manage all the databases in a single application I created Docker-compose, which handled the databases as services. Using Docker to manage the databases allowed me to omit installing every database locally.&lt;/p&gt;

&lt;p&gt;Here is an example which I used to generate sample data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3'

services:
  postgres:
    container_name: postgres_container
    image: postgres
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-postgres}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
      PGDATA: /data/postgres
    volumes:
    - postgres:/data/postgres
    ports:
    - "5432:5432"
    restart: unless-stopped

  mysql:
    image: mysql:5.7
    privileged: true
    command: "--skip-grant-tables"
    volumes:
    - my-datavolume:/var/lib/mysql
    environment:
      MYSQL_ROOT_USER: mysql
      MYSQL_ROOT_PASSWORD: mysql
      MYSQL_DATABASE: mysql
      MYSQL_USER: mysql
      MYSQL_PASSWORD: mysql
    ports:
    - '3306:3306'

  mongodb:
    image: mongo:latest
    container_name: mongodb
    ports:
      - "27017:27017"

  redis:
    container_name: redis
    image: redis
    ports:
    - "6379:6379"
    volumes:
    - ../data/redis:/data
    restart: always

  web:
    build: .
    depends_on:
    - postgres
    - mysql
    - redis
    - mongodb

volumes:
  postgres:
  my-datavolume:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to create similar execution of every operation, I created database dispatcher, which executed a specified operation for every database.&lt;/p&gt;

&lt;p&gt;Here you can see the part for the insert operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class DataDispatcher:
    databases = {
        'mysql': MySQLDatabase(),
        'postgres': PSQLDatabase(),
        'redis': RedisDatabase(),
        'mongo': MongoDatabase()
    }

def get_insert_data(self):
    insert_data = {}
    for name, database in self.databases.items():
        print(Insert for: {name})
    insert_data[name] = database.generate_insert_data()
    return insert_data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Operations
&lt;/h2&gt;

&lt;p&gt;For the comparison I used all CRUD operations, so we will be looking at &lt;strong&gt;create, read, update,&lt;/strong&gt; and &lt;strong&gt;delete&lt;/strong&gt;.&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%2Fl292m6zxryx8hemnjrcj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl292m6zxryx8hemnjrcj.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
In the &lt;strong&gt;create&lt;/strong&gt; category we can observe that Mongo and Redis are definitely better. At about 400–500 operations MySQL also looks good, but it decreases in performance after 600 records, with results similar to Postgres.&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%2Fj981sr44zpon9gp30js0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj981sr44zpon9gp30js0.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
The &lt;strong&gt;select&lt;/strong&gt; operation shows that SQL also has a bad time here. Performing it in MySQL and Postgres, time grows rapidly. For NoSQL it doesn’t matter how many records it needs to select, time is basically constant.&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%2Fx046k6f1amnosmok2bsi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx046k6f1amnosmok2bsi.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Time consumption for &lt;strong&gt;update&lt;/strong&gt; is also much bigger for SQL databases, but the increase in time is similar for both databases. Time of operation for Redis and Mongo and MySQL is under 1 second for 5000 records. Only Postgres gives results over 10 seconds.&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%2Fygiaa1m987pqqwu77zpe.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygiaa1m987pqqwu77zpe.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Here we have the biggest differences in results. The &lt;strong&gt;delete&lt;/strong&gt; operation for Redis shows that having all records in memory allows for almost instant data removal. Time of removing records for SQL databases is stable. For Mongo we can see that the time of removal depends on the number of records.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Interested in working for our software development company in Poland?&lt;br&gt;
&lt;a href="https://profil-software.com/careers/" rel="noopener noreferrer"&gt;Check out our current job offers now&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;This comparison shows the time for a specific type of operation and single use case of database. In most cases, &lt;strong&gt;Redis&lt;/strong&gt; had the best performance because it is just key/value storage, so when I performed operations to find records with a specified value it was logical that it should win.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NoSQL&lt;/strong&gt; relies on demoralization and creates optimization for the deformalized case. If we take a blog post for example, everything connected with single (text, comments, likes etc.) will be stored in a single document, so there won’t be a need to perform any join operations.&lt;/p&gt;

&lt;p&gt;In this comparison we can see that single CRUD operations are much faster in NoSQL databases, but we still need to remember that SQL can perform many more operations. Besides this, the speed of the database depends on the application you are creating.&lt;/p&gt;

&lt;p&gt;For other articles on programming you may refer to our software development blog from which you'll learn how to use Django Rest Framework more effectively, how to improve your coding skills, and more.&lt;/p&gt;

</description>
      <category>database</category>
      <category>postgres</category>
      <category>python</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Demystifying Python metaclasses Why are they so special?</title>
      <dc:creator>Profil Software</dc:creator>
      <pubDate>Thu, 22 Dec 2022 07:37:51 +0000</pubDate>
      <link>https://forem.com/profilsoftware/demystifying-python-metaclasses-why-are-they-so-special-38gf</link>
      <guid>https://forem.com/profilsoftware/demystifying-python-metaclasses-why-are-they-so-special-38gf</guid>
      <description>&lt;h2&gt;
  
  
  Classes with class — metaclasses in Python
&lt;/h2&gt;

&lt;p&gt;Hi! My name is Jakub Barański and I’m a full stack developer at Profil Software, a &lt;a href="https://profil-software.com/services/python-app-development/" rel="noopener noreferrer"&gt;Python software development&lt;/a&gt; company that also offers the services of &lt;a href="https://profil-software.com/services/react-native-app-development/" rel="noopener noreferrer"&gt;react native agency&lt;/a&gt; and more. For creating backend, I usually use Python, so I wanted to dive into one of the aspects of this language that I find very interesting.&lt;/p&gt;

&lt;p&gt;When you are beginning to learn any object oriented programming language, you need to understand two concepts: classes and instances. A basic simplification that allows you to quickly understand them is that classes are blueprints or schematics, logical entities based on which instances are created. On the other hand, instances are actual “physical” objects that have a state and some specific behavior. Going further into machine-related stuff, declaring a class will not allocate memory, whereas creating an instance will. This is a bit of an oversimplification, but for the most part it is correct.&lt;/p&gt;

&lt;p&gt;Instances are created using a constructor, a block of code that specifies what should happen when memory is allocated for an object. Things that in other programming languages you would do in a constructor, you usually do in the &lt;strong&gt;init&lt;/strong&gt; method in Python.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Dog:
    def __init__(self, good_boy: bool):
        self.good_boy = good_boy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, when you take a close look at arguments passed to the constructor, you will notice that the first argument is always self. Isn’t this object already created at this point? Well…it is. What you will most likely find when googling “python constructor” is not actually a constructor but a so-called “initializer”. It is not responsible for creating an object instance but for instantiating its state. The method that creates an object in Python is called &lt;strong&gt;new&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;class Dog:
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, *args, **kwargs)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Enjoying this article? Need help? Talk to us!&lt;br&gt;
&lt;a href="https://profil-software.com/estimate-project/" rel="noopener noreferrer"&gt;Receive a free consultation on your software project&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s take a look at the arguments again. This time we have cls as the first argument instead of self. Its name can probably already suggest what it is, but let’s do a sanity check by adding print to the constructor.&lt;/p&gt;

&lt;p&gt;Now when we create our object we should see what that mysterious cls is all about.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dog = Dog()
# &amp;lt;class 'Dog'&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual class is passed to the constructor of the object. But should that even be possible? Didn’t we establish in the first paragraph that typical classes are just logical entities that are not stored in runtime memory? Well, of course we did. Using the built-in id() method, however, will return the memory address of our class. Therefore, we can now say with absolute certainty that  is an actual object. This is an example of a first class citizen — an entity that can be used in any operation in your code, whether that’s passing it as an argument to the function, returning it from the function, or even modifying it at runtime. We often say that in Python everything is an object, but for some reason it’s hard to accept that classes are objects too.&lt;/p&gt;

&lt;p&gt;OK, but if a class is an object, shouldn’t it also be constructed somehow? Shouldn’t it have some…well, &lt;strong&gt;class&lt;/strong&gt;? Thanks to Python’s great ability for introspection, we can easily check that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dog_class = dog.__class__
print(dog_class)
# &amp;lt;class 'Dog'&amp;gt;
print(dog_class.__class__)
# &amp;lt;class 'type'&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it will get a little weird. Looks like the class of our Dog class is type It may look very similar to the built-in method type, that we use to acquire the type of an object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type('hello')
# &amp;lt;class 'str'&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s very similar because it’s actually the very same thing. It might be getting a bit confusing at this point, but don’t worry. When we are in trouble, Python has another useful built-in method for us to clear things up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;help(type)
"""
Help on class type in module builtins:

class type(object)
 | type(object_or_name, bases, dict)
 | type(object) -&amp;gt; the object's type
 | type(name, bases, dict) -&amp;gt; a new type
...
"""
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So as you can see, the built-in type method is overloaded and behaves differently depending on what it gets as arguments (it doesn’t really comply with the Zen of Python, right? “Simple is better than complex”?. Oh well, they had their reasons).&lt;/p&gt;

&lt;p&gt;Keeping that in mind, we’ve slowly but surely reached the actual subject of this article — metaclasses. Our built-in type method is a metaclass - a class that is used as a blueprint to create classes. Let’s try to go deeper. What is a class of a metaclass?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;obj.__class__.__class__.__class__
# &amp;lt;class 'type'&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fortunately, that’s it. All classes in Python by default have type as a metaclass. A metaclass is then used to create a class that is then used to create objects.&lt;/p&gt;

&lt;p&gt;But what can we use this knowledge for? Firstly, we can use the second functionality of type to do something that is unheard of in most other programming languages. We can dynamically create classes. We can invoke type and provide it with three arguments. First is the name of our new class. Second is a tuple of bases — parent classes that our new class should be derived from. Third is a dictionary with our class attributes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cat = type("Cat", (), {})
c = Cat()
c
# &amp;lt;__main__.Cat object at 0x7fcbb21eb358&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating classes like that is not a very common scenario, but it can be useful in some cases.&lt;/p&gt;

&lt;p&gt;Also, now that we know type is a metaclass, we can subclass it to create our own metaclasses and provide our own logic to the class constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class GreatestMetaclass(type):
    def __new__(metacls, name, bases, attrs):
        x = super().__new__(metacls, name, bases, attrs)
        # do some absolutely amazing stuff here...
        return x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we want to create a class that implements our GreatestMetaclass we can do it 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;class GreatestClass(meta=GreatestMetaclass):
    pass
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GreatestClass will now implement all of the magic we wrote in the metaclass definition.&lt;/p&gt;

&lt;p&gt;What can we use a metaclass for? Plenty of things. For example, you can use it to keep a registry of classes that implements it.&lt;br&gt;
&lt;/p&gt;

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


class RegistryMetaclass(type):
    def __new__(metacls, name, bases, attrs):
        registry[name] = super().__new__(metacls, name, bases, attrs)
        return registry[name]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Interested in working for our software development company in Poland?&lt;br&gt;
&lt;a href="https://profil-software.com/careers/" rel="noopener noreferrer"&gt;Check out our current job offers now&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Metaclasses are also used a lot in many different Python frameworks. We can take a look at the biggest &lt;a href="https://profil-software.com/blog/development/2-questions-ask-choosing-python-framework/" rel="noopener noreferrer"&gt;Python web framework&lt;/a&gt; Django and its extensive use of metaclasses in its ORM (the &lt;a href="https://github.com/django/django/blob/main/django/db/models/base.py#L61" rel="noopener noreferrer"&gt;custom logic of just the ModelBase metaclass constructor takes about 300 lines of code!&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Thanks to the use of the ModelBase metaclass in Model classes that are used to reflect database tables, we can simply declare our model 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;class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With such an implementation, we can very quickly create models with a minimal amount of code. We just declare fields by creating attributes and assigning field types to them. All the work related to connecting your class with Django ORM is covered by the metaclass’s inner mechanisms and you can instead focus on creating your model structure and application logic.&lt;/p&gt;

&lt;p&gt;Another example of a popular library where metaclasses are used is &lt;a href="https://profil-software.com/blog/development/10-things-you-need-know-effectively-use-django-rest-framework/" rel="noopener noreferrer"&gt;Django Rest Framework&lt;/a&gt; and it's &lt;a href="https://profil-software.com/blog/development/10-things-you-need-know-effectively-use-django-rest-framework/#understanding-different-types-of-serializers" rel="noopener noreferrer"&gt;serializers&lt;/a&gt;. SerializerMetaclass creates a _declared_fields dictionary in the serializer class which contains all instances of the Field class that were included in the serializer class as attributes (or as attributes in the inherited superclass). Objects that implement SerializerMetaclass can then create a deep copy of these fields and use them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class UserSerializer(serializers.Serializer):
    email = serializers.EmailField()
    username = serializers.CharField(max_length=200)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One metaclass that many python programmers might have used is an abstract base class metaclass (ABCMeta). Usually we create abstract classes in Python by deriving our class from the ABC, but in reality it is just a helper class that has ABCMeta as its metaclass. ABC was created to bypass the usage of metaclasses in cases that can be more confusing than simple inheritance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from abc import ABC, ABCMeta


class MyABC(ABC):
    pass


# this is the same thing as :


class AlsoABC(metaclass=ABCMeta):
    pass
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, so earlier I wrote that “there are plenty of things you can use metaclasses for”. The real question is though — SHOULD we do this? To be completely honest, I had only a handful of situations where I thought that creating a metaclass would help me with anything. Even then I immediately came to the conclusion that there are a ton of other solutions that are much simpler. I think it’s useful to know they exist because it allows you to better understand how Python is designed and how it works under the hood. However, if you want to actually use these features in your code you should have a good reason to do so. Otherwise, you are just making your implementation more obscure and that is never a good idea. Once again, look at the Zen of Python: “If the implementation is hard to explain, it’s a bad idea”. The creator of said zen has an opinion about metaclasses, so in the end let me just quote him:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don’t.&lt;br&gt;
-Tim Peters&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>gratitude</category>
    </item>
    <item>
      <title>Python riddle to solve in reasonable time</title>
      <dc:creator>Profil Software</dc:creator>
      <pubDate>Tue, 13 Dec 2022 11:51:39 +0000</pubDate>
      <link>https://forem.com/profilsoftware/python-riddle-to-solve-in-reasonable-time-459i</link>
      <guid>https://forem.com/profilsoftware/python-riddle-to-solve-in-reasonable-time-459i</guid>
      <description>&lt;p&gt;Hello. My name is Robert Krawiec. I am a mathematics major. I’ve been working for Profil Software (a company offering &lt;a href="https://profil-software.com/services/python-app-development/"&gt;Python Development Services&lt;/a&gt; that also offers s&lt;a href="https://profil-software.com/services/software-testing-and-quality-assurance/"&gt;oftware testing services&lt;/a&gt; and &lt;a href="https://profil-software.com/services/ui-ux-design-services/"&gt;UX/UI Design Services&lt;/a&gt;) for quite some time. I often use different algorithms and I find my mathematical background useful while developing web apps using object-oriented languages.&lt;/p&gt;

&lt;p&gt;Today I would like to share with you a riddle that I came across while working here. It goes like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Find a number that ends with the digit 2 and has the following feature: if you create a new number by moving the last digit into position as the first digit, this new number will be twice as big as the original one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As complicated as it sounds, we can transcribe this riddle into an equation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Re0quyq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/erykcfen8tp7cjzabctf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Re0quyq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/erykcfen8tp7cjzabctf.png" alt="Image description" width="306" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are looking for a number ab…n2; let’s call it x for the remainder of the article. Just to clarify things, the dots are meant to represent that we don’t know how many digits this number has.&lt;/p&gt;

&lt;p&gt;Seems quite straightforward eh? Well, that was my first observation too. Anyway, let me share my research with you. I would also like to show you some different approaches to this problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Construction method
&lt;/h2&gt;

&lt;p&gt;Some of you may be familiar with the concept of constructing different mathematical objects. We’re going to use construction method here, but it’s not really something that is straightforward, so let’s take a closer look at it.&lt;/p&gt;

&lt;p&gt;Let’s take two sides of the equation. Let’s say y=2*(ab..n2) and z = 2ab..n . We already know that in order to fit the equation, y and z must be the same length.&lt;/p&gt;

&lt;p&gt;This is derived from the fact that two numbers may be equal only when they share the same length. Wait, what… since y and z are the same length, and y simply equals 2*x, and the first digit in the number z is 2, we can conclude that the first digit in the number x is indeed 1.&lt;/p&gt;

&lt;p&gt;So now the problem gets easier. We can conclude that the digit in position n in the number x is twice as big as the digit in position n+1. This is another feature that is derived from what we’ve stated above. Now we can start constructing such a number having in mind that the written method for multiplication uses carry overs. So it goes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2
42
842
6842
36842
736842
4736842
94736842
894736842
7894736842
57894736842
157894736842
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, let’s check this number. It may be our solution since it has a 2 at the end and a 1 at the beginning. Nope, let’s proceed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
3157894736842
63157894736842
263157894736842
5263157894736842
05263157894736842
105263157894736842
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ve finally found a solution by constructing such a number. We can see that if we continue constructing numbers, we will come across a pattern.&lt;/p&gt;

&lt;p&gt;Every 16 construction steps we’re going to have a number that is a solution to our problem. Moreover, since the set of all natural numbers is infinite and there is a pattern, we can say that there are an infinite number of solutions to this problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Enjoying this article? Need help? Talk to us!&lt;br&gt;
&lt;a href="https://profil-software.com/estimate-project/"&gt;Receive a free consultation on your software project&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Brute-force search method
&lt;/h2&gt;

&lt;p&gt;Since we use a lot of Python in our everyday work, I figured I would use it to perform an exhaustive search, even though I’m quite aware of the fact that this is not the most effective language for such a task. I am also going to use my own i7 4/8 processor.&lt;/p&gt;

&lt;p&gt;For the sake of clarity, I will note down the partial time needed for an exhaustive search script to reach 10 figures. For obvious reasons, I won’t run every version of the code until it finds the solution.&lt;/p&gt;

&lt;p&gt;Let’s summarize what we know about the candidates for such a number. We certainly know that it ends with 2, which means we can decrease our search by a factor of 10. Here’s the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import time
start_time=time.time()
start = 12
while True:
 if 2*start == int(str(start)[-1] + str(start)[0:-1]):
      print(time.time() - start_time)
      break
 else:
     start += 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s run it and measure its partial efficiency. We’ve calculated that it has taken around a minute to reach the first number that consists of 10 digits.&lt;/p&gt;

&lt;p&gt;Now that we can see the code works, let’s look at how we can possibly improve it. The problem here is that we are wasting a lot of time because of how we increment.&lt;/p&gt;

&lt;p&gt;Let’s use this code to jump to a higher range to ignore numbers that do not start with 1. Here’s the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import time
start_time=time.time()
start = 12
while True:
 if 2*start == int(str(start)[-1] + str(start)[0:-1]):
      print(time.time() - start_time)
      break
 else:
      while True:
           start += 10
           if str(start)[0] == '1':
                break
           else:
                start += 8*(10**(len(str(start))-1))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As with the previous algorithm, we’ve tested it and it takes about 45 seconds to reach 10 digits.&lt;/p&gt;

&lt;p&gt;That’s a significant improvement. Now let’s use a generator to populate the queue on the fly. Here’s some code that is doing pretty much the same thing, but in a different way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import time
start_time=time.time()
def gen(start):
 while True:
      start += 10
      if str(start)[0] == '1':
           yield start
      else:
           start += 8*(10**(len(str(start))-1))
g = gen(12)
for number in g:
     if str(number)[0] and 2*number int(str(number[-1]+str(number[0:-1]):
          print(time.time() - start_time)
          break
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can run this code, but unfortunately it does not hasten our search, because it still takes around 45 seconds to fulfill its job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There’s an exponential growth in the amount of numbers that we have to check. Let’s take for instance the amount of numbers that we need to check that have 9 digits.&lt;/p&gt;

&lt;p&gt;We know that each number must have 1 as the first digit and 2 as the last, so we end up with 10 000 000 numbers to check. We can see that each time the range is increased, the amount of numbers that we have to check is 10 times bigger than the previous one. Using this information, we can express how many possible solutions there are. To count the amount of digits that might be a solution to our problem, we can use the formula for the partial sum of a geometrical series, which in this case is represented by:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8xA6hxdi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/py2hhaqolseblgj07gm9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8xA6hxdi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/py2hhaqolseblgj07gm9.png" alt="Image description" width="240" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, there are 1111111 numbers that we have to check before getting into numbers that have 10 digits. That way, we can estimate how much checking each candidate takes, which is 0.0405000041 ms per number. We can use it as the lower limit of this operation, which means that operations on bigger numbers can take at least that long, but might take longer.&lt;/p&gt;

&lt;p&gt;As we all know, it’s a mundane assignment to use an exhaustive search to find a really big number. After countless attempts to speed up finding the solution using multiprocessing or multi-threading with Python, I came to the conclusion that distributing everything across the processors yourself is almost as good as Python managing these kinds of tasks on its own.&lt;/p&gt;

&lt;p&gt;Next, I thought I’d estimate the time needed to check all possible candidates that have less than 18 digits. I figured out that it would take years, which makes solving this problem using a brute-force search very ineffective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Interested in working for our software development company in Poland?&lt;br&gt;
&lt;a href="https://profil-software.com/careers/"&gt;Check out our current job offers now&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Breaking down the problem
&lt;/h2&gt;

&lt;p&gt;To solve a problem, it’s imperative to find as many features of the problem as possible.&lt;/p&gt;

&lt;p&gt;Looking at the brute-force search, it’s ineffective mostly because we didn’t find more features or assumptions to start with. Let’s take a look at the problem using the first equation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yOh9rZ6A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/biyq1daqqyo9bjq5rvsk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yOh9rZ6A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/biyq1daqqyo9bjq5rvsk.png" alt="Image description" width="307" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can transform it into:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---e5syCw4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jl8sg2w5kvt7x5cp6tsf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---e5syCw4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jl8sg2w5kvt7x5cp6tsf.png" alt="Image description" width="536" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LV7Io00G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0vjx0g0adyf954fnx3j6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LV7Io00G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0vjx0g0adyf954fnx3j6.png" alt="Image description" width="465" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let k = ab..n (Which is our number without the 2 at the end). Then:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mm-UU-jW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ixmt7hsp9xkjsl2z4141.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mm-UU-jW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ixmt7hsp9xkjsl2z4141.png" alt="Image description" width="309" height="70"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally we get:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zf586RWC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zjsn4z0rbsnjorxi69a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zf586RWC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zjsn4z0rbsnjorxi69a.png" alt="Image description" width="261" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We know that k is a possible solution to our problem. Let’s create a function that takes n = len k as an argument. Which in this case will be next natural numbers.&lt;/p&gt;

&lt;p&gt;We get:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cKufJtb8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/40w1gl2f9wse6eekep7d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cKufJtb8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/40w1gl2f9wse6eekep7d.png" alt="Image description" width="237" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s take a look at what this function’s values are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2
10.315789
3
105.052632
4
1052.421053
5
10526.105263
6
105262.947368
7
1052631.368421
8
10526315.578947
…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that this function approximates solutions to our problem based on it’s length.&lt;/p&gt;

&lt;p&gt;For n = 17 we get the first whole number which is our ab…z without 2 at the end. If we were to continue, another solution would pop up every 16 incrementations. We can see this function works like a generator, especially when you look for the integer part of those numbers. It works just like the construction method above except it builds the solution from the left side and omits the number 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;We have just shown some examples of how to solve this kind of puzzle. Despite the fact that we worked hard to make the brute-force search time effective, we failed to do so.&lt;/p&gt;

&lt;p&gt;This is something that we could have expected based on its nature and the vast number of possible solutions. That’s why it is always useful to seek more elegant solutions, even when they do not come to us very easily. If you're curious about other things related to Python, such as making your code more Pythonic using &lt;a href="https://profil-software.com/blog/development/make-your-code-more-pythonic-magic-methods/"&gt;Python Magic Methods&lt;/a&gt; or choosing a&lt;a href="https://profil-software.com/blog/development/2-questions-ask-choosing-python-framework/"&gt; Python Framework &lt;/a&gt;for a Startup, make sure to look through our software development blog.&lt;/p&gt;

&lt;p&gt;I hope that you have found this article useful.&lt;/p&gt;

</description>
      <category>python</category>
      <category>mathematics</category>
      <category>riddles</category>
      <category>programming</category>
    </item>
    <item>
      <title>10 things you need to know to effectively use Django Rest Framework</title>
      <dc:creator>Profil Software</dc:creator>
      <pubDate>Wed, 07 Dec 2022 10:14:44 +0000</pubDate>
      <link>https://forem.com/profilsoftware/10-things-you-need-to-know-to-effectively-use-django-rest-framework-c4b</link>
      <guid>https://forem.com/profilsoftware/10-things-you-need-to-know-to-effectively-use-django-rest-framework-c4b</guid>
      <description>&lt;p&gt;In this article I want to share some ideas and tricks that I got to know while working with Django Rest Framework for a Python Development Company. Django Rest Framework, created by Tom Christie, is probably the most endorsed package for building RESTful APIs in Django. Examples shown here are compatible with version 3 of DRF. If you have questions about choosing a Python Frameworks or want to learn how to solve riddles in python, check out our software development blog.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Viewsets
&lt;/h2&gt;

&lt;p&gt;Let’s start with a simple (thus one of my favorites) DRF functionality. Viewsets can be considered as extremely useful templates for your API views that provide typical interactions with your Django models. While regular views act as handlers for HTTP methods, viewsets give you actions, like create or list. The great thing about viewsets is how they make your code consistent and save you from repetition. Every time you write views that should do more than one thing, a viewset is the thing that you want to go for.&lt;/p&gt;

&lt;p&gt;Let’s imagine there is a Tag model in your project and you need to prepare a functionality that will let your users: list all the tags, create a new tag and retrieve its details. Here’s how you can define a viewset for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class TagViewSet(
    mixins.ListModelMixin,
    mixins.CreateModelMixin,
    mixins.RetrieveModelMixin,
    GenericViewSet,
):
    """
    The following endpoints are fully provided by mixins:
    * List view
    * Create view
    """

    queryset = Tag.objects.all()
    serializer_class = TagSerializer
    permission_classes = (permissions.IsAuthenticated,)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Viewset mixins can be combined as needed. You can define your own mixins or use ModelViewSet, which provides the following actions: .list(), .retrieve(), .create(), .update(), .partial_update(), and .destroy() .&lt;/p&gt;

&lt;p&gt;In addition, when using viewsets you typically want to use routers for url configuration. This enforces best practices in naming your ulrs, making your API urls easily predictable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.conf.urls import url, include
from rest_framework.routers import DefaultRouter

api_router = DefaultRouter()
api_router.register(r"tag", TagViewSet, "tag")

urlpatterns = [url(r"^v1/", include(api_router.urls, namespace="v1"))]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your viewset is functional enough that you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;list all your tags by sending GET request to v1/tag/,&lt;/li&gt;
&lt;li&gt;POST new tag to v1/tag/ or&lt;/li&gt;
&lt;li&gt;retrieve one of the tags by GET v1/tag/.
You can even add some custom action to your viewset using @action decorator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that writing views is finished, you’ve saved enough time to have a cup of coffee.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding different types of serializers
&lt;/h2&gt;

&lt;p&gt;As a DRF user you don’t need to bother with views and url configurations, so you will probably pay most of your attention to serializers, which act as translators between Django model instances and their representations such as json. There is a handful of functionalities connected with serializers that you might want to know.&lt;/p&gt;

&lt;p&gt;Every serializer can be used for both reading and writing operations. The way it is initialized determines the action that it will fulfill. In these terms we can distinguish 3 types of serializers: create, update and retrieve.&lt;/p&gt;

&lt;p&gt;If in your view you want to serialize data that will be transmitted outside of your API, this is how you do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def retrieve(self, request, *args, **kwargs):
    instance = self.get_object()
    serializer = ProfileSerializer(instance=instance)
    return Response(serializer.data)`

But in your create view you will define it in a different way:
def create(self, request, *args, **kwargs):
   `serializer = ProfileSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    serializer.save()
    return Response(serializer.data)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, when updating an instance, you need to provide instance as well as data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def update(self, request, *args, **kwargs):
    instance = self.get_object()
    serializer = ProfileSerializer(instance=instance, data=request.data)
    serializer.is_valid(raise_exception=True)
    serializer.save()
    return Response(serializer.data)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;serializer.save() invokes an appropriate internal method based on arguments passed at initialization.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Interested in working for our software development company in Poland?&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;a href="https://profil-software.com/careers/" rel="noopener noreferrer"&gt;Check out our current job offers now!&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Using SerializerMethodField
&lt;/h2&gt;

&lt;p&gt;SerializerMethodField is a read only field that computes its value at request processing time, by calling a method on the serializer class it is attached to. Let’s say you have a model that stores datetime in a models.DateTimeField, but you want to use timestamp from epoch in your serialized representation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from rest_framework import serializers


class TagSerializer(serializers.ModelSerializer):
    created = serializers.SerializerMethodField()

    class Meta:
        model = Tag
        fields = ("label", "created")


def get_created(self, obj):
    return round(obj.created.timestamp())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SerializerMethodField accepts method_name, but it’s usually more convenient to use the default pattern for naming those methods, which is get_. Just make sure you‘re not overburdening your method fields with any heavy-lifting operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the source parameter
&lt;/h2&gt;

&lt;p&gt;Very often, your model field names will differ from the required representation. Using the serializer field source parameter will let you handle this easily. Take a look at this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from rest_framework import serializers


class TaskSerializer(serializers.ModelSerializer):
    job_type = serializers.CharField(source="task_type")

    class Meta:
        model = Task
        fields = ("job_type",)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The field task_type is in the Task model, but it will be represented in your API as a job_type. This works for both read and write operations.&lt;/p&gt;

&lt;p&gt;Moreover, you can use it to fetch data from related objects using dotted notation:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;owner_email = serializers.CharField(source='owner.email')&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Serializer field validation
&lt;/h2&gt;

&lt;p&gt;Aside from a validators argument that can be passed when initializing a serializer field and aserializer.validate() hook, there is also field-level validation, which allows you to write a unique validation method for each field separately. There are two reasons I find it useful: first, it decouples different checks that are related only to a particular field, and second, it generates well formatted error responses. Usage of this kind of validation is similar to using SerializerMethodField, but this time you have to follow a method naming convention: def validate_. Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from rest_framework import serializers


class TransactionSerializer(serializers.ModelSerializer):
    bid = serializers.IntegerField()

    def validate_bid(self, bid: int) -&amp;gt; int:
        if bid &amp;gt; self.context["request"].user.available_balance:
            raise serializers.ValidationError(_("Bid is greater than your balance"))

    return bid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the bid exceeds the user’s balance, this is how the response should look:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
 "bid": ["Bid is greater than your balance"]&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Validation methods must always return a value, which is later passed to a model instance. Keep in mind that field level validation is invoked by serializer.to_internal_value(), which takes place before calling serializer.validate().&lt;/p&gt;

&lt;p&gt;Passing a value directly to the save methodCopy icon&lt;br&gt;
In some cases it is convenient to pass a value from outside of a serializer directly to its save() method. This method will take arguments that can be equated with serialized objects. Values passed this way won’t be validated. It may be used to force an override of the initial data. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serializer = EmailSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save(owner_id=request.user.id)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using CurrentUserDefault
&lt;/h2&gt;

&lt;p&gt;When it comes to automatically setting a user as a resource owner, there is an even a better way than the one presented in the previous example. It’s by using the CurrentUserDefault class, which doesn’t require any override of views.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from rest_framework import serializers


class EmailSerializer(serializers.ModelSerializer):
    owner = serializers.HiddenField(default=serializers.CurrentUserDefault())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It does two things. First, the user authenticated in the request object will be set as default. Second, because of using HiddenField, any incoming data is not taken into account, so it’s impossible to set another user as an owner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Enjoying this article? Need help? Talk to us!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://profil-software.com/services/software-development-consulting/tech-stack-recommendation/" rel="noopener noreferrer"&gt;Receive a free consultation on your software project!&lt;/a&gt;&lt;br&gt;
_&lt;/p&gt;
&lt;h2&gt;
  
  
  Serializers initial data
&lt;/h2&gt;

&lt;p&gt;Sometimes you may need to access a serializer’s raw input. It’s either because data has been already modified by running serializer.is_valid(), or it’s needed to compare the value of another field in a validation method when validated_data is not yet available. It can be achieved by accessing serializer.initial_data, which stores raw input as a Dict, as shown in this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from rest_framework import serializers


class SignupSerializer(serializers.ModelSerializer):
    password1 = serializers.CharField()
    password2 = serializers.CharField()


def validate_password1(self, password1):
    if password1 != self.initial_data["password2"]:
        raise serializers.ValidationError("Passwords do not match")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handling multiple creates/updates/deletes in nested serializers
&lt;/h2&gt;

&lt;p&gt;Most of the time serializers are completely straightforward and with some experience, there’s nothing that could go wrong. However, there are some limitations. Things can get a little tricky when you have to support multiple creates, updates and deletes in nested serializers within one high-level serializer. It comes with a trade-off: there is a smaller number of requests to process at the cost of a longer processing time. By default, DRF doesn’t support multiple updates at all. It’s hard to imagine how it could support all possible types of nested insertions and deletions. That’s why the creators of DRF chose flexibility over an out-of-the-box “do-everything” solution, and left that privilege for us.&lt;/p&gt;

&lt;p&gt;There are two paths you can follow in this case:&lt;/p&gt;

&lt;p&gt;use the quite popular, third party library &lt;a href="https://github.com/beda-software/drf-writable-nested" rel="noopener noreferrer"&gt;DRF Writable Nested&lt;/a&gt;&lt;br&gt;
do it on your own&lt;br&gt;
I would recommend choosing the second option at least once, so you will know what’s going underneath.&lt;/p&gt;

&lt;p&gt;After analyzing incoming data, in most scenarios, we are able to make the following assumptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;all items that should be updated have id,&lt;/li&gt;
&lt;li&gt;all items that should be created don’t have id,&lt;/li&gt;
&lt;li&gt;all items that should be deleted are present in data storage (eg. database), but are missing in the incoming request.data
Based on this, we know what to do with particular items on the list. Below is a snippet that shows this process in detail:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class CUDNestedMixin(object):
    @staticmethod
    def cud_nested(
        queryset: QuerySet,
        data: List[Dict],
        serializer: Type[Serializer],
        context: Dict,
    ):
        """
        Logic for handling multiple updates, creates and deletes on nested resources
        :param queryset: queryset for objects existing in DB
        :param data: initial data to validate passed from higher level serializer to nested serializer
        :param serializer: nested serializer to use
        :param context: context passed from higher level serializer
        :return N/A
        """
        updated_ids = list()
        for_create = list()
        for item in data:
            item_id = item.get("id")
        if item_id:
            instance = queryset.get(id=item_id)
            update_serializer = serializer(
                instance=instance, data=item, context=context
            )
            update_serializer.is_valid(raise_exception=True)
            update_serializer.save()
            updated_ids.append(instance.id)
        else:
            for_create.append(item)

            delete_queryset = queryset.exclude(id__in=updated_ids)
            delete_queryset.delete()

            create_serializer = serializer(data=for_create, many=True, context=context)
            create_serializer.is_valid(raise_exception=True)
            create_serializer.save()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And here is the simplified version of how a high-level serializer can make use of this mixin:&lt;br&gt;
from rest_framework import serializers&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class AccountSerializer(serializers.ModelSerializer, CUDNestedMixin):
    phone_numbers = PhoneSerializer(
        many=True,
        source="phone_set",
    )

    class Meta:
        model = User
        fields = ("first_name", "last_name", "phone_numbers")

    def update(self, instance, validated_data):
        self.cud_nested(
            queryset=instance.phone_set.all(),
            data=self.initial_data["phone_numbers"],
            serializer=PhoneSerializer,
            context=self.context,
        )
        ...
        return instance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep in mind that nested objects should consume initial_data instead of validated_data. That’s because running validation calls field.to_internal_value() on each of a serializer’s fields, which may modify data stored by a particular field (eg. by changing primary key to model instance).&lt;/p&gt;

&lt;h2&gt;
  
  
  Override data to force ordering
&lt;/h2&gt;

&lt;p&gt;By default, Django querysets are not ordered at all. Enforcing ordering on the list view can easily be accomplished by adding ordering to the view’s queryset, but in cases where nested resources should also be ordered, it’s not so simple. For read-only fields, it can be done within SerializerMethodField, but what to do in a situation where a field has to be writable? In such a case, a serializer’s data property can be overridden, as shown in this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@property
def data(self):
    data = super().data
    data["phone_numbers"].sort(key=lambda p: p["id"])
    return data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;I hope that you’ve found some new interesting techniques in this article. There are plenty of other functionalities that I would like to cover in another article on this blog, so it’s worth coming back here. If you want to read more content about Python, I recommend checking out the one about &lt;a href="https://profil-software.com/blog/development/demystifying-python-metaclasses-why-are-they-so-special/" rel="noopener noreferrer"&gt;Python metaclasses&lt;/a&gt;. Profil Software also offers &lt;a href="https://profil-software.com/services/react-native-app-development/" rel="noopener noreferrer"&gt;react native agency&lt;/a&gt; and&lt;a href="https://profil-software.com/services/javascript-app-development/" rel="noopener noreferrer"&gt;javascript development services&lt;/a&gt;, and we have some articles written on these subject as well so feel free to scroll through our blog.&lt;/p&gt;

&lt;p&gt;Do you know any DRF tricks that you want to share? Post your ideas in the comment section!&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>writing</category>
    </item>
    <item>
      <title>‘7 Tips to Reduce SaaS Customer Churn Rate’ by UX Lead</title>
      <dc:creator>Profil Software</dc:creator>
      <pubDate>Tue, 12 Jul 2022 06:50:03 +0000</pubDate>
      <link>https://forem.com/profilsoftware/7-tips-to-reduce-saas-customer-churn-rate-by-ux-lead-a6m</link>
      <guid>https://forem.com/profilsoftware/7-tips-to-reduce-saas-customer-churn-rate-by-ux-lead-a6m</guid>
      <description>&lt;p&gt;Nowadays a lot of startups and business software face the problem of losing users. And we are not talking about quick unsubscriptions that happen when the product is really bad, but about the loss of regular users who have been with you for some time.&lt;/p&gt;

&lt;p&gt;Let’s take a look at this problem.&lt;/p&gt;

&lt;p&gt;It seemed to be a great start — you attracted an excellent dedicated software development team and UI and UX design agency who created a beautiful and useful product, you spent time and money on promotional materials, videos, advertising, and landing pages, then you got the first users, first paid subscriptions and good reviews. Success! Some time has passed, six months, a year or two… and you begin to notice that users are leaving you. What hurts the most is that those who have been with you from the very beginning are leaving as well. Why is this happening? Based on my experience, there are usually two possible reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User behaviour.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The fact is that it is not enough to create a cool project. The user is not a robot, but a person with feelings and emotions, which means that their interest needs to be maintained.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Product development.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It’s not enough to launch a product and only engage in technical support. Today the IT industry is developing so rapidly that sometimes products lose relevance before they hit the market. It may seem like a joke, but there’s a lot of truth to it.&lt;/p&gt;

&lt;p&gt;What can we do to stop our users from leaving and multiply them instead?&lt;/p&gt;

&lt;p&gt;I combined 7 short tips into a small checklist:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BhBasFZD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r4tnedqhgrzokwes2537.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BhBasFZD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r4tnedqhgrzokwes2537.png" alt="Image description" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s get into the details:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make your users feel important&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Have you ever wondered how to reduce customer churn rate? Here are a few things that you can do. Send out information about new updates, ask users for their opinion, and set up useful tips according to their preferences and previous behavior. Knowing what they want, need, and look for in your application will help you find a way to personalize the content and connect with your user. This will in turn make them feel valued and increase their attachment to your product.&lt;/p&gt;

&lt;p&gt;This goal can also be achieved by sending a newsletter.&lt;/p&gt;

&lt;p&gt;If you don’t feel that you will be able to continuously add new content for newsletter purposes, you could prepare a 90-day onboarding strategy and automate it. User onboarding is a process that can be very crucial for the success of your app and it can prevent you from losing users in the first week after your app’s launch. Studies show that there is a huge decrease in users over the first 90 days after launch. Typically, users will install an app and then lose interest in it in the coming weeks, which can be seen on the graph prepared by Google Play Store for a study on users’ behavior:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p30R5Z_U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pb343zpxmjug82errqsb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p30R5Z_U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pb343zpxmjug82errqsb.png" alt="Image description" width="880" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, what can you do to keep these users even after this 90-day period and prevent customer churn? Create a user onboarding experience that will bring your customer and product closer together. You need to introduce your product, activate the user, and then make sure that you retain them to the point which your product becomes a part of their lives. You can achieve this with a user-friendly design and personalization.&lt;/p&gt;

&lt;p&gt;It will make them stay during those first few weeks, and if you complete the process in the right way, it will make them stay for a longer period of time.&lt;/p&gt;

&lt;p&gt;Enjoying this article? Need help? Talk to us!&lt;/p&gt;

&lt;p&gt;Receive a free consultation on your software project&lt;/p&gt;

&lt;p&gt;Another good idea is to send re-engagement emails to inactive subscribers.&lt;/p&gt;

&lt;p&gt;You can use Mailchimp &lt;a href="https://mailchimp.com/"&gt;https://mailchimp.com/&lt;/a&gt; to do it — it is a very popular service with a large community, or e.g. Woodpecker &lt;a href="https://woodpecker.co/"&gt;https://woodpecker.co/&lt;/a&gt; — an alternative solution that is less complex but also a bit more basic. It has a lot of necessary functions such as importing users in xls files, creating AB campaigns, great functions that facilitate personalization, and even the ability to send messages to people in relation to their time zone so they will be receiving emails at the time that will guarantee the highest level of response.&lt;/p&gt;

&lt;p&gt;In addition to addressing users personally, the newsletter/90-day onboarding strategy/re-engagement emails should also include in a graphic form (if available) the avatar of the user that we are addressing our mailing to. Thanks to this there will be an even greater feeling of personalization. For example, this technique is used by Linkedin, which also recently enabled users to create newsletters. The graphic form used in a newsletter should be minimalistic and simple. If you want to learn more about creating a newsletter on Linkedin, you can find more information here: &lt;a href="https://www.linkedin.com/help/linkedin/answer/a517925/create-a-newsletter-on-linkedin?lang=en"&gt;https://www.linkedin.com/help/linkedin/answer/a517925/create-a-newsletter-on-linkedin?lang=en&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Shower users with benefits&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Do not treat a user who is with you for a month and one that is with you for a year in the same way. Long-term users should get benefits, discounts, special offers, and unexpected bonuses. Highlight it all with numbers showing statistics and money saved. This will show the user how important they are to you and take attention away from small imperfections of the product. Everyone likes to feel special — preserve this feeling.&lt;/p&gt;

&lt;p&gt;In addition to designing your custom solutions to provide benefits, you can use ready-made software to manage them. I do not want to give a specific example here, but after entering “SaaS Customer Loyalty Management Software” in Google you will find ready-made solutions to be implemented in your SaaS product. I have also found a lot of interesting articles on this subject and I would like to recommend you this one especially: &lt;a href="https://userguiding.com/blog/loyalty-management-program-software/"&gt;https://userguiding.com/blog/loyalty-management-program-software/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zy6w3mjq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/81b93apzn3u6afhhsqc3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zy6w3mjq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/81b93apzn3u6afhhsqc3.png" alt="Image description" width="880" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build a personal connection with the user.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is necessary to show a personal attitude to your user. Your product should not be “cold”, but friendly and inviting. Recently there has been a lot of talk about the importance of personalization of products.&lt;/p&gt;

&lt;p&gt;It might seem obvious, and to a certain extent it is, but sending personal messages to users, calling them by their names, and wishing them a good day in a welcome message is a practice that can help you build a connection with your users and thus make them more open to the idea of investing in your product or service. You’ll find a few examples of this kind of message below. The first one is a welcome message that not only restates the purpose of the app, making sure to let you know that by registering you’ll be doing something good by taking your “first step towards the sustainability of the public eco-transport”, but also welcomes you warmly and offers to answer any questions you might have.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3Ac26fIH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t4gphj78wd0t5xbze5ds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3Ac26fIH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t4gphj78wd0t5xbze5ds.png" alt="Image description" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second is a personalized message that encourages the customer to keep investing in the product. Notice how they use the customer’s name, remind them that they have already used the products offered by the company, and that the products offered by the company are very much needed, cheap, and of the highest order. It clearly states that the customer should load the cart with the product THEY want, making it all about their needs, and it ends with a thank you note (“Thanks as always for being a customer”).&lt;/p&gt;

&lt;p&gt;Personal plans and algorithms are also used by a lot of companies. There’s a trend to allow a customer to choose a theme — set the app on dark/light mode, or even use your own background to make it even more personal. You can see that on Google, among other places. It offers many different themes that you can choose from, like the ones below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pk0rZmux--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bm6wg59md16p77adrv3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pk0rZmux--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bm6wg59md16p77adrv3g.png" alt="Image description" width="880" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F1tsyXkH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iiqqli9jzpiwl0w1carq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F1tsyXkH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iiqqli9jzpiwl0w1carq.png" alt="Image description" width="880" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The other great example is Slack, which you can set for either dark or light mode or even create your own custom theme:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--trR6y1X_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gic9ktdm59qz5wgyrvhh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--trR6y1X_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gic9ktdm59qz5wgyrvhh.png" alt="Image description" width="670" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You may also incorporate your logo and company colors (if this is a business application).&lt;/p&gt;

&lt;p&gt;What is even more interesting is that some companies offer special promo gifts for birthdays. For example, if you have a Starbucks app on your phone, you’ll get offered a free coffee on your birthday. Some of the other birthday offers that you may see in different apps include promo codes for half-priced or free products, free monthly subscriptions for up to even 3 months, and discounts on services on your birthday. This is a trend that can be mostly observed in a lot of restaurants, coffee shops, etc. that offer free meals or drinks on your birthday but only if you have downloaded their application and signed up.&lt;/p&gt;

&lt;p&gt;This helps to strengthen the connection with the product and to see the product as your “friend”, not just software for daily tasks. Thanks to this, the user will “feel” the people behind the software who are trying to make them happy. As you know, it is much more difficult to break off a relationship with a friend than with a stranger :)&lt;/p&gt;

&lt;p&gt;So, if you are worried about your SaaS retention rate, you might want to take some of these ideas into consideration and include them in your strategy.&lt;/p&gt;

&lt;p&gt;Interested in working for our software development company in Poland?&lt;/p&gt;

&lt;p&gt;Check out our current job offers now&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Maintain up-to-date product design.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Trends change rapidly, so at the initial stage I am always afraid of using the “freshest” trends; usually, they become irrelevant after a year at the most. Design should be as “timeless” as possible.&lt;/p&gt;

&lt;p&gt;Some of the things that can help make your design “timeless” are the things that we’ve already talked about above. Some of them may also seem obvious, but that doesn’t make them any less important. Here are a few tips on how to do this:&lt;/p&gt;

&lt;p&gt;Keep it simple and user-friendly — users need to be able to accomplish what they need from your app as quickly and easily as possible. The design has to be user-friendly and the navigation should be as easy and straightforward as possible. Otherwise, it can put users off. Make sure your layout is clear and that there are not too many toolbars, buttons, or other features that can distract or confuse the user.&lt;br&gt;
Get to know your user — and what I mean by that is do your research on what people want. You can learn about your users’ needs through surveys, focus groups, and other feedback. Don’t just guess what users want — ask them. User and market research can keep your product from failing.&lt;br&gt;
Don’t waste your time on something that has already been done well — There are patterns and practices for UX designs that are well-honed and familiar to users. This applies to things such as icons and the meaning behind them. Changing their meaning or changing them into something else could easily confuse the user and that is not something anyone wants.&lt;br&gt;
Keep your brand consistent — if you want users to recognize your brand instantly after opening your app, keep it consistent. Use the same or similar features: the color palette, voice assistance, pictures, icons, and style across your app shouldn’t change from one site to another or one icon to another.&lt;br&gt;
Personalization — as already mentioned, users love customizing their products. They also love when it is done for them by the service, like Netflix does — the algorithm personalizes the account, giving recommendations based on users’ behavior (with previously watched films and TV shows). It’s wise to include it in your design, if possible.&lt;br&gt;
This is a topic for a separate article, but if you find yourself working with an experienced design agency, they will know how to achieve all of this and more. Such a design can live for three or four years and stay relevant, requiring only small stylistic changes to refresh the interface.&lt;/p&gt;

&lt;p&gt;But if your product does not look modern, was made more than two years ago and has not changed since that time, this is a serious reason to start to collaborate with designers.&lt;/p&gt;

&lt;p&gt;I often hear from clients that users don’t complain about the design. This is normal — it is hard to find negative comments about the visual design in the AppStore. But believe me, the user subconsciously understands what the trends are now; they see products, websites, and ads every day. If your design is very different from today’s trends, this often creates the wrong experience: outdated look = incompetence.&lt;/p&gt;

&lt;p&gt;The truth is that very often when faced with a choice between a beautiful, shiny interface with inconvenient logic and an “old-looking” but thoughtful one, app users will choose the first option. Therefore, we follow the trends and periodically update the design.&lt;/p&gt;

&lt;p&gt;Here are some blogs worth following that will help you to stay up to date with changing trends:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.awwwards.com/blog/"&gt;https://www.awwwards.com/blog/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.behance.net/"&gt;https://www.behance.net/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dribbble.com/"&gt;https://dribbble.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.pinterest.com/"&gt;https://www.pinterest.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.siteinspire.com/"&gt;https://www.siteinspire.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ui8.net/"&gt;https://ui8.net/&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the latest interface interaction trends.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Another thing you need to do is to make sure to keep an eye on what is in use now.&lt;/p&gt;

&lt;p&gt;From what I’ve seen, the following things are repeated very often in numerous applications even though they should not be.&lt;/p&gt;

&lt;p&gt;If you have a mobile application and you still use arrows to scroll through slides, then now is the time to change it to swipe. Use gestures, replace outdated pop-ups with neat toasts, and adapt web applications to all screen resolutions, including having a convenient mobile version, not just scaling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--veg-fknm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/729rwkw371bxn0wd6cv8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--veg-fknm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/729rwkw371bxn0wd6cv8.png" alt="Image description" width="880" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, ensure that all active elements have their own behavior: make the buttons react to mouse hover as well as tabs in the menu and active links, add the ability to collapse the menu bar, and use small animations to make the interface lively and not static. Work on the smoothness of transitions.&lt;/p&gt;

&lt;p&gt;If you ignore this, the user will unconsciously get a bad experience, since all the other products around have already introduced it into their applications. It’s like giving a fork with the soup in a restaurant when everyone eats it with a spoon.&lt;/p&gt;

&lt;p&gt;Here’s a roundup of some well-designed websites with modern interactive interfaces:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dopplepress.com/"&gt;https://www.dopplepress.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/"&gt;https://www.amazon.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.hubspot.com/"&gt;https://blog.hubspot.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.yantra.com.sg/"&gt;https://www.yantra.com.sg/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.noniceramica.com/"&gt;https://www.noniceramica.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.donnasrunningclub.com/"&gt;https://www.donnasrunningclub.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mikaelareuben.com/"&gt;https://www.mikaelareuben.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.airbnb.com/"&gt;https://www.airbnb.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.nurturedigital.com/"&gt;https://www.nurturedigital.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.khanacademy.org/"&gt;https://www.khanacademy.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.ikonpass.com/"&gt;https://www.ikonpass.com/&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Improve your product.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Everything is simple here: be sure to increase the functionality and the design by adding new, useful features, constantly analyze user experience and feedback, study competitors, and expand the capabilities of your application.&lt;/p&gt;

&lt;p&gt;Everything that is being improved over time is respected by the user. Introducing constant changes does not let users get used to the way the product looks and functions, and by extension, it doesn’t let them get bored. Remember, as the number of features increases, your audience also increases, which means there is a chance to attract more users. Every serious product should not only have developers and testers in the maintenance team but also UX designers who are studying the user experience and constantly working on improving the product.&lt;/p&gt;

&lt;p&gt;Here are some popular tools that can help you analyze an app’s user experience:&lt;/p&gt;

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

&lt;p&gt;for real-time data-driven analytics &lt;a href="http://www.google.com"&gt;www.google.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google Analytics&lt;/p&gt;

&lt;p&gt;for current and predictive analytics &lt;a href="http://www.google.com"&gt;www.google.com&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;for analysing web activities &lt;a href="http://www.clicky.com"&gt;www.clicky.com&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;for session recording &amp;amp; heatmapping &lt;a href="http://www.smartlook.com"&gt;www.smartlook.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adobe target&lt;/p&gt;

&lt;p&gt;for A/B testing &lt;a href="http://www.adobe.com"&gt;www.adobe.com&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;for mouse movement, scrolls, clicks, and forms using analysis &lt;a href="http://www.mouseflow.com"&gt;www.mouseflow.com&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;for a visual feedback analysis &lt;a href="http://www.debugme.eu"&gt;www.debugme.eu&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_h1-4YEx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vdhlrcjjtxpmh8ox8coc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_h1-4YEx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vdhlrcjjtxpmh8ox8coc.png" alt="Image description" width="880" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update your expertise.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No outdated data and approaches that were relevant two years ago. Depending on your specialisation you must provide the user with the latest data or algorithms. For example, if this is a business application for job searching or recruiting, update filters and logic focusing on the fact that a lot of work is now 100% remote and recruiting itself is often conducted completely remotely. That way we can make this process perfect and convenient and the user will get the wow effect: “This is exactly what I need to see in the app”. Another example is the choice of gender in lifestyle applications. In many countries it is already mandatory to specify all genders and such things need to be monitored, since you may unknowingly lose a huge group of users who regard the lack of this option as a disloyal attitude. These are just two of many examples. A UX designer will help you do a review and will suggest the changes and updates needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QVWJs_62--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6iiadddqiq96398atvn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QVWJs_62--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6iiadddqiq96398atvn.png" alt="Image description" width="880" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you go through this short checklist, you will be able to see whether your business process is aligned with all the points. If not, I recommend working on it with a team of professionals. Coming up with a customer churn prevention strategy based on the steps that we went through in this article and introducing them into your application will give your software a longer life.&lt;/p&gt;

&lt;p&gt;Your customers will be grateful and you will see an increase in interest and in the number of users, as well as a stable statistical growth.&lt;/p&gt;

&lt;p&gt;I wish your product the best of luck! 🚀&lt;/p&gt;

</description>
      <category>customer</category>
      <category>saas</category>
      <category>customerchurn</category>
      <category>ux</category>
    </item>
    <item>
      <title>UX/UI mobile app, website Redesign Case Study</title>
      <dc:creator>Profil Software</dc:creator>
      <pubDate>Wed, 13 Apr 2022 13:59:17 +0000</pubDate>
      <link>https://forem.com/profilsoftware/uxui-mobile-app-website-redesign-case-study-1c0k</link>
      <guid>https://forem.com/profilsoftware/uxui-mobile-app-website-redesign-case-study-1c0k</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was created by the UX/UI Designers Szymon Wiśniewski and Maria Krupskaya. Our UI/UX Designers are highly specialized in creating a unique user experience for any software. Seek the expertise of a &lt;a href="https://profil-software.com/services/ui-ux-design-services/"&gt;UI/UX design agency&lt;/a&gt; and ensure the best quality of your product.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tarot Routing uses state-of-the-art algorithms to plan more efficient last-mile driving routes faster than humans can.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customers reduce their driving time by 30% and, of course, reduce their CO2 emissions, petrol consumption, driver salaries, and maintenance costs.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge&lt;/strong&gt;&lt;br&gt;
Tarot Routing was in the MVP stage when &lt;strong&gt;Profil Software&lt;/strong&gt;, an &lt;a href="https://profil-software.com/blog/saas-build-and-grow/in-house-vs-outsourcing-software-development-teams-for-a-startup/"&gt;outsourced development team&lt;/a&gt;, began working on it. They needed to develop substantial &lt;strong&gt;new features&lt;/strong&gt; in order to create an offering sufficient for Enterprise clients. Additionally, as Tarot Routing’s user base increased, they needed to address platform resiliency and scalability more and more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--swLlIRKL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/60t6tupfc8hy4g1h8zxz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--swLlIRKL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/60t6tupfc8hy4g1h8zxz.png" alt="Image description" width="700" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Profil Software’s full-stack team has developed many substantial features in Tarot Routing, including** Map-Based Drag &amp;amp; Drop Route Adjustments, Websockets for real-time updates, Real-Time Driver Tracking, Cross-Platform Mobile App, and Frontend Unit Tests.**&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cXJEVdoQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ethj69gkvvnug7gsdtx5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cXJEVdoQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ethj69gkvvnug7gsdtx5.png" alt="Image description" width="875" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UX Review&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The web service and the app Tarot Analytics lose the love of users, due to a myriad of reasons. *&lt;em&gt;Along with the competition, one major factor for the losing users is a clumsy design.&lt;br&gt;
*&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bZUUJFST--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gciqm2htuatb2r29pk9z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bZUUJFST--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gciqm2htuatb2r29pk9z.png" alt="Image description" width="700" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No trust through communication with the user&lt;/li&gt;
&lt;li&gt;Lack of connection with the real world&lt;/li&gt;
&lt;li&gt;No consistency within the product&lt;/li&gt;
&lt;li&gt;No error prevention whatsoever&lt;/li&gt;
&lt;li&gt;Ancient, inconsistent, hideous visuals&lt;/li&gt;
&lt;li&gt;Issues with compatibility and responsiveness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lT2AQ-K_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/co6okpgnvruzmagq08dp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lT2AQ-K_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/co6okpgnvruzmagq08dp.png" alt="Image description" width="700" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal was to deliver mobile-friendly, responsive design to create a seamless and attractive user experience across all devices.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our Approach and process:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context Study&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lLu2MaXa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hyjrl4w1cbcmm4ehezpr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lLu2MaXa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hyjrl4w1cbcmm4ehezpr.png" alt="Image description" width="880" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our client struggled with the outdated look and feel of his service. &lt;strong&gt;Our task was to refresh the appearance and the experience.&lt;/strong&gt;&lt;br&gt;
We had to remember about 2 user profiles — the drivers and the managing people. The drivers were supposed to use mainly the mobile application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Target Audience&lt;/strong&gt;&lt;br&gt;
Using the results of the information given and the analysis, we created three personas that embody the traits of the target audience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CLaR4J_W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b01d54uz9uc199ddt8rp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CLaR4J_W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b01d54uz9uc199ddt8rp.png" alt="Image description" width="880" height="834"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our workflow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rebranding&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Creating the Style Guide&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal is to make people aware that our client updated his brand.&lt;/strong&gt;&lt;br&gt;
We have developed a design system to establish the brand’s identity in the minds of users and product owners.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;2. Website redesign&lt;br&gt;
Changing and updating the content, structure, format, and navigation of the service to improve performance.&lt;br&gt;
*&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Timeline&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VZbV7IRi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zyf7ebxqw8znv05wa64g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VZbV7IRi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zyf7ebxqw8znv05wa64g.png" alt="Image description" width="700" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This feature lets you Drag and Drop to reallocate or reorder your jobs.&lt;/strong&gt; Watch the map update automatically and see the impact on your ETAs. We made sure the user can choose their favorite timeline’s position.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tracking&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ijut7CrT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o3pprvdcjzi0iwnlzroy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ijut7CrT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o3pprvdcjzi0iwnlzroy.png" alt="Image description" width="700" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tarot Analytics let its customers track the driver to the door, just like Uber.&lt;/strong&gt;&lt;br&gt;
The customers also get real-time ETAs, and self-service PoD so they don’t have to call them 100x per day anymore.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fdg2WcRC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87yt6ufqn78h6py7n7nv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fdg2WcRC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87yt6ufqn78h6py7n7nv.png" alt="Image description" width="700" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3x_9yAIg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/50i5hhorrvvmfluem6sk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3x_9yAIg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/50i5hhorrvvmfluem6sk.png" alt="Image description" width="700" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mv4PX2ON--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9u60rsdlxz8687eluqx4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mv4PX2ON--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9u60rsdlxz8687eluqx4.png" alt="Image description" width="700" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TUyA49bz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cbkexuj03txzcfb9y4zr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TUyA49bz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cbkexuj03txzcfb9y4zr.png" alt="Image description" width="880" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. App Redesign&lt;br&gt;
We applied all the rebranding decisions to keep the application up to date and make it look and feel fresh.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P8ZWwqgB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1drlaunxo097p9lj9gi5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P8ZWwqgB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1drlaunxo097p9lj9gi5.png" alt="Image description" width="875" height="1032"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Themes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Light &amp;amp; Dark Mode&lt;/em&gt;&lt;br&gt;
The research carried out revealed &lt;strong&gt;a frequent problem faced by drivers was the poor visibility and contrast&lt;/strong&gt; of the application due to their shifts.&lt;br&gt;
To prevent this from happening, &lt;strong&gt;we came out with a solution in the form of screen modes (Light &amp;amp; Dark).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nKkwr7AO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j2h6ld177bgj9uhsw0h4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nKkwr7AO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j2h6ld177bgj9uhsw0h4.png" alt="Image description" width="875" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ux</category>
      <category>design</category>
      <category>ui</category>
      <category>casestudy</category>
    </item>
    <item>
      <title>4 non-coding tips on how to improve coding skills</title>
      <dc:creator>Profil Software</dc:creator>
      <pubDate>Thu, 17 Feb 2022 11:30:17 +0000</pubDate>
      <link>https://forem.com/profilsoftware/4-non-coding-tips-on-how-to-improve-coding-skills-5gm8</link>
      <guid>https://forem.com/profilsoftware/4-non-coding-tips-on-how-to-improve-coding-skills-5gm8</guid>
      <description>&lt;p&gt;“What do you do in your job?” Simple question, but usually the answer is not that simple. We write code, but is the knowledge of your languages of choice the only thing that you should learn? &lt;strong&gt;Are there other things that you can learn and utilize to make you work faster and enjoy your job more?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I admit, this article will be a bit of a fluff piece. I wanted to list and take note of some very simple &lt;strong&gt;things we do in our work all the time but rarely think about improving.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Touch typing
&lt;/h1&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%2Fypoqgy6n97e9sbgv0vc5.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%2Fypoqgy6n97e9sbgv0vc5.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are some skills that are &lt;strong&gt;very basic building blocks of a profession.&lt;/strong&gt; Chefs cook, but there are very few recipes that will not include cutting something. Because of that most chefs are masters at using a knife.&lt;/p&gt;

&lt;p&gt;Builders will construct complex things, but to do that, they must be &lt;strong&gt;proficient&lt;/strong&gt; at using a simple hammer.&lt;/p&gt;

&lt;p&gt;Similarly, &lt;strong&gt;even the most complex application is represented in code&lt;/strong&gt;, therefore programmers type. A lot! Code is written, then refactored, then refactored some more. Similarly to chefs, &lt;strong&gt;we should be masters of the keyboard.&lt;/strong&gt; In our current day and age, people use keyboards from a very early age and most can use them relatively well. But to &lt;strong&gt;use something and be efficient at it&lt;/strong&gt; is a different thing.&lt;/p&gt;

&lt;p&gt;There are multiple &lt;strong&gt;typing techniques.&lt;/strong&gt; A common and ineffective one is &lt;strong&gt;“hunt and peck”&lt;/strong&gt;, where a person looks at the keyboard to find and press the right button. There is also a &lt;strong&gt;hybrid technique&lt;/strong&gt;, where a person has the layout of the keyboard memorized, so there is no need to look at it, but still uses just a few fingers. This is a very fast technique once a person finds his style but the problem is that your hand is moving while doing it and this can lead to some painful problems like carpal tunnel syndrome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The most effective technique is touch typing.&lt;/strong&gt; It is the skill of inputting characters without looking at the keyboard and also by using all your fingers. With a lot of practice, &lt;strong&gt;it allows for ridiculously fast typing with a minimal error rate.&lt;/strong&gt; Also, at least for me, it makes typing fun!&lt;/p&gt;

&lt;p&gt;So if you are going to spend your life typing, why not have some fun doing it? &lt;strong&gt;There are multiple resources on the internet that will help you practice this vital skill.&lt;/strong&gt; I can personally recommend this tool for practice. Just make sure that you know and understand the correct way of typing, because getting rid of bad habits can be very hard.&lt;/p&gt;

&lt;h1&gt;
  
  
  Googling
&lt;/h1&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%2Fcbyh10ch36qbx5t6bkv8.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%2Fcbyh10ch36qbx5t6bkv8.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, &lt;strong&gt;googling.&lt;/strong&gt; Every programmer’s bread and butter. I can’t even imagine how annoying it would be if we had no way to &lt;strong&gt;quickly find documentation&lt;/strong&gt; of the library we are using, or even worse — the solution to the same problem we’re having that has been discussed and answered some time ago by someone much smarter. Being forced to use books that are usually outdated shortly after publishing, or even more bizarrely — asking questions in mailing lists, is unthinkable!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The internet is the source of knowledge for every programmer&lt;/strong&gt; and finding stuff you need is usually just a matter of entering the phrase into the search box. &lt;strong&gt;Search engine algorithms&lt;/strong&gt; are currently so good that usually, you don’t even need to be very specific in order to get the answer you are looking for. &lt;strong&gt;Google&lt;/strong&gt; however also &lt;strong&gt;provides you with some tools to refine your query!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s be honest, when you &lt;strong&gt;search for the solution to a problem&lt;/strong&gt;, you expect that someone has had this problem before and asked about it on Stack Overflow. &lt;strong&gt;So if you know where you want to find your answer, why don’t you tell that to Google up-front?&lt;/strong&gt; To do that just put &lt;code&gt;site&lt;/code&gt;: in front of the query like so: &lt;em&gt;“site:stackoverflow.com”&lt;/em&gt; django. (In case you actually want to search for the movie called “Django”, the phrase &lt;em&gt;“site:imdb.com”&lt;/em&gt; django can help you.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to find something with a weird name without Google showing you the results of something it thinks you need?&lt;/strong&gt; Just place it in quotes to look for exactly that.&lt;/p&gt;

&lt;p&gt;Does Google keep showing you results with a phrase that you already know is not related to your problem? &lt;strong&gt;Using “-” can exclude results with this phrase.&lt;/strong&gt;&lt;br&gt;
There are multiple such operators that will allow you to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;search `for a number in given range&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;use OR&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;exclude words&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;and many more!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are described on the &lt;a href="https://support.google.com/websearch/answer/2466433?hl=en" rel="noopener noreferrer"&gt;Google Search Help site&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Using your IDE
&lt;/h1&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%2F3blklxdyvhbn8qsieebs.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%2F3blklxdyvhbn8qsieebs.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are some who are determined to be as close to nature as possible and refuse to use any “overly complicated software” like &lt;strong&gt;Integrated Development Environments.&lt;/strong&gt; I for one cannot imagine working without an IDE. &lt;strong&gt;It is a great help and makes working with code so much more pleasant.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;However, I must agree that it is complicated. There are plenty of options that you most likely still don’t know about even after working with &lt;strong&gt;the application&lt;/strong&gt; for several years. So, why not find out about them?&lt;/p&gt;

&lt;p&gt;People tend to just use what they know and only search for new things when they are strictly required for something. &lt;strong&gt;An IDE does provide some solutions that may not be required, but once you start using them, you start to understand their usefulness.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One such thing is shortcuts.&lt;/strong&gt; You don’t need them. You can do just fine without them. But you really should learn to use them. &lt;strong&gt;You are going to do some things often when navigating a project&lt;/strong&gt; — quickly jumping to a file, opening the terminal, going to the next tab in the editor. Doing such things once or twice doesn’t take much time when using a mouse, but it really stacks up in the long run. &lt;strong&gt;Doing it with a keyboard is faster and the flow of your work feels so much better.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other useful features that most IDEs provide are refactoring options and code generation.&lt;/strong&gt; Ever had this feeling after the refactor that the function name no longer clearly conveys what it actually does? But you already used it in so many places that changing its name now would just not be worth it, right? That inevitably leads to ugly code. But with a modern IDE that should never be a problem. &lt;strong&gt;It can track usages and automatically change the names for you.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are plenty of other features like &lt;strong&gt;column selection, cursor duplication, smart code completion, intentions, template generation, debugging, navigation, code analysis, and many more&lt;/strong&gt; that are just waiting for you to discover and use them. I will provide just a short list for IDE I use — &lt;strong&gt;Pycharm.&lt;/strong&gt; These will also work for most of the &lt;strong&gt;JetBrains products.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Ctrl + Alt + M&lt;/code&gt; — &lt;strong&gt;Extract Method.&lt;/strong&gt; This is great for splitting your code into small, single-purpose functions. &lt;strong&gt;Makes your refactoring so much easier.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Shift + F6&lt;/code&gt; — &lt;strong&gt;Rename.&lt;/strong&gt; This is one of the most often used. Sometimes the name is no longer correct and the difficulty related to changing it used to stop programmers from refactoring. &lt;strong&gt;IDE can track all uses and refactor names everywhere.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;F6&lt;/code&gt; — &lt;strong&gt;Move module member.&lt;/strong&gt; I often like to prototype in a single file. &lt;strong&gt;Once classes are ready I use the move feature to split code into separate files.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Alt + Shift + Insert&lt;/code&gt; — &lt;strong&gt;Toggle column selection mode.&lt;/strong&gt; This is useful when you want to &lt;strong&gt;add / change something in multiple lines.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Ctrl + O&lt;/code&gt; — &lt;strong&gt;Override method.&lt;/strong&gt; When used inside the class you will be presented with the list of inherited methods. Selecting one will quickly &lt;strong&gt;generate the code needed for overriding it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Ctrl + I&lt;/code&gt; — &lt;strong&gt;Implement methods of an interface / abstract class.&lt;/strong&gt; This saves you a ton of boilerplate typing.&lt;/p&gt;

&lt;p&gt;There are much, MUCH more of these and you can check them out in the documentation of your IDE. I strongly encourage you to search for it next time you must do any refactoring in your code. &lt;strong&gt;Most likely the function you need exists in some form.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Time management
&lt;/h1&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%2Fmvb97fo0hg9pdw1bcvmr.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%2Fmvb97fo0hg9pdw1bcvmr.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is hard to focus on things.&lt;/strong&gt; It is even harder to &lt;strong&gt;prioritize&lt;/strong&gt; them. When you have a lot of things to do, everything seems to be important enough to do them right away. Doing everything at the same time is unfortunately not possible and you will end up completing nothing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For time management there is no universal solution.&lt;/strong&gt; Every human is different and our brains work differently. &lt;strong&gt;What you can do is try different methods and see what is the most effective.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Find the ones that are recommended the most often and try them. Maybe you will click with the &lt;strong&gt;Pareto Analysis&lt;/strong&gt;, or maybe the &lt;strong&gt;Time Blocking method&lt;/strong&gt; will be your thing. Maybe something as simple as &lt;strong&gt;creating a daily TODO list&lt;/strong&gt; or &lt;strong&gt;using a Pomodoro timer&lt;/strong&gt; will be enough. Maybe you need to mix and match some elements from different methods to create something that works best for you.&lt;/p&gt;

&lt;h1&gt;
  
  
  Your thoughts?
&lt;/h1&gt;

&lt;p&gt;These are four things I thought about when I asked myself the question based on the title of this article. Maybe you have some &lt;strong&gt;other ideas about non-coding skills that we should all learn&lt;/strong&gt;? If so, let me know in the comments below!&lt;/p&gt;

</description>
      <category>codingskills</category>
      <category>touchtyping</category>
      <category>googling</category>
      <category>timemangagement</category>
    </item>
  </channel>
</rss>
