Accelerating Enterprise Software Delivery Through Automated Release Processes in Scaled Agile Framework (SAFe)

Key Takeaways

Accelerating enterprise software delivery through automated release processes in a SAFe environment can help organizations to improve their software product quality, agility, flexibility, visibility, security, and governance and stay competitive in a rapidly changing marketplace, maximizing business value, trust, and time to market.

By automating and incorporating quality gates and security scans in the CICD pipelines, businesses may improve the quality of their software products, identify critical vulnerabilities, bugs, code smells, and security hotspots, and as a result, future tech debt will be decreased.

The 5 Books You Absolutely Must Read as an Engineering Manager

Continuous learning is one of the guiding principles that all people should apply in their life. Reading is an excellent tool to learn, and it is a habit that we should all be doing on a regular basis. Since I love reading books about different topics, in this article, I'm going to share five books that have helped me a lot to improve as Engineering Manager.

When we read a book, we should always remember three important things: 

Simulating and Troubleshooting BLOCKED Threads in Kotlin [Video]

In this latest article of the series about simulating and troubleshooting performance problems in Kotlin, let’s discuss how to make threads go into a BLOCKED state. A thread will enter into a BLOCKED state if it can’t acquire a lock on an object because another thread already holds the lock on the same object and doesn’t release it.

Kotlin BLOCKED Thread Program

Here is a sample program that would make threads go into a BLOCKED state.

AWS IP Address Management

In a recent project, I worked with a client who was managing over 100 accounts and recently adopted AWS Control Tower. Despite this, I noticed that the management of CIDR ranges was still a manual process and all IP ranges were being tracked through an Excel sheet in a centralized location. This approach proved to be a significant challenge, as it required a considerable amount of effort to maintain, calculate, and reclaim IP addresses every time. This was especially challenging for new IT team members who joined the IT operations team.

AWS provides a powerful solution for managing IP addresses in your cloud environment through its IPAM (Internet Protocol Address Management) service. AWS IPAM allows you to automate IP address allocation and management, track IP address usage, and detect potential IP address conflicts. In addition to these features, AWS IPAM can be used in conjunction with AWS Control Tower to manage IP addresses across multiple accounts and VPCs in a centralized, standardized way. In this article, we will explore the features and benefits of AWS IPAM with Control Tower and discuss some best practices for using these services effectively.

Best Augmented Reality WordPress Plugins

Best Augmented Reality WordPress PluginsOnline shopping has become especially popular in the past few years, and it’s not just people ordering socks from Amazon. Consumers are increasingly turning to the internet to shop for unique items such as home decor, formal attire, and custom-made products. Homebuyers commonly browse for potential houses on the internet, and landlords rely on online […]

The post Best Augmented Reality WordPress Plugins appeared first on WPExplorer.

How To Migrate From Oracle Database to YugabyteDB With YugabyteDB Voyager

In this article, I demonstrate how you can migrate a comprehensive web application from Oracle Database to YugabyteDB using the open-source data migration engine YugabyteDB Voyager. To improve the availability, scalability, and performance of their applications, many developers are migrating from traditional, single-server relational databases to distributed database clusters. Migrating to YugabyteDB allows engineers to use the well-known SQL interface, while also benefiting from the data-resiliency and performance characteristics of distributed databases.

Whether you prefer reading or watching, let’s migrate a sample movie rental application to YugabyteDB.

Metrics Part 2: The DORA Keys

The DORA metrics are pretty much an iceberg, with the five indicators sticking out above the surface and plenty of research hidden beneath the waves. With the amount of work that has been put into that program, the whole thing can seem fairly opaque when you start working with them. Let’s try to peek under the surface and see what’s going on down there.

After our last post about metrics, we thought it might be interesting to look at how metrics are used on different organizational levels. If we start from the top, DORA is one of the more popular projects today. Here, we’ll tell you some ideas we’ve had on how to use the DORA metrics, but first, there have been some questions we’ve been asking ourselves about the research and its methodology. We’d like to share those questions with you, starting with:

I need help finishing this game

This is a simple zombie survival game, i need to have finished by tomorrow, and I am having multiple problems with vectors being out of range. I also need to change some stuff into classes and make inheritances. I have tried fixing the problems but no success so far and I don't know how to deal with vectors as well as I thought I would be able to, and also since I made the mistake of not making classes from the start it kind of makes things harder now.
this is the code.

#include <cstdio>
#include <ctime>
#include <iostream>
#include <windows.h>
#include <fstream>
#include <vector>
using namespace std;

bool zmbexist(vector<vector<int> >& sqarep, int posx, int posy);
int nrzombies(vector<vector<int> >& plain);
void display(vector<vector<int> >& terain);
bool movezombies(vector<vector<int> >& plain);
bool smartmovezombies(vector<vector<int> >& plain);
bool play(int nrz, int nrholes, vector<vector <int> >& plain);

