Author Archives: Connor V.

Sprint Retrospective – 2 May 2018

As the final full sprint comes to a close, I find myself wishing for just a bit more time to work. With the testing issues resolved, we were able to work much better than we have in the past, and with a newfound grasp of the technologies at hand. Had we begun the semester with this kind of understanding of what we were working with, I think we would have had a vastly different product than what we currently do. During this sprint, we corrected what was left of the sync/async issues we were having, made a switch over to a singleton pattern for our service (with a bizarre development), and got as much of the service in minimum working order as we were able.

Having redone the tests to be compatible with Promise objects, I spent the first bit of the sprint trying to convert the offline storage service into a singleton pattern. The primary difficulty in this turned out to be that Ampath had its own tslint.json file for enforcing the organization’s style guide. When coupled with the fact that WebStorm regards conflicts with the tslint file in the same way it regards syntax errors, it meant that the code wouldn’t compile, and I had no clue what was wrong with it. Only after reordering my field and static method declarations would the tslint stop holding my code hostage. After going through this whole ordeal, I think it would be nice if at the start of future semesters, Ampath provided capstone sections with a style guide to avoid headaches like this one. After the conversion to singleton, I moved to the tests to rewrite them to interact with the singleton object. In the middle of this process, however, something very non-intuitive and very obnoxious became visible.

First, a recap of the purpose of Singleton Pattern: by making the default constructor for a class private, one can disable willful instantiation of that class. Then, a static method which returns the single instance of the class allowed to exist is written. With this structure, you can guarantee that only one instance of a class exists, and there is an easily available mechanism to grab a reference to that class.

“Not in my house,” says Angular. It turns out that making the default constructor private doesn’t actually give it any kind of private visibility; you can still instantiate the class with “new.” I only realized this when halfway through writing my test cases, I accidentally wrote “= new OfflineStorageService();” and was not told that it was a problem. Rather, the tests all ran and passed, even though – and I triple checked myself on this one – the default constructor in OfflineStorageService was most definitely declared private. I shared this information with my group at the next meeting, and we each agreed that it was one of the most baffling things we’d ever seen in programming.

In spite of my shock, things proceeded smoothly and steadily for the rest of the sprint. Our communication was spot-on, as we were giving each other daily, sometimes hourly updates in our group text message. The code, while sometimes strange and alien, was actually starting to behave like we wanted it to behave. We were in consistent communication with one of the other groups, and occasionally communicating with the other two. Really, this felt like a culmination of what we’d learned from the last five sprints – as it ought to have. Perhaps we could have done something better; I probably could’ve been better about standup meetings and asking questions about Ampath, but I think in general, each of us feels far more comfortable with this entire process. With only the documentation left to do, along with our final presentation, I think I can say I’m beginning to feel what it means to be this thing called a “software developer.”

From the blog CS@Worcester – Studio H by Connor V. and used with permission of the author. All other rights reserved by the author.

Be The Worst

Intimidating in much the same way that The White Belt pattern is, Be The Worst encourages software developers to surround themselves with peers that have much greater skill levels. As the weakest member of a team, one has ample amounts of room to learn and grow. Practically speaking, due to the skill present in the surrounding developers, they will be able to correct the unseasoned programmer’s mistakes, and prevent those mistakes from recurring in the future. Furthermore, the goal of the pattern is quite emphatically to cease to be the weakest; the person making use of this pattern will be working extra hard to climb up to the level of the professionals surrounding them.

Admittedly, this is a bit of a difficult pattern to put into practice – at least for me – in the immediate present. The only time I can relate to Being The Worst is when I first joined the programming team back in sophomore year of college. I certainly noticed the gap in capabilities; I was much slower than the other members at solving problems, and my solutions tended toward the bulky side, with optimizations that weren’t necessary for the problem at hand. Over time, being among the other members of the team taught me to evaluate context to determine how thorough I needed to be with my code, and gave me mechanisms for assessing problems in a way that was more programmatic.

