Categories
Development Technology

Decoupling Code

I’ve written before about my use of SQLite and the GRDB framework in my new app ExerPlan. After spending more time coding and getting to grips with the approach I detailed here, I’ve made the decision to alter the approach again.

While GRDB is an excellent framework, it’s not part of the Swift standard library and as such there may come a time when it’s no longer supported or actively developed. I decided I didn’t want my code so tied to the framework that replacing it could be an issue. The solution? To make a small alteration that would decouple me from GRDB, while still letting me use the power of GRDB as I was before.

I split my data code across two objects; one is a Struct that is basically a 1-to-1 mapping of a database table. However, it has no knowledge of how it will be persisted as I’ve removed all references to GRDB. The second type is a class that does reference GRDB, and is where all the persistence methods have been moved to.

The persistence class contains one “save” method per table, and takes a value of the Struct as a parameter.

struct Plan
{
   var planID: Int64?
   var planName: String

   func save()
   {
      Persist.save(self)
   }

}

class Persist
{
   func save(plan: Plan)
   {
       // Create a GRDB version of the Plan object
       // Then we can use GRDB to persist
   }

   func save(activity: Activity)
   {

   }
}

Having split the code like this, my persistence layer is now decoupled from the objects it is persisting. If I decide to stop using GRDB, I only need to re-write the save methods in the Persist class and the rest of the code will carry on working in the same way.

I have also created a Fetch class, which works in a similar way to Persist, but is for returning data that my app requires. Again, this means I only need replace code in Fetch if I were to use a new data access framework in place of GRDB.

It’s been a long journey getting to this point with Swift, GRBD, and iOS coding in general. I’m happy with where I’m at now and I’ll be moving on to the next stage, learning how to do UI programming with Swift and iOS.

Categories
Development Technology

Swifty SQL With GRDB

In my previous post I explained why I chose to use SQLite and GRDB for my app ExerPlan, and in this post I’m going to share implementation details with some Swift code.

I wanted to use Structs to map to database tables. This way I could do things like:

var activity = Activity(activityID: nil, activityType: 1, activityDate: Date() )

activity.save()

I also wanted to be able to have my structs encapsulate functionality to provide data validation. Although I will use some protection at the database level to enforce certain things (primary keys, constraints, triggers) I also like to take action at the UI level before it even hits the database.

To facilitate this I chose to create two structs per database table; one struct would be a “pure” GRDB-focussed struct that would give me the persistence code for free, and the second struct would be more like the public-facing API that I would use throughout my code for actually interacting with the data in the database. The first struct would become a property of the second.

struct ActivityDB: Codable, MutablePersistableRecord, TableRecord
{

   // Let GRDB know the name of the database table, otherwise it will assume it is the same as the struct’s name
   static let databaseTableName = “Activity”

   // This is the primary key, but it’s optional
   // because until a row is Inserted there is no value
   var activityID: Int64?

   var activityType: Int64
   var activityDate: Date

   mutating func save()
   {
      // Save record here
      // GRDB handles Insert/Update for new/modified row
      // and returns the auto-generated ID if there is one
   }

   // This is where the auto-generated ID can be used
   mutating func didInsert(with rowID: Int64, for column: String?)
   {
      activityTypeID = rowID
   }
}

My second struct would have ActivityDB as a property, but allow for data validation that I didn’t want to have on the GRDB-focussed struct.

struct Activity
{
   var dataStore: ActivityDB

   var activityID: Int64?
   {
       get
       {
           return dataStore.activityID
       }
   }

   var activityType: Int64
   {
      get
      {
         return dataStore.activityType
      }

      set(newValue)
      {
         // Perform some validation logic here
         dataStore.activityType = newValue
      }
   }

   var activityDate: Date
   {
      get
      {
         return dataStore.activityDate
      }

      set(newValue)
      {
         // Perform some validation logic here
         dataStore.activityDate = newValue
      }
   }

   mutating func save()
   {
      dataStore.save()
   }
}

There are a few kinks to work out with this approach, notably I’m not sure if I need the two structs and could just use one. At this stage it’s working as I want so I’ll continue with it until/unless I hit any major issues.

The next step was to create some code that would allow the easy retrieving of rows. GRDB provides a number of methods to do this, but I wrap those up inside a big Data Access Layer or DAL class. The class consists of a number of static methods that return arrays of structs, or whatever else is needed from the database. The following code shows the basic structure of how I return an array of one type.

class DAL
{
   private static func returnArray<T>(fromRows rows: [Row], ofType: DatabaseTypeEnum) -> Array<T>
   {
      var list = [T]()

      for row in rows
      {
         switch ofType
         {
         case .ActivityTableView:
            list.append(ActivityTableView(dbRow: row) as! T)

         case .PlanTableView:
            list.append(PlanTableView(dbRow: row) as! T)

         }
      }

      return list

   }

   private static func doFetchAll(withSQL sql: String, returnType: DatabaseTypeEnum) -> Array<T>
   {
      let rows = try! dbQueue.read
      { db in
         try Row.fetchAll(dB , sql)
      }

      returnArray(fromRows: rows, ofType: returnType)
   }

