The Password-Strength Checker Design Kata – Part 1

In two of my three technical courses (Essential Agile Engineering Skills and Essential Test-Driven Development), the first major topic I cover is refactoring, its role on an Agile software development team, and its role in software design.

Sometimes, but not always, the participants have the time and inclination to come back to the topic of software design. I have an optional learning “module” that—at a minimum—covers Kent Beck’s “Four Rules of Simple Design,” and how we look at the Open-Closed Principle from an “Agile” standpoint.

Before we do a lot of talking, however, I give folks a lab (or “kata”). Since we don’t always get to it, I’m offering it here for you to experience, if you choose. This post will likely be one of three: The lab has two parts, and then I’ll summarize it in the third post.

I encountered Part 1 of this lab many years ago and was delighted to see just how quickly certain issues arose. I’ve added to it, which is why it will be split over a series of posts. (In Part 2, I’ll reveal why I had to invent a “Part 2.”)

Part 1 may take you 10 minutes. It may take you a month. And, if you choose to try it, you can send me e-mail with questions or solutions (Rob.Myers@agileforall.com), and I will [infamously] reply within 30 days. That conversation may (or may not) have impact on the third post. You could also wait until you’ve had a chance to read all three posts, but that’s like reading the last chapter of a mystery novel: “Spoilers!”

This lab may seem deceptively simple. And, in some ways, it really is simple. It’s always an instructor’s dilemma: The labs have to be simple and clear enough to be completed, but have to convey the intended lessons. They have to be toy examples, but the technical solution to the challenge has to be a real and valuable technique.

Think of this as a microcosm of your usual software development challenges. Treat it as though you were really getting paid to build what is asked, and be extra-sensitive to testing constraints, design forces, and code-smells that arise. Imagine that this system, and each of those smells, are much larger and more critical than they may seem for such a tiny lab. Utilize the knowledge, skills, and tools available to you.

That’s not to suggest that you pull in every framework or design pattern you’re familiar with. No need to over-engineer or show off. 😉 Again, this lab is uniquely tuned to be a stand-alone software design kata. The best designs are simple designs. And simple isn’t always easy.

The Password-Strength Checker – Part 1

Technical requirements:

1. Use Test-Driven Development. I.e., write a failing test, then write the code to make it pass, then refactor a little, before writing another test. Yes, that’s really ONE TEST AT A TIME! It might help you to know that part of TDD is having a short to-do list of things to test and things to refactor. I tend to prefer a 3×5 index card, so that the list doesn’t get too long.

2. You can choose any programming language with a simple unit-testing framework.

3. You are encouraged to pair/mob on this. Via Zoom, perhaps. Or, perhaps you have a parent, child, or partner living with you who is interested in learning some of this programming stuff. I believe TDD-plus-pairing is the best way to learn programming, or a new programming language, or an unfamiliar API. Of course, you have to learn the unit-testing tool first.

Product requirements:

1. We need a simple, in-process, easy-to-use password-strength-checking API.

2. The caller shouldn’t have to have knowledge of what checks are being done to the password string.

3. A simple Boolean return value of true (strong enough) or false (too weak) is wanted.

4. In order to be an acceptably strong password, a string must…

[ ] Have a length greater than 7 characters.

[ ] Contain at least one alphabetic character.

[ ] Contain at least one digit.

That’s it!

When you are done building it, please answer the following questions for yourself. (I recommend you write your answers down someplace where you won’t lose them in the next four weeks.)

1. Did you have a prior test fail when a subsequent test was made to pass? If so, what did you do in response to that issue?

2. If asked to alter the API, what sort of changes would be easy to test and develop? What changes might be more difficult to test and develop? Why?

Have fun with it!

Want Part 2 before it gets posted here? Sign up for my Developer Essentials Newsletter HERE! and you’ll receive it via e-mail.

The Three Jobs of Agile Management (Part 4)

Tip 4 – Use the Agile Management Canvas as a guide to Agile adoption or transformation. 


After explaining the basics of the model (three jobs, two sides), share the canvas with a group that is interested in adopting an agile approach. Have them provide their subjective input into which elements on the canvas are the biggest impediments and accelerators to getting the benefits of an Agile approach by giving everyone a single red sticker and a single blue one.

(Note – while you could use red and green as more closely aligned to the stereotypical good and bad evaluations, 1 in 12 adult males are red-green colorblind, so switching to blue helps avoid confusion).

