Saturday, August 17, 2019

Git Branching Strategies That I've Used

I've used two different branching strategies for Git at previous jobs. Each had their own advantages and disadvantages.

Job #1 - Testable Master Branch, Single Development Branch, Tags for Releases


My memory is a little fuzzy on this workflow, but I think that a previous employer's workflow went something like this:

  1. Use a central development branch for all development
  2. Push ready-to-test increments to master
  3. Tag each release

At this job, I worked with the company's QA team and developers on my team to create a Git workflow that would work for everyone. We used an iterative development process where QA would typically test after the development increment. This required a workflow that did the following:

  • Have separate branches for in-development and ready-to-test changes
  • Allow QA to quickly access ready-to-test code
  • Have a history of releases
  • Allow access to code via automated tooling

I'm not sure how it happened, but we had some long meetings on it and decided to have developers work off of the development branch. It worked quite well. QA was able to easily identify, access, and test ready-to-test features, and developers could work from development and merge into master for increments and hot fixes

This Git workflow was used for development of a white-label application. I built a custom website that would, among many other things, commit new variants of the white-label app to source control. It helped to have master contain a potentially releasable code base. If there was a branch for each release, the website would need to be manually updated to use each release branch, and someone would have to merge variant additions back into master/development. Using tags for releases was a great decision because my site could pull from master and I didn't have to worry about what version was being built at any given time.

All users of the application used the latest in-production version of the application. Because of this, there wasn't much of a need to go back to old versions of the code base. I don't see the approach working very well for teams that support multiple versions of the same application, but the workflow was great for what we needed it for.

Job #2 - Development on Master Branch, Branch on Release


At a different job, my team was among the last in the company to use Git for source control. As a result, my project inherited a Git workflow that the rest of the company had already implemented, and this ended up being the mirror image of the previous workflow:

  1. Use master for development
  2. Branch for each release

This probably worked well for the other projects because they released infrequently. But my project could see multiple releases in a week, so this approach quickly lead to the server having many branches that you would not need to restore.

On the other hand, having branches for each release allowed me to quickly see the version of the code base in-use in release by a user. Not all users ran the same version, so being able to see/hotfix old versions was essential. If we had used tags for releases, it would have been far more difficult to switch between them and work on hotfix releases.

At this job, development and testing went on concurrently, so working off of master made sense there. It might not work well for places utilizing a development -> test cycle because the version that testers get could have bugs or workflow changes introduced by in-development features.

Sunday, September 23, 2018

My Thoughts About Angular

Angular (not to be confused with AngularJS) is a web development platforms that I've used professionally and on a few personal projects.

Here are my thoughts on Angular and how I think it is compared to its peers (such as Ember, Vue.js, and React).

TypeScript Support (/Requirement?)


I think that one of the biggest things that separates Angular from other web development libraries is its TypeScript support. I'm a fan of TypeScript; it's a programming language that introduces static type checking to JavaScript.

As far as I know, Ember.js doesn't officially support TypeScript. React and Vue support TypeScript, but their documentation for it is somewhat sparse.

But Angular went all-out on their TypeScript support. All examples throughout the official site use TypeScript, and its API documentation has plentiful information about typing. When coding Angular apps using TypeScript, I rarely struggle with finding the right types to use.

But Angular's depth of support for TypeScript has come at an apparent price - I cannot find much information on Angular's official site about how to actually use Angular with JavaScript. I think that there used to be a page on the Angular site for using Angular with JavaScript, but I can no longer find it.

In my opinion, learning Angular requires having to know or learn TypeScript. Otherwise, you're learning Angular by writing code that has little in common with code examples.

Learning Curve


When I started learning Angular, I struggled. I picked-up TypeScript at the same time as I did Angular, so I had to learn both technologies at the same time.

Once I got past the "hello world" phase, I found out that I had a third thing to learn RxJS. Some things in Angular, most notably its HTTP Client, are built using RxJS, so becoming well-versed in RxJS is essential for fluent Angular application development.

It took me a while to understand Angular, TypeScript, and RxJS. But once I did, the act of making Angular applications felt natural. Angular suggests using an application structure (app/component/view/CSS) that is pleasant to work with and excels at separating concerns into manageable pieces. Angular's boilerplate is terse but is easily understood and serves an obvious purpose. And I don't spend a lot of my time looking up what to do, which allows me to focus on actually building applications. I still struggle a bit with RxJS, but I find it pleasant to work with in the context of an Angular app.

Ember.js (pre-2.0) was similarly tough for me to learn, but I never reached the point where developing applications Ember.js was easy for me. Its more "magical" aspects made it rather difficult for me to fully comprehend what my code was actually doing.

