views:

457

answers:

5

I'd like to adhere to the Don't-Repeat-Yourself principle, but sometimes when I write PHP together with HTML and CSS, if I re-use the same code for different situations, my code soon will have so many if-then-else that the code is not easily maintainable.

This may be a bigger issue if Smarty, the templating engine is used, because most code editor won't match up {if} {else} {/if} So the programmer needs to look for the matching tag visually, and is not easy when there are 3 or 4 levels of nested {if} {else} {/if}.

In such situation, is there a way to stick to DRY, but still have good maintainable code?

+2  A: 

Short of a full framework, what I tend to do for content (even if it contains logic) is separate it out into files and use another logical evaluation to merge them together (mangle them) and then evaluate the templating logic after that. This chunkifies your content and makes chunks sharable / reusable on common state.

This way each final template buffer is a flattened tree of discrete re-usable content nuggets that you can store on disk or a database. Even something as simple as a little parser that replaces:

<h1>{{insert:shared_page_header}}</h1>

With shared_page_header.txt helps keep things separate. It also forces you to look at separation on concerns even in the logic that is embedded in your templates. Manageable, reusable chunks of anything (dynamic or not) are always the way to go. Your templates are just strings until evaluated, so treat them as shared components merged into a big-dirty-string(TM) and then evaluated.

Good Luck

Aiden Bell
I like the idea of a tree style setup for caching.
Ballsacian1
@Ballsacian1 - I have a Python file that is about 200 lines that I use for string-tree flattening and caching of static subtrees. Always handy!
Aiden Bell
A: 

The first sentence of your question is the problem, IMO. You really shouldn't be mixing code with your view (i.e. HTML and CSS). There are several PHP MVC frameworks that will help you not do this. The Zend framework is pretty decent but there are others as well.

If you don't want to use a framework, then I'd suggest refactoring your pages to not use code like this and call objects on the back end. Mixing your code and view quickly becomes unmaintainable in any language, not just PHP.

Alex Beardsley
even separating the HTML and CSS into templating, the situation still occurs: too many if-then-else nested. and the Smarty if-then-else is even harder to read and match up.
動靜能量
A: 

Now I may not be that familiar with implementing OOP concepts using PHP, but refactoring those nested if-else statements and placing them in a well-named function helps a lot in keeping up with the DRY principle. And besides, sticking with the DRY principle does make your code maintainable.

Julson Lim
A: 

With an example script file it would be a lot easier for us to point out where you are going wrong, however some things which may or may not help you depending on what you are trying to achieve:

  • Taking a look at alternative syntax for control structures. Some people prefer to use this style when writing files which mainly contain HTML, with PHP being used only to decide which HTML sections to output.

  • Split up the reusable sections of code into files which you can later include, ie. header.php, footer.php etc.

  • Using an IDE which supports code folding

Good luck

Gerry
+1  A: 

Just so we have more info... What program are you using to write your code?

Tips for not repeating yourself:

Use some sort of templates. Doing this keeps you from having to repeat code for displaying content in each of your pages. I.E. If you have a site with 20 pages and you decide to change your layout, you don't want to have to go through and then change all 20 of your pages.

Use functions. If you have code that performs a specific task, DON'T write that code multiple times throughout your program/page. Create a function and then call it in each spot where you need that task performed. That way if you need to make a change you just modify that one function and don't have to search through your code to find every place that you performed that task. If you know about classes & methods (a method is a function in a class), for many tasks, this is even better as it provides you with data encapsulation and allows you to group related functions together so that you can include the class in future projects as needed.

If you are having difficulty with lots of if/else statements and code not being very readable there are a few things you can do:

1. Consider trying a new editor. Code folding is a must. Some editors also have vertical lines that highlight and match up indented code so you know what goes with what. If you want a decent free editor, I would recommend Notepad++ as it has both these features (just google it, I can't add links here).

2. There are techniques you can use to reduce the number of nested if statements that you have...

Example (this code):

if (item1 == true) {
   if (item2 == true) {
      item3 = 5;
   }
   else {
      item3 = 10;
   }
}
else {
   if (item2 == true) {
      item3 = 15;
   }
   else {
      item3 = 20;
   }
}

Can also be flattened out into:

if (item1 == true && item2 == true) {
   item3 = 5;
}
else if (item1 == true && item2 == false) {
   item3 = 10;
}
else if (item1 == false && item2 == true) {
   item3 = 15;
}
else {
   item3 = 20;
}

So if you have 3 or 4 levels of nested if/elses and you want to flatten them out, you may find your code more readable to use multiple arguments such as above. It does the same thing, it's just a matter of preference for which way you do it.

Try and not mix your logic (I'm assuming PHP) and your display (I'm assuming HTML/CSS). This is not always easy to do, but using templates and css, it is possible. Let me give you a practical example of how you can do this on a home page that displays a users name as a welcome message.

Inline PHP (try to avoid):

<html>
   <body>
      <?php
      if ($logged_in == true) {
         echo "Welcome ",$user->name(),"!";
      }
      else {
         echo "Welcome Guest!";
      }
      ?>
   </body>
</html>

Logic separate from display (better):

<?php
if ($logged_in == true) {
   $greetingMessage = "Welcome ",$user->name(),"!";
}
else {
   $greetingMessage = "Welcome Guest!";
}
?>

<html>
   <body>
      <?php echo $greetingMessage; ?>
   </body>
</html>

^ Keeping your logic separate from your view (HTML) will help you not get overwhelmed when your project starts getting really complex. It's best just not to mix! :)

Good luck man!

Joe Bubna