# data[].attributes.headline
An Initial Investigation of Test Driven Development in
Industry

# data[].attributes.subject
An Initial Investigation of Test Driven Development in
Industry

# data[].attributes.body
By Boby George and Laurie Williams

# data[].attributes.body
licensed under cc by-sa 3.0 with attribution required

# data[].attributes.attachment_link.readable_text
Asked

I am working to integrate unit testing into the development process on the team I work on and there are some sceptics. What are some good ways to convince the sceptical developers on the team of the value of Unit Testing? In my specific case we would be adding Unit Tests as we add functionality or fixed bugs. Unfortunately our code base does not lend itself to easy testing.

closed as not constructive by Robert Harvey Jan 27 '12 at 1:02

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, If this question can be reworded to fit the rules in the visit the help center for guidance. help center, please edit the question.

locked by Shog9♦ Jan 23 '15 at 1:49

This question exists because it has historical significance, but it is not considered a good, on-topic question for this site so please do not use it as evidence that you can ask similar questions here. This question and its answers are frozen and cannot be changed. See the help center for guidance on writing a good question.

Read more about locked posts here.

Every day in our office there is an exchange which goes something like this:

"Man, I just love unit tests, I've just been able to make a bunch of changes to the way something works, and then was able to confirm I hadn't broken anything by running the test over it again..."

The details change daily, but the sentiment doesn't. Unit tests and test-driven development (TDD) have so many hidden and personal benefits as well as the obvious ones that you just can't really explain to somebody until they're doing it themselves.

But, ignoring that, here's my attempt!

1. Unit Tests allows you to make big changes to code quickly. You know it works now because you've run the tests, when you make the changes you need to make, you need to get the tests working again. This saves hours.

2. TDD helps you to realise when to stop coding. Your tests give you confidence that you've done enough for now and can stop tweaking and move on to the next thing.

3. The tests and the code work together to achieve better code. Your code could be bad / buggy. Your TEST could be bad / buggy. In TDD you are banking on the chances of both being bad / buggy being low. Often it's the test that needs fixing but that's still a good outcome.

4. TDD helps with coding constipation. When faced with a large and daunting piece of work ahead writing the tests will get you moving quickly.

5. Unit Tests help you really understand the design of the code you are working on. Instead of writing code to do something, you are starting by outlining all the conditions you are subjecting the code to and what outputs you'd expect from that.

6. Unit Tests give you instant visual feedback, we all like the feeling of all those green lights when we've done. It's very satisfying. It's also much easier to pick up where you left off after an interruption because you can see where you got to - that next red light that needs fixing.

7. Contrary to popular belief unit testing does not mean writing twice as much code, or coding slower. It's faster and more robust than coding without tests once you've got the hang of it. Test code itself is usually relatively trivial and doesn't add a big overhead to what you're doing. This is one you'll only believe when you're doing it :)

8. I think it was Fowler who said: "Imperfect tests, run frequently, are much better than perfect tests that are never written at all". I interpret this as giving me permission to write tests where I think they'll be most useful even if the rest of my code coverage is woefully incomplete.

9. Good unit tests can help document and define what something is supposed to do

10. Unit tests help with code re-use. Migrate both your code and your tests to your new project. Tweak the code till the tests run again.

A lot of work I'm involved with doesn't Unit Test well (web application user interactions etc.), but even so we're all test infected in this shop, and happiest when we've got our tests tied down. I can't recommend the approach highly enough.

thetalkingwalnut asks:

What are some good ways to convince the skeptical developers on the team of the value of Unit Testing?

Everyone here is going to pile on lots of reasons out of the blue why unit testing is good. However, I find that often the best way to convince someone of something is to listen to their argument and address it point by point. If you listen and help them verbalize their concerns, you can address each one and perhaps convert them to your point of view (or at the very least, leave them without a leg to stand on). Who knows? Perhaps they will convince you why unit tests aren't appropriate for your situation. Not likely, but possible. Perhaps if you post their arguments against unit tests, we can help identify the counterarguments.

It's important to listen to and understand both sides of the argument. If you try to adopt unit tests too zealously without regard to people's concerns, you'll end up with a religious war (and probably really worthless unit tests). If you adopt it slowly and start by applying it where you will see the most benefit for the least cost, you might be able to demonstrate the value of unit tests and have a better chance of convincing people. I realize this isn't as easy as it sounds - it usually requires some time and careful metrics to craft a convincing argument.

