Pokazywanie postów oznaczonych etykietą dependency injection. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą dependency injection. Pokaż wszystkie posty

czwartek, 3 grudnia 2015

Dependency Carrying in Swift (with storyboards)


Every programmer must've struggled with Dependency Carrying, even though he might've not known that it has it's own name. Dependency Carrying is extremely uncomfortable, when you have a lot of dependencies and you have to pass them deeper through the object tree. You have to define the same code for each class in the hierarchy - there must be a different way, right ?

View Controllers are actually a great example. Let's say that you have a Navigation Controller that navigates between 20 different View Controllers. If you have a database context, a networking context, you have to inject it manually into all of the controllers. What if you have 6 or 8 dependencies ? That's a lot of copy and paste injection code. What I usually did was refactor the dependencies into an aggregate and create different interfaces for that aggregate, but there must be an easier way to manage your dependencies, right ?

Swinject

I usually avoid using any dependency frameworks, because it just seems too extreme for me to have a library in your project just for a design pattern, but maybe I was wrong ? Let's try and use a dependency injection framework and see how it solves our problem.

The only reason I decided to test this approach is because Swinject is so easy and lightweight. You don't need any configuration files and it supports storyboards, which is awesome!

Let's create a new project with a storyboard and two view controllers.


Now let's create an separate file, an extension for Swinject that will run when setting up the storyboard.


That's it! Your view controllers will now be injected with the objects you've registered. I must say that I really liked it. It's very easy, you configure everything in one file and in Swift and it works great with storyboards. The code isn't very elegant, but if you have 20 view controllers you can just use a function that will inject needed dependencies depending on the view controllers protocol.

One more awesome thing: your view controllers are ready to unit test! Well, not really in my example, because I didn't obscure concrete classes with protocols, so I can't mock, but if you do, you can register a different class configuration in your unit tests and you're ready to go!

Swinject has a lot of different features that you can leverage, so you should definitely check it out!

There's very little code (that's good!), but if you want to check out how it's all connected here's the repo.

wtorek, 24 lutego 2015

When to use dependency injection ?

Dependency injection is a great pattern that implements Inversion Of Control. I wrote about it in my first post.

Overusing a pattern is as bad as not using any architecture at all. It's called overengineering. As I mentioned before, it's hard to draw the line between no architecture and too much architecture.

How do we know when to use dependency injection and when don't ?

As mentioned here, this are great examples for when to use DI:

  • You need to inject configuration data into one or more components.
  • You need to inject the same dependency into multiple components.
  • You need to inject different implementations of the same dependency.
  • You need to inject the same implementation in different configurations.
  • You need some of the services provided by the container.

I also mentioned that creating an interface for every class just for the sake of it, might be a bad idea. It breaks RAP and YAGNI rules.

So what if we really want to use DI and play right by SOLID, but not overdo it ?

Breaking SOLID

If you stop using DI for some modules, doesn't that mean that you break the dependency inversion principle ?


"High-level modules should not depend on low-level modules. Both should depend on abstractions"


I was really confused so I sought help on StackOverflow asking:




I was lucky to get an answer from a StackOverflow veteran. You should read it carefully. It states that you should seek common behaviour from all the modules and try to extract one generic interface (an abstraction). I won't get into detail, because it's all described here in examples:

- Generic queries
- Generic commands

Should I use IoC containers ?

The opinions are mixed. IoC are great in managing dependencies but involve a lot of complexity. There are books with hundreds of pages about IoC container frameworks.

In my opinion, you should consider IoC containers only if your project is really big, with a huge dependency tree.

One great thing about IoC is resolving dependency carrying. Dependency Carrying is when you create object A at the beginning and you carry it through all dependencies just because one class needs it. 



poniedziałek, 19 stycznia 2015

Drawing clear lines in software architecture

While reading the web I've stumbled upon an interesting article "Reusable Software? Just Don't Write Generic Code" that instructed:

