Take-Away
If you are in a hurry, here’s the take-away:
Pros:
- You can carry lots of technical books with you, without breaking your shoulder.
- The e-ink is easy on your eyes, pretty much like real paper.
- Most books in native (mobi) format show code listings nicely and are fully searchable.
- Getting a new book is just one click away.
Cons:
- Kindle DX does not reflow PDF content, therefore you cannot increase the font size of all those technical papers. You can only zoom in and then use navigation keys to move around.
- No Wi-Fi means you need a cable to upload a book or paper you just downloaded from the net outside Amazon Store (or pay a fee to get it delivered via e-mail).
- Only black and white (a few charts might benefit from being rendered in their original color).
- Getting a new book is just one link away.
Overall: it’s a pleasure to read from it, you can stop printing all those 4-6 pages white papers and fit them in your Kindle. PDF rendering is excellent and images are crisp. Too bad that the prices for many e-books are pretty much the same as their paper equivalent.
A Few Pictures Are Worth A Thousand Words
If you are still with me, then let’s see a few examples of how some native (mobi) and PDF books and technical papers are rendered. A word of caution: the quality of the photos themselves is barely tolerable and I apologize for it. On some photos you can see a distinct barrel distortion due to the point and shoot camera I used. You should be able to get an idea anyway.
The first book I am showing is Don’t Make Me Think!. This is a typical example of technical book with mixed graphic and text. As you can see image is pretty readable.
The second image is from a free PDF version of the famous book Syntax and Semantics of Programming Languages. This is one of the best PDF experience you can get, since the font size and margins are pretty about perfect for the dimensions of the DX.
Compare instead to the smaller font used in C# in Depth (great book by the way): this are just a bit too small for my taste, even though I managed to read almost half the book this way.
Eventually the editor finally released a mobi version, where I could set a bigger font size, as shown in the following picture. Note that I am showing exactly the same portion as above, so that you can get a feeling of the difference between PDF and mobi: PDF is usually better looking, while mobi is usually easier to read. In the mobi version you can also see that the two code snippets are rendered differently: the Listing 9.9 is “normal” text with a different font than regular text, while the Listing 9.10 is actually a picture. Probably that was the only way to insert those arrows to highlight specific code sections, but unfortunately the listing itself is much less readable (and zooming into the picture doesn’t seem to help).
Conclusions
Overall, I can say I am pretty much satisfied with the Kindle DX. I cannot say how it compares to a tablet (be it the iPad2 or any of Android tablets that are popping out recently), since I don’t have one, so this is not yet another “Kindle vs iPad” post (I am sure your favorite search engine can help you there).
I wanted a device optimized for reading (with as few distractions as possible) and Kindle DX delivered as expected. The battery lasts weeks and weeks if you turn 3G off when you don’t need it, so you can be assured that even on a long travel you don’t risk to run out of batteries. I only have a few wishes I hope Amazon will consider for next versions:
- A complete tree-like folder structure. Right now you can only have one level of folders to structure all of your digital content. I am bit compulsive when it comes to organizing my files, so I would like to have the freedom to create any reasonable folder structure as I see fit.
- Wi-fi (as found for example in the Kindle 3) would simplify downloading content from your PC without resorting to the micro-USB cable. This would be especially useful for items downloaded from the net (technical papers, Prag Prog magazine issues, etc.).
- Touch UI. Although I don’t use the internal dictionary too often for technical documents, I surely have to when reading some fiction (Gulliver’s Travels had a lot of weird words!
) Being able to simply touch a word instead of moving the cursor to it through the page would certainly save seconds.
It was exactly 2 years ago.
I was embarking on the biggest change in my career as a software developer. Coming from about 10 years of development for Motorola, in an embedded environment, almost exclusively based on a closed proprietary OS, almost exclusively in a procedural language (C), I was moving to a modern VM-based environment (.NET), using an object oriented programming language (C#) always on the move (C# 3.0 had just been released), in a small sized company. I have learned a lot in these past two years in ORS, having the pleasure to work with a bunch of very talented developers, where I could practice being the worst on several occasions.
Now, after two years, it's time for a new journey: I have recently joined Deltatre, a fast growing company in the sport IT business that is behind many big sport web sites (think uefa.com or fifa.com). I will be part of the core infrastructure team, reporting to the chief software architect, helping shaping the engine that delivers match events to a group of diverse client applications.
Not only is this a very exciting professional opportunity, but luckily enough the office is located at a walking distance from my home (I have literally reduced my commuting time by more than one order of magnitude!). This will leave me more time for my family, and I especially look forward to spending more time with my two kids.
Photo by chiaralily.
Go to Part 1
Controlling the Life Cycle of your Objects
In the previous post we did not concern ourselves with the lifecycle of the object returned from Ninject kernel. Ninject provides the following 4 built-in lifecycles (scopes):
- Transient (default)
- Singleton (only one instance)
- Thread (one instance per thread)
- Request (one instance per web request).
You can create custom scopes if needed.
Singleton:
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<ITaxCalculator>()
.To<TaxCalculator>()
.InSingletonScope()
.WithConstructorArgument("rate", .2M);
var tc1 = kernel.Get<ITaxCalculator>();
var tc2 = kernel.Get<ITaxCalculator>();
Assert.Same(tc1, tc2);
}
Transient:
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<ITaxCalculator>()
.To<TaxCalculator>()
.InTransientScope()
.WithConstructorArgument("rate", .2M);
var tc1 = kernel.Get<ITaxCalculator>();
var tc2 = kernel.Get<ITaxCalculator>();
Assert.NotSame(tc1, tc2);
}
More Details on Injection Patterns
With Ninject you can inject:
- Constructor parameters
- Properties
- Methods
Before considering each one in turn, we just need to introduce the [Inject] attribute which may be used to tag constructors, properties and methods requiring injection. Obviously, by tagging constructors, properties or methods, your objects cease to be POCOs.
Constructor Injection
We have already seen an example of constructor injection in Part I when the kernel auto-magically injected an implementation of ITaxCalculator to the Sale Area constructor. In that case, even if we didn't tag the constructor with the [Inject] attribute, the kernel was able to perform the required binding. How?
That was actually a special case: when there is only one constructor available, the tagging is not needed. On the other hand, if there's more than one constructor defined, then then kernel can inject a dependency to only one constructor that needs to have the [Inject] attribute:
public class Sale3
{
private readonly ITaxCalculator taxCalculator;
public Sale3() { }
[Inject]
public Sale3(ITaxCalculator taxCalculator)
{
this.taxCalculator = taxCalculator;
}
// other stuff
}
Properties Injection
Instead of passing in the dependencies through the constructor, you can also inject them as properties. Injecting properties is pretty straightforward:
public class Sale2
{
[Inject]
public ITaxCalculator TaxCalculator { get; set; }
// implicit default constructor and other stuff...
public decimal GetTotal()
{
decimal total = 0M;
foreach (var item in lineItems)
{
total += TaxCalculator.CalculateTax(item.TotalPrice)
+ item.TotalPrice;
}
return total;
}
}
Usage (note that we never explicitely set the TaxCalculator):
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<ITaxCalculator>()
.To<TaxcCalculator>()
.WithConstructorArgument("rate", .2M);
var lineItem1 = new SaleLineItem("Gone with the wind", 10M, 1);
var lineItem2 = new SaleLineItem("Casablanca", 5M, 2);
var sale = kernel.Get<Sale2>(); // property injection!
sale.AddItem(lineItem1);
sale.AddItem(lineItem2);
Assert.Equal(24M, sale.GetTotal());
}
There's an important caveat: if you have 2 or more properties injected, the order in which each dependency is injected is not predictable. This might complicate your design, if those dependencies are coupled somehow (e.g. dependency A needs dependency B). For this kind of situations, constructor or method injection is usually preferred.
Methods Injection
Finally, it’s also possible to tag methods for injection. As with constructor parameters, it’s possible to inject more than one value at once.
public class Sale4
{
private ITaxCalculator taxCalculator;
// other stuff
// method injection, will be called by the kernel
[Inject]
public void SetTaxCalculator(ITaxCalculator taxCalculator)
{
this.taxCalculator = taxCalculator;
}
public decimal GetTotal()
{
decimal total = 0M;
foreach (var item in lineItems)
{
total += taxCalculator.CalculateTax(item.TotalPrice)
+ item.TotalPrice;
}
return total;
}
}
Usage (note that we never explicitely call the SetTaxCalculator):
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<ITaxCalculator>()
.To<TaxCalculator>()
.WithConstructorArgument("rate", .2M);
var lineItem1 = new SaleLineItem("Gone with the wind", 10M, 1);
var lineItem2 = new SaleLineItem("Casablanca", 5M, 2);
var sale = kernel.Get<Sale4>(); // method injection!
sale.AddItem(lineItem1);
sale.AddItem(lineItem2);
Assert.Equal(24M, sale.GetTotal());
}
Go to Part 1