Each person gets one vote on the element that they think is most enhancing their ability to realize the benefits of Agile and one vote for the biggest impediment. See where the clusters of Red are, and pull that card out. Use that as the starting point for organization impediment removal.

Have the group talk through the current approach and how the element is aligned or not aligned with the three key principles of Agile Management:

  • Move authority to where the work is being done
  • Be mindful of complex systems
  • Create safety and engagement

You could use an approach like A3 problem solving to define an experiment in improving that element to more align with those principles.


Download Peter’s Three Jobs of Agile Management PDF for an infographic of the three jobs to help in your Agile management journey.

Technical Debt, & the “Core Four” Practices to Avoid It

Readers! Subscribers! “Followers”! I hope you are all healthy and safe.

What is “Technical Debt”?

People are still debating over the one true meaning of the term “technical debt.” It was coined by Ward Cunningham around 2009, and the short definition is this:

Technical Debt is the deferment of good software design for the sake of expediency. Put simply, we’ve chosen to make some questionable design choices in order to get product delivered. This may be a conscious choice, but—more often than not—it’s unconscious, and the result of a time-crunch.

Why is Technical Debt a concern?

Technical debt has real impact on the bottom line. It can slow the delivery of future releases or sprint increments, make defects harder to find and fix, and erode good testing practices.

Detour: What is “Software Design”?

The word “design” has many meanings within the software industry. “Software design” is distinct from user-interface design (roughly the “look and feel” of the software product) and also user-experience design (roughly, how the user uses the software to do something they want to do, and the subjective quality of that experience).

Software design is the internal structure of the code. It’s something that is chosen and written by software developers, and typically needs to be read and understood only by software developers on the team.

It’s not magic, and it’s not some pie-in-the-sky notion of perfection or art. There’s certainly skill and finesse that goes into doing it well. But the value of a good design is entirely pragmatic. A good software design does two things:

1. Communicates the intent of all software behaviors to the team’s developers, now, and in the future.

2. Facilitates future enhancements, both expected and unexpected.

And that’s really it. There’s a whole library aisle written about it, and a lot of that is very informative. All the lessons of Design Patterns, for example, are very useful. It’s not a waste of time to learn about Design Patterns. And still, they all boil down to those two.

Do we need to get the software design right, upfront?

I built software in ye olde “pre-Agile” days, prior to 1996, and the techniques we used were—in comparison—excessively predictive, rather than relying on fast feedback and empirical methods that we used on XP teams, for example. (Don’t know XP? For now, just think of it as “Scrum++”!)

Doing all the design up-front, in a “design phase,” worked fine until we started testing (if the business felt there was still time for testing…), or until it was in the hands of the customers.

That’s why we enthusiastically embraced Agile methods like Scrum and XP, long before the term “Agile” was used. We said “Let’s do just enough for now, and fold in what we learn.”

That won’t work! We’re doing Agile, and it’s still a painful experience.

Let me tell you about what I call the “Agilist’s Dilemma.”

For about the first 5-8 sprints (or “iterations”), everything may go smoothly: everyone is happy to be doing what they enjoy. Coders code, testers test, teams demonstrate tiny fractions of high-priority working software to stakeholders. There are balloons and cake. (But no glitter! For the love of all that has nooks and corners, please, NO GLITTER!)

After that, everything typically starts to slow down considerably. Why is this?

In order for the developers to add new features, they have to alter code they’ve already written, throughout the application. That’s just the nature of good software development: the more central the lines of code, the more likely they are to change over time, in order to support new functionality.

But developers really don’t want to break anything they’ve worked hard to build. (See, they’re really not trying to make your life miserable…quite the opposite!) So as the software becomes more complex, they have to proceed more and more carefully or risk introducing defects. Either they slow down, or they make mistakes resulting in defects, which means more time spent searching for and fixing those defects. And fixing defects involves more changes, possibly resulting in more defects…

Testers run into a similar dilemma: At first, it’s easy to keep up with the new features. But, because the developers need to change things, testers need to test everything, every sprint. Again, this gets to be a greater and greater challenge. We see teams doing some crazy things, like prioritizing certain tests, or running tests less frequently. Those defects from the previous paragraph sneak past the testers and fall into the user’s lap. Or laptop.