int main()
{
    srand(time(NULL));
    vector<vector<int> > vectx;
    //initialise the vector
    vectx.resize(10);
    for (int i = 0; i < 10; i++)
    {
        vectx[i].resize(10, 0);
    }

    //convention : hole number is 3 , zombie number is 2, and human number is 1;
    //ask for nr of houls
    int nrholes;
    cout << "number of holes(0 for random) : ";
    cin >> nrholes;
    //if type 0 , then the nr of houls is generated automaticaly
    if (!nrholes)
    {
        nrholes = (rand() % 9) + 1;
    }

    //place the houls

    for (int i = 0; i < nrholes;)
    {
        int xhol = rand() % 10;
        int yhol = rand() % 10;
        if (vectx.at(xhol).at(yhol) == 0)
        {
            vectx.at(xhol).at(yhol) = 3;
            i++;
        }

    }

    //ask for nr of zombies
    int nrzombies;
    cout << "number of zombies(0 for random) : ";
    cin >> nrzombies;
    //if nr is 0, then is generated automaticaly
    if (!nrzombies)
    {
        nrzombies = (rand() % 9) + 1;
    }
    for (int i = 0; i < nrzombies;)
    {
        int xhol = rand() % 10;
        int yhol = rand() % 10;
        if (vectx.at(xhol).at(yhol) == 0)
        {
            vectx.at(xhol).at(yhol) = 2;
            i++;
        }
    }

    cout << "now we place the man";
    for (;;)
    {
        int xhol = rand() % 10;
        int yhol = rand() % 10;
        if (vectx.at(xhol).at(yhol) == 0)
        {
            vectx.at(xhol).at(yhol) = 1;
            break;
        }
    }
    display(vectx);
    play(nrzombies, nrholes, vectx);
    cin.ignore(255, '\n');
    return 0;
}

