“Learn how to do it manually first, then use abstractions to save time. Code generation tools which pretend to abstract out something, like all abstractions, leak, and the only way to deal with the leaks competently is to learn about how the abstractions work and what they are abstracting. So the abstractions save us time working, but they don’t save us time learning. And all this means that paradoxically, even as we have higher and higher level programming tools with better and better abstractions, becoming a proficient programmer is getting harder and harder.”
One of the primary points of encapsulation is to control the internal state of the object, by only providing a limited interface. This protects the integrity of the state.
But the other purpose of private variables and encapsulation in any language is not simply security or protection from nefarious people. It’s abstraction. An external entity should not need or care to know how the internals are accomplished. The smaller the footprint of the interface, the less complexity exists for the consumer to understand. You should expose no more than is necessary to leverage the functionality. The result of doing so is code that has looser coupling and is easier to understand by those who wish to consume it.
Have you heard of the Law of Demeter? If you develop software, you should. You may actually be familiar with its concepts without actually knowing that it had a formal name. At it’s core, the Law of Demeter is the explicit capture of the intent of encapsulation. The rules are as follows.
A method FooMethod of a class Foo should only call the methods of these:
An object created by FooMethod
An object passed as an argument to FooMethod
An object reference held as an instance variable of Foo
I spend a lot of time talking about the craft of software development. So what do I think makes a good software developer?
Do you just go pick up an undergrad degree and you’re done? Of course not. At that point you know mechanical technique, without the deeper understanding of how to make good software.
The truth of the matter is that undergrad degrees are really just the primer. They teach you that to make sounds come out of the cello, you must draw the bow across its strings; But they don’t teach you how to make amazing sounds. In order to create amazing software you have to read about the craft, play with languages, try new patterns, keep up with the industry, and be passionate about writing reusable and highly-maintainable code.
So this is my list of the things that make a really great software developer, in no particular order.
Read. Lots. There are certain books that I would almost consider required reading.
Code Complete by Steve Mcconnell – This book is the bible of software engineering. The principles and practices taught in these pages form the core of what it means to write quality software.
Connect with other software developers. The difficult part about software development is communication. You cannot grow as a software developer without interacting with your peers. This can include:
Software engineering discussions with friends
Participate in sites like Stackoverflow.com, Programmers, etc
Attend a local user group for whatever language or software engineering aspect interests you
Be an encapsulation and loose-coupling ninja.
Orthogonality is key in creating maintainable, extensible software.
Loose coupling must be burned into who you are as a programmer. The only constant in our industry is change.
Dependency injection is your friend.
Don’t make anything public unless it needs to be.
Don’t use exceptions except in exceptional cases.
Project estimation is hard. Don’t make a mess just to meet a monolithic schedule. Develop incrementally and iteratively. Don’t accumulate technical debt by kidding yourself that you’ll clean things up later. Measure twice, cut once.
Embrace the agile mindset. Do prototypes. Pseudo-code. White board your ideas. Develop a skeleton application and then iterate on it. Have an agile approach/methodology to your software development, so that you can react quickly and painlessly to change.
K.I.S.S. Keep it simple stupid. Don’t over-think a problem. Favor the simpler solution over the complex one. Don’t optimize code up front. Readability of code is far more important than micro-optimizations for performance.
DRY: Don’t repeat yourself. If you find commonalities or duplication in your code, refactor it into a method/module/whatever. Refactor, refactor refactor.
Be explicit. You must write code with the future developer in mind. If the future developer will be confused by your code, refactor it so your intent is obvious. Code should be self-documenting. Code is for how, comments are for why. Program defensively. Name variables and types in an obvious manner. Don’t abbreviate or shorten variable names.
Know the greats. Stand on the shoulders of giants. In order to become a great software engineer, you have to know what to shoot for. You can learn an incredible amount by looking into the big names in our industry. These are some names that you should be able talk conversationally about:
Miguel de Icaza
Robert C. Martin
Practice Test Driven Development. Write code with the goal of passing your unit tests; Don’t write tests later, because you’ll probably just write the tests so that they pass, and won’t uncover the bugs, one off errors, etc.
Don’t reinvent the wheel. If there is a quality software component or framework that will accomplish what you need, then use it.
Use the right tool for the job. This is true for the programming language, the tools, the frameworks, everything.
The code exists for solving a problem, not for itself. Recognize what adds value to your problem and what does not. Do not build castles in the clouds. Y.A.G.N.I. (You ain’t gonna need it.) Don’t build something into the system unless it helps solve the problem.
Strong-typing is your friend. Any errors you can catch at compile time helps you offload your imperfection as a human being onto the computer. Solve all warnings generated by your compiler, not just the errors. Recognize when dynamic typing is valuable and when it isn’t.
Favor convention over configuration. Nobody enjoys XML soup, especially when it’s unnecessary.
Understand what the abstractions are doing for you, at a basic level. You don’t need to know all the nitty gritty details, but you at least should know enough so that you understand the benefits and trade-offs of using the abstraction.
There is of course far more that could be said, but I think that’s a pretty good list for starters.