"Do not introduce an abstraction layer unless it is clear that you will have multiple implementations (YAGNI principle)."

This comes on strong for one important reason:
  • it explicitly tells you not to do something, which in my opinion needs strong arguments in software architecture.

Evil interfaces!


According to Jos de Jong introducing an interface for every implementation is bad because:
  • it violates YAGNI principle
    it says not to program something, just for the sake of it. Write something only if you are going to need it.
  • it violates RAP principle
    it says that adding an interface for every implementation adds "indirection and code clutter, which just makes the code harder to understand"
  • it breaks encapsulation
    it exposes external classes to internal implementation.


YAGNI is of course a good and sensible principle, but not something to be followed blindly. The RAP principle description gives you a thesis but no proof. It says that adding an interface for one implementation is bad, but doesn't tell you why - other than it might look bad. It breaks encapsulation, I agree but it's not necessarily bad, which I'll explain later.

What about unit test mocks and dependency injection ? Shouldn't we use interfaces to get these working? According to Jos: not necessarily. He says you can still inject concrete classes and test with concrete implementations, instead of mocks.

but: "
When you test that code path with the actual dependency, you are not unit testing; you are integration testing. While that's good and necessary, it isn't unit testing."

That means that if you want to unit test... you have to use mocks (just don't overuse them!)

Well, at least in some languages. In dynamically typed languages like Objective-C you can create stubs and mocks without creating a concrete class (which I strongly advise you to).

Good interfaces!


By injecting concrete classes instead of interfaces you break two of the five very important SOLID principles.

If your project will be maintained for a long time, there's going to be a huge probability that you will need a different implementation for some module you didn't expect. You're going to break the open/close principle and create a nasty code smell by going through every reference to implementation A and changing it by hand to implementation B. 

You also break the dependency inversion principle that says one should "Depend upon Abstractions. Do not depend upon concretions".

Sure, you also kind of break the YAGNI rule, but ask yourself, what the lesser of the evils here ? A question you have to ask yourself very often in programming.

Component-based software engineering

Why do we inject interfaces, instead of concretions, even though it introduces code clutter and breaks encapsulation? I've found a great explanation that's hard to argue with on Stackoverflow.

"...When we use IoC/dependency injection, we're not using OOP concepts. Admittedly we're using an OO language as the 'host', but the ideas behind IoC come from component-oriented software engineering, not OO..."

Great out of the box thinking. Of course, we're breaking OO a little bit here, but we don't care, because we're using another concept that's meta OO to have our software modularised.

Lesser evil

So we have extremely contrary points of view on software architecture. The best way out of this mess would be to find common characteristics between all of our modules and abstract their behavior into shared modules (example). You can't always do that, though.

As I said: programming is very often about choosing the lesser of two evils. It's mostly never a clear line like "this is bad", and "this is good". These are just tools, and we have to use them for the right job. How? Experience, time, and patience.




piątek, 26 grudnia 2014

Your code sucks - things you need to know about clean code and architecture

    
 Although the title is an exaggeration, all code I've seen in my (short) professional career did indeed suck. Because it's my first post, it'd be appropriate to talk about something very important to me: code quality. 


I want this post to be something of a quick collection of references for programmers on how can they recognize if their code sucks and how should they try to fix it. I'll avoid getting into details or code examples.

I'd like to say it's targeted to junior programmers, but I know for a fact that there are some senior programmers out there that didn't hear of such basic concepts as Dependency injection or Don't-Repeat-Yourself principle.

Clean up your code, would you ?

I wish I ruled the world and that's just for one selfish reason: force all programmers to read this book. If all developers followed the simple rules described in Clean Code by Robert C. Martin the IT world would be so much nicer.

It would most definitely prevent such classes as Start from being created. It's actually a pretty decent one compared to some other classes on the repo of Polish Electoral Calculator client, which is only... one of the most important programs in the country. 

There are a few basic rules a decent developer should follow:

  • Replace comments with meaningful method/variable names. 
    Code should comment itself
  • Methods should do one thing and one thing only
  • Methods should be very short 
    If a method is longer than 10-30 lines, consider dividing it into separate methods
  • Don't keep dead code - your repo is your history, not commented code
  • Don't use magic strings and magic numbers
    The only exception I use are log and error mesage strings. It would be tiresome to create a constant for every possible log.
  • If a class is very long, consider dividing it
  • Don't use snake expressions
    If one expression is long, divide it into several different expressions
  • Don't repeat yourself
    If you have two blocks of similiar looking code, it means it probably needs to be put in one method
And probably many more I missed. The point here is: if you didn't know about at least one of these rules, that's more the reason to browse through the book.

My two cents

I find comments and macros very useful when it comes to arranging insides of your file. 

I like to keep my private methods and public methods divided by comments/macros.


I also put comments before every method to put method/parameters/return information for documentation (check out automatic documentation generators for IDE you're using, to see what format to use) and put a clear sign that "this method starts here". When you open the DOOM 3 source files you immediately notice when methods start. Actually, DOOM3 source code is pretty good example of clean code, here's a good blog post about that:" The exceptional bueaty of DOOM 3`s source code".


“Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.” - Someone

Design Patterns

If you're a developer and you've never heard of design patterns, well then better hurry: click.
Even if you find out that you don't like to use design patterns, you have to know them by heart. Why? It has an undeniable advantage: it's a universal language of software architecture.

You are the architect

Your classes are your blocks, your program is your city. The bigger the city, the better architect you have to be to prevent the city from falling apart.

Architecture is a huge chunk of computer software. It's not something you learn in a short blog post. It's also unique for every programming language or kind of program. But hey, we can always cover some basics, right ?

The most basic thing you need to follow is:

 Keep your program modular (loosely coupled)

It's easier to look at a program that's just simple modules talking to each other, than a growing spaghetti monster. It's also easier to switch stuff around.

Example

Let's say you have a Client class that uses a SQLite Database object to write and read from that database. One day your project manager tells you that SQLite sucks and he wants to to write and read to a file instead.

Interface


How can we switch writing to database to writing to a file ? They seem like two very distant things. Yeah, but they have something in common, they're both writing to some local storage. Let's make an interface/protocol/abstract class LocalStorage. Make SQLiteImplementation, and FileReadWriteImplementation, conform to this interface and make the Client talk to LocalStorage object. It explains a one simple rule:



 Always separate your interface, from your concrete classes if you have more than one implementation.

It's done using a simple design pattern called Bridge, or Strategy. They're the same thing implementation-wise but have different uses. 

IoC

How can we tell the Client which implementation to use ? Doesn't the Client create his own LocalStorage objects ? Well, it does, if the code is tightly coupled. 

In a perfect scenario, something from outside tells the Client which local storage to use. It's called Inversion of Control and the most popular implementation of that principle is Dependency Injection. We inject (tell the Client) the dependencies (Client depends on the database) to the class. Which brings us to our next rule:


 Use Dependency Injection (IoC)


It makes code highly reusable, losely coupled, easy to test, plus it has a great advantage while creating Unit Tests.



A little extra: Using mocks in unit testing


How do you write unit tests for server calls? Calls to databases without actually connecting to one ? Or how do you unit test if you still haven't finished some modules ? It's easy if you're using Dependency Injection.



Let's say we want to test our Client but we don't have access to the database. Just create a class LocalStorageMockImplementation that extends the LocalStorage interface and inject that class into the Client. Now you can test your client properly. Here's a quick tutorial if you want to know more.

Let it sink in


In my opinion, these are the basics that every developer should know, before writing a single line of code. It's not a lot to take in, and by sticking to these rules, you create a readable, highly reusable, changeable code - a miracle I have yet to experience.