bool zmbexist(vector<vector<int> >& sqarep, int posx, int posy)
{
    if (sqarep[posx][posy] == 2)
        return true;
    else
        return false;

}
int nrzombies(vector<vector<int> >& plain)
{
    int nrzmb = 0;
    for (size_t i = 0; i < plain.size(); i++)
        for (size_t j = 0; j < plain[i].size(); j++)
        {
            if (plain[i][j] == 2)
                nrzmb++;
        }
    return nrzmb;
}
void display(vector<vector<int> >& terain)
{

    system("cls");
    cout << endl;
    for (size_t i = 0; i < terain.size(); i++)
    {
        for (size_t j = 0; j < terain[i].size(); j++)
        {
            switch (terain[i][j])
            {
            case -1:
                cout << " D ";
                break;
            case 0:
                cout << " * ";
                break;
            case 1:
                cout << " M ";
                break;
            case 2:
                cout << " Z ";
                break;
            case 3:
                cout << " G ";
                break;
            default:
                cout << " E ";
                break;
            }
        }
        cout << endl;
    }

    // Sleep(5000);
}
bool movezombies(vector<vector<int> >& plain)
{
    bool dead, zombiemove;
    for (size_t i = 0; i < plain.size(); i++)
    {
        for (size_t j = 0; j < plain[i].size(); j++)
        {
            //make sure that all the zombie moves

            if (plain[i][j] == 2)
            {
                zombiemove = false;
                while (!zombiemove)
                {
                    int rndmove = rand() % 4 + 1;
                    cout << rndmove << "\n";
                    // Sleep(1000);
                    cout << "now move zombie \n";
                    //move up if is possible

                    if (rndmove == 1)
                    {
                        cout << "move up \n";
                        if (i > 1)
                        {
                            if (plain[i - 1][j] == 3)
                            {
                                plain[i][j] = 0;
                                zombiemove = true;
                                //  break;
                            }
                            else if (plain[i - 1][j] == 1)
                            {
                                dead = true;
                                //return true;
                                zombiemove = true;

                            }
                            else if (plain[i - 1][j] == 0)
                            {
                                plain[i][j] = 0;
                                plain[i - 1][j] = 5;
                                zombiemove = true;
                                //break;

                            }
                        }
                    }
                    //move down if is possible
                    if (rndmove == 2)
                    {
                        cout << "move down \n";
                        if (i < 9)
                        {
                            if (plain[i + 1][j] == 3)
                            {
                                plain[i][j] = 0;
                                zombiemove = true;
                                //break;
                            }
                            else if (plain[i + 1][j] == 1)
                            {
                                dead = true;
                                //return true;
                                zombiemove = true;
                                //break;
                            }
                            else if (plain[i + 1][j] == 0)
                            {
                                plain[i][j] = 0;
                                plain[i + 1][j] = 5;
                                zombiemove = true;
                                //break;

                            }
                        }
                    }
                    //move left if is possible
                    if (rndmove == 3)
                    {
                        cout << "move left \n";
                        if (j > 1)
                        {
                            if (plain[i][j - 1] == 3)
                            {
                                plain[i][j] = 0;
                                zombiemove = true;
                                //break;
                            }
                            else if (plain[i][j - 1] == 1)
                            {
                                dead = true;
                                zombiemove = true;
                                //return true;
                            }
                            else if (plain[i][j - 1] == 0)
                            {
                                plain[i][j] = 0;
                                plain[i][j - 1] = 5;
                                zombiemove = true;
                                //  break;
                            }
                        }
                    }
                    //move left if is possible
                    if (rndmove == 4)
                    {
                        cout << "move right \n";
                        if (j < 9)
                        {
                            if (plain[i][j + 1] == 3)
                            {
                                plain[i][j] = 0;
                                zombiemove = true;
                                //break;
                            }

                            else if (plain[i][j + 1] == 1)
                            {
                                dead = true;
                                //  return true;
                                zombiemove = true;
                            }
                            else if (plain[i][j + 1] == 0)
                            {
                                plain[i][j] = 0;
                                plain[i][j + 1] = 5;
                                zombiemove = true;
                                //  break;
                            }
                        }
                    }
                }//end while
            }
        }
    }
    //}
    for (size_t i = 0; i < plain.size(); i++)
    {
        for (size_t j = 0; j < plain[i].size(); j++)
        {
            if (plain[i][j] == 5)
                plain[i][j] = 2;
        }
    }
    return false;
}
bool movehuman(vector<vector<int> >& plain)
{
    char move;
    bool dead;
    bool pmove = false;
    int x = 0, y = 0;
    for (size_t i = 0; i < plain.size(); i++)
        for (size_t j = 0; j < plain[i].size(); j++)
        {
            if ((plain[i][j]) == 1)
            {
                x == i;
                y == j;
            }

        }

    while (!pmove)
    {
        system("cls");
        display(plain);
        cout << "move human (2=down,8=up,4=left,6=right): ";
        cin >> move;
        cout << move;
        if (move == 52)
        {
            if (y > 0)
            {
                if ((plain[x][y - 1] == 3) || (plain[x][y - 1] == 2))
                {
                    cout << "is mort acuma2";
                    Sleep(2000);
                    dead = true;
                    //  return dead;
                }
                plain[x][y] = 0;
                plain[x][y - 1] = 1;
                y--;
                pmove = true;
            }

        }

        if (move == 54)
        {
            if (y < 9)
            {
                if ((plain[x][y + 1] == 3) || (plain[x][y + 1] == 2))
                {
                    return true;
                }
                plain[x][y] = 0;
                plain[x][y + 1] = 1;
                y++;
                pmove = true; 
            }

        }
        if (move == 56)
        {
            if (x > 0)
            {
                if ((plain[x - 1][y] == 3) || (plain[x - 1][y] == 2))
                {
                    return true;
                }
                plain[x][y] = 0;
                plain[x - 1][y] = 1;
                x--;
                pmove = true;
            }

        }

        if (move == 50)
        {
            if (x < 9)
            {
                if ((plain[x + 1][y] == 3) || (plain[x + 1][y] == 2))
                {
                    return true;
                }
                plain[x][y] = 0;
                plain[x + 1][y] = 1;
                x++;
                pmove = true;
            }

        }
    }
    return dead;
}
bool smartmovezombies(vector<vector<int> >& plain)
{

    size_t x = 0;
    size_t y = 0;

    //get human position

    for (size_t i = 0; i < plain.size(); i++)
    {
        for (size_t j = 0; j < plain[i].size(); j++)
        {
            if (plain[i][j] == 1)
            {
                x = i;
                y = j;
                break;
            }
        }
    }
    //for everyzombie possition calculate how to get closer to human quickly
    for (size_t i = 0; i < plain.size(); i++)
        for (size_t j = 0; j < plain[i].size(); j++)
        {
            if (plain[i][j] == 2)
            {

                if ((i > x) && (j > y))
                {
                    if (i - x > j - y)
                        if (plain[i - 1][j] == 2)
                            plain[i][j] = 0;
                        else
                        {
                            if (i > 1)
                            {
                                plain[i][j] = 0;
                                plain[i - 1][j] = 5;
                            }
                        }

                    else
                    {
                        if (plain[i][j - 1] == 2)
                            plain[i][j] = 0;
                        else
                        {
                            if (j > 1)
                            {
                                plain[i][j] = 0;
                                plain[i][j - 1] = 5;
                            }
                        }

                    }

                }

                if ((i < x) && (j < y))
                {
                    if (i - x > j - y)
                        if (plain[i + 1][j] == 2)
                            plain[i][j] = 0;
                        else
                        {
                            if (i < 10)
                            {
                                plain[i][j] = 0;
                                plain[i + 1][j] = 5;
                            }
                        }

                    else
                    {
                        if (plain[i][j + 1] == 2)
                            plain[i][j] = 0;
                        else
                        {
                            if (j < 10)
                            {
                                plain[i][j] = 0;
                                plain[i][j + 1] = 5;
                            }
                        }

                    }

                }

                if ((i < x) && (j > y))
                {
                    if (i - x > j - y)
                        if (plain[i + 1][j] == 2)
                            plain[i][j] = 0;
                        else
                        {
                            if (i < 10)
                            {
                                plain[i][j] = 0;
                                plain[i + 1][j] = 5;
                            }
                        }

                    else
                    {
                        if (plain[i][j - 1] == 2)
                            plain[i][j] = 0;
                        else
                        {
                            if (j > 1)
                            {
                                plain[i][j] = 0;
                                plain[i][j - 1] = 5;
                            }
                        }

                    }

                }

                if ((i > x) && (j < y))
                {
                    if (i - x > j - y)
                        if (plain[i - 1][j] == 2)
                            plain[i][j] = 0;
                        else
                        {
                            if (i > 1)
                            {
                                plain[i][j] = 0;
                                plain[i - 1][j] = 5;
                            }
                        }

                    else
                    {
                        if (plain[i][j + 1] == 2)
                            plain[i][j] = 0;
                        else
                        {
                            if (j > 1)
                            {
                                plain[i][j] = 0;
                                plain[i][j + 1] = 5;
                            }
                        }

                    }

                }

                if ((plain[i - 1][j] == 1) || (plain[i + 1][j] == 1) || (plain[i][j + 1] == 1) || (plain[i][j - 1] == 1))
                {
                    return true;
                }
            }

        }
    for (size_t i = 0; i < plain.size(); i++)
        for (size_t j = 0; j < plain[i].size(); j++)
        {
            if (plain[i][j] == 5)
                plain[i][j] = 2;

        }
    return false;

}
bool play(int nrz, int nrholes, vector<vector<int> >& plain)
{
    bool dead, endgame;
    endgame = false;
    dead = false;
    while (true)
    {
        endgame = smartmovezombies(plain);
        dead = movehuman(plain);
        nrz = nrzombies(plain);
        if (dead = true)
        {
            cout << "human dead";
            exit(1);
        }
        if (nrz == 0)
        {
            cout << "human win";
            exit(1);
        }
    }
    return true;
}

