Software Craftmanship at its core is all about the development from journeyman to master in your field of expertise. Before you can become a journeyman, you should get a map or at least a path to begin with. Let me show you a brief description of the path I chose in the order I think works best.
From Coder beyond Senior Developer in ten steps:
1. Version Control System
If you work alone or in a team, version control systems offer you restorability of your files from any point in time and the ability to be able to deliver anytime by encapsulating new develompents in feature branches. It also enables teammembers to work in parallel on the same files by offering merging and patching abilities. Working in a small team at the same location, I started with Subversion. It is easy to use, has a broad acceptance in the community and is free of charge. If you prefer Microsoft products take a look at TFS. It will cost you though, and I think it is way to complex and contraints you in a lot of ways. If you want to know more, drop me a line. If your team works in diffent places or has members that are only parttime connected to the system or if you just want the next best thing, go for distributed version control systems like GIT / Mercurial.
2. Unit testing
I increased the quality of my software by automating tests for my interfaces, classes and methods. Thus I could guarantee functionality and prevent once repaired bugs from occuring again. Start to think test driven and define specifications in tests before implementing the solution. The architecture and code emerging from there are better and cleaner and one gets some metrics like code coverage etc. to report to the businesspeople.
Go for any derivate of xUnit (.Net: NUnit / Java: JUnit), it is wide spread and has a lot of support in other tools like ReSharper etc..
If you try to store objects in a relational database, you’ll suffer from the object-relational impedance mismatch. Since many object-specific paradigms like polymorphism or encapsulation can not be projected into relational data simply, you either end up with a very complex and hard to maintain database model, or an anemic object model. I had the last one and I had too much of it.
To free yourself from the burden of maintaining such databases, people have invented Object Relational Mappers like nHibernate. With an ORM you can focus on your business objects instead of worrying about persistence. In addition it enables you to switch databases like MSSQL, Oracle and MySQL without any hustle.
4. DI & IoC
To decouple your classes will improve testability and reduces dependencies in the compiling process. I’ve learned about the factory pattern and how Dependency Injection by Inversion of Control could help me with that. There is a wide variety of IoC-Containers and DI Frameworks. I use Castle Windsor and Ninject, but you should find one, that fits your specific needs.
Watch a short video demonstration on TekPub to get the notion of what DI&IoC can do for you: ConceptVideo.
Learn about delegates, lambdas and functional programming. You’ll be able to implement business workflows a lot easier and in a much more readable style. Functional programming is side effect free, in contrast to the notion of functions in imperative programming languages, where the result might depend on an internal state, hence it is easier to maintain.
Watch a short video demonstration on TekPub to get the notion of what Lambdas can do for you: ConceptVideo.
6. Continuous Integration
With high frequentcy check-ins (at least daily), an automated build and test system can provide the developers with quick response on integration problems without interrupting their own workflows. It also enables team wide check-in policies like unit test code coverage and more. It will let developers deliver more cohesive software faster. Martin Fowler wrote about Continuous Integration.
Tools I recommend: TeamCity (free for small teams) or Jenkins (licenced under MIT)
7. NoSQL persistence
A while after fiddling with all the problems ORMs gave me in addition to the solutiuon they offered I stopped bothering about relational databases as a persistence technology for my business objects. RDBMSs serve their purpose for reporting and business intelligence, and they do that job exceptionally well, but liberate yourself and don’t misuse them to store objects anymore. There are object stores, key/value stores or document stores out there that fulfill all your object persistence needs. Take a look at RavenDB, mongoDB, couchDB and many others. If you use them choose wisely and don’t let the producers of one tool lure you to their side. They are all on different sides of the CAP-triangle and it is always a trade off between consistency, availability and partitionability.
8. Domain Driven Design
Eric Evans wrote a book on domain driven design and how to tackle complexity in the heart of software. By focussing on the language of your customers domain and building your software along business needs instead of technical ones, DDD will help you to dismantle your legacy software piece by piece and rebuild it in a flexible, maintainable and more valuable manner. With focus on the language of the business DDD enables you to define your tests in a human readable language, using business terms as verbs and nouns, use a simple set of grammar called gherkin to make those specifications machine readable. Your tests will look like:
Given a customer has a premium account
When the customer orders product a
Then delivery is free of charge
Tools like Specflow will help with the translation from gherkin to code, but after you’ve gotten used to it, you’ll see that it is quite simple to do it without tooling.
After TDD and DDD I have a very nice decoupled system that is flexible and easy to maintain, but it’s components still know enough about each other to interact. To fully decouple them and to make the relationships between the systems components explicit, I recommend to use messaging. From lightweight and lightning fast messagetools like ØMQ for interprocess communication to full blown service busses like Udi Dahan’s nservicebus, there is a wide variety of messagebus, -queue and -handler systems for any requirement. I think messaging is very useful as a top level architectural pattern.
Reading information from a system and processing commands through business rules are two actions with highly different requirements, yet most (and by most I mean politely all) software I have seen uses one objectmodel to answer both of them. The Command Query Responsibility Segregation offers a way to build the optimised model for each need, instead of finding the least shitty model that serves all needs simultaniously. Once the command side is free of querying responsibilities, it is very beneficial to replace its state database with Event Sourcing. It provides you with the changes instead of a final state of your objects, therefore you can gather new insight from old events and has some other pros, but its killer feature is the enabling of event centric testing. I feel my next blog post tickling
It is a very benefitial architectural pattern for complex and collaborative domains and enables way too many things to be covered in this blog post. You can read all about it written by the founding fathers Greg Young and Udi Dahan, or more recently the journey into CQRS by Microsoft’s P&P team.
Of course there is a lot more to be written about each and every single step of this path, but I hope you like my brief summary. To learn all of these steps well enough to use them in production and to guide others along the path takes time. Don’t rush it, but find a steady pace that you can keep, and you’ll get there.
Please tell me about your journey, about other ideas and different experiences.
Have a nice code,