I expect that this pattern will come into play whether I like it or not as I enter the workforce. Whatever team I happen to join will have been doing the things it does for years before I ever showed up, and may have tools and environments that I’ve had minimal exposure to, if any. As such, I will need to keep the ideas of Being The Worst in mind while I learn to navigate that team, working in any ways I can to raise myself to their standard and beyond. For now, though, I will have to settle for my position of Being The Neither-Worst-Nor-Best in my current team for the remainder of the capstone.

From the blog CS@Worcester – Studio H by Connor V. and used with permission of the author. All other rights reserved by the author.

Sprint Retrospective – 18 April 2018

By stark contrast to all previous sprints, Sprint #5 was a violent roller coaster of efficacy. For the first half of the sprint, I continued in the role set for myself in the previous sprint: the guy who writes the tests. Up to this point, we had been using a simple set of tests for the purpose of making sure we knew how to write tests and get them to pass. Now, the focus had shifted to constructing good tests – with appropriate code coverage and level of complexity – to be able to test our code against the standard we were seeking to hold it to. This sprint definitely taught us a thing or two about consistently committing changes to our GitHub, as I believe that many of our issues we encountered over this sprint could have been resolved – or, at the very least, spotted – much more quickly had we been up to date with one another’s code more frequently than we were.

As mentioned before, there was real turbulence as far as the amount of work being done adequately throughout the sprint. About a week into this more strict test-writing process, one day in the middle of a class meeting, something very strange began to happen. It started as what we thought was some bizarre install issue: karma would no longer open the browser for testing when we tried to run ng test in the CLI. We decided after a bit of reading on the issue to try reinstalling our node modules – which technically solved the problem we were seeking to address, but came with an entirely new, arguably much worse problem. Now, the tests were inexplicably no longer working.

It doesn’t end there either; not only did our newer tests suddenly stop working, but when we tried reverting back to the old, successful tests to find the step that made things go wrong, we found yet another strange issue. Now, the tests were still passing, but when we looked into the IndexedDB in the browser, and the console, both were empty. I.e., no database had been created, no patient objects had been added to said nonexistent database, and not even the console logs we put in the middle of the code for debugging were being sent to the console. We would not resolve this perplexing set of issues until only a few days ago, when we came to the abrupt realization that we were trying to use synchronous methods to test and implement an asynchronous service (PouchDB).

As soon as we figured this out, we were actually able to get back on track fairly quickly. We learned how to use Promises in our tests so that the asynchronous values being returned by our services methods could be properly evaluated. Since Promise objects are the core component of the asynchronous behaviors of our service, we needed to understand fundamentally what sorts of information they provided us to work with. Prior to this, we were trying to extract boolean, string and integer values from our methods – which proved fruitless, due to the fact that these are synchronous values. Promise objects, it turns out, give us back a kind of message. They give back a JSON object, which contains information about its status, with the most relevant field to us being the “ok” field within it. The “ok” field is simply a boolean – which is exactly what we were after. So rather than something like:

 

          expect(service.addDoc(testDB, patient1)).toBe(true);

 

We needed to actually have:

 

          service.addDoc(testDB, patient1).then( (resultOfAdd) =>

                    expect(resultOfAdd.ok).toBe(true);

          });

 

Where “resultOfAdd” is the response object returned from the addDoc method’s Promise.

For as frustrating as much of this sprint turned out to be, it was also incredibly satisfying at the end of it all. It was very reassuring to see such a monumental problem have one issue resolved that made the entire mountain of trouble it created flatten. Going forward, I will be sure to keep in mind the conditions that lead to this set of difficulties – primarily lack of diligence on commits – and the steps that were most effective in figuring out the root of the problems.

From the blog CS@Worcester – Studio H by Connor V. and used with permission of the author. All other rights reserved by the author.

Reflect As You Work