PySpark Data Pipeline To Cleanse, Transform, Partition, and Load Data Into Redshift Database Table

Data is the driving force behind many of today's businesses. With the ever-growing amounts of data available, businesses need to create optimized data pipelines that can handle large volumes of data in a reliable and efficient manner. In this article, we will discuss how to create an optimized data pipeline using PySpark and load the data into a Redshift database table. We will also cover data cleansing, transformation, partitioning, and data quality validation.

Before diving into the code, let's take a quick look at the tools we will be using:

How to Choose an Ecommerce Domain Name in 10 Simple Steps

We recommend GoDaddy or Hostinger for researching and registering your chosen domain name. Get a free domain name when you sign up with Hostinger.

A domain sticks with you and represents your online identity. It pays to get your domain name right the first time, as you likely won’t change it in the future unless you want to go through an entire rebrand.

This guide is for ecommerce newcomers. You’ll learn the most useful methods for developing a strong domain name, the best practices to stick to, and the faux pas to avoid.

How to Choose an Ecommerce Domain Name in 10 Simple Steps

The 7 Best Domain Registrars for Choosing an Ecommerce Domain Name

Collectively we’ve purchased hundreds of domain names over the years. We used our experience and in-depth research to come up with the best domain registrars to help you choose a domain name. Take a look:

  • GoDaddy — Best for domain protection and privacy
  • Hostinger — Best for bundling domain registration and web hosting
  • Porkbun — Best for creative domain extensions
  • Domain.com — Best for fast and simple domain purchasing
  • Network Solutions — Best for long-term domain registrations
  • Namecheap — Best for affordable domain registration
  • NameSilo — Best for buying domains in bulk

Choose an Ecommerce Domain Name in 10 Simple Steps

Choosing a domain name seems like a simple task on the surface, but you need to carefully consider choosing a name that reflects your brand and that customers appreciate. Here are our top tips, along with the dos and don’ts of choosing a domain name for your online store:

1. Sign Up for Hostinger

2. Align Your Domain Name with Your Branding

3. Think About the Meaning Behind Your Domain Name

4. Consider Using SEO Keywords

5. Come Up with Unique Domain Name Ideas

6. Use a Domain Name Generator if You’re Stuck

7. Opt for a Short and Simple Domain Name

8. Search for Trademarks

9. Research Your Domain Name Across the Web

10. Come Up with Alternative Domain Names if Yours is Taken

Step 1: Sign Up for Hostinger

If you’re ready to get a domain name for your ecommerce store, we recommend you sign up for Hostinger. It has the best deal out there – you get a free domain name for a year when you sign up for hosting at just $2.59 per month.

Another good thing about Hostinger is you get a free SSL certificate for your domain. SSL makes your domain “https” rather than “http,” which is necessary to rank well on Google and keep your site secure.

You also get free privacy protection when you register a domain with Hostinger. It prevents internet users from looking up the details attached to your domain using the WHOIS database.

When you have a domain name in mind, go to Hostinger’s Domain Name Search to see if it’s available.

Hostinger domain name search landing page
Get your domain for free when you sign up for hosting with Hostinger.

If the domain name is taken, Hostinger will show you other available options, such as .co or .store.

Step 2: Align Your Domain Name with Your Branding

Your domain name is synonymous with your brand. It’ll be at least part of your domain name, if not the whole thing. As such, it’s how people will recognize and remember your online store.

If you don’t already have a name for your ecommerce business, choose one that reflects your brand’s values, the atmosphere you hope to generate, or how you want to be seen online. That’s what good branding is all about.

To give you an example, “4ocean.com” is an ethical brand where customer purchases fund ocean clean-up initiatives.

4Ocean homepage
Your domain name should illustrate what your ecommerce business is all about.

The domain/store name makes complete sense, representing what the company does and what they stand for.

Another way to hint at your branding with your domain or company name is to choose an adjective that reflects what you’re all about. Happysocks.com is a great example–they sell quirky socks that make people happy.

Step 3: Think About the Meaning Behind Your Domain Name

Your domain name should have meaning. Tell a story with it and use it to represent what you stand for. 

Plus, when there’s meaning behind your domain/online store name, you humanize your brand. Modern consumers care about this as they increasingly want to shop with more authentic, smaller brands than big corporations.

Peloton at onepeloton.com has a deep and interesting reason for its name.

The word “peloton” is a cycling term, which makes sense for a brand that sells exercise bikes. But there’s more to it–a peloton is a group of riders that work together in a race to reduce drag, save energy, and make winning more likely. 

Thus, the name evokes ideas of using teamwork to succeed in a sport that is usually considered quite solitary.

Peloton Advisory page with headline that asks "What is a Peloton" and a definition underneath
Consider the meaning behind your domain name carefully.

Step 4: Consider Using SEO Keywords

You can use a keyword describing what you sell in your domain name. This signals to Google and users about the kind of store you operate. So, it helps get your web pages to rank higher on the search engine results pages.

Use just one keyword alongside your brand name. Otherwise, your domain name would look spammy and less like it’s for a credible company, e.g., “shoesandsneakers.com.”

You can use your niche as the keyword. For example, “herocosmetics.us” works well for this skincare brand. 

Screenshot from Mighty Patch about us page
Add a keyword to your brand name to generate a strong domain name.

