Brain friendly programming in Java

We have many principles for writing better more maintainable software, but still end up with a tangled mess.

Most of us have heard about the Single Responsibility Principle (SRP), Robert C Martin expressed this principle as “A class should have only one reason to change”.

He later clarified this by stating “Gather together the things that change for the same reasons. Separate those things that change for different reasons”.

We also have the Single Layer of Abstraction Principle (SLAP) which is expressed as “Don’t mix levels of abstractions”.

Dan Terhorst-North presented his Unix Philosophy as “does one thing well”.

The goal is to create more maintainable software, not to fulfill the principle. It’s still possible to create a mess even though we follow all the SOLID principles. So what do these principles mean, and how can I as a developer use them to create better software?

The Science Behind Brain-Friendly Programming Methods

In “The Programmer’s Brain“, Dr. Felienne Hermans talks about how our brain works working with code.  It’s a highly recommended read.

One of the key takeaways for me was the fact that our working memory can only keep track of 3 – 5 chunks of information at the same time. How big a chunk is depends on how much experience we have with the current task.

It can be individual statements, lines, or entire design patterns.

We can make our code easier to understand, to lower the cognitive load of the reader, by limiting the number of chunks of information we have to keep track of.

Ok, so how do we do that then?

Cognitive Load: Minimizing Mental Strain for Optimal Programming Performance

This is when the presentation “Simple Made Easy” from Rich Hickey, comes in.

He talks about how we complect our code.

Complect is an old word that means to braid together, to weave together. By completing our code we make it harder to understand by requiring the reader to keep more chunks of information in memory. We are increasing the cognitive load for the reader.

He suggests that we should separate our code based on the following questions:

  • What needs to be done?
  • Who wants to do it?
  • How should it be done?
  • When should it be done?
  • Where should it be done?
  • Why should it be done?

By mixing these, complecting them, we create code that is harder to understand because it requires the reader to keep more chunks in memory, which creates a higher cognitive load.

By keeping these separate, we get code that is easier to change and reuse, for instance, we can then change how something is done without affecting who wants it done.

Another thing we can do to make our code easier to understand is to take advantage of new features in the language we are using.

We often hear that we should update to the latest version of our language for performance and security reasons. But there are also improvements in the language that can make our code easier to understand.

Let’s take Java as an example.

Leveraging New Java Language Features to Lower the Cognitive Load of the Programmer

Java, being one of the most popular programming languages in the world, is constantly evolving to meet the changing demands of software development. With each iteration, Java introduces new language features that not only enhance the performance and scalability of applications but also aim to make the lives of programmers easier.

I’ll list a few of the new Java language features that, when used, can lower the cognitive load of programmers, allowing us to write more efficient and maintainable code.

Concise Code with Lambda Expressions

Lambda expressions, introduced in Java 8, allow developers to write more concise code by expressing instances of anonymous functions. By using lambda expressions, programmers can reduce boilerplate code and focus on the core logic of their applications. This feature is a good match for handling collections, stream processing, and event handling. For example, instead of writing lengthy loops to iterate over a list, lambda expressions can be used to achieve the same result in a more compact and readable manner.

Improved Null Safety with Optional

Java 8 introduced the Optional class, which helps handle null values more effectively. By using Optional, programmers can avoid NullPointerExceptions and write safer code. Optional encourages developers to handle null values explicitly, leading to more robust and error-free applications. This feature reduces the cognitive load of programmers by providing a clear and standardized way to deal with null values, making the code more predictable and easier to reason about.

Enhanced Pattern Matching

Java 14 introduced pattern matching for instanceof and this has been extended and improved on in newer versions since then. This feature simplifies the code by combining type checking and type casting into a single operation. Programmers can write cleaner and more concise code when working with complex data structures by using pattern matching. Pattern matching reduces the cognitive load of programmers by eliminating the need for if-else blocks and switch statements, leading to more readable and maintainable code.

Simplified Asynchronous Programming with CompletableFuture