I was particularly interested in this pattern the more I read about it, because it sounds incredibly similar in essence to keeping a journal – which is something that I already do. I had never considered maintaining a “Personal Practices Map” as they called it, but it sounds like a perfectly sensible thing to start doing. The problem that Reflect As You Work is concerned with is that of the developer who becomes stuck at his level of incompetence, waiting for the “aha” moment to come along and transform him into and experienced software craftsman.

The practice map they suggest refers to the conscious logging of one’s personal practices, and the connections between them. This does not have to consist only of inadequacies; it is encouraged to record both the effective and ineffective behaviors to have a full picture of one’s abilities as a developer. The idea is also extensible to the behavior of others, i.e., recording the behaviors observed in others to have a map of how other developers act in effective and ineffective ways.

While I may not have been keeping a log of my software development habits up to this point (although now I intend to), I feel that a worthwhile comparison in the present is the practice of standup meetings and sprint retrospectives in this course. These posts get us reflecting on what worked versus what did not work – the sprint retrospectives in particular provide a vague map through these periods, both in terms of what was literally accomplished as well as our thoughts about our utility within the group. And even on top of this, the CATME evaluations we perform each sprint give us a small mechanism through which to assess the ups and downs of our peers.

I believe I will be picking up a second journal for myself. One for the continued recording my thoughts and observations about my own life, and one for the recording of my practices as a software developer. Over time, my Personal Practices Map will be able to paint a picture of my progress as a computer scientist and grant insights into what nurtures my growth, much in the same way that my more general purpose journal provides a picture of my growth as a person.

From the blog CS@Worcester – Studio H by Connor V. and used with permission of the author. All other rights reserved by the author.

Learn How You Fail

Hitting particularly close to home, the Learn How You Fail pattern seeks to instill in inexperienced developers the notion that failure is inevitable and manageable. As written in the Context of the pattern, “Someone who has never failed at anything has either avoided pushing the boundaries of their own abilities or has learned to overlook their own mistakes.” This is a problem that I think must certainly persist in all fields – not just for Computer Scientists. The presence of failure indicates to us that in some way, a person was lacking. That can be a dreadful thing to have to confront, depending on the nature of the failure and the attitude of the person who has failed. Even during the course of this very semester, I and my teammates have experienced numerous failed endeavors that required analysis and discussion to either repair or mitigate.

The suggested method for responding to failure is to actively seek to understand in oneself the patterns, conditions, habits and behaviors that lead to that failure. As that self-awareness is cultivated, it becomes much easier to operate in a way that consciously and productively considers relevant boundaries and limitations. It allows for the choice between either fixing the identified issues or cutting one’s losses; moreover, it vastly improves one’s ability to set realistic limitations on goals.

I think that in this project for Ampath in particular, my group has already been encountering this pattern and applying it in some capacity without realizing it. Each week at our retrospective, we have discussions that touch upon what could have been done better by each person, and we make/uphold plans to address those areas accordingly. This has resulted in each of us finding roles within the group that maximize on our usefulness – we are each focusing on the areas most attuned to our strengths, while minimizing the amount of weakness in those areas. Of course, by virtue of the unfamiliarity with Angular that persists throughout the group, we all have several areas that need refining. However, over time, we have identified which weaknesses are being addressed by which people, and assign ourselves work in accordance with those findings. Indeed, this seems to be a model that will be extremely effective beyond this project.

From the blog CS@Worcester – Studio H by Connor V. and used with permission of the author. All other rights reserved by the author.

Sprint Retrospective – 4 April 2018

This sprint was easily our best one yet. We were highly productive, completing a range of tasks concerning design, merging with other teams and test-driven development. Where the previous few sprints have illuminated the pitfalls and obstacles of Agile development to our team, this sprint gave us a feel for what it’s like when Agile development is running like a well-oiled machine.