Another option is to use the primary type of product you sell, as in “chubbiesshorts.com.”

Step 5: Come Up with Unique Domain Name Ideas

Your domain name should distinguish your brand from others in your niche. Unique domain names are memorable, and that’s the goal. You want customers to remember and visit your online store, after all.

One way to come up with a unique domain name is to opt for a portmanteau or made-up word. Adidas, for example, isn’t a real word; it’s a portmanteau of the founder’s name Adolf Dassler. 

Or go for a play on words. One fantastic example of this is Lettucegrow.com, an online shop that sells seeds and accessories for growing your own vegetables:

Lettuce Grow homepage
Show your playful side by using a play on words as your domain/store name.

Another way to generate a unique domain name is to use an acronym. ASOS, at asos.com, is actually short for “As Seen On Screen.” But most people don’t know this; they just think of ASOS as a distinct word.

Step 6: Use a Domain Name Generator if You’re Stuck

If you’re struggling to come up with a creative domain name idea, there are many domain name generators on the web. Most ask you to enter one or two keywords to generate a domain name and check its availability. But this isn’t particularly useful for coming up with a unique domain name idea.

Instead, go to NameStation. Enter the type of business you’re starting and create an account. Type in a list of preferred words and/or keywords, then hit Generate Names. The tool generates thousands of domain name ideas and separates them into handy lists.

First, there are the domain names that are the closest match to the words you entered. Then there’s a list that brings context into account. It combines your preferred words with keywords related to your business.

The hand-picked section generates the most unique, available domain names. 

NameStation domain name search results
Use NameStation to generate relevant domain name ideas for inspiration.

There are also lists with broad keyword matches, popular affixes, alliterations, one-word domains, and more.

Step 7: Opt for a Short and Simple Domain Name

Short, simple domain names are easier for customers to retain. Make your domain name too complex, and it’s harder for people to find you online.

Make sure your domain name is no longer than 15 characters. Also, it needs to be easy to spell and say out loud. You don’t want people to get frustrated and give up on trying to find your store. 

Avoiding hyphens and numbers is also a good idea, as these just complicate the domain name. Note that no other special characters are allowed in a domain name.

Step 8: Search for Trademarks

When you have a domain or online store name in mind, you’ll need to research to ensure that other companies aren’t using it. 

Naturally, you don’t want to be slapped with a fine for copyright infringement. But more than that, you need to establish a distinct brand of your own.

Check if the name is trademarked. The United States Patent and Trademark Office (USPTO) website has a trademark search tool.

United States Patent and Trademark Office trademark search tool
Visit the USPTO website to see if your store name is already trademarked.

If there’s a company selling the same kinds of products as you with the same or a similar name, head back to the drawing board. Your name is likely fine if there’s a trademark for a similar name, but they sell something different, e.g., you’re “Unicorn Stationery,” and they’re “Unicorn Coffee”.

Step 9: Research Your Domain Name Across the Web

Search Google for brands that may have a similar name to yours. Even if it’s not trademarked, the online store may still exist. Your online store must stand out among the crowd.

If the domain or store name is indeed taken, that’s not good for your business. Imagine doing a ton of promotion for your product and store, only for the customer to go ahead and buy from a competitor with a similar name.

If you’re sure you have a unique domain/brand name, check the domain’s availability with Hostinger’s Domain Name Search tool.

It’s also a good idea at this point to see if your brand name is available on social media channels. If not, you can always add a word or phrase such as “store” or “official” to your username. 

Remember, this should be consistent across channels, i.e., if you have @unicornstore on Instagram, you should ideally have @unicornstore on TikTok, and so on. This ensures users can find you easily across all channels.

Step 10: Come Up with Alternative Domain Names if Yours is Taken

If your chosen domain name isn’t available, we recommend you develop a new name. You must set yourself apart from other companies.

However, if you’re dead set on your chosen brand name, there are a few things you can do. First, combine your brand name with an SEO keyword as in “brand” + “keyword” + “.com,” e.g., this made-up web address, “terraformplants.com.”

Alternatively, add a phrase or word before your brand name, such as “wear,” “this is,” “I love,” “official,” and so on. Take the brand Lively’s domain name “wearlively.com,” for instance.

Another option is to choose a different top-level domain (TLD), i.e., .store, .net, .co and so on. However, this isn’t ideal, as .com is the most credible TLD you can acquire.

Final Thoughts About Choosing a Domain Name

Your domain name represents your identity on the web. It must reflect your branding and distinguish your ecommerce store from others. The best domain names are simple, unique, and memorable.

You may choose to come up with a domain name that’s meaningful for your brand and reflects your values. Or perhaps you’ll add an SEO keyword to make what you sell even more explicit and contribute to a higher ranking on the search engines. Be sure to check that your domain is available to avoid copyright issues and ensure you have a clearly defined online presence.

How To Execute Cypress E2E Test Cases Using CI/CD GitLab

Cypress is an end-to-end testing framework that is used to test web applications. It is an open-source JavaScript-based framework that enables developers to write and run automated tests for their web applications in a simple and easy way.

Cypress provides a fast, reliable, and easy-to-use testing experience for web developers. It allows developers to write tests in JavaScript, and its powerful features include automatic reload of tests, time travel debugging, and interactive debugging. Cypress also provides a dashboard to view test results and insights.

Use After Free: An IoT Security Issue Modern Workplaces Encounter Unwittingly

