2

With relation to what's considered good OOP engineering principles, SOLID, DRY, KISS etc I am wondering whether to complete multiple tasks within one loop when easily done.

The problem is that this conflicts with some principles (SRP), but could also partially lean in favor of others (DRY, KISS).

A simple example would be

We have a array of image file paths and we want to complete 4 overall tasks per image

get size of image
resize the image
apply a watermark to the image
apply a border to the image

This could be achieved by using one for each loop on the array, and applying each function one after the other, or we could do this with four separate foreach loops, one for getting the size, one performing a resize and so on for the other tasks.

I am trying to adhere to these principles as much as possible to remove any bad habits and improve my coding skills.

0

I beg to differ to what Creative Magic said. Unfortunately, our craft ain't easy and it is the same book that leads me to the conclusion that you should not do those 4 tasks within the loop itself, as that indeed violates the SRP.

Nevertheless, a simple change of your design satisfies all your desires: Let's start by implementing the four operations on their own, but for just one image (file). No loops, just the nitty gritty detail. Apart from maybe the first operation, all of these take an image as input, and return a slightly modified image - which as it just so happens, is the input to the next operation.

Mathematically, we call this a function composition. I don't know if there is a PHP library to directly support this, but nevertheless what you end up with is a composed function which needs to be applied to each of the images. So you have one loop with one statement and one responsibility.

As an example of how this may look like in another language, consider this pseudo code (similar to Google's guava library for Java) :

composedFunction = Functions.compose(applyBorderFunction, applyWaterMarkFunction,
                      resizeImageFunction, fileToImageFunction)
resultingImages = allMyImageFiles.transform(composedFunction)

If your language is not capable of expressing higher-order functions, then you can think of the transform call as one loop, and within that loop you may have to loop over your individual functions. Nevertheless, the responsibility of that resulting function is not implementing the individual transformations of your image, but simply applying those operations, whatever they may be.

So you end up with a clear separation of those two things: one, individual (and again properly separated) definitions of the operations you perform on your images, and two, the application of these operations.

As usual, you can find a design that is SOLID, and still DRY/KISS/whatever. It does take a lot of experience though to play around with different design options in your mind to find one that satisfies your needs.

  • There is a PHP library for composing image transformations like that called Imagine. There's example code here and on a few slides after that one. – Alex Barrett Jan 22 '14 at 11:23
  • @Frank OK this approach seems better suited, Thanks. Regarding the handling of each image(or line in the array for generalization purposes), Would you update/append the results of these operations to each key within the original array, Or would you deal with each array entry(image,line) individually up until its final requirement, a example of what I mean here would be if we have to also save the result of these operations in a database, we would also have to include a database function as an argument in your compose function. – cecilli0n Jan 22 '14 at 19:10
  • Personally, I prefer immutability, so you can stuff something in and something else pops out - no surprises attached. Writing to DB is a bit more special than transformation functions though. In particular, it has the side-effect of writing data somewhere. This warrants a separate treatment, as a composition would no longer be as transparent as when you compose side-effect free functions. – Frank Jan 23 '14 at 6:02
  • Thanks alot! I would up vote the answer but I don't have the reputation to do so. – cecilli0n Jan 24 '14 at 14:32
1

If your program is already working and a predictable result can be expected (in other words there are no bugs) you are left with two things to improve your code:

1) Optimisation - try to make your code run faster, take less memory, perform less operations etc. 2) Code readability - make your code more readable and understandable to reduce the WTF per Minute rating.

Funny thing, these two often contradict each other. To make the code more readable, you need to separate it into smaller classes, divide functions into smaller functions etc.
Optimization, on the other hand, would rather have many things stored locally to perform less calls to other classes, get some object nested in a parent object etc.

You example is interesting, because having 4 loops one after each other would make the code less readable, take more space (curly braces are often taking one line each) and perform less if the compiler wouldn't compile it as one loop anyway. In your case, PHP doesn't have a compiler, so it might actually affect performance, even if a little bit.

A simple advice would be: don't over engineer, strive to get your program working as first priority, make it readable and understandable and then optimize the bottle necks; sacrifice readability for optimization on performance critical code providing comments for that part.

A good book that helped many to understand how to be a better programmer: Clean Code: A Handbook of Agile Software Craftsmanship

  • Yes I'm sure having four loops will effect performance negatively, With regards to that book, I have been studying most of these principles from there founders. Thanks for your input. – cecilli0n Jan 22 '14 at 18:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.