Not long after the beginning of the sprint, we identified a design dilemma that had us scratching our heads. We noted that if we had the patient data encrypted with an algorithm that made use of the active user’s password (as all groups seemed to agree upon), then we would run into a problem:

Suppose Doctor A is logged into a machine, making use of the offline data module. He does his work, no problems, everything is fine; all patient data is encrypted with respect in some capacity to his password. Suppose, then, that Doctor B comes along and tries logging into the same device. In spite of having provided perfectly valid login credentials, Doctor B will be unable to access the patient data, due to the patient data being encrypted with respect to Doctor A’s password. We spent a few days trying to figure out exactly how to solve this predicament, but our ideas kept coming up unsatisfactorily for a number of reasons.

I take some pride in being the one to figure out the answer, and consider it one of my two major contributions to the team this sprint. It turns out that the way to both satisfy the specification (which lists that the login must feature encryption using the user’s password + a salt) and the dilemma we encountered was a split in what we were storing. Rather than a single offline database, we would have two. One of these would be responsible for storing the patient data – encrypted with its own algorithm, irrespective of the user’s login credentials. The second database, however, would consist of only strings. Specifically, each string would be the result of running the encryption algorithm with respect to the user’s password on their user ID. For login, the method would therefore be:

  1. User enters username/password
  2. Run the encryption service on the username provided, using the password provided
  3. Perform a database lookup for the result in database 2
  4. If there is a match, successful login. If there is not a match, unsuccessful.

This information was spread to the other groups and has been accepted as the plan for all encryption service use moving forward.

In addition to this important design step, my other major contribution this sprint was in writing test cases for the create, addDoc, and getDoc methods. In class, we were able to get tests to pass with the code written by other members of the team, and observed in browser that a PouchDB database had successfully been created, added to and read from.

The biggest takeaway from this sprint was easily that having specific roles in the group is a powerful motivational force. When it was determined that I would fall into the role of test writer, and the other members of the group picked their specific methods to focus on, it was clear that we had each found the direction we needed in order to get the ball rolling. Going forward, I hope we will continue this practice of providing concrete roles for one another, to make the project feel less like a behemoth and more like a set of separate goals to be achieved.

From the blog CS@Worcester – Studio H by Connor V. and used with permission of the author. All other rights reserved by the author.

Concrete Skills

Concrete Skills is particularly relevant to those of us coming to the end of our college careers; the problem it talks about is one that is outside of the inexperienced developer’s bubble. Specifically, the pattern is concerned with hiring managers’ inherent level of risk when hiring somebody who may not be able to contribute to the workload of the team due to their lack of ability. Hoover and Oshineye make the point to distinguish between knowledge – the possession of information – and skill – the ability to acquire and implement one’s knowledge in a way that is useful.

The suggestion provided is to acquire a set of skills that are either universally useful, or indicate strongly one’s ability to obtain skill in an unfamiliar technology or environment. Moreover, the recommendation to new developers is to obtain the CVs of people whose skills they respect, and identifying five discrete skills listed on each. This way, one can determine the sorts of skills that are valuable across the industry, and effort can be focused directly into strengthening those skills.

I believe that these are worthwhile and sensible courses of actions. The Software Development is a wide blanket, with countless possibilities for beneficial skill sets across the countless media that demand developers. Personally, as someone who dreams of ending up in game development, I have a vested interest in attaining this kind of proficiency. I do not anticipate my beginnings in the workplace to be in game development, and therefore my focus must include skills that are applicable in as many forms as possible.

Of course, after reading through this pattern, I couldn’t help but read through my own résumé. In concordance, I have identified several skills which align with this pattern of thought, and several which did not. After making my edits to better reflect my universally transferable skills and experience, I feel much more confident reading my résumé. Going forward, I will seek out more ways in which I can obtain the technical, business and interpersonal skills that will make me not only more attractive to hiring managers, but more versatile as a software developer.

From the blog CS@Worcester – Studio H by Connor V. and used with permission of the author. All other rights reserved by the author.