I remember the software engineering course I took during my last two semesters of study. We learned UML, OOP, project planning, CASE tools, documentation, a bunch of design patterns and lots of other tactics to tame huge hypothetical abstract software codebases. The problem was that, in fact, they remained abstract in my mind.
As students, we never dealt with code longer than some thousands of lines of code. I distinctly remember how proud I was the first time I wrote a C program that was longer than 1000 lines. If you enjoy programming though, chances are that you will get some sort of job involving development. Additionally, you will likely deal with a large legacy codebase.
That’s the old passage to Ravenholm. We don’t go there anymore. – Alyx Vance, Half Life 2
That’s what all the nice things you learned during your software engineering lectures were for, right? It turns out it’s not that easy to apply that knowledge. For example, at the beginning I had a hard time to understand design patterns in practice. All I had was my GoF book sitting there and judging me from the shelf. I wanted to keep things pragmatical, though, and not overcomplicate things, so I rarely saw where patterns fit the picture. Considering that I was working on a legacy codebase that had no distinguishable patterns whatsoever, it didn’t look like a problem.
Little did I know that the codebase I was working on at the time was very far from the quality standards that the industry strives to achieve. Lacking any form of automated tests, working on the code was painful and many bug fixes felt like hacks. I was even more oblivious to the fact that a lot of projects are in this state nowadays all around the world.
Without a mentor, I turned to the Internet. I gathered a list of books about principles we didn’t treat in our coursework and started avidly reading. So this is the list of books I wish I had 5 years ago, when I was a junior developer working on a huge legacy codebase.
This book I found on Jeff Atwood’s blog, and it was so influential for him that he named his blog after a mechanism used in the book to identify bad practices, highlighted as “coding horrors”. I started reading it during my last year of study, but I went back to it when I started working and found out it’s full of practical tips. Very recommended at the beginning of your career.
This one contains a lot of best practices and is a wake up call for professionalism. It is opinionated, but opinions are what a junior developer needs, especially without mentors around. A must read for everyone in our industry working in object oriented land.
When you know how code is supposed to look like, you want to make your code “cleaner”. These two books show you how to get there starting from a sub-optimal codebase. It is not easy and it requires patience and discipline, but it’s far from impossible. While you are untangling the coupled concepts from the codebase, you will want to test them. That is why the next book is…
This is a very easy read about unit testing and the concepts behind it. It also contains lots of practical advice on how to structure tests and how to get started if all you have is a blank slate. If you feel the need to have a deeper understanding of testing, stubs and mocks you can always dive into xUnit Test Patterns. It’s a bit long, but I found the first part of the book especially useful.
HFDP takes the GoF patterns and puts them into scenarios where you can see how and why they fit. It has been very useful to get some practical insight that was lacking from the GoF book.
Weinberg wrote this a long time ago, but I believe it still contains very relevant advice. When you know how to write better software, you will want to tell your colleagues and convince your boss, and it is possible that you will meet some resistance in the process. This book tells you how to present your ideas and gain traction, whether you want to pursue the management path or not.
What do you think, what books should junior developers read?
I have been asked for advice on how to wade through the masses of information available online to developers. Every day there is something new and everybody wants your time, vendors try to convince you that their products are the best and will live forever then dump a product shortly after (cough cough silverlight cough cough). So how can one make sense of this huge mass of information?
Prioritize. When you have a set of technologies and concepts you are interested into, you need to start somewhere. The high priority items on the list are the ones that are being adopted right now by the rest of the industry, if you are lucky, and the ones that have been adopted since forever, if you are working on a hardcore legacy project.
Pace yourself. There is no need to sprint, we’re here for the long run. Choose a comfortable pace at which you can learn and try to stick to it.
Create routines. Make learning part of your daily routine. My news aggregator helps me in giving me my daily dose of what’s happening around the world. As discussed previously, filtering the news you are getting served every day is the only way to remain sane when it comes to your news feeds. Pick a few high quality sources to maintain a high signal-to-noise ratio.
Get involved in the community. Online or offline, conferences or forums, Stackoverflow, nowadays you have lots of possibilities to get in touch with passionate developers. Learn and teach, attend to and give talks, whatever your time allows for, interacting with other developers can be very rewarding. And I know that in Europe we shun it, but Twitter can have its uses.
Everything until now is fine and dandy, but a bit abstract. A way to concretize it is using ThoughtWorks technology radar. The radar allows you to both filter and prioritize technologies and techniques you are interested into, therefore deciding your level of commitment to them.
The implementation might look complicated, but it is really quite simple. You have four categories called Techniques, Tools, Platforms and Language & Frameworks. Each category is subdivided into four layers defining the relevance to the industry of the topics, which go from “hold off for now” to “this technology should be used in modern software development”. The idea is to regularly keep track of what’s on your radar and modify it as you grow, guiding your learning choices. For more details here you can find information on how to build your own technology radar.
If you are staring at an empty news aggregator, here is a selection of some of the sources I have in my feed in no particular order:
- .NET Rocks
- Mark Seemann’s blog
- Schneier on security
- Coding Horror
- Greg Young’s blog
- Hanselminutes / Scott Hanselman’s blog
- Martin Fowler
- Troy Hunt
- The morning brew
- Udi Dahan
- Phil Haack’s blog
How are you keeping up with technology?
ASMX web services have been defined a legacy technology for a while now. In fact, Microsoft itself put a disclaimer on the MSDN documentation page regarding ASMX.
This is not going to be news to the most of us, but we still kept creating services with ASMX. The problem is that I keep seeing projects implementing web services with ASMX instead of WCF. So why are we working with a legacy technology, while Microsoft keeps recommending against it?
Because WCF is a pain. It can do everything, but it always felt clunky for something small and simple like a web service. Have you ever seen the standard configuration of a WCF service, the one that is added by default when you create a service?
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IService1" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <security mode="None"> <transport clientCredentialType="None" proxyCredentialType="None" realm="" /> <message clientCredentialType="UserName" algorithmSuite="Default" /> </security> </binding> </basicHttpBinding> </bindings> <client> <endpoint address="http://localhost:36906/Service1.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1" contract="IService1" name="BasicHttpBinding_IService1" /> </client> </system.serviceModel> </configuration>
It makes me want to poke my eyes out. StrongWildCard? ReaderQuotas? It is a huge amount of unnecessary cryptic information. In fact, it is so bad that in the book “Programming WCF Services” there is an explicit essential coding guideline for configuration files: “Do not use SvcUtil or Visual Studio 2010 to generate a config file”. What about sharing the session with ASP.NET? Yes, it might be frowned upon, but it worked out of the box with ASMX. Oh right, you have to extend the configuration setting the aspNetCompatibilityEnabled attribute to true. As if the configuration weren’t large enough.
To make the matter worse, we are also deceived when we want to create a new web service. Suppose that we are asked to create a web service to expose a certain functionality of our application, when we go to Visual Studio we are faced with this:
Since we are about to create a web service we should probably choose the “Web Service” item from the list, right? Guess what that is? An ASMX Web Service. So much for legacy technology, this surely does not help the adoption of WCF services.
All in all, it has been difficult to convince developers to use WCF in the last years. Luckily Microsoft noticed, hence things have changed and with .NET 4.5 they simplified things a bit. Enter .NET 4.5 and the WCF “Simplification Features”.
For starters, there is a new default configuration.
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IService1" /> </basicHttpBinding> </bindings> <client> <endpoint address="http://localhost:36906/Service1.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1" contract="IService1" name="BasicHttpBinding_IService1" /> </client> </system.serviceModel> </configuration>
Much less intimidating than the older one, isn’t it? And we don’t need to bother to configure the ASP.NET compatibility mode, since it is activated by default now, meaning that we can access ASP.NET session out of the box. There are some other improvements that you should check out on the dedicated page on MSDN.