Workstations, laptops, and smartphones are no longer the only web-enabled electronic devices in workplaces. The rise of wearables and the Internet of Things has added more gadgets that connect to the internet at home. This has created more conveniences but also introduced new problems.

One of the problems brought about by the reliance on smart web-enabled electronic devices is the expansion of cyber threats. New devices being added to the enterprise network become new attack surfaces. They create more opportunities for threat actors to exploit vulnerabilities and launch attacks.

Real-Time Analytics for IoT

We’ve been hearing that the Internet of Things (IoT) would transform the way we live and work by connecting everyday devices to the internet for a long time now. While much of the promise of the IoT always seems to be "coming soon," the proliferation of IoT devices has already created a massive amount of data that needs to be processed, stored, and analyzed, in real-time. I’ve said for years—actually over a decade now—that if your IoT data isn’t timely, accurate, and actionable, you’re mostly wasting your time in collecting it.

This is where the Apache Pinot® database comes in. Pinot is an open-source, distributed data store designed for real-time analytics. The high scalability, reliability, and low latency query response times of Pinot make it a great solution for processing massive amounts of IoT data. In this post, we will explore the benefits of using Pinot in IoT applications.

From Data Stack to Data Stuck: The Risks of Not Asking the Right Data Questions

Companies are in continuous motion: new requirements, new data streams, and new technologies are popping up every day. When designing new data platforms supporting the needs of your company, failing to perform a complete assessment of the options available can have disastrous effects on a company’s capability to innovate and make sure its data assets are usable and reusable in the long term.

Having a standard assessment methodology is an absolute must to avoid personal bias and properly evaluate the various solutions across all the needed axes. The SOFT Methodology provides a comprehensive guide of all the evaluation points to define robust and future-proof data solutions. However, the original blog doesn’t discuss a couple of important factors: why is applying a methodology like SOFT important? And, even more, what risks can we encounter if we’re not doing so? This blog aims to cover both aspects.

Internationalization In Next.js 13 With React Server Components

With the introduction of Next.js 13 and the beta release of the App Router, React Server Components became publicly available. This new paradigm allows components that don’t require React’s interactive features, such as useState and useEffect, to remain server-side only.

One area that benefits from this new capability is internationalization. Traditionally, internationalization requires a tradeoff in performance as loading translations results in larger client-side bundles and using message parsers impacts the client runtime performance of your app.

The promise of React Server Components is that we can have our cake and eat it too. If internationalization is implemented entirely on the server side, we can achieve new levels of performance for our apps, leaving the client side for interactive features. But how can we work with this paradigm when we need interactively-controlled states that should be reflected in internationalized messages?

In this article, we’ll explore a multilingual app that displays street photography images from Unsplash. We’ll use next-intl to implement all our internationalization needs in React Server Components, and we’ll look at a technique for introducing interactivity with a minimalistic client-side footprint.

Fetching Photos From Unsplash

A key benefit of Server Components is the ability to fetch data directly from inside components via async/await. We can use this to fetch the photos from Unsplash in our page component.

But first, we need to create our API client based on the official Unsplash SDK.

import {createApi} from 'unsplash-js';

export default createApi({
  accessKey: process.env.UNSPLASH_ACCESS_KEY
});

Once we have our Unsplash API client, we can use it in our page component.

import {OrderBy} from 'unsplash-js';
import UnsplashApiClient from './UnsplashApiClient';

export default async function Index() {
  const topicSlug = 'street-photography';

  const [topicRequest, photosRequest] = await Promise.all([
    UnsplashApiClient.topics.get({topicIdOrSlug: topicSlug}),
    UnsplashApiClient.topics.getPhotos({
      topicIdOrSlug: topicSlug,
      perPage: 4
    })
  ]);

  return (
    <PhotoViewer
      coverPhoto={topicRequest.response.cover_photo}
      photos={photosRequest.response.results}
    />
  );
}

Note: We use Promise.all to invoke both requests that we need to make in parallel. This way, we avoid a request waterfall.

At this point, our app renders a simple photo grid.

The app currently uses hard-coded English labels, and the dates of the photos are displayed as timestamps, which is not very user-friendly (yet).

Adding Internationalization With next-intl

In addition to English, we’d like our app to be available in Spanish. Support for Server Components is currently in beta for next-intl, so we can use the installation instructions for the latest beta to set up our app for internationalization.

Formatting Dates

Aside from adding a second language, we’ve already found that the app doesn’t adapt well to English users because the dates should be formatted. To achieve a good user experience, we’d like to tell the user the relative time when the photo was uploaded (e.g., “8 days ago”).

Once next-intl is set up, we can fix the formatting by using the format.relativeTime function in the component that renders each photo.

import {useFormatter} from 'next-intl';

export default function PhotoGridItem({photo}) {
  const format = useFormatter();
  const updatedAt = new Date(photo.updated_at);

  return (
    <a href={photo.links.html}>
        {/* ... */}
        <p>{format.relativeTime(updatedAt)}</p>
      </div>
    </a>
  );
}

Now the date when a photo has been updated is easier to read.

Hint: In a traditional React app that renders on both the server and client side, it can be quite a challenge to ensure that the displayed relative date is in sync across the server and client. Since these are different environments and may be in different time zones, you need to configure a mechanism to transfer the server time to the client side. By performing the formatting only on the server side, we don’t have to worry about this problem in the first place.

¡Hola! 👋 Translating Our App To Spanish

Next, we can replace the static labels in the header with localized messages. These labels are passed as props from the PhotoViewer component, so this is our chance to introduce dynamic labels via the useTranslations hook.

import {useTranslations} from 'next-intl';

