Does anyone have a good analogy for dependency injection? [closed] - dependency-injection

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I have read a lot of articles on Dependency Injection as well as watched a lot of videos, but I still can't get my head around it. Does anyone have a good analogy to explain it?
I watched the first part of the Autumn of Agile screencast and still was a little confused.

Analogy? I'll give it a whack... Your CD Player stereo is useless without a CD with music on it... (It's dependent on the CD). If they built CD Players with the CD already in it, it would get boring very quickly...
So they build them so you can "inject" the CD, (on which it is dependent) into the player. That way you can inject a different one each time, and get "different" behavior (music) dependent on which one you inject.
The only requirement is that the CD must be compatible with the interface defined by the player. (You can't play a blue-ray disk in a 1992 CD player.)

The best analogy I can think of is that of hiring a mechanic.
Without dependency injection, you hire a mechanic and the mechanic brings his own tools. He may have lousy tools, he may have great tools, he may be using a pipe wrench when he should be using a socket. You don't know, and may not care, so long as he gets the work done.
With dependency injection, you hire a mechanic and you provide him with the tools that you want him to do his work with. You get to choose what you consider to be the best or most appropriate tools for the work you are hiring him to do.

Think of it as a realisation of the "Inversion of Control" pattern. I guess, your problem is, you are so used to it, you don't realize it's that simple.
Let's start at the beginning.
In the early days programs followed a given path through the code. The order of the called functions was given by the programmer.
In interactive programs, e.g. mostly ANY program, you can not say, which function is called at what time. Just look at a GUI or website. You can not say, at what time what button or link is clicked. So the "control" of what's happening is no longer at the program, it's at an outer source. The "control" has been inverted. The function is no longer "acting" it is instead "listening". Think of the hollywood principle: "Don't call us, we call you". A listener is a good example for a realisation of this pattern.
IoC is realized by functions or "methods" in the "object oriented world" of today.
"Dependency Injection" now means the same, but not for "methods", which do something, but for "objects", which hold data.
The data is no longer part of the object holding it. It is "injected" into the object at runtime. To stay in hollywood, think of a film star, playing golf to talk about the business, but to keep in shape, she hungers herself down, minimizing her muscle weight and therefore she is only able to carry one club at a time.
So, on the golf course her game would heavily depend on the one club, she is carrying.
Lucky for her, there are caddies, carrying a whole lot of clubs at one time, and also having the knowledge what club to use at what time. Now she is independent of her limited possibility to carry golf clubs. "Don't think about a concrete club to wear, we know them all and give you the right one at the right time".
The film star is the object and the golf clubs are the members of the object. That's dependency injection.

Maybe focus on the "injection" part? When I see that term, I think of syringes. The process of pushing the dependencies of a component to the component can be thought of as injecting into the component.
Just like with the body, when there is something that it needs in the way of medicine (a component that it needs) you can inject it into the body.

In their 2003 JavaPolis presentation (slides), Jon Tirsén & Aslak Hellesøy had an amusing analogy with a Girl object that needs a Boy to kiss. I seem to remember that the BoyFactory is sometimes known as a 'nightclub', but that's not in the slides.

Another analogy: let us say you are a developer and whenever you like you order computer science books from the market directly - you know the sellers and their prices. In fact your company might have a preferred seller and you contact them directly. All this works fine but may be a new seller is now offering better prices and your company wants to change the 'preferred' seller.
At this point you have to make the following changes - update the contact details (and other stuff) so as to use the new seller. You still place the order directly.
Now consider we introduce a new step in between, there is a 'library' officer in the company and you have to go through him to get the books. While there is a new dependency, you are now immune to any changes to the seller: either the seller changes mode of payment or the seller himself is changed, you now simply put an order to the librarian and he gets the books for you.

From Head First Design Patterns:
Remember, code should be closed (to change) like the lotus flower in the evening, yet open (to extension) like the lotus flower in the morning
A DI-enabled object can be configured by injecting behaviors defined in other classes. The original object structure doesn't have change in order to create many variations. The injection can be made explicit by having a class request other worker-classes in its constructor, or it can be less obvious when using monkeypatching in dynamic languages like Python.
Using an analogy of a Person class, you can take a basic human framework, pass it a set of organs, and watch it evolve. The Person doesn't directly know how the organs work, but their behaviors confirm to an expected interface and influence the owner's physical and mental manifestation.

A magician's sleight of hand! What you may think you see may be secretly manipulated or replaced.

Life is full of dependency injection analogies:
printer - cartridge
digital device - battery
letter - stamp
musician - instrument
bus - driver
sickness - pill

The essence of Inversion of Control (of which Dependency Injection is an implementation) is the separation of the use of an object from the management thereof.
The analogy/example I use is an engine. An engine requires fuel to run, i.e. it is depdendent on fuel. However, the engine cannot be responsible for the fuel it needs. It just 'asks' for fuel, and it is provided (typically by a fuel pump in a car).
The analogy starts breaking down when you look too deep, in that an engine doesn't ask for fuel, it is given it by some kind of management element, like an ECU. One might be able to compare the ECU to a container but I'm not certain how valid this is.

Your project manager asks you to write an app.
You could just write some code based on your career experience so far, but it's unlikely to be what your PM wants.
Better would be if your PM dependency injected you with say a spec for the app. Now your code is going to be related to the spec he gives you.
Better if you were told where the source repository was.
Better if you were told what the tech platform was.
Better if you were told when this needed to be done by.
Etc..

I think a great analogy is a six-year-old with a lego set.
You want your objects to be like the lego bricks. Each one is independent of all the others, and yet offers a clear interface for connecting them to the others. When connecting them together, it doesn't really matter exactly which two bricks you hook together so long as they have a matching interface.
Your dependency injection framework is like the six-year-old. He follows the instructions (i.e., your config file, annotations, etc.) to connect specific bricks together in certain ways to make a particular model.
Of course, since the bricks' interfaces are pretty generalized, they can go together in lots of different ways, so it's easy to come up with new sets of instructions which the six-year-old can use to make a completely different model out of the same bricks.

Related

Interviewer asks: "What's the value of dependency injection?" [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is dependency injection?
I respond: "You don't need to use the new operator."
Interviewer's response: "<SIGH>. That's it?"
That's all I could come up with.
What would have been a more correct response if that is not correct?
It decouples a component from its external dependencies (e.g. other libraries, databases, etc.) allowing you to easily change them - even at runtime.
This can (for example) be useful in automated testing as you can inject mock objects via the public API.
Dependency injection decouples classes from the services they depend on, allowing you to register a set of services once and use them throughout your codebase.
This allows you to switch implementations non-intrusively, especially if the implementations are unit-tested.
It also allows you to put different service implementations with the same classes for different use-cases, such as web vs. GUI vs. testing.
The wikipedia article is a good reference: http://en.wikipedia.org/wiki/Dependency_injection.
Mainly, it reduces coupling and eases testing. You can conveniently unit test the class just by feeding it a mock instead of the real class. It's a good question in interviews to see if the candidate is familiar with TDD good practises.
Rather than thinking in terms of the words "dependency injection", think "list of factories". To use a real-world example, think of a catalog supply firm with thousands of different products. It would like to use a common scheme for keeping objects in inventory and reordering them when empty. It would be hard to run such a business if every product had its own independent means of ordering, and there had to be one person who knew how to order every product. That's not how businesses operate, however. Instead, there will be a file which contains for each product the information and procedures necessary to order it. Many products would use the same procedures, but a few products might require special procedures (e.g. call 815-555-6666 between 2pm and 3pm, ask for Steve, and ask him for widgets with blue end-caps, since the company normally puts on yellow end-caps).
Think of dependency injection as being the ability to include procurement instructions within the list of product types. Think of how smoothly the catalog firm can run with such ability, and how awkward it would be to have a firm of any size without it.
PS--"Dependency injection", like "Resource Allocation Is Initialization", is a phrase I dislike because its practical meaning has little to do with the words that comprise it. Most uses of DI don't seem to have much to do with "dependency", nor with "injecting" anything. I think "list of factories" is a word longer (but syllable shorter) and conveys the meaning much better. Incidentally, for RIAA, I'd substitute "object lifetime matches object scope".

Things you look for when trying to understand new software

I wonder what sort of things you look for when you start working on an existing, but new to you, system? Let's say that the system is quite big (whatever it means to you).
Some of the things that were identified are:
Where is a particular subroutine or procedure invoked?
What are the arguments, results and predicates of a particular function?
How does the flow of control reach a particular location?
Where is a particular variable set, used or queried?
Where is a particular variable declared?
Where is a particular data object accessed, i.e. created, read, updated or deleted?
What are the inputs and outputs of a particular module?
But if you look for something more specific or any of the above questions is particularly important to you please share it with us :)
I'm particularly interested in something that could be extracted in dynamic analysis/execution.
I like to use a "use case" approach:
First, I ask myself "what's this software's purpose?": I try to identify how users are going to interact with the application;
Once I have some "use case", I try to understand what are the objects that are more involved and how they interact with other objects.
Once I did this, I draw a UML-type diagram that describe what I've just learned for further reference. What happens after depends on the task I've been assigned, i.e. modify the code, document the code etc.
There is the question of what motivation do I have for learning the new system:
Bug fix/minor enhancement - In this case, I may focus solely on that portion of the system that performs a specific function that needs to be altered. This is a way to break down a huge system but also is a way to identify if the issue is something I can fix or if it is something that I have to hand to the off-the-shelf company whose software we are using,e.g. a CRM, CMS, or ERP system can be a customized off-the-shelf system so there are many pieces to it.
Project work - This would be the other case and is where I'd probably try to build myself a view from 30,000 feet or so to know what are the high-level components and which areas of the system does the project impact. An example of this is where I'd join a company and work off of an existing code base but I don't have the luxury of having the small focus like in the previous case. Part of that view is to look for any patterns in the code in terms of naming conventions, project structure, etc. as this may be useful once I start changing some code in the system. I'd probably do some tracing through the system and try to see where are the uglier parts of the code. By uglier I mean those parts that are kludge-like and may have some spaghetti code as this was rushed when first written and is now being reworked heavily.
To my mind another way to view this is the question of whether I'm going to be spending days or weeks wrapping my head around a system like in the second case or should this be a case where it hopefully takes only a few hours, optimistically that is, to get my footing to make the necessary changes.

Building core shop framework in Rails. Suitable or not?

I work at an in-house IT department for company running 10 or so only shops of varying complexity. The shops code has been written over the last 8 years, each shop a new branch growing father and father away from the stem (I guess that makes it a bush?)
The need for more and more complex discounts, campaigns and user monitoring are growing rapidly - and changing rapidly as well (you never know what they come up with). So we have decided to write a new system from scratch and bring the different shops back together having them run on the same core code. We have considered .NET, but due to the fact that the design requirements change so fast we have more or less decided to give Rails a try. But we have some uncertainties/questions about rails.
Is Rails (stack) suitable to run to build a shop framework and who should this be organized?
We are running around 10 shops of which some are very much alike only differing in style, where others stands out in functionality, flow and content. But behind the business logic is all the same. The shops functionality is to a great extend the same as well. As an example the checkout page of one shop might display great details about VAT, discounts, P&P, etc. where as another might only show the necessary minimum.
Which approach would you take? Would you build and maintain a runable template shop with a functional superset of the shops. As new functionality is developed then merge the code with the other shops? Sounds a bit cumbersome.
In the example with the checkout page the views would differ from shop to shop, but the controllers and the models would remain the same, as long as you externalize configurations, like payment method types, and so on.
From this perspective it would make more sense just to create a repository of the views and configurations for each shop and then maintain model and controller code in a separate repository.
Would be possible to arrange the views according to shop, keeping all resources in one repositoary /views/shopname/Product. Would this make sense?
What do you think? how would you do this? Will working with rails in this way bring to much trouble?
Our campaign/discount system is growing steadily complex, both GUI and business logic. (in this view Rails seems interesting with its fast turnaround). Our discounts are property based and these properties are stored in a database row.
Making changes in the requirements to the workings of a discount is a real headache. So we are slowly replacing this property based system with a system that for each discount attaches a class (PHP) and a configuration so that each discount type has its own class and each utilization of such discount could specify some values for this class to operate on given current context (basically: what is in the basket)
In rails what approach would you take?
In rails you can easily extend your model (discount) with yet another property, migrate and you are ready (maybe a bit simplified). Could you write a base discount class that relied on a few basic properties and then write modules that hook into (extends) this class in case you need more advanced functionality?
Specifically what would this be in Rails terms a helper?
Some of this post might be a bit unclear. Please do ask questions. Also I'm in the process of learning Rails so please excuse me if don't use the right terms or if I've missed some of the main ideas of Rails.
Thanks
Michael
Is Rails (stack) suitable to run to
build a shop framework and how should
this be organized?
Sure, it can be suitable see:
http://www.shopify.com/
http://www.liquidmarkup.org/
I would not recommend it as a first project though.
Dont forget Spree Commerce as a viable solution that may or not suid your needs. On the other hand, if you want to roll your own solution, also check ActiveMerchant for payment gateway integration.

Difference between BPM and App. workflow?

I know there is a lot of talk about BPM these days and I am conscious that some may see it to be a craze rather than a fundamentally important piece of software.
As someone from what most would call 'The Business', I have been doing my best to learn about BPM to ensure we continue to make decisions that not only make sense to the business, but IT as well.
I have noticed while reading that mention is made to application workflow when sometimes discussing BPM. I hadn't given this much thought until recently.
Therefore, what is the difference? When would you use one and not the other?
BPM is about the process and improving it, which takes into account users and potentially more than one application,e.g. an ERP system may have more than one application to it, though there may be other uses of the term. Note that the process could be viewed without what applications or technologies are used.
Application workflow is how an application is used to go from a to b. Here it is a specific set of code that is used and what happens over the course of an application getting from a to b. In this case, the application is front and center rather than the process.
Does that provide an answer? Another way to think of it is that multiple application workflows can make up a system which is used in a process that can have BPM applied to it.
Late to the game, but workflow is to database as BPMS is to DBMS. (Convenient how the letters line up, huh?)
IOW, BPM(S) is traditionally meant to refer to a particular framework/application that allows you to manage business processes: defining them, storing them, versioning them, measuring them, etc. This is similar to how a DBMS manages databases.
Now, a workflow is a definition, much like a database is a definition. In the former case, it is a definition of operations/work (Fufill Order), steps thereof (Send Invoice) and rules/constraints on the work (If no stock, send notice). In the latter, similar case, it is a definition of data structure (CREATE TABLE) and constraints (InvoiceTotal must be > $0.00).
I think this is a potentially confusing subject, particular as some development environments use a type of process flow model to generate user facing applications (I'm thinking about Outsystems here, for example).
But, for me, the distinction is crystal clear. Application workflow, as people talk about it, refers to a user's path through an application, i.e. the pages they complete/visit, the data they enter, etc. on their way to completing a transaction of some sort. Application orkflow is a poor term for this though, I think application flow would be more meaningful.
BPM on other hand, is about modelling and executing a workflow process. By workflow, in this context, I mean a series of discrete steps (or tasks) that have to be completed (either programmatically or via human interaction) in a certain order to complete a process. These tasks can be implemented as individual application modules (each with their own "application workflow", see above). The job of the workflow engine is to make sure that these separate steps are assigned to the right people (of groups of people) in the right sequence, and that overall the process completes in an orderly way.
I don't think there's a clear answer to this at all. These are words, as opposed to theoretical concepts. If you add the word "checklist" into the mix - that just turns out to be a linear version of a process (but you can have conditionals in checklists - making them a workflow).
I am not sure how to help in reframing this question, but it's almost as if no answer can ever be possible. My own thoughts are at https://tallyfy.com/improving-efficiency-workflow-vs-business-process-management/

When to violate YAGNI? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
The YAGNI "principle" states that you shouldn't focus on providing functionality before you needed as "you ain't gonna need it" anyway.
I usually tend to use common sense above any rule, no matter what but there are some times when I feel it is useful to over design or future proof something if you have good reasons, even if it's possible you'll never use it.
The actual case I have in my hands right now is more or less like this:
I've got an application that has to run over a simple proprietary communication protocol (OSI level 4). This protocol has a desirable set of characteristics (such as following NORM specification) which provide robustness to the application but which are not strictly required (UDP multicast could perform acceptable).
There's also the fact that the application is probably (but not surely) be used by other clients in the future which will not have access to the proprietary solution and, therefore, will need another solution. I know for a fact the probability of another client for the application is high.
So, what's your thinking? Should I just design for the proprietary protocol and leave the refactoring, interface extraction and so on to when I really need it or should I design now thinking for the (not so far) future?
Note: Just to be clear, I'm interested in hearing all kind of opinions to the general question (when to violate YAGNI) but I'd really like some advice or thoughts on my current dilemma :)
The reason YAGNI applies to code is that the cost of change is low. With good, well refactored code adding a feature later is normally cheap. This is different from say construction.
In the case of protocols, adding change later is usually not cheap. Old versions break, it can lead to communication failures, and an N^2 testing matrix as you have to test every version against every other version. Compare this with single codebases where new versions only have to work with themselves.
So in your case, for the protocol design, I wouldn't recommend YAGNI.
IMHO
I'd say go YAGNI first. Get it working without the NORM specification using 'the simplest thing that would work'.
Next compare if the cost of making the 'design changes' in the future is significantly greater than making the change now. Is your current solution reversible ? If you can easily make the change tomorrow or after a couple of months don't do it now. If you don't need to make an irreversible design decision now.. delay till the last responsible moment (so that you have more information to make a better decision)
To close if you know with a considerable degree of certainity that something is on the horizon and adding it later is going to be a pain, don't be an ostrich.. design for it.
e.g. I know that diagnostic logs would be needed before the product ships. Adding logging code after a month would be much more effort than adding it in today as I write each function... so this would be a case where I'd override YAGNI even though I dont need logs right now.
See-also: T. & M. Poppendieck's Lean books are better at explaining the dilemma of bullet#2 above.
Structuring your program well (abstraction, etc) isn't something that YAGNI applies to. You always want to structure your code well.
Just to clarify, I think your current predicament is due to over application of YAGNI. Structuring your code in such a way that you have a reusable library for using this protocol is just good programming practice. YAGNI does not apply.
I think that YAGNI could be inappropriate when you want to learn something :) YAGNI is good for the professionals, but not for students. When you want to learn you'll always need it.
I think it's pretty simple and obvious:
Violate YAGNI when you know that, in full certainty, You Are Going To Need It
I wouldn't worry. The fact that you aware of "YAGNI" means you are already thinking pragmatically.
I'd say, regardless of anything posted here, you are statistically more likely to come up with better code than someone who isn't analysing their practices in the same way.
I agree with Gishu and Nick.
Designing part of a protocol later often leads to thoughts like "damn, I should have done this that way, now I have to use this ugly workaround"
But it also depends on who will interface with this protocol.
If your control both ends, and that they will change of version at the same time, you can always refactor the protocol later as you would with a normal code interface.
About doing the extra protocol features implementation later, I found that implementing the protocol helps a lot to validate its design, so you may at least want to do a simple out-of-production code sample to test it, if you need the design to be official.
There are some cases where it makes sense to go against the YAGNI intuition.
Here are a few:
Following programming conventions. Especially base class and interface contracts. For example, if a base class you inherit provides a GetHashCode and an Equals method, overriding Equals but not GetHashCode breaks platform-documented rules developers are supposed to follow when they override Equals. This convention should be followed even if you find that GetHashCode would not actually be called. Not overriding GetHashCode is a bug even if there is no current way to provoke it (other than a contrived test). A future version of the platform might introduce calls to GetHashCode. Or, another programmer who has looked at documentation (in this example, the platform documentation for the base class you are inheriting) might rightfully expect that your code adheres without examining your code. Another way of thinking about this is that all code and applicable documentation must be consistent, even with documentation written by others such as that provided by the platform vendor.
Supporting customization. Particularly by external developers who will not be modifying your source code. You must figure out and implement suitable extension points in your code so that these developers can implement all kinds of addon functionality that never crossed your mind. Unfortunately, it is par for the course that you will add some extensibility features that few if any external developers ultimately use. (If it is possible to discuss the extensibility requirements with all of the external developers ahead of time or use frequent development/release cycles, great, but this is not feasible for all projects.)
Assertions, debug checks, failsafes, etc. Such code is not actually needed for your application to work correctly, but it will help make sure that your code works properly now and in the future when revisions are made.

Resources