Different Styles of Dependency Management

Recently I was hacking out a quick Python script. Everything was fine until I needed to import one common third party library and then Boom! I was dropped head first into the messy chain of Python dependencies, weak typing, virtual environments, and conflicts. I couldn’t even install the necessary library with pip. I’d just get an unintelligible hash of error messages and stack traces.

So off to DuckDuckGo I went to remind myself how one actually builds and packages real world Python programs that do more than print Hello World! It wasn’t pretty, and it took me quite a while to understand it. This was actually harder for me than it might have been for a newbie because I was so invested in the way Java manages dependencies. I’ve spent years working with dependency management in Java at a depth most developers never sink to. I’m an Apache Maven committer. I’ve rewritten most of their documentation about dependencies. I’ve written tools to analyze Java jars, dependency trees, and classpaths. I wrote or edited most of Google’s Java Library Best Practices. I’ve debugged many problems caused by Java class loaders. So I’ve got a pretty good understanding of how Java dynamically links third party dependencies.

But Python? Python doesn’t work like that. And neither does everything else.

Read the rest of this entry »

Assume vs. Assert

Assumptions are an underused feature of modern testing frameworks that should be more widely known. Briefly, an assumption verifies that conditions are right to execute the test. An assertion verifies that the test passes. If an assertion fails, the test failed, and we know the code is broken. If an assumption fails, the test was not run and the code may or may not be broken.

Read the rest of this entry »

“Is A” vs. “Represents A”

We’ve all had the distinction between “Is A” and “Has A” in object oriented programming drilled into us. “Is A” relationships call for inheritance. “Has A” relationships call for delegation. Some theorists will even bother to distinguish between “Is A” and “Is a Role Played By“. However, recently I’ve been wondering about the distinction between real “Is A” and “Represents A” relationships, and I wonder if it may help explain some otherwise confusing points.

Read the rest of this entry »

Code Coverage Has a Blind Spot

Here’s the coverage report on a recent PR of mine:

All modified and coverable lines are covered by tests ?

    Comparison is base (a765aef) 85.95% compared to head (fe02e1b) 85.95%.

Additional details and impacted files

@@            Coverage Diff            @@
##             master     #546   +/-   ##
=========================================
  Coverage     85.95%   85.95%           
  Complexity     3480     3480           
=========================================
  Files           230      230           
  Lines          8225     8225           
  Branches        960      960           
=========================================
  Hits           7070     7070           
  Misses          865      865           
  Partials        290      290           

Precisely identical. What happened? Did I change a comment? Well, no. In fact I added tests for
situations that were not currently covered, so why didn’t coverage increase?

Read the rest of this entry »

Why Python is Better than Java

Reason 1: Mocking.

unittest.mock, Python’s mocking framework is so much more powerful than EasyMock, Mockito, or any other Java mock framework I’ve ever used. You can replace any method you like with essentially arbitrary code. No longer do you have to contort APIs with convoluted dependency injection just to mock out network connections or reproduce error conditions.

Instead you just identify a method by name and module within the scope of the test method. When that method is invoked, the actual code is replaced with the mock code. You can do this long after the class being mocked was written. Model classes do not need to participate in their own mocking. You can mock any method anywhere at any time, in your own code or in dependencies. No dependency injection required. You can even mock fields.

By contrast Java only lets you mock objects (not methods) and only when you have an available API to insert the mock in place of the real thing.

Reason 2: None is its own type.

Read the rest of this entry »