   static func fetchAllActivities() -> [ActivityTableView]
   {
      let sql = “””
Select src.ActivityID, src.ActivityType, src.ActivityDate
From Activity src
Order By
   src.ActivityDate desc
“””

   return doFetchAll(withSQL: sql, returningType: .ActivityTableView)

   }

}

The DAL can easily be extended with new methods for retrieving data, and also for the retrieval of single values/rows rather than an array. It’s still a work in progress design and as I get further into the UI development and have to start using these methods I may end up making new design decisions.

Writing this article has been a useful exercise as it has forced me to consider my choices again, and even led to some refactoring as I wrote it. The next step is to progress with the UI prototype which will give all this code a really good workout.

Categories
Development Technology

Swift SQLite With GRDB

Any app like ExerPlan needs a good data model and data store, and given my SQL skills and the fact that SQLite is part of iOS there was only ever one choice for me.

I work with Microsoft SQL Server in my day job and I am very comfortable with writing SQL code to handle inserts, updates, and deletes. I come into contact with lots of different systems at work, and as such I witness many crimes against data. These range from column names making as much sense as Brexit, to seemingly well-designed schemas that lack the database constraints to enforce that design. I wanted to ensure that I created a database that didn’t suffer from these problems.

Swift and SQLite don’t necessarily play well together because it’s not as though SQLite is part of the Swift standard library. But Swift is open source and so maybe there’d be an open source solution for me?

Enter GRDB a “SQLite databases toolkit with a focus on application development”.

I’ve looked at a few such toolkits for SQLite and Swift, but GRDB is by far my favourite. The main reason is that SQL code is front and centre in GRDB if you want it to be, and with my background I very much do. GRDB has some really nice abstractions away from SQL if you want to use them, but as the docs say “your SQL skills are welcome”.

I’ll address how I’m using GRDB more fully in a later post, but for now it’s enough to say that GRDB and Swift play very nicely together. I’ve now got a solid base to work with, and GRDB feels as much like Swift as the standard library.

Select “Happy” As MyFeelingAboutGRDBAndSwift

Categories
Development Technology

Workflow V2.0

Since upgrading my hardware and buying a Mac Mini and an iPad Pro, my workflow has undergone a big change for the better.

I used to spend time designing on lots of A4 paper, creating written notes and drawings of UIs. This was a good way of working, but it meant either carrying around loads of A4 to wherever I was working, or more often just leaving the paper notes behind thus rendering them useless: Enter iPad Pro, Apple Pencil, and Notability.

Notability is my note-taking app of choice, as it combines typed notes and drawings in one note. I’m now able to make design notes sat in front of the TV (relaxed working), and take them with me when I need to translate the notes into Swift code at my computer desk (focused working). No more piles of A4 cluttering up my desk.

ExerPlan UI notes.
ExerPlan UI notes.

Another app that’s been useful on the iPad is Swift Playgrounds. I can try out code ideas before I delve into Xcode and doing this has helped me learn a lot about Swift in isolation. Again, I can take the iPad with me when working at my desk, and transfer what I’ve learnt to my main app.

Finally, I’ve been using Numbers to store my data model. A spreadsheet is a good tool for a data model, as the tabular format makes entering a table’s column details easy. In conjunction with the excellent Git client Working Copy, I’ve been easily keeping the data model and code base up to date.

Although it was a big investment in new kit I’m really glad I did it. My workflow has altered for the better and I am more productive with my app work than I’ve ever been.

Now if you’ll excuse me I’ve got some websites to search for details of implementing UIViewControllers in Swift code…

Categories
Development Fitness

ExerPlan – Exercise Planning App

ExerPlan is the working title of a new app I’m working on, designed as a general exercise planner.

In the past I used Excel to plan my running training. More recently I’ve started doing more types of exercise, such as strength training, yoga, and lots of walking. I wanted an app to record and monitor my plans, rather than having to use Excel, and so I started work on ExerPlan.

With Excel and a big screen it was easy to see a full training plan at once. That won’t be possible on an iPhone screen, but my aim is to offset the loss of readability with the fact that I’ll have the plans to hand more often. I may eventually extend the app to iPad so I can get some of that big screen functionality back, but my initial focus will be on the iPhone.

ExerPlan will be based around the concept of activity types and sub-types. An activity will be something like “Running”, “Walking”, “Yoga”, while a sub-type might be “Hill Running” or “Intervals”. The app will allow the user to plan sessions of those activities in one of two ways. They’ll be able to add the planned activities to a calendar-style view, but also group activities into Plans. For example, a user might want to do yoga twice a week but not have it be part of any particular plan. Whereas, another user might want to enter a 16-week marathon training plan. ExerPlan will allow for both these things to be logged.

Once an activity is added it can be updated with the actual activity, e.g. I planned to run 5 miles, but only ran 3. In this way I’ll be able to track planned vs actuals, and provide data visualisations. I’ll be able to track performance against the plan, and also against specific activity types, e.g. how often do I plan a Hills session and how often do I actually complete them! I may also implement a badge system to “reward” users if they complete enough planned activities, but I think that’ll be a V2 development.

I’ve been designing ExerPlan for a few weeks and I finally started coding the app last week. Most of the database gubbins has been written and I’ll be moving onto the good bit next; the UI.

Well, that’s the plan 🙂