Month: June 2015
What I want to talk about is all the things that go into an open-source project besides the idea and the code. Now of course, one should have a cool idea for an open-source project and someone is going to have to write the code. I absolutely care deeply about quality, clean code. Yet with an open-source project there is a lot of other stuff that goes into it. Often times, it is all that other stuff that makes an open-source project great and gets people to use it. Now I can’t promise you that if you do all these things people will use your project, but it will certainly help.
All Open-Source Projects
There were a couple things I saw that we all need to do better at, regardless of whether one manages a massive project with hundreds of contributors or just wrote some code in a hour and posted it on GitHub.
Clearly Indicate the Status of the Project
The most important thing you can do with any code you post online is clearly say at the top of the read me or other most visible place, the status of your project. This should answer questions about the current state of the code and about the likely future path of development. Here are some ideas for statuses one might use. Though a couple sentences of explanation in addition will always be helpful.
To describe the state of the code:
- Works for Me or No Warranty: Indicates this is some code you threw together, it solved your problem or met your goal, but there has been no effort spent making sure it is suitable for others to use.
- Sample, Example or Starting Point: The code demonstrates how to do something, but shouldn’t be taken as production code. It should probably be incorporated into other projects as their own code that they will own and further develop in the future.
- Pre-release or Beta: The project has gone through multiple rounds of active development with a goal of reaching a stable release version, but is not there yet.
- Stable/Release: The project has reached a stable point where there should be a minimum of bugs and the necessary features are present. Use this even if there is a previous stable release, but you are working on a new version that is in beta.
To describe the future path of development:
- Active (with Date): This indicates people are currently actively contributing and addressing issues and questions on a semi-regular basis. The current date should always be included with an active status and updated at least twice a year so that people know it is true and not just a statement that hasn’t been updated correctly.
- Inactive: The project is not currently being maintained, but there are still people who would notice if someone reported a horrible bug or submitted a pull request. No guarantee is made that they would be addressed though they would at least get a reply.
- Hiatus: The project is currently inactive, but there is an intention that it will return to an active status in the future. An idea of the time-frame is helpful here.
- Ignored: This code is not being maintained, issues, questions, bugs and pull requests will not be looked at.
- Legacy: The project was once active and may have had a reasonable community. There are is still some work to fix important bugs and answer some questions, but no major features will be added.
- Obsolete: The project uses technologies or versions of those technologies or approaches the owner and contributors think are obsolete and not worth further development. The code remains available for existing users or new users who are for some reason stuck on the old technologies. It may be helpful to combine this with a status like inactive, ignored or legacy to give a better indication of what users can expect.
You might imagine that large open-source projects with slick websites are exempt from needing to describe the project status because their website indicates the amount of effort being invested into the project. However, it is not uncommon to come across a beautiful open-source project website that was created four years ago and the site and project have been ignored ever since.
State a Clear Value Proposition
Explain in a short paragraph what your project is and does and why people would want to use it. Don’t assume other technologies you reference are known to the reader. They may have stumbled across your project even though they work in a totally different technology stack. When referencing other technologies, provide a link and a couple word description of what it is. Make sure it is clear what your project does. It is very easy for you, who knows the project inside and out, to not make this clear, because it is so obvious to you. Finally, include why someone would choose your project over other options. Try to avoid purely technical features like performance. Focus on features that are distinctive and not shared by most projects like yours. If you really want others to use your project, think of this as your sales pitch.
Committed Open-Source Projects
The above two things are what I think every bit of open-source code thrown up on the web needs to do. But what if you are actually wanting to start an open-source project that you hope people will use? Or what if you become a core contributor to a project you want to see succed? The follow is my advice on how to make that project a success.
Recognize the Commitment and Make it
Creating and maintaining a successful open-source project is a lot of work. It is often as big as any project you might tackle at your job. Furthermore, you will be called on to do tasks you probably aren’t responsible for at work, like documentation and website design. There will be important bugs that if not fixed in a timely manner risk alienating your user base. There will be lots of questions and requests for help, many of which will be pretty “stupid” questions. All that will be done in your free time when you could be doing something else (unless you are one of the lucky few who is responsible for an open-source project at work). While you are spending your free time, there will be long stretches with little to no positive feedback. All that will take a lot of commitment. The most important thing you can do before starting an open-source project or becoming an important contributor to one is to carefully consider all the work it will entail. Don’t shy away from it, you need to face it upfront so when difficult days come you will know you anticipated them. If after all that, you still want to do the project. Then make a firm commitment to do the project and stick with it. The most successful open-source projects generally have a core team of contributors who were very committed for a very long time.
Don’t try to be All Things to All People
Given that this is an open-source project and not a product one is profiting from, it is important to limit the scope and focus on the important things. In large part, that means you don’t need to cater to every option and work style your users might have. It is good for your project to be opinionated and focused. If users don’t like those aspects, there are lots of other projects for them to choose from. It is much more important for the project to be excellent for a small dedicated user base. Trying to include as many users as possible often leads to a system that is incomplete and buggy. For example, the Pretzel project is trying to create a .NET port of the popular Jekyll static site generator. However, at the same time they are throwing in support for the razor template engine. Now their effort and focus is divided and they have twice as many things to test and document. I think this is leading to reduced quality. For example, when I last downloaded the project, the sample razor template site didn’t even compile. Once a project has successfully completed its core and has a growing user base, then it can expand to other functionality if it makes sense.
Docs Are as Important as Features
I see this all the time, a project is described in glowing terms and lists really cool features, so I go to use it only to discover there is no documentation except for one or two blog posts that barely count as an introduction. What the majority of potential users do at that point is look for other options. That is why your documentation is just as important as your features. Commit yourself to writing the documentation for a feature as soon as it is in a state where it is ready to be used. Also, don’t forget to update them as features are changed. That way the docs will always be up to date. The documentation needs to be a website or wiki or read me available on the web. If users have to download something to read the docs, a certain percentage of them won’t bother. Also, a bunch of blog posts don’t count as documentation. Blog posts are great for introducing new projects and features and for promoting a project, but they aren’t documentation. They can’t be updated to match the current version. It is incredibly frustrating to be referred to a blog post as documentation only to find that the API and features have changed significantly since then. Often there is no post describing the changes. Even if there is, it now takes twice as much work to read both posts and synthesize an understanding of the project.
Learn the Lessons of Your Predecessors
Typically there have been projects like yours before in your technology stack or in others. They have tried what you are doing and discovered the pitfalls and best practices. Look carefully at other projects doing what your project does. Make sure you understand how they work and why they work that way. Read through the issues they had. You might discover your exact approach has been tried but found wanting. You will likely save yourself a lot of time in the less core areas of the project which you haven’t been carefully thinking about.
A Slick Website Looks Professional
As developers we don’t value beautiful marketing material as much as we should. Even though your project isn’t a product you are selling for money, you are basically selling the use of it to your users. Having a slick website to sell the project gives people a good feeling about your project and makes it look very professional. If you can invest the time for a great website, then you must have the time to invest in a great project. The site doesn’t have to be large. Even a couple pages of description, features and contact information with links to documentation, code and downloads will go a long way.
Make Sure the Project Runs out of the box
If you have a sample project or example of using your library, be absolutely certain that it works immediately out of the box after users download and install it. If a user’s first experience with your project is that you can’t get the sample to work, they will be left with a very bad taste in their mouth. With each new version, test the sample. If possible make unit tests to cover as much of it as possible. Another way to fail in this area is to have the download instructions or link not updated so that they point at an old or broken version.
Practising What I Preach
Looking at all these open-source projects and realizing the important things I listed above, I realized some of my projects are failing in one or more of these areas. My next step is to go through each of the projects I have posted online and address these.
In summary, here again is my advice. The first two are for all open-source code posted online. The rest are for serious open-source projects:
- Clearly Indicate the Status of the Project
- State a Clear Value Proposition
- Recognize the Commitment and Make it
- Don’t try to be All Things to All People
- Docs Are as Important as Features
- Learn the Lessons of Your Predecessors
- A Slick Website Looks Professional
- Make Sure the Project Runs out of the box
My starting point in this process was the “Gruntfile.js” created for me by the useful scaffolding tool Yeoman. Out of the box it came configured to use Sass with SCSS, while I prefer Less. So, I looked into what it would take to switch. The Grunt configuration, for what I considered a fairly typical build, was hefty, weighing in at 450+ lines. Digging in further, I discovered a number of things I didn’t like. That led me to evaluate other options. Moving on from Grunt, I looked at the next most popular option, Gulp. Then, I investigated the less common Broccoli.js and Brunch. I briefly considered the obscure Mimosa and Jake, but didn’t see anything compelling enough on their websites to make me think they needed to be considered over and above the others. This posts details my findings.
Being a professional web developer, I also expect that a web focused build tool will have lots of support for the complex asset pipelines of modern web apps. This is an area where Visual Studio definitely falls down. This is also an interesting and unique requirement for build tools. Traditional tools like “make” rarely had to deal with situations like this. Compiling a C++ app is mostly about finding all the source code, compiling and linking. There was rarely much more to it than that. For web applications, there are many different kinds of files that must each pass through their own long pipeline of transformations and combinations. Additionally, the result isn’t a single executable, but a large assemblage of files. That makes the need for good file clean-up much more important. Finally, developer expectations have risen since the original days of make tools. Then we were happy to get an executable when we ran the make command. Now, we expect file watching with incremental rebuilds and live browser reloads.
- Bundling/Concatenation: combining of scripts and styles into multiple files
- Minification: scripts, styles and html
- Source Maps: for both scripts and styles
- CSS Preprocessor: Less, Sass, Stylus etc.
- Style Transforms: Autoprefixer, PostCSS etc.
- Cache Busting: renaming files with a hash to prevent incorrect caching
- Image Optimization
- Compiling Templates: Mustache or HandlebarsJS, Underscore, EJS, Jade etc.
- Copying Assets: html, fav icon etc.
- Watching for Changes
- Incremental Rebuild
- Clean Build: deleting all files at start or preferably cleaning up files as needed
- Injecting References: generating script and style tags that reference the bundled files
- Build Configurations: separate Dev, Test and Prod configuration, for example to not minify html in dev build
- Serve: running a development web server
- Running Unit Tests
- Dependencies: handle dependencies on npm and Bower packages, Browserfy etc.
So what did I find? There were some common failings in all the build tools. One was the presumption that npm and Bower package restore were outside the scope of build. Unlike with an IDE such as Visual Studio that automatically runs Nuget package restore as needed, none of the JS build tools attempts to. This was often impossible to work around due to the fact that the build tool required it be one of the npm dependencies of your project and would not run until it was restored. Several of the tools did have plug-ins supporting Bower package restore. However, almost all examples I saw assumed one would first run
npm install then
bower install before building. They didn’t even setup
bower install as an action triggered by
Gulp is the hot new tool. It is rapidly gaining in popularity and there are some justifiable reasons for this. It recognizes and attempts to handle the primary unique requirement of web build tools, namely the long pipelines. In Gulp all plug-ins work on streams (well as of today there are still a number that don’t, which is very annoying). This streaming model allows Gulp tasks to be chained together in streams without worrying about or even producing intermediate temporary files. Gulp touts its high performance due to both streams and parallel task running. Yet, many users have complained that the parallel task execution is confusing and there are plans to extend the configuration to give more control over this. Personally, I found the parallel task execution very intuitive and feel the proposed cure is worse than the problem.
While streams are a compelling base for a build tool, I ultimately found Gulp lacking. Since the core configuration options are minimal, the attitude seems to be that little documentation is needed, but I found the documentation inadequate. Like Grunt, it was necessary to rely on the usually poor documentation of the plug-ins. This was somewhat mitigated by the greater consistency in plug-in usage versus Grunt. The Gulp authors believe in opinionated software and have some strong opinions when it comes to Gulp plug-ins. Normally, I appreciate opinionated software, but in this case I have to disagree with the authors’ opinions. They believe that a tool that already supports streaming should not be wrapped in a plug-in, but used directly. This runs counter to making builds as easy as possible to setup because it requires one to learn and adapt the tools’ unique APIs to the Gulp system. For a peek into the mess this causes, check out the GitHub issue over the blacklisting of the gulp-browserify plug-in. In it, dozens of users attempt to figure out the correct way of using Browserify. I don’t think any quite hit upon the difficult to find official recipe. But note, even that fails to support the important case of streaming files into Browserify. The whole issue is complicated enough that it takes an excellent but lengthy blog post to fully explain. Furthermore, the streaming model becomes confusing for things that don’t fit into it, such as cleaning. Source maps in particular are odd. I attempted to combine external source maps with cache busting with a manifest file and cleaning up old revisions and while the final config was quite short, it took me several hours and additional plug-ins to get working. Watching still requires manual configuration and incremental building is quite confusing to setup. Figuring out how to do anything is made worse by the plethora of plug-ins for doing the same task. Finally, while I don’t understand the issue myself, I found many discussions of needing to do extra configuration to get reasonable error messages out of Gulp.
Despite all these excellent attributes, Broccoli is still very immature and in beta. It is lacking in the area of documentation. The read me boldly states windows support is spotty. The fact that there is little to no source map support was a big issue for me. It seemed to me that Broccoli wasn’t quite ready for prime time, but I’d really like to see it mature and supplant Grunt and Gulp.
So which tool would I recommend? Personally, I am still working with Brunch to see if it will work for my project. It would be at the top of my list right now (if you like the convention over configuration approach of Brunch, you could also check out Mimosa). However, if you don’t mind the large awkward configurations then you might want to select Gulp or even Grunt just for the size of the community around them and the selection of plug-ins (though I haven’t had a problem finding the Brunch plug-ins I need). I’m really interested in watching the development of Broccoli and hope it becomes a viable option in the future. The ultimate answer is likely to be a tool that doesn’t even exist today. Once package dependencies are ironed out correctly, I think we are likely to find all the existing tools don’t quite make sense anymore. Of course, there is no telling how long it will take to get to such a state.