Tuesday, September 3, 2013
Presenting at SDC on Empowering a Team as an Individual Contributor
http://www.meetup.com/SoftDev/events/134325872/
Most developers are individual contributors (IC) – in other words they do not have direct reports. But even as a non-manager, you can empower an entire team. This is due to the nature of software engineering, where developers create their own tools, a star developer can be 10x as productive as an average developer, and a single developer can use technology for team-wide impact. With the right mindset ("add business value"), and using a combination of hard skills (automation, tooling, code generation, open source, code reuse, etc…) and soft skills (interviewing, mentoring, communication and knowledge sharing, etc…), you can be that IC developer who helps lift your entire team, and have fun along the way.
Monday, August 20, 2012
Digging with spoons – the case against progress
Friday, December 30, 2011
The benefits to “check in early and often”
- Cheaper integration. Someone once said “Integration is pay me now or pay me later”, and I find it much easier to pay now. Especially with automated builds and continuous integration, it’s much easier to check in 10 little changes than 1 big change (Sometimes I think of it like being easier to hold my breath for 30 seconds, ten times, as opposed to holding it for 5 minutes straight). Why? Because with bigger changes, you inevitably get farther out of sync – especially on critical shared files – and there’s more to forget.
- More objective measure of what you really have: Code that isn’t checked in, that just works on a developer’s machine, doesn’t really exist. They might as well say “it works in my head”. Once you actually get the code past a build server’s policy, then we can see what’s really there.
- Earlier Detection: We all know it’s cheaper to fix a bug or redesign the sooner you catch it. I’d rather developers check in code early so we can quick detect things (“why is there 5000 lines but no tests?”)
- More Modular: Checking in 10 chunks of code, where each one works, implies more granular and modular code. I.e. code that can at least be split into multiple check-ins is more modular than code that can’t be split at all.
Friday, December 2, 2011
10 Reasons why the build works locally but fails on the build server
Wednesday, August 3, 2011
Whatever requirements we're given tomorrow, we got to get that done
Wednesday, July 27, 2011
Why you’re in trouble if you rely on 30-page SOPs
- The doc itself will be wrong (or outdated), such as skipping steps or assuming institutional knowledge. This is especially common if you hire outside consultants (with no institutional knowledge of your systems) to document your process.
- It’s easier to bluff a doc – a busy tech writer will hurry the doc, thinking it looks done ("I’ve written 50 pages!"), but the content won’t be correct or specific enough.
- Screens will vary (example: the software is upgraded or the OS doesn’t match).
- People simply won’t read the docs, they’re skim and miss details.
- Favor automation over documentation where possible. The best document is an automated script. A script is usually kept up to date (compared to a doc) because developers need the script to work. It’s also much faster (and less error-prone) for a new guy to kick off the script than to tediously step through 20 pages of instructions.
- Lower the cost of documenting by leveraging a wiki. Developers are far more likely to update or correct a wiki then a big MSWord doc on SharePoint.
- Favor simplifying the process so the doc itself is simpler.
Monday, May 24, 2010
Developer balance of power
You need people to get the project done, but people are eventually error prone. Just like in government there are "separation of powers", software projects can also benefit from such separation. As a general rule, for production code, the same person should not both:
- Code and Review - The reviewer checks the code quality (It's too easy to give a free pass, or have bias, to your own code)
- Develop and Test - The tester checks the developer. (The dev already thinks their code works fine)
- Build and Deploy - Having someone else deploy what the developer built encourages easier and objective deployment, and helps invalidate the it works on my machine.
Wednesday, May 19, 2010
Using SMO to automate SQL tasks
I used to use shelling out to the console with osql, or splitting out all the "GO" keywords and using ADO.Net to execute non-queries.
And years ago, I guess that was fine.
But Server Management Objects (SMO) are phenomenal. They just work. With a few lines in C#, you can create or kill a database, install schema scripts, enumerate the database, and much more. You also get exceptions thrown if there is an error (much easier than parsing the osql output from the command line).
Good stuff.
Sunday, March 7, 2010
Process as Infrastructure Enhancements
Most devs I meet hate process, almost like it's a stupidity-tax from some ivory-tower folk (who themselves don't actually need to use the process that they're imposing on others). These devs just want to get the app done, and they think that the process gets in their way with tedious constraints that add no value. I recall projects with "process" like forcing devs to go and update all the internal variable names to be compliant with some new coding standard, or not allowing devs to have admin rights to their own machines until three levels of paperwork is approved (good luck being a dev using a Windows OS if you're not an admin), or requiring that developers test the app by taking success screen shots of every single step - and then printing out that 600 page doc and getting it signed by QA.
That sort of stuff bothers me too, but I'm still a big fan of good process. What I realize is that I essentially view "process" as "developer infrastructure enhancements". I think of process as helpful things like automation, unit tests, code generation, proper tools, CI builds, checkout and install scripts, etc... Devs just want to get the job done, and good process assists them in doing that, it doesn't burden them with ivory-tower taxes. If your process code-generates the data access layer, then the dev need not do all that manual ADO.Net plumbing code, and hence the dev gets the job done faster.
Sure, it's semantics - "process" vs. "infrastructure enhancements", but semantics are important because it affects how a thought is communicated to other people, and people are important.
Wednesday, May 13, 2009
Troubleshooting Visual Studio Profiler with ASP.Net
Visual Studio 2008 (and I think 2005) come with a built-in .Net profiler. Profilers are especially useful for troubleshooting performance bottlenecks (Related: CLR Profiler for old versions of Visual Studio; SQL Profiler). There are already good tutorials on it, so here I'm just offering misc tips and troubleshooting. Basically, you can go to Analyze > "Launch Performance Wizard", and just select all the defaults. You can use this with ASP.Net web projects too.
Error: When trying to start, I got "Value does not fall within the expected range".
Solution: You can set the config of a website to "Any CPU".
Error: VSP1351 : The monitor was unable to create one of its global objects
Other times I got this error:
Error VSP1351 : The monitor was unable to create one of its global objects (Local.vsperf.Admin). Verify that another monitor is not running, or that another application hasn't created an object of the same name.
Profiler exited
PRF0010: Launch Aborted - Unable to start vsperfmon.exe
Solution: You can use Process Explorer to see what is locking "vsperf.Admin", and then kill that process tree. For me, it was the aspnet_wp.exe process.
Error: PRF0010: Launch Aborted - Unable to start vsperfmon.exe
Sometimes I got this error:
PRF0010: Launch Aborted - Unable to start vsperfmon.exe
Error VSP1342 : Another instance of the Logger Engine is currently running.
Profiler exited
Solution: I restarted Visual Studio (yes, it's lame, but it appeared to work). I also ensured that all other instances of VS were closed.
Error: Sometimes clicking the stop button caused IE and VS to crash, without even collecting data
Solution: By just closing the IE browser directly, it worked.
Thursday, May 7, 2009
Technical Debt is like a steep hill, not a brick wall
Overtime, bad software decisions (design, coding, process) get compounded, like interest on a loan, and effectively presents the team with a "technical debt" that yearns to be repaid. This debt weighs down the system, making it harder and harder to make changes or add new features. One way to measure technical debt is by lines of code that require maintenance. Therefore you can reduce debt by reducing lines of code (codeGen, refactor, automate, buy instead of build, etc...).
For example, a developer may copy and paste duplicate code a hundred times (like in HTML or SQL), or create thousands of lines of tedious plumbing code, or create an army of brittle JavaScript files, or write an entire app with no code coverage. Many of the best practices out there are designed to explicitly reduce technical debt.
One thing to note is that technical debt is like a steep hill that can go infinitely high. You can go fast bicycling on a flat road, but as that road turns into a steep hill that gets gradually steeper, you slow down. In software terms, because code may have been copied to 10 different places, making a single change requires 10 separate updates - so it takes longer.
I don't think technical debt is like a brick wall - where suddenly at a specific point you're blocked and you simply cannot go further. And that's part of the problem. As long as you're moving, albeit slower and slower, it's seductive to think that you can still keep making "enough" progress so you don't need to change yet. The stubborn leader can just keep pushing on: "longer hours, more developers..." There are two choices to make: keep going forward, or turn around. However, if you were to hit that brick wall, then it forces you to stop and reevaluate. It's easier in the sense that you now only have one choice - you must "turn around".
Tuesday, April 14, 2009
Tips to incrementally check in code without breaking the build
No one wants to break the build. However, every time you check in code, you risk breaking the build. This leads some developers to avoid checking in for days (or weeks!) until they have a dangerously-big component. That has its own problems. Integration is pay-me-now-or-pay-me-later. I'm a big fan of paying upfront with small, continuous check-ins. Here are some tips to do check-ins without breaking the build:
- Try to do multiple smaller commits as opposed to one giant commit.
- Where reasonable, try to keep a component split into multiple smaller files instead of one giant file, especially if these files are updated by many developers. This reduces contention, and hence likeliness of breaking the build.
- Check in a file that won't hurt anything, like a class file that's not added to the project yet.
- Make sure you understand how code-generation integrates into your build. It's easy to have the code "work on your machine", only to have a code-generated script on the build server overwrite your changes and break the build. Make sure all your local code is in sync with what will be actively code-generated.
- Make sure you always check in all the needed files, especially files that get "registered" with a master file list. For example, C# files get registered with a csproj project file.
- Use a source control that allows merging (SVN, not VSS)
- Split your code into isolated components - i.e. reduce dependencies in your code.
- If you're working on a unit test, and you "need" (?!) to check in a partially-completed test that currently breaks, then consider applying the "Ignore" attribute so the test doesn't run yet.
- If you really need to check it in, perhaps comment out the breaking section.
- If you're checking in to send code to another dev, consider not checking in, and sending them a patch instead
- If you're checking in to the global trunk just to "back up" your work, consider checking into your own private branch.
Sunday, March 29, 2009
Tips to be a good code-reviewer
Code reviews are essential to high-quality code. Imagine back in high school when you're taking a difficult math test, and then in the last few minutes, the teacher lets you pair up with another student to compare your answers. You almost always will catch extra errors that way, and it's the exact same result with a code review. So, given that we all know that we should do some sort of code review, here are ideas on how to be a good code reviewer:
- Always keep in mind that the other person worked hard on it, and they probably have an emotional attachment. Someone once said something like "Their code is like their baby - don't say 'he looks so ugly', rather make a nice comment like 'Oh, he looks just like his father.' "
- Start with major things first. Don't start nit-picking ("your naming convention isn't good"), if they have major other issues. Focus on their biggest need. If they want your opinion on the data access strategy, that's what they'll be most receptive too.
- Don't just be a rubber stamp - it wastes their time by giving them a false sense of security and tells them nothing new.
- Look to affirm good ideas as well as discourage bad ones.
- Unless they are really missing the basic concepts, don't just tell them to go read some 500 page book - they'll see it as you dismissing them. Give them a tangible example and perhaps provide a web link to a short article or reference guide. If they read that (or they ask for more material), then suggest the books.
- Keep the session relatively short, short enough to fit within their attention span.
- Keep in mind the goal is to make better code for the good of the team, not show off how smart you are.
Thursday, March 5, 2009
How to integrate Generated code into your application
Code generation is great, but sometimes it can be confusing how to integrate that generated code into your custom application. Keep in mind that an application isn't solely SQL or C#. It could include Html, ASP.Net, Xml, JavaScript, project files, and much more.
- New file: Generate its own, new, separate file. This is the most basic way. You could then integrate it into your other files:
- (C#) Base Class - For an OOP language like C#, you could code-generate the base class, and then have your derived classes inherit it.
- (C#) Partial classes - Starting with .Net 2.0, C# offered partial classes which let you split the class definition across multiple physical files.
- All: Include statements - Many languages offer a way to include one file within another. For example, ASP.Net offers server side includes, MSBuild offers the import command, HTML allows you to reference an external JavaScript, etc... (Yes, you could to this with SQL to using SqlCmds)
- Existing file: Merge into existing file with custom regions. For example, CodeSmith offers two kinds of custom regions:
- InsertRegion - Insert your generated code into a marked region of a custom file
- PreserveRegion - Insert your custom code into a code-generated file.
You could also integrate CodeSmith into your builds and processes by calling the CodeSmith console app.
Tuesday, March 3, 2009
Getting source code from places other than source control
Of course all official code should ultimately be stored in source control (real source control, not VSS). However, when creating an automated build on a build server, getting the source code may not be as easy as just doing a single SVN checkout. There may be other steps to effectively get the latest source code:
- Copy in other reusable blocks - Where feasible, you want avoid checking in binaries into source control when those binaries will be constantly updated. Unlike plain-text files, you can't do an effective diff on binaries - it will just look like a mess. So instead of storing just the change set, it will probably need to store the entire physical assembly - which will bloat your source control. So, say you've got a team that is actively working on a set of reusable class libraries, to be shared across multiple departments and product groups. It may make sense to have your product's build copy in those latest reusable blocks (from their build's published output) to some external folder where you store your third-party assemblies, as opposed to constantly storing the latest version in source control. (So, ultimately the reusable blocks are still stored in source control, it's just a different repository).
- Code Generate from input files - You can use code-generation for lots of things, such as SQL base data or your data-access layer. If these files are completely code-generated (i.e. no merge regions), then you may not want to check them into source control, as you'll just face synchronization errors. For example, if you generate your data-access layer, and it's 100% determined from some set of xml files and database schema, then your build server could simply re-generate that code. If you check it into source control, then that version may be out-of-sync with what gets regenerated, and your build fails. In other words, as long as the server can already obtain the code by regenerating it, there's no reason to check it in - and risk checking in something that doesn't match what will be re-generated. (So, the generated files are effectively stored in source control via the inputs necessary to recreate them are being stored in source control).
Sunday, March 1, 2009
Things to CodeGenerate besides the Data Access Layer
CodeSmith is a powerful code generator (worth its weight in gold). And while one of the most popular things to automatically generate is the data access layer, there's a lot more to CodeSmith than just wrapping databases:
- System data - Given an xml file, you can generate all your interrelated system data. For example, say your application has a data-driven relationship of groups, roles, menu items, tabs, and such (i.e. security and navigation) - you could write tons of tedious and brittle SQL scripts, or you could abstract it to an xml file and generate the SQL scripts from that.
- Data Structures - Especially before Generics in .Net 2.0, CodeSmith was popular for its strongly-typed collections (much faster performance than boxing and unboxing an ArrayList). You could make other data structures as well, depending on your application's need.
- Documentation - While CodeSmith's default DataDictionary template is popular for documenting your database schema, you could use CodeSmith as a Super-XSLT to transform any arbitrary xml list (like a file containing business rules, config, or test cases), into human-friendly HTML reports.
- Domain-Specific-Language - It's often more efficient to work at a higher level of abstraction. So, you could write an xml script, and use CodeSmith to translate that ("compile?") into useful actions.
- Say you were trying to write automated UI tests, but the UI technologies keep changing, so you write a simple abstract xml script for the basic actions you care about (Load page, click button, etc...), and CodeSmith transforms that into the UI testing code for the relevant testing framework.
- You could write abstract tests in xml (i.e. the data for pairs of input and output), and then use CodeSmith to dynamically generate all the unit tests from that.
- You could read your file system to create an MSI installer using something like Wix.
- Starting Templates - I favor active re-generation when possible, and there's a balance between what to code-generate vs. what to refactor, however, sometimes it's useful to passively generate a starting template - just to give you a head start. For example, say your UI is too complicated to actively re-generate, but you could take an xml file of input and generate a stating template, from which you could then modify.
Basically, CodeSmith lets you take any input (a database, xml file, your file system, etc...) and generate any text output (sql, xml files, C#, aspx, html, js, etc...), and then also call C# to do anything on those files (install them in the database, commit it to source control, execute the resulting C#, etc...). It's a beautiful thing.
Sunday, February 22, 2009
Killing the file handles, but not the process (from the command line)
Most developers have come across that annoying error where you try to delete or rename an innocent file, only to be rebuffed with "Access denied, another process is accessing this file." For example, you'll get this type of error if you create a text file, open it in Microsoft Word, and then try to delete the file. This happens for all sorts of things - whether it's a process that didn't clean up after itself (perhaps from an unexpected crash), or something like IIS that locks certain website directories. While PSTool's ProcessExplorer GUI is great for finding what process is locking the file, what if you just want to find the handle, and kill it - from the command line?
Note that there's s a difference between the process, and the handle that that process has on the file. For example, if you want to delete a website that IIS is locking, you could shutdown or kill IIS (i.e. the process itself), but say you want to leave IIS running? Killing just the handle would leave the process intact, while allowing you control of the file again.
A useful tool for this is the (free) PsTools Handle.exe. From the command line, you can query all handles to a file, and then you can delete those handles. For example, this will find all handles on the given directory:
handle.exe C:\MyFolder
And returns something like so:
inetinfo.exe pid: 1696 3DC: C:\MyFolder\MySubfolder
inetinfo.exe pid: 1696 3E0: C:\MyFolder
You can then use this info to close the handles (one-by-one), without killing the process by passing in the "-c" switch, along with the handle id (in hex), and the process id, and the "-y" switch to confirm the delete.
handle.exe -c 3DC -p 1696 -y
handle.exe -c 3E0 -p 1696 -y
You could glue these two steps together into one by calling System.Diagnostics.Process to run the first command, parse its output, and then use that to create the parameters for the second command.
I'm sure there are more elegant ways (perhaps direct C++ calls, or even some special method in the .Net Framework), and I'm all ears to any, but this approach will get the job done.
Sunday, February 15, 2009
Part of the problem testing UI technologies is that they change so frequently
Anyone who has actually tried to write automated tests knows that testing the UI is much harder than testing a backend class library. Besides having an obscure interface to the test (like parsing an HttpResponse), and juggling far more dependencies (like needing a live application, complete with database and HttpContext), another problem is that UI technologies change much more frequently than backend ones. For example, you could still call a C# .Net 1.0 library from 8 years ago. However, during that time, the web UI has gone from Html (request/response) to JS-enabled, to advanced JS with Ajax/JSON/JQuery (by now your test harness needs its own JS engine), to Silverlight (where the request/response model no longer even applies). By the time you've built a robust UI test framework, your UI could be using a different technology that your framework cannot handle.
This makes it much harder to write automated tests for the GUI - i.e. not the sort of thing you just add in hindsight. There seems to be a lot of projects out there that have designed themselves into a corner. A manager rushes the project to market with an un-testable design because they think they'll just whip up UI testing later, but then they find they've accrued an insurmountable technical debt, and they just can have it. It's like they spent years constructing the pyramid on the east side of the river, but oops - now they realize they wanted it on the left side instead.
I think this is one of the reasons why good unit testing (and MVC) is becoming so popular in many circles.
Tuesday, February 10, 2009
How slow build time hurts code quality
Every developer on a large-scale project has probably had to deal with slow compile times. For example, you change one line in a backend assembly, and you wait three whole minutes for the assembly to recompile. While I understand that there are some cases out there where this is just life (I've had smart people on enormous projects drool over the thought of "just" three minutes to compile), in general, this is very bad for application developers.
It's not just the three minutes lost waiting for the compiler. There are at least a few other big problems:
- It constantly ruins your train of thought. Imagine a train that needs to stop at every station - it's not just the time stopped (i.e. compiling), it's also the time accelerating and decelerating (i.e. getting back in the groove). If Visual Studio is effectively frozen for over a minute because it's compiling, most devs will distract themselves with something else - and remain distracted even once Visual Studio finishes.
- It discourages developers from writing unit tests. For example, in an ASP web project, you can compile just the single page you're one. So, rather than a developer putting code in a backend assembly (where you can test it), they'll put it in the codebehind (where you cannot test it) so that it compiles fast enough and they can move to the next thing (this example assumes no MVC).
- It discourages developers from re-factoring. If even removing a dead comment will cost you several minutes, developers simply won't clean up "working" code.
In other words, given human nature - slow compile times don't just slow you down, they degrade your code quality.
While sometimes the machine is just slow, there are a lot of tips and pointers out there to tweak Visual Studio to run faster:
- http://weblogs.asp.net/scottgu/archive/2006/09/22/Tip_2F00_Trick_3A00_-Optimizing-ASP.NET-2.0-Web-Project-Build-Performance-with-VS-2005.aspx
- http://dotnettipoftheday.org/tips/speedup_visual_studio.aspx
- http://dotnettipoftheday.org/tips/optimize_launch_of_vs2005.aspx
Another big thing is to split up your assemblies. If you have a 5MB assembly, changing one line will requiring building all 5MB. However if you split that up into five one-MB assemblies, changing a line requires building just that single assembly, sparing you from rebuilding the other 4MB. There's a balance between number vs. size of assemblies, but it's a good thing to keep in mind when dealing with slow build times.
Wednesday, January 14, 2009
Why good-intentioned devs might not write good unit tests
I'm a big fan of unit testing. A related question to "How many tests are sufficient?" is "Why don't we write good unit tests?" While I've seen some people attribute it to purely negative things like laziness or dumbness or lack or care for code quality, I think that misses the mark. While sure, there are some devs who don't write tests for those reasons, I think there are tons of other devs who are hard-working, smart, and do care about their work, but still don't write good or sufficient unit tests. Calling these hard-working coworkers "dumb" isn't going to make anything better. Here are some reasons why a good-intentioned developer might not write tests.
I think I already write sufficient unit tests for my code.
I don't have time - the tests take too long to initially write.
I don't have time - the tests take too long to maintain and/or they keep breaking.
The unit tests don't really add value. It's just yet another buzzword. They don't actually catch the real errors. So it's not the best use of my time.
It's so much faster to just (real quick) run through my feature manually because all the context is already there (the data, the web session, the integration with other features, etc...).
My code isn't easily testable - unit tests are great for business logic in C#, but I write code other than C# (SQL, JS), or things that aren't business logic (like UI rendering), or my code is too complex for unit tests.
My code isn't easily testable - there are too many dependencies and limits. For example, I can't even reference an ASP.Net CodeBehind in a unit test.
The tests take too long to run (the full test suite takes about 10 minutes, even without the database tests it still takes 3 minutes).
I write code that already works, so it doesn't require unit tests.
My code is so simple so that it doesn't need tests. For example, I'm not going to test every option in a switch-case.
Sounds great, but I just don't know how to write tests for my code.
Note that I absolutely don't offer these as excuses, but rather as practical ideas to help understand a different perspective so you can improve things. For example, if someone is working on a 2-million line project that takes 5 minutes just to compile, let alone run any sort of test, they might skip running the tests with a "I don't have time" mindset. Yes, I still think it's overall faster to write and run the tests, but at least it helps you understand their perspective so you can try to meet them half way (perhaps improve their machine hardware, split up the solution, split up the tests, etc...). Of, if someone thinks that unit tests don't catch "real errors", then you can have a discussion with concrete examples. Either way, understanding someone's reasons for doing something will help bridge the gap.