What Is A Complete Feature: A Developer's Perspective

16 July 2017

What is a complete feature, and how does that affect your team and product?

As a developer, what does a complete feature mean? This is a question that should be answered both as an individual and for the team or organization as whole. Part of being a cohesive team revolves around everyone being on the same page regarding what constitutes completeness. A higher level of completeness ensures that your customers, developers and managers will be happier since they’ll enable you to do things correctly the first time. Delivery of polished items is how key stakeholders are impressed and kept coming back for more or, in the case of budget makers, approving bigger and better things for your team.

The different levels

Read on for the different levels of completeness. Each level encompasses the previous levels and describes what’s needed to break through for increased operational efficiency and product reliability.

Level 1: Feature Functionality is 100%

This is the most basic level of completeness. The developer in question has built out the code neccessary to complete a feature; this typically involves manual testing in a development environment to ensure that it works as expected.

Level 2: Full Unit Test Coverage

Hopefully all the code in your codebase meets at least this level of completeness. Here, all committed code has 100% coverage via unit tests. This is the bare minimum needed to ensure that:

1) Each function does what’s expected 2) Should there be edge cases, they can be easily added to coverage so you can ensure they aren’t repeated

Level 3: Manual Feature Testing with Permutations

The next level involves a more formal QA process around the feature, with acceptance from someone who isn’t the developer. This ensures there are a second set of eyes on the functionality and also helps spot unintended side effects that the dev may not have noticed. It’s typical for a developer to do operations the same way every time, so if there’s another path to accomplish the same thing, a dev may not think about testing it as, in their minds, “Why would someone do it that way?”. I also include code reviews here. At this level it’s all about having extra sets of eyes and different approaches to the same feature that way you can be as sure as possible that all your bases are covered.

Level 4: Full Integration Coverage

Adding full integration coverage for a feature is the closest you can come to being sure that your feature behaves as expected end-to-end and that it stays that way. Doing full manual regressions across every feature in your application every deploy just isn’t feasible; that’s why you need integration tests. The QA team will focus their attention towards the most critical items in your application but will rarely hit every permutation of a feature. Each user is unique, and the users of your application will always find a way to do things which you didn’t anticipate. Should they be able to break something, it’s important that you’re able to replicate it. Most well run codebases fall within this tier of completeness.

Level 5: Feature Has Complete Documentation

Adding documentation to your code is an oft overlooked aspect of feature completeness. Maintaining good documentation is key for certain areas of your app which aren’t easily apparent to a new dev picking up the project. This is particulary true for the following:

  • Complicated user workflows
  • Specific restrictions or limitations and why they are in place (ie, do we limit users to X items in a SaaS app because of performance, business or paid tiering?)
  • API endpoints (speicifically Protocol, URL, Port, Payload and Return Values)
  • Programming patterns, why they developed that way and how they’re helpful
  • Custom code which replicates commonly used libraries (was there a reason you wrote your own Delayed::Job implementation and extensions rather than using Sidekiq?)
  • Internal processes
  • How to access/trigger key functionality within the codebase
  • Bootstrapping the app for a new dev
  • Deployment process

All points of code are fair game for documentation. The above however are what I currently consider the bare minimum for maintaing a good bus factor.

Level 6: Instrumentation Around Key Metrics Are Present

Finally is instrumentation. This refers to sending metrics about key parts of your app off to a service so that you can set up alerts, graphs and monitors around the counts, execution times and usage patterns of your application. A well put together dashboard and alert system will save you a bunch of trouble as it enables you to address many problem points before they negatively impact all your users. Being able to quickly respond to, mitigate and clean up hot spots is what seperates a good operation from an excellent, tightly run ship.

Level N + 1

This list is by no means meant to be the be all, end all of what completeness entails. Always be on the lookout for identfying new ways to increase your code quality.

The Takeaway

There are always ways to put out more complete features. Be aware of them and put out the best code possible for your business and timeline constraints. Keep them in mind when dedicating to feature development and how they’ll alter your development pace. Remember, more time spent upfront on these will reduce code churn in the future, make for less problems in production and enable you to more quickly address any issues which do arise.


How to Specify the Foreign Class for Rails Associations in a Different Namespace

15 June 2017

Referencing Classes From Another Namespace

Say you’ve got the following classes:

class Foo < ApplicationRecord

class Foos::FooBarBazs::Baz < ApplicationRecord
    belongs_to :foo

Normally for Rails, we can pass a simple has_many :baz, but for models in a different namespace, you have to specify the class name, so it would look like this:

class Foo < ApplicationRecord
    has_many :baz, class_name: "Foos::FooBarBazs::Baz"

The above works great, and is what’s recommended in the official docs. However, it presents a problem when code is refactored and you don’t have sufficient code coverage. To remedy that, do the following:

  • enable eager loading for your test environment
  • use a constant, not a string

Using a Constant

The following don’t work:

  • has_many :baz, class_name: Foos::FooBarBazs::Baz
  • has_many :baz, class: Foos::FooBarBazs::Baz

However, what DOES work is: has_many :baz, class_name: Foos::FooBarBazs::Baz.to_s

Now eager loading will catch any typos made here since that would introduce a NameError: uninitialized constant. Also, we’re working with classed and objects in ruby, not strings, so my opinion is that it looks and reads much nicer as well.


Customize Spree Views Without Deface

05 February 2017

Spree and Deface

Spree is a very powerful and highly configurable Rails based ecommerce solution. It’s loaded full of awesome features which will let you handle most any situation or special edge case you may have for your business needs. From a user’s perspective, it’s awesome. In the current version of the Spree guide for customizing view, the recommendation is to use deface for these customizations. Deface is very powerful and aims to make Spree upgrades seamless. Unfortunately, it adds extra complexity and will make your codebase diverge from the standard Rails conventions. These conventions are part of what make efficient development using Rails possible, so why would you get away from that? Looking for a customized ecommerce solution? Spree is fantastic, shoot me a message if you’d like to discuss your needs.

In this post I’ll run through a quick example of what using Deface looks like, and then propose we return to the built in Rails functionality of overriding views as a means to have a more useable and efficient codebase.


Simple Elasticsearch Aggregation vs Postgres Counts Benchmark

01 February 2017

Aggregations for Elastisearch: Quick Like F1

In my last post, I dove into sub aggregations. This time, we’ll look at aggregations, which are the elasticsearch equivalent of SQL’s count group. If you’ve seen ecommerce sites where they say how many products belong to each category or brand, this is most likely how they accomplish that quickly and at scale.


How To Use Sub Aggregations With Searchkick To Return Multiple Terms Per Document

29 January 2017

Aggregations for Elastisearch: Lightning Fast

Elasticsearch is a fantastic way to store denormalized data for searching or serving up as an API in order to reduce database load. Those cases are just the surface of what elasticsearch has to offer. The next step in is using aggregations (formerly known as filters). Though a simple terms count aggregation (very similar to count(*) distinct in sql) is a great place to start, I’m going to dive into something more complex and powerful: Sub Aggregations.


Page: 1 of 10 Next