Asynchronous programming is essential for building responsive and scalable applications. Java 8 introduced the CompletableFuture class, which makes asynchronous programming simpler by providing a convenient way to work with future values. Programmers can chain asynchronous operations and handle their results more intuitively using CompletableFuture. This feature reduces the cognitive load of developers by abstracting the complexity of asynchronous programming and allowing them to focus on the business logic of their applications.

The evolution of Java language features has brought significant improvements to the way programmers write and maintain code. By leveraging features such as lambda expressions, Optional, pattern matching, and CompletableFuture, developers can lower the cognitive load associated with programming tasks. These features enable programmers to write more concise, robust, and maintainable code, ultimately leading to increased productivity and efficiency in software development. 

As Java continues to evolve, developers can expect more innovations to enhance their programming experience further and make Java an even more powerful and developer-friendly language.

Conclusion

By understanding how the brain processes information, developers can create programming languages and environments that are more intuitive, efficient, and less cognitively demanding for users. This approach can improve the overall user experience, increase productivity, and promote greater accessibility for individuals of all cognitive abilities.

Embracing brain-friendly programming will not only benefit individual programmers and users but has the potential to revolutionize the way we interact with technology and shape the future of computing.

Mastering the Craft: 7 Habits of Highly Effective Developers

Physical training

Physical training, also known as exercise or fitness training, is crucial to maintain a healthy lifestyle and improve overall well-being. It involves engaging in planned physical activities targeting specific muscle groups, enhancing cardiovascular endurance, improving flexibility, and building strength.

Besides the physical benefits, exercise positively impacts mental and emotional well-being. Physical training stimulates the release of endorphins, often called the “feel-good” hormones. These neurotransmitters alleviate stress, anxiety, and depression, promoting a positive mood and overall mental well-being.

Exercise is proven to enhance cognitive abilities, memory, and concentration.

Sharing

As a software developer, you possess a wealth of knowledge and experiences that can benefit others in the field.

Sharing your knowledge helps others, but it will also showcase your expertise and solidify your position as an authoritative figure in the software development community. Teaching is the best form of learning. Try keeping a log of problems you have encountered and how you solved them. You will likely have similar issues in the future. You can also use it to find interesting topics to share.

Why not present something you have learned to your company or at a conference? I know it can be scary, but it’s also rewarding. It will help you grow as a developer.

Automate

Automation has become an essential aspect of the developers’ toolkit, especially with the increasing complexity of software development projects and the need for faster delivery. Automating repetitive tasks and processes saves time, improves efficiency, minimizes errors, and enhances productivity.

We will be more productive and can stay in the flow when writing code if we learn the keyboard shortcuts in the IDE rather than switching to the mouse.

A good way is to learn the shortcuts for the operations we do the most. For instance, how do I quickly jump between code and tests? How do I rename something?

We should not be afraid of using the command line to perform actions if it’s more effective.

Focus

Our ability to focus and efficiently manage our tasks is crucial to the success of any project. However, one of the biggest obstacles to achieving this focus is the constant context-switching we have to deal with. Moving from one task to another is referred to as context switching. These switches may happen due to changing priorities, interruptions from colleagues or stakeholders, or simply because we work on multiple features simultaneously.

We should minimize its impact on productivity and mental well-being, even if context switching might appear unavoidable in this fast-paced industry.

Turning off all social media and emails made it easier for me to focus. I put the editor in full screen when I code and try to use as many keyboard shortcuts as possible to avoid switching between keyboard and mouse.

A quiet and organized space promotes better focus. If there’s noise, investing in noise-canceling headphones could be worthwhile.

Reflect

Reflection is an essential and powerful practice that every software developer must embrace to reach new heights of success and excellence in their field. Developers can truly become indispensable team members by investing time and effort into thoroughly reviewing their work, analyzing mistakes, honing problem-solving abilities, elevating code quality, boosting efficiency, fostering professional growth, and nurturing collaboration. The act of reflection not only accelerates individual growth but also plays a pivotal role in driving the overall triumph of software development projects.

Journaling is a valuable practice that will undoubtedly enhance your daily life. By diligently documenting your experiences, you invite introspection and self-reflection and create a sense of closure at the end of each day. This journaling ritual enables you to release any lingering thoughts or emotions, granting you the freedom to unwind and detach from the events that transpired throughout the day.

