# 2. Leap

Hello everyone, today we're looking at the Leap exercise found at exercism.io. More specifically we're comparing two common approaches to solving this problem and discussing the benefits and drawbacks of each. Let's get started.

## Exercise

Given a year, report if it is a leap year according to the following rules. A leap year in the Gregorian calendar occurs:

- On every year that is evenly divisible by 4.
- Except every year that is evenly divisible by 100.
- Unless the year is also evenly divisible by 400.

Here are the tests:

```
class LeapTests: XCTestCase {
func testVanillaLeapYear() {
let year = Year(calendarYear: 1996)
XCTAssertTrue(year.isLeapYear)
}
func testAnyOldYear() {
let year = Year(calendarYear: 1997)
XCTAssertFalse(year.isLeapYear)
}
func testCentury() {
let year = Year(calendarYear: 1900)
XCTAssertFalse(year.isLeapYear)
}
func testExceptionalCentury() {
let year = Year(calendarYear: 2400)
XCTAssertTrue(year.isLeapYear)
}
}
```

So we need a type `Year`

which can be initialized with a `calendarYear: Int`

argument and who's instances have a `isLeapYear: Bool`

property.

## Stored vs computed properties

There are two common approaches to solving this problem.

- Implement
`isLeapYear`

as a stored property and compute it's value in the initializer. - Store the
`calendarYear`

argument as a stored property and implement`isLeapYear`

as a computed property.

```
// 1. Stored property
struct Year {
let isLeapYear: Bool
init(calendarYear: Int) {
self.isLeapYear = calendarYear.isMultiple(of: 4)
&& !calendarYear.isMultiple(of: 100)
|| calendarYear.isMultiple(of: 400)
}
}
// 2. Computed property
struct Year {
let calendarYear: Int
var isLeapYear: Bool {
return calendarYear.isMultiple(of: 4)
&& !calendarYear.isMultiple(of: 100)
|| calendarYear.isMultiple(of: 400)
}
}
```

So which approach should we use? In this case I'm going with the stored property version for the following reasons.

#### Immutability

`isLeapYear`

will always return the same value because `calendarYear`

can not be changed after initialization. There is really no benefit to re-computing the value on each access. The only effect is increased CPU usage which decreases battery life on battery powered devices.

This would be different if `calendarYear`

*could* be changed after initialization. In that case a computed property would be useful by ensuring the correct value is always returned even as `calendarYear`

is changed.

#### Speed

Returning the pre-computed `isLeapYear`

value from memory will be faster than re-computing it on each access. Having said that, I'm not sure the difference will be perceivable in this case because the logic is simple math that modern processors can do very fast.

#### Memory

I haven't actually tested this, but I imagine storing the `isLeapYear: Bool`

will use less memory than storing the provided `calendarYear: Int`

. I'm assuming a `Bool`

uses 1 bit whereas an `Int`

probably uses 64 bits. I could be wrong here.

So that's my thinking, but what do you think? Stored or computed property?

### Brevity vs readability

I realize *readability* is quite subjective. So rather than think of it as "how easy is it for *me* to read this?", I'm thinking of readability as "how complex or simple is this?". The simpler the code, the more readable I consider it. For example, let's look at our existing `isLeapYear`

logic:

```
self.isLeapYear = calendarYear.isMultiple(of: 4)
&& !calendarYear.isMultiple(of: 100)
|| calendarYear.isMultiple(of: 400)
```

There are at least five separate concepts happening in this one statement:

- Property assignment into
`isLeapYear`

property. - Calculation of results from
`isMultiple(of:)`

. - Inversion of second
`isMultiple(of:)`

result via`!`

operator. - Combining of returned values with
`&&`

and`||`

operators. - Order of operations of the
`&&`

and`||`

operators.

Personally I find this too complex and prefer limiting each statement to two or three concepts. Let's break this up into multiple statements using descriptively named variables to serve as documentation and parenthesis to clarify order of operations.

```
let isEvenlyDivisbleBy4 = calendarYear.isMultiple(of: 4)
let isNotEvenlyDivisibleBy100 = calendarYear.isMultiple(of: 100) == false
let isEvenlyDivisibleBy400 = calendarYear.isMultiple(of: 400)
self.isLeapYear = isEvenlyDivisbleBy4
&& (isNotEvenlyDivisibleBy100 || isEvenlyDivisibleBy400)
```

This code is certainly more verbose but also less complex. Each statement now has at most three concepts.

What do you think? Brevity or readability?

## Next episode

Next episode we'll be looking at the Gigasecond exercise found at exercism.io. Feel free to complete that exercise before the next episode and we can compare our answers.

Take care everyone.