So everything slows down, either because people are trying to do their jobs conscientiously; or because the quality of the product is degrading due to statistically unavoidable human fallibility.

This is unsustainable. And, of course, we then hear that “Agile sucks!”

It should be no surprise that if we’re going to ask our teams to do something highly iterative and incremental, the coding and testing techniques we would have used for a gated “waterfall” process are not going to work anymore. It’s not merely that they’re not sufficient; they’re actually counterproductive!

The solution to the Agilist’s Dilemma is to use development practices that are better suited to a highly iterative and incremental approach and to stop doing practices that act as an impediment to the agility we seek.

What technical practices are needed to reduce or avoid technical debt?

Let’s first look at the heart of the problem: We need to be able to enhance the functionality of our software without damaging any of the prior investment in functionality. We need to have software that is soft: it needs to be easy to change. To that end, our software design needs to:

1. Communicate the existing intent.

2. Be easy to extend and maintain.

On an Agile team, we support this by continuously reshaping the design so that it’s (a) appropriate for the current functionality; and (b) flexible enough to receive unexpected, unpredictable enhancements.

We call this practice “refactoring” – and it’s the core design practice for Agile software development.

Refactoring is the reshaping of the code’s structure without changing any of the behavior of the system, so that we can then more easily add the new functionality.

It’s not rework, and it’s not rewriting. A good design is a changeable design, by definition.

It’s an ongoing, never-ending activity that is best done in very tiny increments, like a few seconds of refactoring every 5 minutes.

Sounds crazy, right? It’s actually quite simple, and very powerful. The best software designs I’ve seen got there through simple, continuous, wholehearted refactoring.

But refactoring can’t be done in isolation. You can’t simply tell the team: “Okay, now we refactor!”

How can we refactor safely?

A team can’t refactor unless they have a lot of confidence that their changes won’t alter existing behavior. And the only way to know that is to have a comprehensive and very fast automated test-suite. I will often refer to this test-suite as “the safety-net.”

In order to build and maintain this safety-net of fast tests, A team needs to be doing either Test-Driven Development (TDD), or Behavior Driven Development (BDD). Or both! (But that’s a longer discussion.)

These practices are often called “test-first” practices because we write a single test or scenario, and we work to get that test passing before we move on to writing another test.

Folks always ask me why the team can’t write the tests after coding. There was an old study comparing TDD with unit-test-after that suggested test-after was a little faster. The problem, though, was that the test-after teams’ test-coverage was abysmal, and quality suffered proportionally.

Also, TDD is actually faster in the short-term, because it’s the technique by which developers think about the decomposition of the new behaviors they’re adding to the system. We record what we expect in a test, rather than drawing diagrams and then trying to fit behaviors into our mistaken conceptual notions (been there, done that, pre-1996).

And TDD is faster in the long-term because it keeps defect counts so low that most of my teams stopped tracking defects. Just as one example: The U of M OTIS2 program I worked on in 2002 is still undergoing enhancements via TDD (yes, it’s old enough to vote, now). The last time a developer had to work OT in the evening or weekend hours was in 2004. OTIS2 is a life-critical (“you break it, a patient may die”) application. The phrase “TDD saves” isn’t just a silly meme.

Whereas refactoring is the core solution, TDD and BDD are the core practices of a smoothly-running Agile software team. These practices become the means by which any ambiguities in what we’ve been asked to build get refined into discrete, and concrete, scenarios. Every high-performing Agile software team that I’ve encountered spends most of their day doing one or both of these.

Test-first includes testing, sure, but also incremental design through refactoring, and just-in-time analysis. That is, we think about what is needed, and what is not. The team is continuously growing the product increment, together with the safety-net around it, so that further enhancements and refactorings can happen swiftly and confidently.

Sounds expensive, right? Upfront, perhaps; for a month, perhaps. But the savings in cost-of-rework, and the ability to adapt to changing market conditions, have typically recouped the “additional” expense of time writing tests, and any training/coaching they had received from me.

Okay, Refactoring and TDD. Got it. Anything else?

Another limitation to good, changeable design is a lack of collaboration. I can tell you from my decades of experience writing code all by myself, that I didn’t learn much about software design. Partly because I thought I knew it all; partly because we were expected to learn these things during our copious “free time.” If we ever saw each others’ code, invariably someone else would disagree with my design, or I would disagree with theirs. And how often do you suppose we had the time to go back and incorporate the new knowledge into the code?