Empathy

Empathy is the ability to understand and share the feelings of another person. It involves putting yourself in someone else shoes, considering their perspective, and acknowledging their emotions. Empathy fosters better communication and stronger relationships in a collaborative work environment. It enables teams to work more effectively together. You can find more information about this in a guest post I wrote here: https://digma.ai/blog/the-empathetic-developer/

Simplify

Code is not merely a tool for businesses; it is an essential component that directly impacts the behavior and value of software systems. Good code ensures efficiency, reliability, and maintainability. Poor quality code leads to increased costs and decreased value creation. By prioritizing code quality, businesses can avoid the pitfalls of technical debt, deliver faster and more stable systems, and achieve a competitive advantage in the market. Code is cost, and behavior is value – an equation that every business should strive to balance.

We should aim to provide comments that explain the reasoning behind the design of the code rather than just describing its functionality. Do not comment to cover up poor-quality code. We should program with intent. One way to help us with this is to apply the four rules for simple design by Kent Beck. It passes all the tests. It reveals intention. It avoids duplication and utilizes the fewest possible elements in its construction.

A good code should read like a story, not like a puzzle. William Zinsser describes his principle on writing in his book On Writing Well. We can create better results by focusing on simplicity, clarity, brevity, and humanity. Write programs for people to read and occasionally for machines to execute.

Review often to get feedback to avoid turning it into a blessing. Say what can be improved, not what is wrong.

Level up Your Java Skills with These Recommended Books

In this earlier post, I recommended some books that have helped me in my career as a software developer. I was asked if I had any books to recommend for Java developers. The books in this post are listed in the recommended reading order based on your experience with Java. You will get the most out of each book if you are familiar with the contents of the previously listed books. I’ll give my thoughts on the recommended target audience and what it will teach you. Enough introduction, let’s get to the books!

Head First Java: A brain-friendly Guide

So you have decided to learn Java? Great decision! Welcome to one of the most active communities in the world. This book doesn’t require you to have any previous knowledge of the Java language. It will teach you both fundamentals and some more advanced topics of Java in a brain-friendly way.

Java 8 to 21: Explore and work with the cutting-edge features of Java 21

You should have some experience with Java to get the most out of this book. I can see that it would be perfect for someone who needs a refresher in the language or has worked with older Java versions and wants to learn about all the new and exciting features. It also includes fundamentals on things you need to build, deploy and run your Java application.

Effective Java

It assumes a certain level of knowledge and experience with Java programming concepts. I would say that its target audience is experienced Java developers. The book is structured in several concise and self-contained items, making it easy to read and reference specific topics of interest. It combines theoretical explanations with practical examples and real-world scenarios, allowing readers to apply the concepts directly to their projects.

Cruising Along With Java: Modernize and Modularize with the Latest Features

I had to mention this book even though it’s still in beta. The final version is scheduled for a September 2023 release. You can get it now and receive updates as they are made available. Dr. Venkat Subramaniam explains the new capabilities of the Java language between version 9 and 19. Its target audience is experienced Java developers. Its content overlaps some of the content in the Java 8 to 21 book, but it’s aimed at a more experienced audience. It can be a better match for you if you have a few years of Java experience and want a deep dive into the new features introduced after Java 8.

Practical Design Patterns for Java Developers: Hone your software design skills by implementing popular design patterns in Java

This is a must-have book for any serious Java developer who wants to improve the way they write code. You should be comfortable with the Java language to get the most out of the book. Maybe you are working as a senior Java developer or an architect. It starts by doing a summary of software design principles, followed by information on the design of the Java platform. This gives the reader a good base for understanding the purpose and value of using design patterns. All patterns have a motivation for why they exist and an example of where they are used in the JDK.

The Developer’s Bookshelf: My Favorite Reads for Professional Growth

I wanted to share some recommendations on books that I have enjoyed reading. They have given me valuable information that has helped me in my career as a software developer.

The Pragmatic Programmer: Your Journey To Mastery

