Practical Example of Architecture Using Ebc

Practical example of architecture using EBC?

As far as I understand the video by Uncle Bob using "EBI" (Entity, Boundary, and Interactor) you should completely decouple your business behavior/state from frameworks/OS and services.

So in case of an Rails app your business behavior/state is completly free of dependencies to the Rails framework and hence can be tested like with rspec without firing Rails!

So on the business side you have Boundary classes wich interact with the Rails side using request and response models (very simple dataholders, not to be exchanged with the usual models from Rails). Only the Boundary classes interact with the Interactor classes which implement the (business) use cases / scenarios. And only the Interactor classes interact with the Entity classes which encapsulate the business state.

On the Rails side you find Controller classes interacting with Boundary classes (using Request models) and backwards a Boundary class interacts with a Presenter (using a Response model). Only Presenters/Controllers interact with Views (with the help of models (again simple data-holders). Note that in the realm of Rails Presenters are most likely Controllers.

Where does this leave AR? Well AR just provides the persistant service. On the same level as the Presenter/Controller level you will find Service classes which provide their services to the Boundary classes. So they provide all the necessary services which are frameworks/OS/technology dependent like persistance, security, timing, notifaction, etc..

With this architecture you are really able to reuse your business logic and completely replace the UI or database technology. For example, porting to mobile (iOS, Android, Windows) should be pretty straight forward.

With Rails, your app folder could look like:

app/
controllers/ Only these interact with Boundary classes
models/ simple data-holders, no AR here! (see services)
views/
services/ AR-stuff
boundaries/ To be tested without Rails
models/ Request & Response
interactors/ use cases / scenarios, to be tested without Rails
entities/ "the real business model without technical dependencies"

With this architecture, you need to code a bit more but don't forget the benefits of a good architecture:

  1. A good architecture allows major changes to be deferred
  2. A good architecture maximizes (major) changes not made

Last note: compared to the MVC pattern, its more like the M is replaced by EBI, the C can be splitted in CP/resenter), and an S(ervice) is added. So this could be called: VCPS/EBI but that sounds ugly to me ;-) BEPVICS maybe?

@Seralize, thanks for your feedback.

Let me try to answer your questions, so far I understand them: the stuff in services are coupled to Rails. They provide the implementation for the logic in EBI side. In the usecase of security, you have to be clear what (quantified) requirements you have, so you know what logic you can implement on EBI side, for instance (business) rules about when a user(role) has access to what content(and needs to be authenticated).

This means to implement authentication will be implemented using Rails, this service will be used by EBI. This security related logic in EBI is then pretty easy to reuse in your Java GUI example. There you have only to reimplement the authentication service.

To be clear in the security example:

The EBI side has the logic: what stuff needs what kind of security and when and how. The Rails knows nothing about this, it request what to do from the EBI side and or the EBI side request the Rails side to act.

The Rails side only implements the way how to do security like asking the user to authenticate (when needed) and passing the result of this to EBI so the logic can decide what should be done next.

EBI demands both sides to be decoupled & independent. It were as you
are developing the EBI as a library with a defined API.

How to implement Blowfish algorithm in iOS

I got Paul Kocher implementation from Bruce Schneier's website. And here is how an encryption method may look like:

#define PADDING_PHRASE @"       "

#import "CryptoUtilities.h"
#import "blowfish.h"
#import "NSData+Base64Utilities.h"

@implementation CryptoUtilities

