Oasis Digital summer intern program starts with 3-4 weeks in which the interns primarily learn (at a firehose pace) as much as possible about the technologies we have selected – Angular, JavaScript, HTML, etc. The rest of the summer, the interns work on projects to create software.
In between, we hold an internal, one-day hackathon. The theme this year was “Minions”, and the goal to build a working game based on this theme. As you can see in the video below, the interns did a surprisingly good job, given just a few weeks of Angular knowledge and less than eight hours of work time.
In 2015 we completed our 5th year of a successful summer intern program. In this program high school students engage in an intensive 3 weeks of training followed by 7 weeks of working on a real software development project. You can learn more about the intern program at http://summer.oasisdigital.com. This year the team worked on a pro-bono exhibit project for the St. Louis Science Center.
The leader of the intern team for 2015, Maneesh Tewani, and I are both fans of OnePlus. OnePlus makes unconventional smartphones in that they are highly desired but can only be purchased if you are invited. A very idiosyncratic and unusual approach to marketing that is clearly working. OnePlus launched a new phone this summer, the OnePlus 2, and held a promotional contest to give out free phones and invitations for purchase. There were ten categories under which entries were accepted, one of them being a community service project.
We quickly pulled together the following video which garnered 3rd place in its class. We did receive an invite although we barely missed a free phone offered to the top two in each category. Enjoy the video.
Modl Buildr is a configurator that allows users to select and configure a product of choice. It was inspired by a desktop configurator application and the question, “How can this problem be solved better in the browser?.”
As with many of our projects, we used AngularJS. Built as a framework for enhancing and augmenting the HTML language, Angular provides developers with a toolset supporting web applications consisting of dynamic, data driven content. Angular’s primary components include services for the isolation of business logic, routing for application architecture, controllers for marshaling data and directives for concise templates and view. Modl Buildr is created on these four core concepts.
If you prefer a video exclamation to text, the video below explains how it works in considerable detail.
For text, read on.
Routing
Client side routing is needed in most non-trivial Angular applications. The router allows users to navigate between features of the application without the need for additional server round-trips. When establishing the routes of the application Modl Buildr takes advantage of the syntax and creates a declarative road map of the application’s “pages”. The state declarations that are added highlight what routes are available and their associated models, views and controllers. By utilizing the resolve mechanism it is immediately clear what pieces of data are needed in order for any given route to function properly. This also removes the need for the controller to communicate with an API service or contain promise handling boilerplate.
Controllers and Services
Connecting the models to the view are various combinations of controllers and services. The router takes advantage of custom services to allow the creation of clean, simple and maintainable controllers. Consider the following code used to connect the landing page’s view to its model.
Controller:
(function () {
'use strict';
angular.module('app.home', [])
.controller('HomeCtrl', function ($state, featuredProducts, popularProducts, productDataService) {
var hctrl = this;
hctrl.featured = featuredProducts;
hctrl.popular = popularProducts;
hctrl.selectProduct = selectProduct;
//Prefetch for next route in navigation
productDataService.getProductList();
function selectProduct(selectedProduct) {
$state.go('configure', {productId: selectedProduct.qsBaseID});
}
});
}());
The code responsible for obtaining and shaping the data is isolated nicely in a service, consumed by the router, and made available to the controller. Meanwhile, the controller simply passes the data to the view. This MVVM (MVC, MVW*) pattern is seen throughout the application.
Not all of the controllers and services are this simple. Some data bindings require constant updating in the form functions. For example, as a user configures a product there is a significant amount of calculation that occurs to determine if the product’s configuration is still valid. The result of this calculation is bound to the view for the user to see. Best practices encourage a clean separation of controllers and services while allowing the service to take responsibility for complex computation. The following code snippet demonstrates how Modl Buildr achieves this separation while maintaining two way data binding.
(function () {
'use strict';
angular.module('app.configure')
.controller('ConfigureCtrl', function ($scope, $stateParams, $state,
productDataService, productStateService,appStateService) {
var confCtrl = this;
//the result of execution valid changes with every user input
confCtrl.valid = valid;
confCtrl.reset = reset;
confCtrl.goToSummary = goToSummary;
confCtrl.optionDisplay = optionDisplay;
//Guard against extra API calls by only updating when the user’s selections have changed
$scope.$watchCollection(function () {
return confCtrl.selections;
}, function (n, o) {
if (n && n._seriesId) {
productDataService.getValidity(n).then(function () {
updateAll();
});
}
});
function goToSummary() {
var modelNumber = productStateService.productOptions.BaseLabel;
modelNumber += _.map(productStateService.levelsToBuildModelNumber(), function (level) {
return productStateService.selections[level.Tag];
}).join('');
$state.go("summary", {productId: productStateService.productOptions.qsBaseID, number: modelNumber});
}
//This is called after every change to the user options
function updateAll() {
confCtrl.levels = productStateService.levelsToConfigure();
confCtrl.modelDisplayOptions = productStateService.levelsToBuildModelNumber();
confCtrl.valid = productStateService.valid;
confCtrl.selections = productStateService.selections;
confCtrl.productInfo = productStateService.productOptions;
}
});
}());
In the example above productInfo (the model number) and selections (the user’s choice of options) are bound to the view. The data in productInfo is a result of a function whose input is the selections. This approach not only provides a simple set of bindings, but also matches the application’s primary use case perfectly. The primary use case of the application is to select from a set of options and generate the corresponding model number. The challenge with this solution is that the server acts as a block box while performing the calculation. Fortunately the binding function is designed in such a way that it doesn’t matter where the complex calculation takes place or what it does. As the selections are updated the controller makes a service call and updates the bindings based upon the updated data that’s returned. The services handle the question of what to do and isolates the controller from any complexities or potential changes to this process.
Directives
There are several elements that appear on multiple screens of the application. These include simple pieces of functionality such as a hover text explaining why a button is disabled to custom widgets such as the product tiles. While controllers and services are great for laying out the big picture. Directives shine when used to create reusable and named components.
Modl Buildr contains a custom product tile directive. A reusable tile with a card-like appearance is created by combining a bootstrap panel, an image and a styled definition list. This tile is used to present products to the user. By specifying a few custom properties the same tile directive can be used across multiple situations.
With this definition and an ng-repeat these tiles are easily stamped out in a grid formation. This directive is also used on subsequent screens to display the product being configured.
Another helpful directive is the model number directive. The model number at the top of the configure and summary screens is generated by the users actions. Rather than complicate the main page controllers with the logic for displaying this interactive control a directive was created to isolate this concern. Now a model number can be displayed anywhere in the application by adding the following line of HTML (Jade) in the desired location:
model-number(product-name='{{cfg.productInfo.BaseLabel}}',
current-selections='cfg.modelDisplayOptions',
scroll-target='scroll-container')
// (the above is Jade, http://jade-lang.com/
Conclusions
Angular turned out to be a good fit for this application, yielding a working solution with a modest amount of code. Moreover, the application works quite nicely in a browser, at least as nicely as the native desktop application we were inspired by. The browser environment in 2015 is completely suitable for complex rules-based configurators.
Modl Buildr is a demo application we created at Oasis Digital, a rules-based “configurator”. Its inspiration comes from older desktop application configurators. Modl Buildr can be used to generate model numbers for highly customizable products. A user can select a product, choose from a set of options for that product, review the final product and request a quote. This article explains the details of this process and highlights some key features.
For this demo application, we picked an example of a product with lots of options – hospital beds. All of the data used for this demo is openly available on the Internet; it is not from any customer project. (Our customers’ real information is all hidden behind firewalls and NDAs…)
Choosing a product
Users can select a product from a short list of common products, or by searching a catalog. The common products are shown first:
Should the user choose to browse the product catalog, they see each product presented as a “tile” containing an image of the product and any additional spec information.
Adjacent controls provide the ability to filter through the catalog. This is done by typing a product’s name or choosing one of several product categories. This was designed to resemble many other online marketplaces to create a familiar experiences for first time users.
As the user interacts with the filters the catalog responds immediately by adding or removing the products that fit the user’s criteria. The results respond to the user’s input without the need for the user to request an update. This type of workflow greatly speeds up the process of identifying the desired product and moves them forward in the process quickly.
For users desiring a more compact view of the data there is also a grid view that displays the product information in a dense format. The grid view behaves in the same way as the tile view when interacting with the filtering tool. Once a user clicks on a product they are taken to the configuration page to set the product feature options.
Configuration
The configuration page contains a display of the model number associated with the selected product. The display updates automatically to reflect the changes from interacting with the product options.
A user configures the model by scrolling through the products feature list and selecting various options. As options are selected additional features will be added and removed automatically. If a user’s selection becomes invalid at any point that option will appear in red with an icon indicating that a conflict has occurred. The corresponding component in the model number will also turn red. The user can click on this portion of the model number and the list of features will automatically scroll to the problematic feature allowing the user to update their selection. Once a valid model number is configured the user can click on the “next” button to navigate to the review screen before requesting a quote.
The rules that determine the validity of a product are not “hard-wired” into the application. Instead they are entered by the application administrator and executed on the fly. Examples include, “There are no options for TV controls unless the electric option has been selected” or “Choosing a manually positioned bed invalidates the electric footrest option.” These English phrases can be easily into rules and are associated with a product. These rules are then used by the configuration page to guide the user towards generating a product that meets their needs and the suppliers capabilities.
Having selected and configured the product the user arrives at the summary page. The details of the product and the user’s customizations are displayed and they are presented with a simple contact form from which they can request a quote.
Conclusion
Once the user submits a quote the application demo reaches its end. But the usage for this platform could be extended in a number of directions. Modl Buildr could be extended to include an additional step for browsing and manipulating the components that go into manufacturing the final products at another level of detail. The application could be expanded to include sales information and trends. Additional features common to other marketplace applications could be added such as shopping carts, order history, billing information, etc… On the administrative side of the software additional screens could be added for the management of products, orders and other common administrative tasks.
Modl Buildr is a small example of the kind of business-centric software that we create every day. If you are interested in how it works we would love to show you more.
At Oasis Digital we host a St. Louis Angular Lunch each month. Many months an outside speaker comes in (especially if anyone volunteers!), other months someone from Oasis Digital speaks. In July 2015 we did something a bit unusual, several of us sat around and just talked about our Angular 2.0 preparations for a while. Although quite informal, it was well received. See the video embedded here.
Preparation for Angular 2.0 can include a lot of things, here are a few of the most important which came up in the discussion:
Now is the time to learn/use TypeScript. (We have converted a large Angular project to TypeScript.)
Now is the time to learn/use ES6/2015. (We have converted a large set of Protractor tests to ES2015.)
Angular 2.0 uses native ES6/2015 modules – which already work today.
The new “component router” for Angular 2 is also intended to arrive as a backcourt in Angular 1.x; it is very different from both the old Angular router and the very popular angular-ui-router. Although much work remains to be done, it is possible to start learning it now.
One topic of lively discussion was guessing when Angular 2.0 might ship. No ship date has been released, but several of us in this discussion thought it could be problematic for the Angular community if another major US spring conference goes by without A2. Therefore one obvious guess: Angular 2.0 will ship, perhaps just as “beta”, approximately around the next spring Angular conference. No one present has any connection to the Angular team, so this is just an outside, educated guess.
Transcript
We have also transcribed the discussion to text, provided below. This is a rough, first-draft transcription, so any errors are probably from that process.
This month at the St. Louis Angular Lunch I spoke about Angular’s upcoming “component router”. Originally created for Angular 2 and to-be-back-ported to Angular 1.x, the component router serves as a replacement to the current routing options. While still too early to use in production it looks like a promising alternative. In this talk (video below) I outline where the component router stands and a brief example of how it can be used.
Transcript
Here is the talk, transcribed to text. This is a lightly edited, draft transcription, so any errors are probably from that process.
This month (May 2015) at the Angular Lunch we had a very special guest speaker. Matt Follett (currently working at Observable Networks) shared his extensive experience working with end-to-end testing of browser-based web applications, including Angular applications. Although Matt only briefly mentioned Protractor (the Angular specific wrapper around Selenium), nonetheless almost everything he said was highly relevant to protractor.
Matt did not pull any punches in describing the difficulties of this type of test, and his comments certainly match our experiences at Oasis Digital testing Angular applications using Protractor. Still, the payoff of this level of testing is so high that we find it generally worth the effort. Automated testing is a (the?) way to keep quality up and regressions away as an Angular application grows in complexity and size.
Perhaps the best part of Matt’s talk is toward the end, when he (gently) compares the various available hosted browser/selenium services.
Transcript
We have also transcribed the the talk to text, provided below. This is a rough, first-draft transcription, so any errors are probably in that process, rather than in Matt’s actual content!
System Administrators often find themselves caught trying to fulfill the promises and hype that come with a new system purchase. As ERP companies learned the hard way over the last twenty years, a system is only as good as its user adoption. Metrics cannot flow to management without individual users, on a consistent basis, doing their part. Those caught in this position are at the mercy of the original system designers. Fortunately there are some strategies that can help.
I would like to use JIRA, a project management platform from Atlassian, as an example. JIRA is one of a new generation of SaaS based, deeply configurable, business tools. I teach a class that empowers organizations to make this powerful tool their own. Reducing user friction is what I have found is the key to user adoption of a tool of this type.
Remove the clutter
An effectively designed product will present you with an incredible combination of configurable features. In the case of JIRA, you can have an almost unlimited number of:
Workflows
Fields
Issue Types
External Inputs
Outgoing Connections
When a company purchases a product with this many options, most new administrators open the floodgates to their users. Every field looks useful, and managers have a long list of things they want to track in their work. The result can be a menagerie of poorly named and organized fields that are tedious and overwhelming.
Fields are the single largest source of clutter in business apps so I will point my attack there. It is good to list out all the fields that you want. If a field is up for discussion, it must have value to some aspect of the business. There are three approaches that can be taken to reduce the number of fields presented to the user:
Present a field only at the time it will be used. If you present 50 fields at the beginning of a process, they won’t all be observed and used properly. If you present fields to users only at the moment those traits appear in the process, the screen never becomes intimidating and fields are not missed or ignored.
Prioritize. Work from the key business goals backwards to the user. When you work in this direction, it will expose obsolete and non-critical fields. These can then be eliminated or put on a secondary screen.
Combine related fields into combination elements. Often a flat set of fields can be placed into a hierarchy. A hierarchy is far more approachable to a user than a flat list. Related fields are attacked together instead of needing to be found.
Relate fields to particular issue types. Just as common as fields that have no relevance, are fields that have a default value for many issue types that rarely changes.
Similar ideas can be applied to other complex work processes common in business applications.
Push your user toward action
In every task within every job there is a context, and a certain set of information that is needed. System designers have learned to present the information the user needs at a particular point in the work process. There are many mechanisms in a JIRA workflow to assist with this. The most powerful is the idea of screens associated with transitions in a workflow.
In a JIRA workflow there are Statuses and Transitions, the primary building blocks of the workflow. I always describe Statuses as places of rest, with Transitions being the action of moving between those places of rest. When new administrators first build a workflow, they INEVITABLY focus on the statuses. After about the third try, they realize that transitions are where the action is, literally and figuratively.
Focusing on the transitions, or forward movement, means giving users the ability to speed up their work by making the important information available. A major caveat here: do not take away access to all the other fields and information. For example, it is common to “pop” a screen on a transition. If you do so, add a tab to the screen with quick access to all the fields and information. This will allow users to correct previous mistakes or misunderstandings without disrupting their workflow.
Business systems commonly are based around a workflow. Try to understand what moves your user forward in their daily efforts and push it forward in their view.
Focus, focus, focus
It is almost impossible to overstate the importance of this in any organization. We often preach focus in the business world but then we constantly break our workers’ focus throughout the day. I have written pretty extensively about workflow design and the need for focus. Here are a couple of points.
If you have task-driven work, then always present the user with task-oriented workflow transitions and statuses. It is common for a workflow to start out being about tasks and end up being focused on deadlines and time. This confuses users and causes them to have to think harder than they should to stay focused.
Maintaining user focus is an area where user personas are quite valuable to the person configuring a system. If the administrator has a good understanding of a particular job, and can visualize what that user is going through, they will build a better system.
Listen and empower
Pride of authorship can be devastating to a system. Every organization is different, and your users matter. Listen to them and iterate on your workflows. Provide a mechanism, often another JIRA project, where users can make suggestions. Ask your users to critique screens and provide feedback about ways to improve their productivity.
Erring on the side of empowerment early in a system implementation can be the difference in making or breaking system adoption. It is common to want to restrict access early on and only give access when needed. This is very frustrating to users and I have witnessed the abandonment of systems over this particular issue. Users need to get their jobs done, and they will resort to Excel to make it happen! Once they abandon using a system because of restricted access it is very difficult to turn things around.
Conclusions
The success of implementing JIRA, or other extensive business systems, is like any other endeavor. It goes better with a proactive plan that considers implications rather than reacts to them. A system is only as good as the data entered, and a user that is empowered by a system will enter far more accurate and complete information than a user that must simply comply. By using these strategies you can chart the path to system adoption rather than abandonment.
The old saying about the cobbler’s kids that have no shoes is as true in concept now as it was a millenia ago. At Oasis Digital, where we find great solutions to increase the success of our customers, we have been so focused on those projects that we find ourselves lacking our marketing shoes. Our marketing efforts have been tertiary at best.
A few years ago we realized the need to develop our brand, a few months ago we started moving forward, and a few weeks ago we sat down and started the process with our team. I asked them to articulate what we are really good at, what they were proud of. The list was broad, and spoke to their understanding of the value they bring to our clients. Here is the list:
We don’t just build what the customer describes, we address needs in a well-thought out manner. We creatively solve problems, not just execute.
What we build can last (longevity). and scale
Our teams communicate and collaborate
Challenges/problems are shared in the team
Our tech stack stays fresh
We teach about what we use
High quality, comprehensive design documents that hit the mark the first time.
We can bridge the gap between techies and lay people
Our team can communicate effectively
Always look to improve, solve the problem with less code
We push for regular delivery, to finish items, not have long-standing open work items
This is the first bit, what we do well. The further question is how do we do these things. Very often, how you do things communicates your value to your customers. For example, people find our training very valuable because it is intensely workshop based, and taught by an actual practitioner of the craft, not a professional teacher.
We build high quality software
We empower our customers to prosper
We leave customers and projects better than we found them
We are a values based organization, so the “what” and the “how” are not the full answer. When you answer the “why” you find the values that motivate your work. The answer I came to was two-fold:
We love to solve problems
We love to help people
The wording will change over time but our core motivator is solving hard problems that have value. We really enjoy that process. Adding value, helping people and businesses to be successful, those are solid values that we believe will resonate with the right kinds of customers.
I love the powerful words pushed forward by the team. They are full of meaning and demonstrate the consistency through the team of our values.
I cannot wait to have these ideas permeate our web presence and our marketing communications. If we can push this to conclusion I believe we will finally have a nice pair of shoes!
Several members of the Oasis Digital team attended ng-conf in Salt Lake City recently. This month for the St. Louis Angular Lunch (April), we had a roundtable discussion of the conference and what we all learned at it. Here’s a video of the discussion:
Transcript
Here is the discussion, transcribed to text. This is a lightly edited, draft transcription, so any errors are probably from that process.
A student in a recent JIRA Boot Camp commented on how I described agile processes differently than a consultant her company had brought in. She noted that what I described seemed to make more sense. This got me thinking about those differences, why our approaches were different, and why it should matter.
I read a lot and I see lots of commentary on agile software development. In many of the discussions the dialog is often very detailed, laced with procedure and process. This style of explanation leads to reactionary implementations that may not be well thought through. These implementations are like a thin coat of paint on a hard surface. It looks pretty but it does not go very deep. Companies that go down this path usually have a history of other such implementations of new ideas. Employees are used to it and respond with a surface change that only lasts until the next idea comes along or until nobody is looking.
When I think about agile, continuous improvement, iterative project management, etc., I view these as tools to accomplish my goals. They are not the end all solution but a screwdriver to improve the productivity of my team. I do not blindly follow a methodology, I strategically apply these tools to accomplish my goals.
I decided when I was very young, watching various members of my grandparents generation, that I wanted to be a lifelong learner. I did not know what that meant at the time, but I knew I wanted to be like the intellectually engaged, vibrant seniors that I knew. I did not want to be stuck in a small personal world inhabited by a few people and the television set.
As a young engineer, many of the lean, downsizing focused approaches to business did not seem healthy to me. These were epitomized in the story of “Chainsaw” Al Dunlap and his approach to turning around companies. I was far more interested in what companies like Toyota and other leaders in “Lean Manufacturing” were learning. They seemed to be pushing for elimination of waste and just in time approaches that did not squeeze more production out of less but optimized the production of the staff you have. That was a mouthful so let me explain.
The Chainsaw approach cuts as much as possible, “cut to the bone” is the mantra. Toyota on the other hand pushed to improve their staff, processes, quality and production through a cycle of implementation, feedback, and adjustment. This was my first attraction to iterative change and I have adopted it as a way of life. I approach my business, my behavior, my hobbies, and my relationships with an idea that I can improve and get better.
Back to my student and her question. The reason I sound different is that an iterative approach is my way of life, not a process I promote. Agile is a process that has elements that really do improve the performance of teams. But like any tool it is not one size fits all. There are a number of agile principles we do not follow in my company, because they do not apply to our business. There are many that we do follow. We pick and choose when and how we use agile principles because we see it as a tool, not a religion, or something to sell.
Many consultants make a living selling agile processes. Most of them are quite good but a few will try to force ideas that do not make sense on an organization. These few are very much like some of our political leaders today. They want you to follow without understanding based on a promised result. This is not a way to run a business!
As much as I like the agile way, I love the Baldrige Continuous Improvement Model(CIP). I believe it is the missing tool that helps the agile processes sink into the organization. Much more like paint permeating a porous surface. Paint on such a surface is very difficult to remove, this is the way you want good processes to be absorbed by your organization. Following the CIP model helps you focus on building up your staff, helping them grow and become lifelong learners. Help them achieve a new level of professionalism and/or productivity. By doing this the organization improves.
If you have been implementing agile or other ideas because it is currently the “hot” thing and promises incredible results, then I encourage you to step back and evaluate. Look at the principles, look at the processes, consider which ones will improve your organization the most, and implement them. These are tools, not black and white affairs. They are a tool to be used to achieve the goals you have for your business and if used properly they can help your employees grow. Then everyone wins.
A few years ago we needed to migrate a large project issue tracker from Mantis to JIRA. At time, JIRA’s Mantis import feature was very limited; looking at it now in 2015, it appears to be more mature.
We needed specific features for the Mantis to JIRA conversion:
Include comments
Include attachments
Include inter-issue links
To achieve this, we implemented our own Mantis to JIRA import. It takes the form of a Java program, which interacts with Mantis and JIRA as follows:
Uses the Mantis SOAP API to retrieve issues data, comments, links, and attachment metadata.
Uses the JIRA CSV import for the above.
Enables JIRA to retrieve attachments from Mantis over HTTP during CSV import.
Uses the JIRA REST API to put in issue links – they are (were?) not supported via the JIRA CSV import.
Translate usernames via a lookup file, as JIRA usernames may not match Mantis username.
The resulting software was tuned for our specific needs, but it also reasonably generic: none of the URLs, names, or authentication settings are baked in, they are all set via configuration. Therefore, we are happy to release the software here, in case anyone finds it useful. All necessary files (aside from Mantis, JIRA, and a JVM) are included in the ZIP file, including rough documentation.
This is a binary-only release; we haven’t cleaned up the source code for release, or decided whether to do so. This software at no cost but with no promise of support; but feel free to contact us with questions, or to engage us in consulting work using this tool.