Maybe the book that made the biggest impact on how I work as a software developer. Read it, and become a pragmatic programmer. Learn about things like avoiding programming by coincidence. This book was first released in 1999 and is now updated and revised to reflect the changes in our field. It’s filled with practical advice to make you a better developer. I think that it should be mandatory reading for any developer.

On Writing Well: The Classic Guide to Writing Nonfiction

Writing software is not that different from writing an article. This book will teach you techniques to write text that are easy to read and understand, characteristics that we want our code to have. By structuring our code as an article, we give the reader a fast overview of what it does. The reader can decide to learn more about a specific function by following the flow of the story. It explains the Single Layer of Abstraction principle in an easy-to-understand way.

Atomic Habits

You can change your life with tiny changes in behavior. By continuously making tiny changes, we can get remarkable results. It presents a way to build good habits and break bad ones.

Pragmatic Thinking And Learning: Refactor Your Wetware

As a developer, we constantly need to learn new skills. This book will teach you how the brain works and how we learn. We are introduced to a model for skill acquisition and how that affects how we learn new skills. By being aware of this model, we can adapt how we teach skills to others.

Ask

By asking the right questions, you discover what your customer wants. This book is about marketing, but we can use the method to understand what our customers want the software we are building to do.

Maintainable code: what is it and why should Java back-end developers care?

Most of us would rather work on a new project instead of on an old messy legacy system. Most developers I talk to tell me that they like to work with code that is easy to maintain. Somehow we end up with all these legacy systems that no one dares touch for fear of breaking something. Why is it that we continue to create projects that are hard to maintain when no one wants to work on them?

We are quite good at identifying if a codebase is maintainable or not by how hard it is to make changes to it. At the same time, we are not so good at preventing it from becoming that way in the first place. Some examples of common reasons code become hard to maintain are:

Over-engineering: The solution tries to solve a problem that doesn’t exist. The code is more complex than it needs to be.

Inconsistent coding practices: The team doesn’t have a common way of writing code.

Lack of refactoring: Existing code is only changed if there is a problem with it.

The lack of a good definition of what maintainable code is can make it easy to miss that the codebase is becoming less maintainable.

If we instead define some wanted characteristics of maintainable code. These are then used to check the code we create to see if we are making it more or less maintainable. We will also look into what benefits writing maintainable code can have for you and your career.

Characteristics of maintainable code

The goal of maintainable code is that it should enable developers to quickly understand and update it without introducing errors or unintended behaviors. A software system is rarely “finished” and is always evolving to meet new requirements. Code is like a garden. It has to constantly be cleared of weeds or otherwise, it will grow completely overgrown. To achieve this a codebase needs to have the following characteristics:

Modularity. It should consist of components that are small, independent, and reusable.

Readability. Written with a clear and consistent domain language, where all variables, functions, and modules have meaningful names.

Testability. It should have automated test suites that test the behavior of the system so changes to it do not cause unintended consequences.

Scalability. It should be able to handle increasing amounts of data and users without becoming slow or difficult to change. Do this with moderation. There is no need to be able to scale up to infinity unless there is a specific business need for that.

Documentability. It should have up-to-date documentation describing why it is implemented the way it is to help new developers understand how it works. Well-written tests can also be used as a form of documentation to show the intended behavior of the system.

Flexibility. Designed in a way that it’s easy to change and adapt to meet changes in the requirements.

Reusability. Designed in a way so that modules can be used to build and integrate with other systems.

What’s in it for me?

By writing maintainable code that is easier to change and debug, you will save time and increase productivity in the long run. You and your team will have better collaboration and teamwork because the code is easier for other developers to understand and work on. Demonstrating the ability to write maintainable code can be a valuable skill in the job market, increasing the likelihood of being hired for high-quality projects and advancing in your career. It will also enhance your reputation and credibility, leading to better opportunities and greater recognition in the software industry.

Overall, writing maintainable code is a best practice that can lead to better software and a more successful career for developers. In the coming posts I’ll talk about what we can do to achieve these characteristics so don’t forget to register to be notified when new articles are posted.