What solved this for us was intense, continuous collaboration. Agile developers need to talk to each other about the code, and they need to design that code together. Two practices that have arisen from this need are “Pair Programming,” and “Mob Programming.”

Pairing is two developers working together to test, write, and design the code. Mob Programming is the whole team sitting together, usually including either the Product Advocate (Scrum’s PO) or a business-savvy BA or QA. They are all seeing the product being developed in real-time on a big screen or two, usually by a pair that changes frequently.

Also sounds untenably expensive, yeah? Yet there are numerous benefits that swamp the costs. For example:

1. The code is reviewed as it’s written. Code reviews no longer constrain the team, and the incorporation of good ideas happens immediately, rather than later or not at all.

2. Like brain cells packed closely together in your cerebral cortex, the immediate cross-connectivity of product, tester, developer, ops, et cetera allows the “mob” to instantly put together an optimal solution. Coding, testing, analysis, research all happen simultaneously towards the completion of the most important piece of the most important feature for the most important customer, today.

3. Questions that arise about some enhancement are answered immediately, rather than waiting for a meeting, or—worse—having the team guess at what you meant, and likely guessing incorrectly.

4. Everyone is engaged. What many “mobs” have discovered is that the shorter the length of time you spend in the same role (driver, navigator, observer), the more likely you are to be engaged in what’s happening up on the screen. During one recent training/coaching session I gave to a mobbing organization, they tried one-minute rotations and thought it worked very well.

5. Cross-team understanding of the design, the technologies and frameworks being employed, and the business domain being expressed. Everyone gets some experience in, and a lot of appreciation for, the various skills required to deliver your specific style of high-quality high-value software.

6. It’s very social, creating a bond amongst the teammates, including product, dev, test, ops, et cetera.

Back to design: If the whole team agrees it’s a maintainable design, then it is. When I used to write code alone, there was only one person who thought it was a great design: Me. Just increasing the number of eyes on a particular bit of fresh code turns one…into MANY. Odds are if two agree it’s a good design, the team will agree. Particularly if they’ve all been working together in this way. Paradoxically, fewer heated design arguments happen on teams that pair or mob.

Refactoring, TDD/BDD, Pairing/Mobbing…that’s three. What is the fourth of the “Core Four”?

The final core Agile tech practice is Continuous Integration (CI).

Your sprint isn’t delivering a shippable product increment if it’s from a version-control repository branch that hasn’t been incorporated into a potentially shippable whole. So all the existing features and new User Stories (Scrum Product Backlog Items) need to be integrated together.

We take this to the extreme by integrating each pair’s work multiple times per day. The repo trunk—also known to git users as the “master branch”—is therefore always the “source system of record” as to what has been built. And when a pair or mob starts to work on a new task, they first obtain all the useful changes that others have made.

If we didn’t do this, then refactoring comes to a quick standstill. If I refactor something on a branch, and you refactor that same code but in very different ways on another branch, we’re going to have a hard time integrating. The smaller the incremental changes, though, the easier they are to integrate.

Mob Programmers working with their own isolated code-base still use a repo to avoid losing any changes and to track versions and change-sets. They may never encounter a merge conflict. Multiple pairs on a team will have the occasional merge conflict, but if they integrate numerous times per day, conflicts are rare and easily resolved. Continuous Integration means we integrate continuously! No surprise, right?

Can you summarize the “Core Four” again?

1. At the heart we have refactoring. And—supporting healthy, continuous refactoring—we have the other three…

2. TDD or BDD, to build our safety net.

3. Continuous collaboration and dialog using Pair Programming or Mob Programming.

4. Continuous Integration, providing the important enhancements and refactorings we’ve done to others on the team.

There’s also an interesting way to look at all four of these as practices that facilitate strong team communication:

1. Refactoring creates an understandable (readable, clear, straightforward) and changeable design.

2. Test-first practices use test scenarios to communicate WHAT the software does, whereas the code itself tells us HOW it does that.

3. Collaborative practices like pairing and mobbing are primarily about instant communication, thus considerably shortening typical team feedback loops.

4. Continuous Integration distributes the most recent changes to the rest of the team much more efficiently and accurately than a status update or a code review.

Back to Technical Debt: Is it okay to take on some tech debt, as long as we do these core four practices?

