Lumi4
This is the next iteration in a three year project. Here are the current iterations:
-
Vorpal Hoff
-- an attempt at wireless uploading with a HM-11 and LPC1114 combination. Written in C / C++ (Initialized May 22nd 2014).
-
HM-1X Aid
-- this project was meant to be a GUI on top of the HM-1X modules, allowing "easy" editing of the module's behavior. It was my first venture into C#. (It's sooo bad;although, the serial communication was asynchronous.) (Initialized Dec. 19th 2015)
-
Lumi1
-- this the first successful TinySafeBoot uploader. It was written in C# using the .NET WinForms. Unfortunately, it was synchronous. And I was finished with the USB-to-UART uploader before I realized there was no easy BLE support in WinForm's .NET. (Initialized March 2nd 2016)
-
Lumi2
-- this is where things start getting better. It is the current version of the TSB wireless bootloader. It works, is asynchronous, and has BLE support. Unfortunately, the code turned into spaghetti. This is largely due to my poor understanding of object-oriented design. It has god-modules, a horrifically implemented SerialEvent response protocol, poor encapsulation, no polymorphism. It's just a mess. (Initialized March 21st 2016)
-
Lumi3
-- this project was stopped early. It was an attempt to build a multiplatform uploader using Xamarin Forms. It would have allowed iOS, Android, and Windows versions of the application. Unfortunately, it is a fairly complex project. Theoretically, the uploader would work by allowing the user to select a HEX file from Dropbox, handshake with TinySafeBoot using BLE or WifI, then upload the HEX file. And though this is theoretically possible, it would take learning two new APIs: Xamarin Forms and Dropbox. And my focus is dilberate practice of language conventiosn and OOP, rather hacking through two new APIs. Most likely, I'll come back to this project after Lumi4 (Jan 13th 2017)
Why? Seriously, dude
It is important to state the objective of the this three-year project has not been to produce a product which works, although, that's a close second. The purpose of these repeated attempts is to improve as a developer.
Of course, I don't believe if I try enough and eat my Wheatie I'll grow into a great developer. But with each iteration I'm focusing on developing a handful of new skills. This learning strategy is from the book
Peak
by Anders Ericsson. The continued
and
intentional practice is labeled by Ericsson as "
deliberate practice
." It's with
this
mindset I've approached this iterative coding project, hoping with each iteration the code improves, but more importantly, my skill as a developer improves.
Focus
Deliberate practice involves selecting particular deficits to focus on. This is more effective, as the improvement is in a few intentional areas, rather than trying to practice every important nuance of a skill at once. This seems easy to get behind; especially, when it comes to developer skills. There are just too many to try and refine all at once.
Sadly, focused practice isn't something I was intentional about for the first few code bases in this series. It wasn't until Lumi3 and Lumi4 did it bubble up as crucial in the process of developing my skills.
Targeted Areas in Lumi4
The areas I'm looking to practice in Lumi4
-
Project Management
-
Project journaling
-
Abstraction
-
Encapsulation
-
Granulization of objects (avoid God-objects)
-
Meaningful names
-
C# Conventions (naming, formatting, placement, etc.)
-
Factory design pattern
-
Observer design pattern
-
Error handling
-
Unit Testing
Some areas which I may take on if all goes well:
-
Integration testing
-
Documentation API
What's the Plan for Lumi4?
Lumi4 will have three basic components:
-
Communication handling for BluetoothLE and WiFi (extendedable to Bluetooth Classic and USB-to-UART)
-
Smart serial display (e.g., recognizes data outside of ASCII range and prints as a hex string)
-
TinySafeBoot uploader
Learning Assests
Unit and Integration Testing
Testing fascinates me. When I studied psychometrics there were a
battery of tests
as to whether and instrument worked as intended. In the psychology world these were the fundemental building blocks of effective research and practice. Why did we use
CPT
? Because it passes a variety of tests to demonstrate efficacy. In the developer world tests still hold my fascination. They consistently demonstrate a product is capable of completing the task for which it was designed.
Of course, I've struggled with adopting testing in projects. A lot of this has to do with poor understanding of how to design a test to meet a purpose. It wasn't until I was listening to a Coding Blocks (#54 --
Writing Amazing Unit Tests
) episode on writing unit tests did I get more comfortable with testing. Specifically, when they discussed the differences between unit and integration testing.
When I
first attempted to write tests
for a project it was unit tests. Unfortunately, this project was the second iteration of my Lumi uploader and the tests resulted in a hot-mess. This is because I was trying to test functions which relied on inputs from other systems.
For example,
[TestMethod]
public async Task<bool> shouldStartBLEWatcher()
{
// Arrange
blueTestObject.init();
await blueTestObject.startBLEWatcher(8);
return true;
}
This is as far as I made it writing a unit test on a method which was meant to test whether the StartBLEWatcher() method was working. In unit testing there should be an assert on the output of the method, but StartBLEWatcher() returned discovered BLE devices (yes, I realize the method could be re-written better, thus the reason for this article). This is where I got frustrated. "How the hell am I suppossed to write unit tests on code which interacts with other hardware!?" I mean, I get it, unit testing is the bread-and-butter of professional programmers. It helps building big projects which would otherwise collapse under size. But how the hell do I write unit tests for code which relies on outside systems!? Saldy, I found the answer too late: You don't.
In the Coding Blocks episodes there is a discussion on the difference between unit tests and integration tests. A unit test is meant to test a small piece of code and it should rely on no other code. An integration tests checks whether a piece of code works as intended. However, unlike unit tests, integration tests
do
rely on outside systems by their very definition.
When I heard this discussion I went to the first StackOverflow answer on the subject:
Question: "What is the difference between integration and unit tests?"
Answer (by
Nathan Huges
)
A unit test is a test written by the programmer to verify that a relatively small piece of code is doing what it is intended to do. They are narrow in scope, they should be easy to write and execute, and their effectiveness depends on what the programmer considers to be useful. The tests are intended for the use of the programmer, they are not directly useful to anybody else, though, if they do their job, testers and users downstream should benefit from seeing fewer bugs.
Part of being a unit test is the implication that things outside the code under test are mocked or stubbed out. Unit tests shouldn't have dependencies on outside systems. They test internal consistency as opposed to proving that they play nicely with some outside system.
An integration test is done to demonstrate that different pieces of the system work together. Integration tests cover whole applications, and they require much more effort to put together. They usually require resources like database instances and hardware to be allocated for them. The integration tests do a more convincing job of demonstrating the system works (especially to non-programmers) than a set of unit tests can, at least to the extent the integration test environment resembles production.
Actually "integration test" gets used for a wide variety of things, from full-on system tests against an environment made to resemble production to any test that uses a resource (like a database or queue) that isn't mocked out.
Well, that's it for a bit.