export default function PhotoViewer(/* ... */) {
  const t = useTranslations('PhotoViewer');

  return (
    <>
      <Header
        title={t('title')}
        description={t('description')}
      />
      {/* ... */}
    </>
  );
}

For each internationalized label we add, we need to make sure that there is an appropriate entry set up for all languages.

// en.json
{
  "PhotoViewer": {
    "title": "Street photography",
    "description": "Street photography captures real-life moments and human interactions in public places. It is a way to tell visual stories and freeze fleeting moments of time, turning the ordinary into the extraordinary."
  }
}
// es.json
{
  "PhotoViewer": {
    "title": "Street photography",
    "description": "La fotografía callejera capta momentos de la vida real y interacciones humanas en lugares públicos. Es una forma de contar historias visuales y congelar momentos fugaces del tiempo, convirtiendo lo ordinario en lo extraordinario."
  }
}

Tip: next-intl provides a TypeScript integration that helps you ensure that you’re only referencing valid message keys.

Once this is done, we can visit the Spanish version of the app at /es.

So far, so good!

Adding Interactivity: Dynamic Ordering Of Photos

By default, the Unsplash API returns the most popular photos. We want the user to be able to change the order to show the most recent photos first.

Here, the question arises whether we should resort to client-side data fetching so that we can implement this feature with useState. However, that would require us to move all of our components to the client side, resulting in an increased bundle size.

Do we have an alternative? Yes. And it’s a capability that has been around on the web for ages: search parameters (sometimes referred to as query parameters). What makes search parameters a great option for our use case is that they can be read on the server side.

So let’s modify our page component to receive searchParams via props.

