DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Beginners Guide to Mocking in Scala
  • Thermometer Continuation in Scala
  • Deploying a Scala Play Application to Heroku: A Step-by-Step Guide
  • Practical Use of Weak Symbols

Trending

  • Overcoming React Development Hurdles: A Guide for Developers
  • Why We Still Struggle With Manual Test Execution in 2025
  • Simplify Authorization in Ruby on Rails With the Power of Pundit Gem
  • Scalability 101: How to Build, Measure, and Improve It
  1. DZone
  2. Coding
  3. Languages
  4. Clean Code Best Practices in Scala

Clean Code Best Practices in Scala

Naming, functions, and TDD — these are Scala clean-code essentials.

By 
Shubham Dangare user avatar
Shubham Dangare
·
Mar. 27, 19 · Presentation
Likes (19)
Comment
Save
Tweet
Share
27.4K Views

Join the DZone community and get the full member experience.

Join For Free

This article was first published on the Knoldus blog.

If you are reading this blog, that's most likely due to two reasons: You are a new Scala programmer, and/or, you want to become a better Scala programmer.

Even bad code can function. But if the code isn’t clean, it can bring a development organization to its knees. Every year, countless hours and resources are lost due to poorly written code. But it doesn’t have to be that way.

So, there might be a question popping in your head: what is clean code?

Clean code always looks like it was written by someone who cares. Clean code means the logic is straightforward and makes it hard for bugs to hide, which means that they can be read and identified by a developer other than the original author. 

So, there are some basic Scala clean-code rules that we will discuss in this post. Let's get into it!

1) Meaningful Names

It is easy to say that a name should indicate its intent. Choosing names can take time, but these names will save more time in the long run. Everyone who reads your code will be happier, including you. Properly naming code can improve consistency, clarity, and code integration. The name of the function or class should answer all of the big questions. Suppose your variable name is:

val x = 10 // This variable name reveals nothing


The name “x” doesn’t reveal anything. Therefore:

Use Intention When Revealing the Name

We should choose a name that specifies what is being measured and the unit of that measurement.

val elapsedTimeinDays // This reveals what is being measured and unit of measurement


Programmers must avoid leaving false cues that obscure the meaning of the code. We should avoid words entrenched in meanings that vary from our intended meaning. For example, hp, aix, and sco would be a poor variable name. So, avoid misleading names, which could create confusion:

def getAccount ()
def getAccounts()
def getAccountInfo()


Use a Pronounceable Name

Also, you should use a pronounceable name. For example, a name like genymdhms means (generate date, year, months, day, hours, minutes, seconds), so we can’t walk around and say “gen why emm dee aich emm ess,” which is very hard to discuss. This could, instead, be written as: generateTimeStamp.

You also don't need to prefix member variables with  m_ anymore. Your classes and functions should be small enough that you don’t need them. And you should be using an editing environment that highlights or colorizes members to make them more distinct. Prefixes become an unseen clutter and a marker of older code:

class Part {
 var  m_dsc = "manager";
 def setName(name:String){ 
  m_dsc = name; 
  }
 }


class Part{ 
 var  description:String = "Manager";
 def setDescription(description:String) {
   this.description = description;
  }
 }


Classes and objects should have a noun or noun phases name, like Customer or wiki page. Additionally, avoid names like Manager, Data, and Info. A class name should not be a verb.

Methods, however, should have a verb or verb phrase as the name, like post payment, deletePage, or save. Accessors, mutators, and predicates should be named based on their value and prefixed with getting, set, etc. Pick one word for one abstract concept and stick with it. For instance, it’s confusing to have fetched, retrieve, and get as equivalent methods of different classes.

Here is an example of a method:

def genymdhms(t: Any): Timestamp = {
 val d1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS")
 val d2 = date1.parse(token_exp.toString)
 new Timestamp(parsed2.getTime)
}


Clean code would look like:

def getCalendarTimeStamp(token_exp: Any): Timestamp = {
 val dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS")
 val parsedDate = dateFormat.parse(token_exp.toString)
 new Timestamp(parsedDate.getTime)
}


2) Functions

“Functions should DO ONLY ONE THING. And they should do it well."

The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than small. So, this means that your function should not be large enough to hold nested structures. Therefore, the indent level of a function should not be greater than one or two. This technique makes it easier to read, understand, and digest.

Your function can take also the minimum number of the argument, which is zero. Such functions do not depend on any input, so there’s always going to be some trivial output from it. However, it will be easy to test.

Next comes one (monadic), which is based on functional programming rules, followed closely by two (dyadic). Three arguments (triadic) should be avoided wherever possible. More than three (polyadic) requires very special justification, and even then, they shouldn’t be used anyway.

However, in case the number of arguments are more than three, we should group them into a meaningful object, like so:

def registerUser(name: String, password: String, email: String,address:String,zip:Long): String = {
    implicit val session = AutoSession
    dBConnection.createConnectiontoDB()
    val token = UUID.randomUUID().toString
    import java.util.Calendar
    val calendar = Calendar.getInstance
    val token_gen = new Timestamp(calendar.getTime.getTime)
    calendar.add(Calendar.MINUTE, 30)
    val token_exp = new Timestamp(calendar.getTime.getTime)
    withSQL {
      insert.into(UserData).values(name, password, email, address,zip,token, token_gen, token_exp)
    }.update().apply()
    token
  }


This can be written as:

case class User(name: String, password: String, email: String,address:String,zip:Long)
def registerUser(user:User): String //


3) Test-Driven Development (TDD)

The primary goal of TDD is to make the code clear, simple, and bug-free. In a TDD approach, first, the test is developed to specify and validate what the code will do.

How does TDD work?

  • Write a test
  • Make it run
  • Change the code to make it right, i.e. Refactor.
  • Repeat the process

By now, everyone knows that TDD asks us to write unit tests before we write production code. But that rule is just the tip of the iceberg. Consider the following three laws:

  • First Law: You may not write production code until you have written a failing unit test.

  • Second Law: You may not write more of a unit test that is sufficient to fail, and not compiling is failing.

  • Third Law: You may not write more production code that is sufficient to pass the currently failing test.

Finally, there should be a single concept per test and only one assertion per test, which is said to be good practice.

Here is an example:

"document is empty" should {
 "not be able to convert a document into an entity" in {
   val result = UserDataDao.documentToEntity(Document())
   assert(result.isFailure)
 }
}


References

  1. Clean Code by Robert C. Martin
unit test Scala (programming language)

Published at DZone with permission of Shubham Dangare. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Beginners Guide to Mocking in Scala
  • Thermometer Continuation in Scala
  • Deploying a Scala Play Application to Heroku: A Step-by-Step Guide
  • Practical Use of Weak Symbols

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!