Technical debt is typically not as valuable as people assume. The notion that we either have to rush to market, or we have to design for the future—but not both—is a false choice.

Once the teams have some experience with these techniques, it takes no additional time to use a test-first technique to think about what the code is solving, and to refactor as you go to keep the design tidy.

To read further about Technical Debt, you can check out my post on the topic: https://agileforall.com/ward-cunninghams-debt-metaphor-isnt-a-metaphor/

You can also check out the video version of this topic on our Agile For All YouTube playlist.

The Three Jobs of Agile Management (Part 3)

Tip 3 – use the full Agile Management Canvas to see the larger system of management when trying to address challenges.


If we take the example of a team complaining that their daily standup is taking too long and start to look for ideas in the canvas, we might start with the Collaboration Structures element.

This element is about how we coordinate, meet, and interact.

We might ask how the meeting is being facilitated – is the purpose of the meeting clear, what approach does the team use to conduct the meeting, are there other circumstance at play like people showing up late?

As we look more deeply into the issue, we might discover that the team is a bit large – 13 people. This might cause us to look over at the People Structures element to examine how we organize and team. Do we have the right team structure in place to deliver value?

The answer might come back that team members don’t really collaborate on work – they just do their tasks and report on them during the meeting, but the reports never cause anything to change, so it just feels like a boring status report to everyone. That might imply that the team is not set up to collaborate around a shared purpose, and are functioning more as a group that coordinates their work.

So we might examine Purpose and Vision from the Clarity job – what’s the team’s mission? What impact do they have for customers? Do we have a sufficiently cross-functional team that can deliver value without dependencies? Perhaps there are some basic team-building skills that are missing – the ability to communicate effectively, to share enough vulnerability to engender trust, etc.

This use of the model helps us consider many multiple aspects of complex systems as potential variables in a challenge.


Download Peter’s Three Jobs of Agile Management PDF for an infographic of the three jobs to help in your Agile management journey.

The Three Jobs of Agile Management (Part 2)

Tip 2: Use the jobs and the two sides to identify areas that may be out of balance in your organization.

As an example, I’ll give you an outside view of Tesla motors. Full disclaimer – I’m a shareholder and a student of Tesla, but I have no insider information so take it with a huge grain of salt – I could be way off base. I use it as an example that has some wide awareness due to CEO Elon Musk’s occasional openness about the goings-on at the company.

image.png

Tesla under Elon Musk’s leadership is particularly good at the objective side of the three jobs. 


Clarity: Musk creates clarity of the highest priorities for the business and the strategic steps they’ll take to get there. Check out this blog post Musk wrote in August of 2006, where he basically lays out the next 10-15 years of strategy for the company. For reference, he wrote this post right after announcing the prototype of the first car, the Roadster. On the human side, Musk is also great at describing a compelling purpose, accelerating the mass-market adoption of sustainable transportation. The same blog post talks about the social impact the company has and wants to have. I gave them a slightly lower rating here, since Tesla does not seem to do a great job of taking care of their employees, and that’s one aspect of Clarity from a human side.


Capability: Tesla once again shines in the job of increasing capability on the objective side, which includes attracting and growing world-class technical skills and acquiring the resources necessary to succeed. On the human side, we give them their lowest score. Musk’s own leadership development and self-awareness seem from the outside to be highly reactive and ego-driven, so it seems unlikely that he’s creating a culture of high self-awareness and personal growth. 


Improve the System: Finally, on the Improve the System job, Tesla has regularly gone all out to create greater efficiencies and innovations in their objective systems, from manufacturing processes to building out the supercharger network to their approach to sales that is revolutionary in the auto industry (and catching up to the rest of the e-commerce world). On the human side, we do see the outcome of people volunteering creativity and energy to solve problems and make a positive impact, so you might make an argument to score them very high here. However, it turns out that nearly all of the engagement is driven by alignment to purpose and other factors like being part of an innovative company. Other effective tools in this space like creating autonomy, psychological safety, and balance in life seem from the outside to be lacking, so we drop their score.


This paints a picture of a company that is objectively excellent – world-class in many areas. From a human perspective, the purpose is so strong and motivating that they are currently successful. It will be interesting to see if the lack of other factors important to human systems ends up catching up to the company’s effectiveness at some point. It is certainly a potential area of improvement, and I suspect it would increase the long-term resilience of the company. I feel like Musk is frequently very close to some kind of a breakdown. That type of leadership usually results in a simmering pot that will boil over unexpectedly.