export default async function Index({searchParams}) {
  const orderBy = searchParams.orderBy || OrderBy.POPULAR;

  const [/* ... */, photosRequest] = await Promise.all([
    /* ... */,
    UnsplashApiClient.topics.getPhotos({orderBy, /* ... */})
  ]);

After this change, the user can navigate to /?orderBy=latest to change the order of the displayed photos.

To make it easy for the user to change the value of the search parameter, we’d like to render an interactive select element from within a component.

We can mark the component with 'use client'; to attach an event handler and process change events from the select element. Nevertheless, we would like to keep the internationalization concerns on the server side to reduce the size of the client bundle.

Let’s have a look at the required markup for our select element.

<select>
  <option value="popular">Popular</option>
  <option value="latest">Latest</option>
</select>

We can split this markup into two parts:

  1. Render the select element with an interactive Client Component.
  2. Render the internationalized option elements with a Server Component and pass them as children to the select element.

Let’s implement the select element for the client side.

'use client';

import {useRouter} from 'next-intl/client';

export default function OrderBySelect({orderBy, children}) {
  const router = useRouter();

  function onChange(event) {
    // The `useRouter` hook from `next-intl` automatically
    // considers a potential locale prefix of the pathname.
    router.replace('/?orderBy=' + event.target.value);
  }

  return (
    <select defaultValue={orderBy} onChange={onChange}>
      {children}
    </select>
  );
}

Now, let’s use our component in PhotoViewer and provide the localized option elements as children.

import {useTranslations} from 'next-intl';
import OrderBySelect from './OrderBySelect';

export default function PhotoViewer({orderBy, /* ... */}) {
  const t = useTranslations('PhotoViewer');

  return (
    <>
      {/* ... */}
      <OrderBySelect orderBy={orderBy}>
        <option value="popular">{t('orderBy.popular')}</option>
        <option value="latest">{t('orderBy.latest')}</option>
      </OrderBySelect>
    </>
  );
}

With this pattern, the markup for the option elements is now generated on the server side and passed to the OrderBySelect, which handles the change event on the client side.

Tip: Since we have to wait for the updated markup to be generated on the server side when the order is changed, we may want to show the user a loading state. React 18 introduced the useTransition hook, which is integrated with Server Components. This allows us to disable the select element while waiting for a response from the server.

import {useRouter} from 'next-intl/client';
import {useTransition} from 'react';

export default function OrderBySelect({orderBy, children}) {
  const [isTransitioning, startTransition] = useTransition();
  const router = useRouter();

  function onChange(event) {
    startTransition(() => {
      router.replace('/?orderBy=' + event.target.value);
    });
  }

  return (
    <select disabled={isTransitioning} /* ... */>
      {children}
    </select>
  );
}
Adding More Interactivity: Page Controls

The same pattern that we’ve explored for changing the order can be applied to page controls by introducing a page search parameter.

Note that languages have different rules for handling decimal and thousand separators. Furthermore, languages have different forms of pluralization: while English only makes a grammatical distinction between one and zero/many elements, for example, Croatian has a separate form for ‘few’ elements.

next-intl uses the ICU syntax which makes it possible to express these language subtleties.

// en.json
{
  "Pagination": {
    "info": "Page {page, number} of {totalPages, number} ({totalElements, plural, =1 {one result} other {# results}} in total)",
    // ...
  }
}

This time we don’t need to mark a component with 'use client';. Instead, we can implement this with regular anchor tags.

import {ArrowLeftIcon, ArrowRightIcon} from '@heroicons/react/24/solid';
import {Link, useTranslations} from 'next-intl';

export default function Pagination({pageInfo, orderBy}) {
  const t = useTranslations('Pagination');
  const totalPages = Math.ceil(pageInfo.totalElements / pageInfo.size);

  function getHref(page) {
    return {
      // Since we're using Link from next-intl, a potential locale
      // prefix of the pathname is automatically considered.
      pathname: '/',
      // Keep a potentially existing orderBy parameter. 
      query: {orderBy, page}
    };
  }

  return (
    <>
      {pageInfo.page > 1 && (
        <Link aria-label={t('prev')} href={getHref(pageInfo.page - 1)}>
          <ArrowLeftIcon />
        </Link>
      )}
      <p>{t('info', {...pageInfo, totalPages})}</p>
      {pageInfo.page < totalPages && (
        <Link aria-label={t('prev')} href={getHref(pageInfo.page + 1)}>
          <ArrowRightIcon />
        </Link>
      )}
    </>
  );
}
Conclusion

Server Components Are A Great Match For Internationalization

Internationalization is an important part of the user experience, whether you support multiple languages or you want to get the subtleties of a single language right. A library like next-intl can help with both cases.

Implementing internationalization in Next.js apps has historically come with a performance tradeoff, but with Server Components, this is no longer the case. However, it might take some time to explore and learn patterns that will help you keep your internationalization concerns on the server side.

In our street photography viewer app, we only needed to move a single component to the client side: OrderBySelect.

Another aspect to note is that you might want to consider implementing loading states since the network latency introduces a delay before your users see the result of their actions.

Search Parameters Are A Great Alternative To useState

Search parameters are a great way to implement interactive features in Next.js apps, as they help to reduce the bundle size of the client side.

Apart from performance, there are other benefits of using search parameters:

  • URLs with search parameters can be shared while preserving the application state.
  • Bookmarks preserve the state as well.
  • You can optionally integrate with the browser history, enabling undoing state changes via the back button.

Note, however, that there are also tradeoffs to consider:

  • Search parameter values are strings, so you may need to serialize and deserialize data types.
  • The URL is part of the user interface, so using many search parameters may affect readability.

You can have a look at the complete code of the example on GitHub.

Many thanks to Delba de Oliveira from Vercel for providing feedback for this article!

Further Reading On SmashingMag

Online submission fprms not working with PHP v8

My online submission pages no longer work after upgrading to PHP v8. After pressing Submit, screen then turns white and no email sent with the submitted info. Screen is not supposed to turn white. After switching back to PHP 7.4, everything worked normally again. I have many online submission pages which all use the same code. The code never had any issues with any version of PHP dating back to 2011. Attached is one of the PHP programs. How can it be edited so it will work with PHP v8 ?

My online submission pages no longer work after upgrading to PHP v8. After pressing Submit, screen then turns white and no email sent with the submitted info. Screen is not supposed to turn white. After switching back to PHP 7.4, everything worked normally again. I have many online submission pages which all use the same code. The code never had any issues with any version of PHP dating back to 2011. Attached is one of the PHP programs. How can it be edited so it will work with PHP v8 ?
<?php
// grab recaptcha library
require_once "recaptchalib.php"; 
// foreach ($_POST as $key => $value) {
    //echo '<p><strong>' . $key.':</strong> '.$value.'</p>';
  // }
// your secret key
$secret = "6LeW4RQUAAAAAJ4NvgWIKJc4b-AeKp6LcLFCFQoS"; 

// empty response
$response = null; 

// check secret key
$reCaptcha = new ReCaptcha($secret); 
// if submitted check response
if ($_POST["g-recaptcha-response"]) { 
   $response = $reCaptcha->verifyResponse( 
          $_SERVER["REMOTE_ADDR"], 
       $_POST["g-recaptcha-response"] 
    ); 
} 
if ($response != null && $response->success) { 

$subject = "Showing Scheduling";
$message = "RadiantNewHorizonHomes.com Showing Scheduling" . "\r\n" . "\r\n" .
"Name: " . $_POST['ShowingName'] . "\r\n" .

"Phone Number : " . $_POST['ShowingPhone1'] . "\r\n" .

"E-mail Address: " . $_POST['ShowingEmail'] . "\r\n" .
"Properties wants to see: " . $_POST['ShowingHomes'] . "\r\n" .
"Date(s)/Time(s) wants to see them: " . $_POST['ShowingTimes'] . "\r\n" .






"Questions or Comments: " . $_POST['ShowingQuestions'] . "\r\n" .

"How Heard About Us: " . $_POST['ShowingHearing'] . "\r\n" .

$from = $_POST['ShowingEmail'];
$headers = "From: $from" . "\r\n";

$to = "david.tigner@radiantnewhorizonhomes.com";
mail($to,$subject,$message,$headers);


} else { } 

?>

Multi-Cloud Integration

Before we jump into the details, let’s answer the question: “What is cloud integration architecture?” Cloud integration architecture is the combination of the cloud components and several cloud providers that allows exchanging of data across several data centers. 

For example, imagine that we have a large banking solution. Some banks don’t want to migrate their core and secured data. They want to keep it in their on-premises data centers. However, they can’t avoid using clouds. They migrate existing projects, new projects that are starting, and even the whole call centers and back office to the cloud. Building this complex architecture requires knowledge of the integration service and tools that the clouds provide. 

Sanity Testing Tutorial: A Comprehensive Guide

Sanity testing is a type of software testing executed on the stable build of an application with minor code changes. It is also known as surface-level testing. A sanity test is performed to ensure the application works as expected after the bug fixes or changes in the code.

In the Software Development Life Cycle, software testing is an integral part of ensuring the performance of the software application. It is performed to find any bug or error that could lead to the failure of the software application. Such failure could be costly for the organization as it could not provide the expected user experience. Hence, it is suggested to check everything before the release of the software application in the market.