Compared to Angular and Ember.js, I had a much easier time learning React. But React is "just" a view library. Angular has more built into it, including dependency injection, URL routing, the aforementioned HTTP client, and extensive tooling.

Tooling


The largest tool in Angular's toolbox is Angular CLI. It's the recommended and best way to develop Angular applications. It handles quite a bit: application scaffolding, dev server instantiation, unit testing, and production builds.

But on one of my applications, I ran into issues with Angular CLI. I'll admit - I ran into an uncommon problem. I was working on a white-label site that's designed to work from any subdirectory, and I couldn't get Angular CLI to build correctly for the site. As it turns out, you don't have to use Angular CLI for your Angular applications. The official site used to have extensive notes about using both webpack (used by Angular CLI) and Rollup. It's mostly gone now, but it was present while I was working on the application, and I successfully built the app using both Rollup and webpack (which I migrated to because of issues with Rollup).

Angular's support for alternative build systems is there, but it's hidden away a bit.

Conclusion


When I build applications for myself, I tend to favor using multiple, small libraries over one large library. I preferred Sinatra over Ruby on Rails, Flask over Django, MVVM Light (and my own KSMVVM.WPF) over larger MVVM libraries for WPF, and React over the original AngularJS.

But I also like modern Angular - it seems every bit as purpose-built as the smaller libraries that I tend to prefer. And even though the documentation is very spotty when it comes to going "off-road", I can appreciate how it does its best to guide developers into a specific way of implementing applications by making decisions for you. Using Angular to its fullest requires using a specific language (TypeScript), a specific way of structuring applications (app/component/view/css), and a specific build system (Angular CLI/webpack). By making these decisions for developers, I feel that Angular is a great fit for larger web-based applications.

Saturday, August 18, 2018

WPF: Ways to Set DataContext

Something that I've struggled when implementing Model-View-ViewModel design in WPF is how to specify DataContext so that I can bind control properties to view model properties. There are quite a few ways to do this, and each have trade-offs in terms of Blendability (design-time functionality in Blend or Visual Studio Designer) and maintainability.

Set in Code-Behind

When I first started doing MVVM in WPF, I used code behind to set the DataContext in all of my windows and pages:


public MyControl()
{
    InitializeComponent();
    DataContext = new MyViewModel();
}


Blendability with this approach is poor. The designer can't actually see that your DataContext is a MyViewModel instance. AFAIK, designers don't run that constructor at design time. (If they do, I'd really be surprised because I've never seen it happen.) So you don't get auto-completion, go-to-definition, or anything else in the designer.

But there is an advantage to the approach: you can design view models that take constructor parameters. This makes it easy to write view models that wrap around model objects as you can pass that model to the view model's constructor.

Set in XAML Using Locator Instance


After a few years, I started using MVVM Light instead of utilizing hand-rolled solutions for MVVM. Installing MVVM Light's full package (MvvmLight, not MvvmLightLibs) adds a few classes to your project. One of these is the ViewModelLocator class, which is responsible for instances of your view model classes. If you add an instance of this locator class to your application's resources in App.xaml, you can set your control's DataContext in XAML:


<UserControl
    x:Class="MyProject.MyControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    mc:Ignorable="d"
    DataContext="{Binding Source={StaticResource Locator}, Path=MyViewModel}">
</Code>


This approach offers far superior Blendability over the previous approach - you get auto-complete, extended error reporting, and design-time preview in Visual Studio Designer. This makes for a much faster feedback loop than running the program every time.

It's still possible to design your view models so that their constructors take parameters. However, this is effectively limited to dependency injection as the locator pattern makes it difficult to send a model object to the view model's constructor.

If you want, you can still load your view model with model-specific data. My typical methodology involves handling the control's Loaded event. The event handler can call a 'load' method on the view model, and you can get the view model instance either from the locator or by casting the value for the control's DataContext property to the correct type.

