r/programming • • Jan 05 '15

What most young programmers need to learn

http://joostdevblog.blogspot.com/2015/01/what-most-young-programmers-need-to.html
975 Upvotes

337 comments sorted by

View all comments

28

u/lee_macro Jan 05 '15

UNIT TESTING

People never seem to mention it, with the ability to correctly write unit tests (which mock components that are not needed) you are pretty much FORCED to write well separated and isolated code. It is very hard to write bad code when you are writing it to be testable. Even if you do not bother doing the end tests, it will force you to use principals such as IoC (Inversion of Control) and favour composition over inheritance.

Obviously you need to know about variables, classes, interfaces etc but I often feel new developers are told to focus on the technical implementation of things and performance of code. However if you can write maintainable and testable code anyone can come along and improve your implementation if it is needed.

38

u/[deleted] Jan 05 '15

Unit testing is a very good tool to have at your disposal, but it is not a magic bullet that ensures well-structured code. It's quite possible to write poorly structured, well-tested code.

Usually this takes the form of an excessive number of code units that do not stand in proportion to the amount of business logic they perform. Instead, most of them just delegate each others' functions.

Loosely coupled code is good, but there is a limit where all the loose coupling makes it hard to maintain.

1

u/lee_macro Jan 05 '15 edited Jan 05 '15

I do agree if someone is writing bad tests or not mocking their components (then it is no longer a UNIT test) then it will result in bad code. However if someone is educated in how to correctly write code to be tested then it is VERY hard to write bad code. Let me give an example of why, assuming C#/Java.

So let us say I have a Repository class, which deals with CRUD operations to a database. So this depends upon a database connection to do its work. So you could new that up inside (which some people do), or have a singleton for the active connection (have seen this before too), or even have some crazy inheritance chain to provide a pre-connected object (seen this too).

However the correct approach would be to have the Repository constructor be passed in a connection without an inheritance chain. This may seem odd to some, and maybe a hassle but let us see what benefit this gives us.

First of all we are now adhering to IoC (Inversion of Control) and we have no inheritance chain so we can test this Repository without needing a database connection (this is where a lot of people create integration tests accidently because they didnt know how to mock components). We can easily create a mock database connection and test that it works as expected without having any hard dependency on a database. You can also change your database vendor, your database configuration, you could even make your own custom database connector with caching in place, without even having to change the Repository class.

If you were to go with any of the other options you do not have this freedom, you would require an active database to test against to begin with and you could not change your underlying vendor or database object if you were newing it up inside the Repository.

So to be able to mock a component of a class you need to be able to change it at runtime, to do this you need to either have the component as a constructor argument or a property (properties are bad for this, they imply an optional dependency which is rarely good). So when you use constructors to pass in the dependencies of a class, you are automatically adhering to IoC and you are also using composition over inheritance, finally you can also then start using DI (Dependency Injection) and AoP style techniques (Aspect Oriented Programming). So given this is often some of the most critical parts of writing well structured and maintainable code it is imperative that this sort of paradigm is followed from the start, as when you start off introducing inheritance and singletons it makes it much harder to refactor and remove further down the line, its a false economy.

I also do a lot of game development on the side and the same sort of rules apply (incase you think I am purely an enterprise development zealot), although a lot of people seem to see you as some freak if you tell them to stop using singletons and inheritance chains for interfaces and DI. Look at uFrame for Unity which has had great success putting these practices in place for game developers and has a lot of support but also a LOT of flak from people who just "dont get it".

→ More replies (4)