Apply it:
How would you rate your team and organization on these jobs? What action could you take to try to create more balance within your sphere of influence? Let’s have a conversation in the comments below.

Download Peter’s Three Jobs of Agile Management PDF for an infographic of the three jobs to help in your Agile management journey.

The Three Jobs of Agile Management (Part 1)

Tip 1: Use the three jobs to clarify responsibilities in the organization.

For example, the job of Creating Clarity has an overlap between the role of the Product Owner on a Scrum team. Which responsibilities belong to management and which belong to the Product Owner? You can use the elements in the Agile Management Canvas, as well as your own elements. An example list for the responsibilities discussion might include:

  • Purpose and Vision
  • Customer Segmentation
  • Strategy Mapping
  • Success Metrics/ObjectivesProduct Backlog PrioritizationProduct Backlog Decomposition


Remember that the three principles of Agile management are:

  1. Move authority to where the work is being done
  2. Be mindful of complex systems
  3. Create safety and engagement

Given those principles and the context for your team, how might you divide the responsibilities? Let us know in the comments below.

Download Peter’s Three Jobs of Agile Management PDF for an infographic of the three jobs to help in your Agile management journey.

https://youtu.be/2xAGNZIcnbs

A Short History of Kanban (and Lean) (Part 3)

The history of lean and kanban is a challenge to boil down, so inevitably, I know there are aspects that are missing here. The title says “short” because, while there is a lot of information here, it is short in terms of how more is out there!  Additionally, there are often disagreements on certain aspects and points around the history, and we’ve sourced the various elements included in this outline.  A key part of understanding kanban is going beyond the principles and practices, to understand what is behind it work. The history points us to a critical key. 

Type-G Toyoda Automatic Loom, the origin of jidoka
The Type-G Toyoda Automatic Loom, the world’s first automatic loom with a non-stop shuttle-change motion, was invented by Sakichi Toyoda in 1924. This loom automatically stopped when it detected a problem such as thread breakage. 2

1920s: Sakichi Toyoda starts Automatic Loom Works, selling sophisticated automatic looms based on his years of inventing and improving looms. One invention was a mechanism that stopped the loom when a thread broke. This evolved into a key pillar in the Toyota Production Read More

Top 5 Ways to Maximize Learning in Virtual Classes

In the past couple of months, I’ve been an instructor for numerous virtual Agile classes. The outcomes are outstanding. I’ve discovered that the people who get the most out of training do these 5 things. Here are some key tips to maximize learning in a virtual environment.

  1. Do the pre-work.
    Any reading, videos, or other material provided by your instructor to view before class, take the time to go through it carefully. Even though many instructors will cover some of the same points in class, we know that the brain requires repetition to learn – this is particularly true for things that may be very new for you where your existing “patterns” may not always apply.
  2. Be an engaged and active learner.
    Choose a class that is interactive and uses virtual tools that allow you to work in breakout groups, have discussions, interact on a virtual whiteboard, etc. Be an active participant if you want to learn.  We learn much more by doing or discussing than we ever do from hearing or listening.
  3. Take breaks, stand up, and move around.
    Practice self-care. Even during class, get up, stretch, and move. Sitting for long periods is hard on you and doesn’t put your brain in the most receptive mode.  On breaks, don’t just check your phone or emails – move around, step outside if you can, maybe do a few jumping jacks.
  4. Don’t multitask or have lots of programs running on your computer.
    Close extraneous windows on your PC or laptop. Not only does multitasking hinder your learning, but having too many things running can cause performance problems on your machine. Some of the new tools like Zoom and Miro or Mural are amazing but can take up significant machine capacity. It’s also a good idea to reboot your machine before a class to make sure everything is running optimally.
  5. Remember that classes are just the start of the journey.
    Connect with classmates and the instructor to continue discussions following the course. Many times, classmates are a great source of networking in the future. Reviewing key ideas from class sometime in the first couple of days after class helps cement concepts in your brain. Most courses come with a list of references, or other suggested reading – check those out and continue the learning process.

We’re all in a difficult time right now as we deal with the pandemic, but happily, learning is something we can still do effectively. If you have available time, now is a great time to consider a class. Choose your providers wisely and then enjoy being immersed in new ideas and ways of doing things.