But if you use loading methods, expect to call them on a regular basis: the locator class can make the lifetime of your view models difficult to reason with. In other approaches, the life of the view model instance ends with the view that created it. But view models in the locator can live to the end of the application (if you keep a reference to each instance) or can change when you least expect it (if your locator's properties return a new instance every time).

You have to change the locator, the view XAML, and the view code-behind every time you want to use a different class for the view model. In my experience, it doesn't come up often, but it can still break unexpected parts of your application after making the change.

Set in XAML, Create New Instance in XAML


I recently learned about a third approach from a question on StackOverflow: Setting DataContext in XAML in WPF. The accepted answer from BradleyDotNET does something like this in the XAML:


<UserControl.DataContext>
    <vm:MyViewModel />
</UserControl.DataContext>


Like the previous method, you get auto-complete and errors during design time. And, if you assign a name to the view model instance, you can access it from code-behind without needing to cast anything. It just works, and it's an elegant solution as far as the code-behind goes.

There is a big downside: the view model class must have a default constructor. It's technically possible to get around it using a type converter, but you lose the ability to preview data, it leads to a lot of confusing code, and I wouldn't recommend it. Implementing a default constructor means having to inject dependencies through properties or put all of the DI code in the default constructor. This can lead to some messy code in your view model that can complicate your unit tests.

Set in XAML, Create New Instance in Code-Behind


While doing research for this article, I found that there's another way to assign a value to DataContext that involves writing some code-behind and XAML. But I don't recommend using it for reasons that will soon become apparent:

You can declare a property in the code-behind:


public MyViewModel ViewModel { get; } = new MyViewModel();


and use it in your XAML:


<Window x:Class="TestApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TestApp"
    mc:Ignorable="d"
    Title="MainWindow"
    x:Name="Self"
    DataContext="{Binding ElementName=Self, Path=ViewModel}">


It seems like you would get design-time support with this approach, but this works almost as poorly at design-time as the code-behind approach. You can hover over property names and see their type, but you can't jump to their definition or preview the bindings in the designer. I understand why preview wouldn't work - the designer is not using an instance of the view model. But it seems weird that type definitions only partially work.

Another big downside is that I've never heard anyone talk about setting DataContext this way. It's a non-standard approach, and would probably receive some funny looks during a code review.

For those two reasons, I can't recommend actually using this hybrid approach. But it's kinda fun to think about.

Conclusion


That leaves me with three usable approaches for setting the DataContext for your windows, pages, and controls:

  • Set in Code-Behind
  • Set in XAML Using Locator Instance (the MVVM Light method)
  • Set in XAML, Create New Instance in XAML

They all have their benefits and problems, but if I had to choose one to use for the rest of my life, it would be MVVM Light's approach. With it, Blendability is excellent, code follows a commonly-used pattern, and you can still do dependency injection through view model constructors.

Monday, July 10, 2017

Coping With Noise at Work

Updated on August 4, 2018 with some information about how I'm coping with noise at work now.
 
Do you work in a noisy office and find it difficult to concentrate on your work? Judging from the amount of blog posts I've read about noisy offices, it seems that you aren't alone! I've been there too, so I wrote this article about how I deal with noise at work.

Don't Give Up!

You may be tempted to quit your job over the level of noise. But I strongly recommend against leaving an otherwise good job over the level of noise. Your next job's environment may not be an improvement!

If you're on the verge of quitting your job, find someone at your company to talk to. Preferably, try to identify someone (like a manager or someone from HR) with the authority to improve the situation.

Don't Damage Your Hearing!

This should go without saying, but I'll say it: do not wear headphones and play music/noise at an uncomfortable volume. You can damage your hearing.

One Possible Solution: Music/Noise on Headphones

That being said, I've found that listening to music/noise on headphones at a comfortable volume is a good way to mask office sounds to an extent. It really depends on what sort of noise you are trying to manage.

I find that headphones are effective against these types of noise:
  • Infrequent, medium-volume noise (people eating crunchy foods, the clack of keyboards, that sort of thing)
  • Constant noise (air conditioner, computer fan noise, etc.)
  • Low-volume office conversations (co-workers using their "inside voices")
But I found that headphones don't help much against loud noises commonly experienced in open office spaces. Radios, people shouting (a common form of collaboration in open offices), and cell phones vibrating/ringing can all be louder than your headphones should be.

As far as I know, noise-cancelling headphones only mask constant noise. They're meant for use on trains and airplanes, not noisy offices, so I've never tried noise-cancelling headphones.

If you're looking for noise-isolating headphones to muffle sound, I wish you good luck! I've yet to find a pair that sounded great and isolated sound well enough for me to use on a daily basis.

Another Possibility: Earplugs/Earmuffs

Earplugs and earmuffs seem to do a better job than headphones of blocking sound. When properly used, they protect your ears from awful noises without a high risk of damaging your hearing. (I'm not a doctor, so I can't say that there's no risk involved, especially when you misuse earplugs.)

Be sure to do some research before buying earplugs or earmuffs. They're not built equally, and you can easily buy hearing protection that does not work.

There are a few downsides to wearing earplugs or earmuffs. I have yet to find a pair of earmuffs that were effective and comfortable to wear for more than an hour. Earplugs require constant replacement or cleaning. Both seem to make me feel disoriented after a while, but that could just be me.

Despite those downsides, good earplugs and earmuffs are quite effective of blocking most office noise. But even the best have their limits. One particularly noisy day, I put on some earmuffs (that were rated at 34 NRR) over some in-ear headphones, and I still heard people talking during quiet portions in the music. Both the noise level and my failed attempt to mask it were ridiculous.

My Solution: Give In (Seriously!)


After a while, it became obvious to me that blocking every annoying noise was impossible. Headphones didn't work, earplugs didn't work, and earmuffs were uncomfortable and didn't work in extreme cases.

So I did something that may sound crazy: I stopped trying to manage noise most of the time and let the distractions happen. And I became a happier person for it. Sure, I feel like I work slower than I used to when I wore headphones, but I am okay with trading a little bit of perceived productivity for my sanity.

If you're able to make the mental shift, I highly recommend just letting most of the noise go - I think you'll be happier (and possibly more productive) in the long run.

2018 Update - No, Wait, Headphones + Noise Is Best

As it turned out, the distractions of the office hurt my productivity and ability to concentrate on important tasks. I still keep a "don't try to eliminate distractions" mentality, but I put on headphones and listen to noise. This approach works for me, and it's the approach that I recommend to others.

Just make sure that you get comfortable headphones. For me, Beyerdynamic's DT-770 headphones are fantastic - they fit well and don't hurt my head after wearing them all day long.

Thursday, April 2, 2015

An Article With Browserify Impressions

This is an opinionated article that discusses Browserify and compares it to RequireJS and Bower.

What is Browserify?

Browserify brings Node.js's require() function to client-side JavaScript. You can call require(...) to import npm packages, so Browserify solves two problems:
  1. Client-side package management (by using npm)
  2. Loading modules

Benefits of Using Browserify

Browserify has some 'magic' built-in that allows you to easily re-use most server-side code in your client-side code.

Because npm handles package management for Browserify, you can specify (most) of your client-side dependencies in your package.json along with your server-side dependencies. In my experience, having one place for dependencies really simplifies the process of adding a new dependency. Otherwise, you have to choose which package manager you want to use for packages that are available through multiple managers.


Problems With Alternatives

Like everything in JavaScript development, there are alternatives to Browserify. RequireJS can be used to load modules. For client-side package management, there's Bower. Either solution has problems that would be reduced or eliminated by using Browserify instead.

RequireJS requires using RequireJS modules or shims. Jam provides packages for RequireJS, but I found extremely out-of-date packages for popular libraries like Moment.js and Modernizr. For the most part, using RequireJS with popular client-side libraries means using shims. RequireJS shims can lead to a few minor problems as you either have to copy & paste JS files into your project or split dependencies into multiple specification files. Browserify shares this problem with RequireJS, but it's a smaller problem for reasons described below.

Bower has some problems of its own. I'll explain, but I must warn you ahead of time: friends and family of Bower should skip to 'Problems with Browserify.'

Bower is an incomplete package management solution. Every Bower package that I have ever installed dumps the complete contents of a Git repository into a directory. And there does not seem to be a standard for Bower package structure or documentation or use in client-side applications.

Every time I use a Bower package, I'm left wondering how to actually use the package in my code. I feel that this is a massive issue that prevents Bower from being as useful as it could be. npm and Browserify typically do not suffer from this problem for a few reasons:
  • npm packages almost always tell you how to start using the package
  • You typically don't need to know the structure of npm packages due to how they're used.
  • If you need to look in the node_modules folder, packages typically use a standard structure.

Problems With Browserify

Browersify is a full solution, but it comes with problems of its own.

It's unclear what npm package should be used for some client-side libraries. Modernizr has a few npm packages: browsernizrmodernizr, and browsernizr2. The first package is outdated, and the second package installs a tool that generates modernizr.js. I only found out about the third package as I was doing research for this article, and I don't know anything about it except its existence.

If a library doesn't have an easy-to-use npm package, you have to shim it with browserify-shim. This complicates inclusion of client-side vendor scripts in your project, and Browserify shares this issue with with RequireJS. Unlike RequireJS, this problem should be uncommon due to the availability of npm modules for popular client-side libraries.

Addendum: Comparison of Browserify and RequireJS

Browserify and RequireJS solve most of the same problems, so I figured that now would be a good time to give a quick rundown of differences and similarities.

Differences

Browserify loads npm modules.
RequireJS loads RequireJS modules.

Browserify always loads synchronously at compile/bundle time.
RequireJS loads asynchronously in the browser (but can be bundled using an optimizer).

Browserify always bundles scripts.
Bundling RequireJS apps requires a special optimizer.

Browserify uses npm.
RequireJS can be used with Jam, but you may be better off with using shims for third-party code.

Browserify allows you to access many Node.js functions and modules from client-side code.

RequireJS allows you to load non-JavaScript files (such as text files and Ember.js templates).

Similarities

Both load modules for client-side JavaScript.
Both have Grunt and Gulp plugins.