Unit tests are a tool, like any other, and should be applied in such a way that the benefits (catching bugs) outweigh the costs (the effort writing them). Don't use them if/where they don't make sense and remember that they are only part of your arsenal of tools (e.g. inspections, assertions, code analyzers, formal methods, etc). What I tell my developers is this:

1. They can skip writing a test for a method if they have a good argument why it isn't necessary (e.g. too simple to be worth it or too difficult to be worth it) and how the method will be otherwise verified (e.g. inspection, assertions, formal methods, interactive/integration tests). They need to consider that some verifications like inspections and formal proofs are done at a point in time and then need to be repeated every time the production code changes, whereas unit tests and assertions can be used as regression tests (written once and executed repeatedly thereafter). Sometimes I agree with them, but more often I will debate about whether a method is really too simple or too difficult to unit test.

If a developer argues that a method seems too simple to fail, isn't it worth taking the 60 seconds necessary to write up a simple 5-line unit test for it? These 5 lines of code will run every night (you do nightly builds, right?) for the next year or more and will be worth the effort if even just once it happens to catch a problem that may have taken 15 minutes or longer to identify and debug. Besides, writing the easy unit tests drives up the count of unit tests, which makes the developer look good.

On the other hand, if a developer argues that a method seems too difficult to unit test (not worth the significant effort required), perhaps that is a good indication that the method needs to be divided up or refactored to test the easy parts. Usually, these are methods that rely on unusual resources like singletons, the current time, or external resources like a database result set. These methods usually need to be refactored into a method that gets the resource (e.g. calls getTime()) and a method that takes the resource as a argument (e.g. takes the timestamp as a parameter). I let them skip testing the method that retrieves the resource and they instead write a unit test for the method that now takes the resource as a argument. Usually, this makes writing the unit test much simpler and therefore worthwhile to write.

2. The developer needs to draw a "line in the sand" in how comprehensive their unit tests should be. Later in development, whenever we find a bug, they should determine if more comprehensive unit tests would have caught the problem. If so and if such bugs crop up repeatedly, they need to move the "line" toward writing more comprehensive unit tests in the future (starting with adding or expanding the unit test for the current bug). They need to find the right balance.

Its important to realize the unit tests are not a silver bullet and there is such a thing as too much unit testing. At my workplace, whenever we do a lessons learned, I inevitably hear "we need to write more unit tests". Management nods in agreement because its been banged into their heads that "unit tests" == "good".

However, we need to understand the impact of "more unit tests". A developer can only write ~N lines of code a week and you need to figure out what percentage of that code should be unit test code vs production code. A lax workplace might have 10% of the code as unit tests and 90% of the code as production code, resulting in product with a lot of (albeit very buggy) features (think MS Word). On the other hand, a strict shop with 90% unit tests and 10% production code will have a rock solid product with very few features (think "vi"). You may never hear reports about the latter product crashing, but that likely has as much to do with the product not selling very well as much as it has to do with the quality of the code.

Worse yet, perhaps the only certainty in software development is that "change is inevitable". Assume the strict shop (90% unit tests/10% production code) creates a product that has exactly 2 features (assuming 5% of production code == 1 feature). If the customer comes along and changes 1 of the features, then that change trashes 50% of the code (45% of unit tests and 5% of the production code). The lax shop (10% unit tests/90% production code) has a product with 18 features, none of which work very well. Their customer completely revamps the requirements for 4 of their features. Even though the change is 4 times as large, only half as much of the code base gets trashed (~25% = ~4.4% unit tests + 20% of production code).

My point is that you have to communicate that you understand that balance between too little and too much unit testing - essentially that you've thought through both sides of the issue. If you can convince your peers and/or your management of that, you gain credibility and perhaps have a better chance of winning them over.

Unit-testing is well worth the initial investment. Since starting to use unit-testing a couple of years ago, I've found some real benefits:

regression testing removes the fear of making changes to code (there's nothing like the warm glow of seeing code work or explode every time a change is made)

executable code examples for other team members (and yourself in six months time..)

merciless refactoring - this is incredibly rewarding, try it!

Code snippets can be a great help in reducing the overhead of creating tests. It isn't difficult to create snippets that enable the creation of a class outline and an associated unit-test fixture in seconds.

I didn't see this in any of the other answers, but one thing I noticed is that I could debug so much faster. You don't need to drill down through your app with just the right sequence of steps to get to the code your fixing, only to find you've made a boolean error and need to do it all again. With a unit test, you can just step directly into the code you're debugging.

A major part of test-driven development that is often glossed over is the writing of testable code. It seems like some kind of a compromise at first, but you'll discover that testable code is also ultimately modular, maintainable and readable. If you still need help convincing people this is a nice simple presentation about the advantages of unit testing.

One of the best things about unit testing is that your code will become easier to test as you do it. Preexisting code created without tests is always a challenge because since they weren't meant to be unit-tested, it's not rare to have a high level of coupling between classes, hard-to-configure objects inside your class - like an e-mail sending service reference - and so on. But don't let this bring you down! You'll see that your overall code design will become better as you start to write unit-tests, and the more you test, the more confident you'll become on making even more changes to it without fear of breaking you application or introducing bugs.

There are several reasons to unit-test your code, but as time progresses, you'll find out that the time you save on testing is one of the best reasons to do it. In a system I've just delivered, I insisted on doing automated unit-testing in spite of the claims that I'd spend way more time doing the tests than I would by testing the system manually. With all my unit tests done, I run more than 400 test cases in less than 10 minutes, and every time I had to do a small change in the code, all it took me to be sure the code was still working without bugs was ten minutes. Can you imagine the time one would spend to run those 400+ test cases by hand?

When it comes to automated testing - be it unit testing or acceptance testing - everyone thinks it's a wasted effort to code what you can do manually, and sometimes it's true - if you plan to run your tests only once. The best part of automated testing is that you can run them several times without effort, and after the second or third run, the time and effort you've wasted is already paid for.

One last piece of advice would be to not only unit test your code, but start doing test first (see TDD and BDD for more)

Occasionally either myself or one of my co-workers will spend a couple of hours getting to the bottom of slightly obscure bug and once the cause of the bug is found 90% of the time that code isn't unit tested. The unit test doesn't exist because the dev is cutting corners to save time, but then looses this and more debugging.

Taking the small amount of time to write a unit test can save hours of future debugging.

I'm working as a maintenance-engineer of a poorly documented, awful and big code base. I wish the people who wrote the code had written the unit tests for it.
Each time I make a change and update the production code I'm scared that I might introduce a bug for not having considered some condition.
If they wrote the test making changes to the code base would be easier and faster.(at the same time the code base would be in a better state)..

I think unit tests prove a lot useful when writing api or frameworks that have to last for many years and to be used/modified/evolved by people other than the original coders.

Yes - Unit Testing is definitely worth the effort but you should know it's not a silver bullet. Unit Testing is work and you will have to work to keep the test updated and relevant as code changes but the value offered is worth the effort you have to put in. The ability to refactor with impunity is a huge benefit as you can always validate functionality by running your tests after any change code. The trick is to not get too hung up on exactly the unit-of-work you're testing or how you are scaffolding test requirements and when a unit-test is really a functional test, etc. People will argue about this stuff for hours on end and the reality is that any testing you do as your write code is better than not doing it. The other axiom is about quality and not quantity - I have seen code-bases with 1000's of test that are essentially meaningless as the rest don't really test anything useful or anything domain specific like business rules, etc of the particular domain. I've also seen codebases with 30% code coverage but the tests were relevant, meaningful and really awesome as they tested the core functionality of the code it was written for and expressed how the code should be used.

One of my favorite tricks when exploring new frameworks or codebases is to write unit-tests for 'it' to discover how things work. It's a great way to learn more about something new instead of reading a dry doc :)

I recently went through the exact same experience in my workplace and found most of them knew the theoretical benefits but had to be sold on the benefits to them specifically, so here were the points I used (successfully):

They save time when performing negative testing, where you handle unexpected inputs (null pointers, out of bounds values, etc), as you can do all these in a single process.

They provide immediate feedback at compile time regarding the standard of the changes.

They are useful for testing internal data representations that may not be exposed during normal runtime.

and the big one...

You might not need unit testing, but when someone else comes in and modifies the code without a full understanding it can catch a lot of the silly mistakes they might make.

Unit testing helps a lot in projects that are larger than any one developer can hold in their head. They allow you to run the unit test suite before checkin and discover if you broke something. This cuts down a lot on instances of having to sit and twiddle your thumbs while waiting for someone else to fix a bug they checked in, or going to the hassle of reverting their change so you can get some work done. It's also immensely valuable in refactoring, so you can be sure that the refactored code passes all the tests that the original code did.

I'm agree with the point of view opposite to the majority here: It's OK Not to Write Unit Tests Especially prototype-heavy programming (AI for example) is difficult to combine with unit testing.

Not the answer you're looking for? Browse other questions tagged unit-testing or ask your own question.

Stack Overflow works best with JavaScript enabled

# data[].attributes.attachment_link.description
Asked I am working to integrate unit testing into the development process on the team I work on and there are some sceptics. What are some good ways to convince the sceptical developers on the team of the value of Unit Testing?

# data[].attributes.headline
S.O.L.I.D: The First 5 Principles of Object Oriented Design

# data[].attributes.subject
S.O.L.I.D: The First 5 Principles of Object Oriented Design

# data[].attributes.body
by Samuel Oloruntoba licensed under Attribution 4.0 International

# data[].attributes.attachment_link.readable_text
S.O.L.I.D is an acronym for the first five object-oriented design(OOD) principles by Robert C. Martin, popularly known as Uncle Bob.

These principles, when combined together, make it easy for a programmer to develop software that are easy to maintain and extend. They also make it easy for developers to avoid code smells, easily refactor code, and are also a part of the agile or adaptive software development.

Note: this is just a simple "welcome to S.O.L.I.D" article, it simply sheds light on what S.O.L.I.D is.

S.O.L.I.D stands for:

When expanded the acronyms might seem complicated, but they are pretty simple to grasp.

S - Single-responsiblity principle

O - Open-closed principle

L - Liskov substitution principle

I - Interface segregation principle

D - Dependency Inversion Principle

Let's look at each principle individually to understand why S.O.L.I.D can help make us better developers.

Single-responsibility Principle

S.R.P for short - this principle states that:

A class should have one and only one reason to change, meaning that a class should have only one job.

For example, say we have some shapes and we wanted to sum all the areas of the shapes. Well this is pretty simple right?

 class Circle { public $radius; public function __construct($radius) { $this->radius = $radius; } } class Square { public $length; public function __construct($length) { $this->length = $length; } }

First, we create our shapes classes and have the constructors setup the required parameters. Next, we move on by creating the AreaCalculator class and then write up our logic to sum up the areas of all provided shapes.

 class AreaCalculator { protected $shapes; public function __construct($shapes = array()) { $this->shapes = $shapes; } public function sum() { // logic to sum the areas } public function output() { return implode('', array( "" )); } }

To use the AreaCalculator class, we simply instantiate the class and pass in an array of shapes, and display the output at the bottom of the page.

 $shapes = array( new Circle(2), new Square(5), new Square(6) ); $areas = new AreaCalculator($shapes); echo $areas->output();

The problem with the output method is that the AreaCalculator handles the logic to output the data. Therefore, what if the user wanted to output the data as json or something else?

All of that logic would be handled by the AreaCalculator class, this is what SRP frowns against; the AreaCalculator class should only sum the areas of provided shapes, it should not care whether the user wants json or HTML.

So, to fix this you can create an SumCalculatorOutputter class and use this to handle whatever logic you need to handle how the sum areas of all provided shapes are displayed.

The SumCalculatorOutputter class would work like this:

 $shapes = array( new Circle(2), new Square(5), new Square(6) ); $areas = new AreaCalculator($shapes); $output = new SumCalculatorOutputter($areas); echo $output->JSON(); echo $output->HAML(); echo $output->HTML(); echo $output->JADE();

Now, whatever logic you need to output the data to the user is now handled by the SumCalculatorOutputter class.

Open-closed Principle

Objects or entities should be open for extension, but closed for modification.

This simply means that a class should be easily extendable without modifying the class itself. Let's take a look at the AreaCalculator class, especially it's sum method.

 public function sum() { foreach($this->shapes as $shape) { if(is_a($shape, 'Square')) { $area[] = pow($shape->length, 2); } else if(is_a($shape, 'Circle')) { $area[] = pi() * pow($shape->radius, 2); } } return array_sum($area); }

If we wanted the sum method to be able to sum the areas of more shapes, we would have to add more if/else blocks and that goes against the Open-closed principle.

A way we can make this sum method better is to remove the logic to calculate the area of each shape out of the sum method and attach it to the shape's class.

 class Square { public $length; public function __construct($length) { $this->length = $length; } public function area() { return pow($this->length, 2); } }

The same thing should be done for the Circle class, an area method should be added. Now, to calculate the sum of any shape provided should be as simple as:

 public function sum() { foreach($this->shapes as $shape) { $area[] = $shape->area(); } return array_sum($area); }

Now we can create another shape class and pass it in when calculating the sum without breaking our code. However, now another problem arises, how do we know that the object passed into the AreaCalculator is actually a shape or if the shape has a method named area?

Coding to an interface is an integral part of S.O.L.I.D, a quick example is we create an interface, that every shape implements:

 interface ShapeInterface { public function area(); } class Circle implements ShapeInterface { public $radius; public function __construct($radius) { $this->radius = $radius; } public function area() { return pi() * pow($this->radius, 2); } }

In our AreaCalculator sum method we can check if the shapes provided are actually instances of the ShapeInterface, otherwise we throw an exception:

 public function sum() { foreach($this->shapes as $shape) { if(is_a($shape, 'ShapeInterface')) { $area[] = $shape->area(); continue; } throw new AreaCalculatorInvalidShapeException; } return array_sum($area); }

Liskov substitution principle

Let q(x) be a property provable about objects of x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.

All this is stating is that every subclass/derived class should be substitutable for their base/parent class.

Still making use of out AreaCalculator class, say we have a VolumeCalculator class that extends the AreaCalculator class:

 class VolumeCalculator extends AreaCalulator { public function __construct($shapes = array()) { parent::__construct($shapes); } public function sum() { // logic to calculate the volumes and then return and array of output return array($summedData); } }

In the SumCalculatorOutputter class:

 class SumCalculatorOutputter { protected $calculator; public function __constructor(AreaCalculator $calculator) { $this->calculator = $calculator; } public function JSON() { $data = array( 'sum' => $this->calculator->sum(); ); return json_encode($data); } public function HTML() { return implode('', array( '' )); } }

If we tried to run an example like this:

 $areas = new AreaCalculator($shapes); $volumes = new AreaCalculator($solidShapes); $output = new SumCalculatorOutputter($areas); $output2 = new SumCalculatorOutputter($volumes);

The program does not squawk, but when we call the HTML method on the $output2 object we get an E_NOTICE error informing us of an array to string conversion.

To fix this, instead of returning an array from the VolumeCalculator class sum method, you should simply:

 public function sum() { // logic to calculate the volumes and then return and array of output return $summedData; }

The summed data as a float, double or integer.

Interface segregation principle

A client should never be forced to implement an interface that it doesn't use or clients shouldn't be forced to depend on methods they do not use.

Still using our shapes example, we know that we also have solid shapes, so since we would also want to calculate the volume of the shape, we can add another contract to the ShapeInterface:

 interface ShapeInterface { public function area(); public function volume(); }

Any shape we create must implement the volume method, but we know that squares are flat shapes and that they do not have volumes, so this interface would force the Square class to implement a method that it has no use of.

ISP says no to this, instead you could create another interface called SolidShapeInterface that has the volume contract and solid shapes like cubes e.t.c can implement this interface:

 interface ShapeInterface { public function area(); } interface SolidShapeInterface { public function volume(); } class Cuboid implements ShapeInterface, SolidShapeInterface { public function area() { // calculate the surface area of the cuboid } public function volume() { // calculate the volume of the cuboid } }

This is a much better approach, but a pitfall to watch out for is when type-hinting these interfaces, instead of using a ShapeInterface or a SolidShapeInterface.

You can create another interface, maybe ManageShapeInterface, and implement it on both the flat and solid shapes, this way you can easily see that it has a single API for managing the shapes. For example:

 interface ManageShapeInterface { public function calculate(); } class Square implements ShapeInterface, ManageShapeInterface { public function area() { /*Do stuff here*/ } public function calculate() { return $this->area(); } } class Cuboid implements ShapeInterface, SolidShapeInterface, ManageShapeInterface { public function area() { /*Do stuff here*/ } public function volume() { /*Do stuff here*/ } public function calculate() { return $this->area() + $this->volume(); } }

Now in AreaCalculator class, we can easily replace the call to the area method with calculate and also check if the object is an instance of the ManageShapeInterface and not the ShapeInterface.

Dependency Inversion principle

The last, but definitely not the least states that:

Entities must depend on abstractions not on concretions. It states that the high level module must not depend on the low level module, but they should depend on abstractions.

This might sound bloated, but it is really easy to understand. This principle allows for decoupling, an example that seems like the best way to explain this principle:

 class PasswordReminder { private $dbConnection; public function __construct(MySQLConnection $dbConnection) { $this->dbConnection = $dbConnection; } }

First the MySQLConnection is the low level module while the PasswordReminder is high level, but according to the definition of D in S.O.L.I.D. which states that Depend on Abstraction not on concretions, this snippet above violates this principle as the PasswordReminder class is being forced to depend on the MySQLConnection class.

Later if you were to change the database engine, you would also have to edit the PasswordReminder class and thus violates Open-close principle.

The PasswordReminder class should not care what database your application uses, to fix this again we "code to an interface", since high level and low level modules should depend on abstraction, we can create an interface:

 interface DBConnectionInterface { public function connect(); }

The interface has a connect method and the MySQLConnection class implements this interface, also instead of directly type-hinting MySQLConnection class in the constructor of the PasswordReminder, we instead type-hint the interface and no matter the type of database your application uses, the PasswordReminder class can easily connect to the database without any problems and OCP is not violated.

 class MySQLConnection implements DBConnectionInterface { public function connect() { return "Database connection"; } } class PasswordReminder { private $dbConnection; public function __construct(DBConnectionInterface $dbConnection) { $this->dbConnection = $dbConnection; } }

According to the little snippet above, you can now see that both the high level and low level modules depend on abstraction.

Conclusion

Honestly, S.O.L.I.D might seem to be a handful at first, but with continuous usage and adherence to its guidelines, it becomes a part of you and your code which can easily be extended, modified, tested, and refactored without any problems.

# data[].attributes.attachment_link.title
S.O.L.I.D: The First 5 Principles of Object Oriented Design

# data[].attributes.attachment_link.description
S.O.L.I.D is an acronym for the first five object-oriented design(OOD) principles by Robert C. Martin, popularly known as Uncle Bob. These principles, when combined together, make it easy for a programmer to develop software that are easy to maintain and extend.

# data[].attributes.body
Article licensed under  Creative Commons Attribution-ShareAlike License

# data[].attributes.attachment_link.description
In object-oriented computer programming, SOLID is a mnemonic acronym for five design principles intended to make software designs more understandable, flexible, and maintainable. The principles are a subset of many principles promoted by American software engineer and instructor Robert C. Martin, first introduced in his 2000 paper Design Principles and Design Patterns.

# data[].attributes.headline
Agile Android Software Development Book Sources

# data[].attributes.subject
Agile Android Software Development Book Sources

# data[].attributes.body
"Agile Android Software Development" by Etienne Savard. This book is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License

# data[].attributes.attachment_link.description
agile-android-software-development-book - This is the official git repository for the contents of the book "Agile Android Software Development" by Etienne Savard. This book is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.

# data[].attributes.body
The source code for SQLite is in the public domain

# data[].attributes.attachment_link.description
SQLite is a self-contained, high-reliability, embedded, full-featured, public-domain, SQL database engine. SQLite is the most used database engine in the world. More Info

# data[].attributes.headline
Applying S.O.L.I.D. Principles in .NET/C#

# data[].attributes.subject
Applying S.O.L.I.D. Principles in .NET/C#

# data[].attributes.body
"Applying S.O.L.I.D. Principles in .NET C#" is licensed under Creative Commons Attribution license

# data[].attributes.attachment_link.title
Applying S.O.L.I.D. Principles in .NET/C#

# data[].attributes.attachment_link.description
Have you heard of the S.O.L.I.D. principles? You have? Can you explain them all? And make your colleague understand them, and why they are useful? If not, you should definitely go to this session, as it walks through each one of the principles, explaining what it means and why it is useful.

# data[].attributes.headline
Unit Testing Code Reviews Best Practices with Roy Osherove

# data[].attributes.subject
Unit Testing Code Reviews Best Practices with Roy Osherove

# data[].attributes.body
"Unit Testing Code Reviews Best Practices with Roy Osherove" by Roy Osherove is licensed under the Standard YouTube License (Creative commons attribution)

# data[].attributes.attachment_link.entities[].name
JS Unit Testing Good Practices & Horrible Mistakes

# data[].attributes.attachment_link.title
Unit Testing Code Reviews Best Practices with Roy Osherove

# data[].attributes.attachment_link.description
This is part of a full course by Roy Osherove at http:/courses.osherove.com. More info at http://ArtOfUnitTesting.com by Roy Osherove

# data[].attributes.body
"From STUPID to SOLID Code!" by William Durand is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License

# data[].attributes.attachment_link.readable_text
Last week I gave a talk about Object-Oriented Programming at Michelin, the company I am working for. I talked about writing better code, from STUPID to SOLID code! STUPID as well asSOLID are two acronyms, and have been covered quite a lot for a long time. However, these mnemonics are not always well-known, so it is worth spreading the word.

In the following, I will introduce both STUPID and SOLID principles. Keep in mind that these are principles, not laws. However, considering them as laws would be good for those who want to improve themselves.

STUPID code, seriously?

This may hurt your feelings, but you have probably written STUPID code already. I have too. But, what does that mean?

In the following, I will explain the individual points with more details. This is more or less the transcript of my talk.

Singleton

The Singleton pattern is probably the most well-known design pattern, but also the most misunderstood one. Are you aware of the Singleton syndrome? It is when you think the Singleton pattern is the most appropriate pattern for the current use case you have. In other words, you use it everywhere. That is definitely not cool.

Singletons are controversial, and they are often considered anti-patterns. You should avoid them. Actually, the use of a singleton is not the problem, but the symptom of a problem. Here are two reasons why:

Programs using global state are very difficult to test;

Programs that rely on global state hide their dependencies.

But should you really avoid them all the time? I would say yes because you can often replace the use of a singleton by something better. Avoiding static things is important to avoid something called tight coupling.

Tight Coupling

Tight coupling, also known as strong coupling, is a generalization of the Singleton issue. Basically, you should reduce coupling between your modules. Coupling is the degree to which each program module relies on each one of the other modules.

If making a change in one module in your application requires you to change another module, then coupling exists. For instance, you instantiate objects in your constructor's class instead of passing instances as arguments. That is bad because it doesn't allow further changes such as replacing the instance by an instance of a sub-class, a mock or whatever.

Tightly coupled modules are difficult to reuse, and also hard to test.

Untestability

In my opinion, testing should not be hard! No, really. Whenever you don't write unit tests because you don't have time, the real issue is that your code is bad, but that is another story.

Most of the time, untestability is caused by tight coupling.

Premature Optimization

Donald Knuth said: " premature optimization is the root of all evil. There is only cost, and no benefit". Actually, optimized systems are much more complex than just rewriting a loop or using pre-increment instead of post-increment. You will just end up with unreadable code. That is why Premature Optimization is often considered an anti-pattern.

A friend of mine often says that there are two rules to optimize an application:

don't do it;

(for experts only!) don't do it yet.

Indescriptive Naming

This should be obvious, but still needs to be said: name your classes, methods, attributes, and variables properly. Oh, and don't abbreviate! You write code for people, not for computers. They don't understand what you write anyway. Computers just understand 0 and 1. Programming languages are for humans.

Duplication

Duplicated code is bad, so please Don't Repeat Yourself ( DRY), and also Keep It Simple, Stupid. Be lazy the right way - write code only once!

Now that I have explained what STUPID code is, you may think that your code is STUPID. It does not matter (yet). Don't feel bad, keep calm and be awesome by writing SOLID code instead!

SOLID to the rescue!

SOLID is a term describing a collection of design principles for good code that was invented by Robert C. Martin, also known as Uncle Bob.

SOLID means:

Single Responsibility Principle

Single Responsibility Principle or SRP states that every class should have a single responsibility. There should never be more than one reason for a class to change.

Just because you can add everything you want into your class doesn't mean that you should. Thinking in terms of responsibilities will help you design your application better. Ask yourself whether the logic you are introducing should live in this class or not. Using layers in your application helps a lot. Split big classes in smaller ones, and avoid god classes. Last but not least, write straightforward comments. If you start writing comments such as in this case, but if, except when, or, then you are doing it wrong.

Open/Closed Principle

Open/Closed Principle or OCP states that software entities should be open for extension, but closed for modification.

You should make all member variables private by default. Write getters and setters only when you need them. I've already covered this point in a previous article, as the ninth rule of the Object Calisthenics is related to this principle.

Liskov Substitution Principle

Liskov Substitution Principle or LSP states that objects in a program should be replaceable with instances of their subtypes without altering the correctness of the program.

Let's take an example. A rectangle is a plane figure with four right angles. It has a width, and a height. Now, take a look at the following pseudo-code:

rect = new Rectangle(); rect.width = 10; rect.height = 20; assert 10 == rect.width assert 20 == rect.height

We simply set a width and a height on a Rectangle instance, and then we assert that both properties are correct. So far, so good.

Now we can improve our definition by saying that a rectangle with four sides of equal length is called a square. A square is a rectangle so we can create a Square class that extends the Rectangle one, and replace the first line above by the one below:

According to the definition of a square, its width is equal to its height. Can you spot the problem? The first assertion will fail because we had to change the behavior of the setters in the Square class to fit the definition. This is a violation of the Liskov Substitution Principle.

Interface Segregation Principle

Interface Segregation Principle or ISP states that many client-specific interfaces are better than one general-purpose interface. In other words, you should not have to implement methods that you don't use. Enforcing ISP gives you low coupling, and high cohesion.

When talking about coupling, cohesion is often mentioned as well. High cohesion means to keep similar and related things together. The union of cohesion and coupling is orthogonal design. The idea is to keep your components focused and try to minimize the dependencies between them.

Note that this is similar to the Single Responsibility Principle. An interface is a contract that meets a need. It is ok to have a class that implements different interfaces, but be careful, don't violate SRP.

Dependency Inversion Principle

Dependency Inversion Principle or DIP has two key points:

Abstractions should not depend upon details;

Details should depend upon abstractions.

This principle could be rephrased as use the same level of abstraction at a given level. Interfaces should depend on other interfaces. Don't add concrete classes to method signatures of an interface. However, use interfaces in your class methods.

Note that Dependency Inversion Principle is not the same as Dependency Injection. Dependency Injection is about how one object knows about another dependent object. In other words, it is about how one object acquires a dependency. On the other hand, DIP is about the level of abstraction. Also, a Dependency Injection Container is a way to auto-wire classes together. That does not mean you do Dependency Injection though. Look at the Service Locator for example.

Also, rather than working with classes that are tight coupled, use interfaces. This is called programming to the interface. This reduces dependency on implementation specifics and makes code more reusable. It also ensures that you can replace the implementation without violating the expectations of that interface, according to the Liskov Substitution Principle seen before.

Conclusion

As you probably noticed, avoiding tight coupling is the key. It is present in a lot of code, and if you start by focusing on fixing this alone, you will immediately start writing better code.

If I may leave you with only one piece of advice, that would be to use your brain. There are a lot of principles in software engineering. Even if you don't understand all these principles, always think before writing code. Take the time to understand those that you don't understand.

Honestly, writing SOLID code is not that hard.

Slides

TL;DR

STUPID is an acronym that describes bad practices in Oriented Object Programming:

SOLID is an acronym that stands for five basic principles of Object-Oriented Programming and design to fix STUPID code:

Rule of thumb: use your brain!

# data[].attributes.attachment_link.description
Last week I gave a talk about Object-Oriented Programming at Michelin, the company I am working for. I talked about writing better code, from STUPID to SOLID code! STUPID as well asSOLID are two acronyms, and have been covered quite a lot for a long time.