App 2: The Database Class (Scala 3 Video)
When I think about how TDL’s main
method starts, I think that one of the first things it needs to do is create an instance of a Database
class:
@main
def ToDoList =
val db = Database("./ToDoList.dat")
...
In that code I pass Database
the name of the file it should use as its flat-file database. Right away, this tells me that I need a Database
class that takes a filename input parameter:
class Database(val dbFilename: String):
// methods go here ...
end Database
As you’ll see in the following lessons, we’ll then define these functions inside that class, to mimic the way SQL functions typically work:
insert
delete
selectAll
NOTE: Writing this code is the same as writing OOP code, where you have a class that takes a constructor parameter (
dbFilename
), and then the methods in that class use that parameter. The only difference is that I won’t mutate that parameter, so, as shown, I define it as aval
parameter.
About the ‘Try’ rule
Recall my rule that any function that reaches out to the outside world must return the Try
error-handling type. This is overkill for a flat-file database, but it helps if you recall that real database code typically accesses another server (or cluster) that may or may not be running when you call it. This is also just like calling a REST API that may or may not be running, across a network that may or may not be available.
In these situations, robust code must return an error-handling type like Try
or Either
, and for our purposes, I’ll use Try
.
How this affects Database
Given this rule, I sketch the Database
class to have methods with these type signatures:
class Database(dbFilename: String):
def insert(record: String): Try[Unit] = ???
def selectAll(): Try[Seq[String]] = ???
def delete(indexToDelete: Int): Try[Int] = ???
end Database
I’ll explain that code in the following chapters, but briefly:
insert
returnsTry[Unit]
, and itsSuccess
andFailure
results tell us if it workedselectAll
returnsTry[Seq[String]]
, which is a list of strings inside aTry
.delete
returnsTry[Int]
, and itsInt
value indicates the number of rows deleted.
In all of those cases, if our “database server” is down, the Try
we get back will be a Failure
, but if the server is up and running, we should get back a Success
.
Methods vs functions
As a final note, this is my personal standard about using the names “methods” and “functions” when talking about Scala code:
- When you define these inside a class, I refer to them as methods.
- Anywhere else, I refer to them as functions.
This isn’t a standard Scala naming convention, it’s my own personal convention. It always feels weird to talk about functional programming while constantly using the term method, so that’s how I came up with this personal standard. Therefore, from here on out, I’ll refer to “methods in the Database
class.”
Update: All of my new videos are now on
LearnScala.dev