+ (NSString *)blowfishEncrypt:(NSData *)messageData usingKey:(NSData *)secretKey
{
NSMutableData *dataToEncrypt = [messageData mutableCopy];

if ([dataToEncrypt length] % 8) {
NSMutableData *emptyData = [[PADDING_PHRASE dataUsingEncoding:NSUTF8StringEncoding] mutableCopy];

emptyData.length = 8 - [dataToEncrypt length] % 8;
[dataToEncrypt appendData:emptyData];
}

// Here we have data ready to encipher
BLOWFISH_CTX ctx;
Blowfish_Init (&ctx, (unsigned char*)[secretKey bytes], [secretKey length]);

NSRange aLeftRange, aRightRange;
NSData *aLeftBox, *aRightBox;
unsigned long dl = 0, dr = 0;

for (int i = 0; i < [dataToEncrypt length]; i += 8) { // Divide data into octets...
// …and then into quartets
aLeftRange = NSMakeRange(i, 4);
aRightRange = NSMakeRange(i + 4, 4);

aLeftBox = [dataToEncrypt subdataWithRange:aLeftRange];
aRightBox = [dataToEncrypt subdataWithRange:aRightRange];

// Convert bytes into unsigned long
[aLeftBox getBytes:&dl length:sizeof(unsigned long)];
[aRightBox getBytes:&dr length:sizeof(unsigned long)];

// Encipher
Blowfish_Encrypt(&ctx, &dl, &dr);

// Put bytes back
[dataToEncrypt replaceBytesInRange:aLeftRange withBytes:&dl];
[dataToEncrypt replaceBytesInRange:aRightRange withBytes:&dr];
}

return [dataToEncrypt getBase64String];
}

I am not really good in C, but it seems that my implementation works correctly. To decrypt you need just repeat same steps, but instead of Blowfish_Encrypt you need to call Blowfish_Decrypt.

Here is a source code for that (I assume that you just decrypt the cipher text, but don't deal with padding here):

+ (NSData *)blowfishDecrypt:(NSData *)messageData usingKey:(NSData *)secretKeyData
{
NSMutableData *decryptedData = [messageData mutableCopy];

BLOWFISH_CTX ctx;
Blowfish_Init (&ctx, (unsigned char*)[secretKeyData bytes], [secretKeyData length]);

NSRange aLeftRange, aRightRange;
NSData *aLeftBox, *aRightBox;
unsigned long dl = 0, dr = 0;

for (int i = 0; i< [decryptedData length]; i += 8) { // Divide data into octets...
// …and then into quartets
aLeftRange = NSMakeRange(i, 4);
aRightRange = NSMakeRange(i + 4, 4);

aLeftBox = [decryptedData subdataWithRange:aLeftRange];
aRightBox = [decryptedData subdataWithRange:aRightRange];

// Convert bytes into unsigned long
[aLeftBox getBytes:&dl length:sizeof(unsigned long)];
[aRightBox getBytes:&dr length:sizeof(unsigned long)];

// Decipher
Blowfish_Decrypt(&ctx, &dl, &dr);

// Put bytes back
[decryptedData replaceBytesInRange:aLeftRange withBytes:&dl];
[decryptedData replaceBytesInRange:aRightRange withBytes:&dr];
}

return decryptedData;
}

You might want to return pure bytes or Base64 string. For the last case I have a category, which adds an initialiser, which initialises NSData object with Base64 string and a method, which allows to get Base64 string from NSData.

You should also think about playing with PADDING_PHRASE, for example, what if you want to add not just several spaces, but some random bytes? In this case you should send a padding length somehow.

Update: Actually, you should not use PADDING_PRASE in your process. Instead, you should use one of the standard algorithms for block ciphers described on Wikipedia page

Is it faster to count down than it is to count up?

Is it really true? and if so does anyone know why?

In ancient days, when computers were still chipped out of fused silica by hand, when 8-bit microcontrollers roamed the Earth, and when your teacher was young (or your teacher's teacher was young), there was a common machine instruction called decrement and skip if zero (DSZ). Hotshot assembly programmers used this instruction to implement loops. Later machines got fancier instructions, but there were still quite a few processors on which it was cheaper to compare something with zero than to compare with anything else. (It's true even on some modern RISC machines, like PPC or SPARC, which reserve a whole register to be always zero.)

So, if you rig your loops to compare with zero instead of N, what might happen?

  • You might save a register
  • You might get a compare instruction with a smaller binary encoding
  • If a previous instruction happens to set a flag (likely only on x86 family machines), you might not even need an explicit compare instruction

Are these differences likely to result in any measurable improvement on real programs on a modern out-of-order processor? Highly unlikely. In fact, I'd be impressed if you could show a measurable improvement even on a microbenchmark.

Summary: I smack your teacher upside the head! You shouldn't be learning obsolete pseudo-facts about how to organize loops. You should be learning that the most important thing about loops is to be sure that they terminate, produce correct answers, and are easy to read. I wish your teacher would focus on the important stuff and not mythology.



Related Topics



Leave a reply



Submit