As the first step in the decommissioning of sasCommunity.org the site has been converted to read-only mode.


Here are some tips for How to share your SAS knowledge with your professional network.


Difference between revisions of "Macro Programming Best Practices: Styles, Guidelines and Conventions Including the Rationale Behind Them"

From sasCommunity
Jump to: navigation, search
(Macro Storage)
(Pointing to Where Macros are Stored)
Line 106: Line 106:
  
 
I use autocall libraries, one for general macros, one for project specific macros. --[[User:John Hendrickx|John Hendrickx]] 08:48, 11 January 2012 (EST)
 
I use autocall libraries, one for general macros, one for project specific macros. --[[User:John Hendrickx|John Hendrickx]] 08:48, 11 January 2012 (EST)
 +
 +
During development I always use %include and normally leave it that way.  If I make a change to the macro I don't need to restart SAS for the changes to be reflected.  I also like having the filepath and filename to the specific macro I use explicitly stated in the program.  It makes it clear which version I'm using.  --[[User:Spjcdc|Steve]] 12:09, 11 January 2012 (EST)
  
 
== Defining Macros Inside other Macros  ==
 
== Defining Macros Inside other Macros  ==

Revision as of 12:09, 11 January 2012

Abstract

Coding in the SAS Macro Language can be a rich and rewarding experience. The complexity of the language allows for multiple solutions to many programming situations. But which solution is best, is there even a best solution, and how do you decide? Should you choose a technique based on ease of programming or because of the efficiency of the solution? What is the best practice for laying out your code, selecting your statements, and organizing the way you use the symbol tables?

Learn about macro language programming styles, guidelines and conventions and why they are important. Since not everyone always agrees on programming practices, this article focuses on the rationales behind the techniques so you can make an informed choice based on your environment.

This article is intended to be living paper (the PDF in the proceedings will point here).

  • You can Sugest a Best Practice Topic for Discussion. Make sure to fill in the Subject/Headline field with your topic and optionally provide some detail in the text box that follows.
  • Comment on an existing topic by clicking the edit link next to.

And don't forget to to use the signature button to sign your comments.

The presenters/authors, Don Henderson and Art Carpenter look forward to a lively discussion on this important topic.

Named vs Positional Parameters

How should a macro developer decide on the use of named vs positional parameters? --Don Henderson 13:07, 8 January 2012 (EST)

Here's my humble opinion: If a parameter will almost always default to a specific value, make it a named parameter, otherwise make it positional. That way one can take advantage of the ability to assign that parameter to a default value when designing the macro. --Otterm1 18:10, 10 January 2012 (EST)

Personally, I always use Keyword Parameters. Keyword Parameters allow for a true default value for parameter used by the macro, can be used in any order and finally allow for tracing back what was enetered as values for what parameter (think debugging). I have seen way to many people in way too many shops try to use positional parameters, what happens is a big boone doggle as the macro calls become unreadable and people forget what parameter should go where and what value was passed to what parameter. What should have taken them 5 minutes to debug takes them half a day or longer. I do beleive that Ian Whitlock once showed an example where one had to use positional parameters on SAS-L, however, I would caveat this with it was an extreme case and one that 99.9999% of the SAS community would ever need to do. --User:TobyDunn 18:43, 10 January 2012 (EST)

In general I prefer keyword parameters. They make the macro call easier to understand and if there are many parameters then keyword parameters will avoid a lot of confusion. But if there are only one or two parameters, I'll often switch to positional parameters. Less typing, easier to understand.--John Hendrickx 08:38, 11 January 2012 (EST)

  1. named is The Way To Go for the following reasons:
  • one positional parameter is ok, in an in-program macro.
    • Two? name them. ... because sooner any good-enough macro gets moved out of the MyProgram into MyProject folder for use by other project programs, then TheWord gets out and the macro is on its way to the site sasautos folder, and Documentation had better be good, by then.
    • following this idea, the macro name has to be explanatory of the value passed to it, as well as the result returned.
    •  %macro Do_This(zq);
    •  %macro Attribute_X_of(entity);
  • named parameters == documentation, no need to find the macro definition.

--macro maven == the radical programmer 09:27, 11 January 2012 (EST)

Local vs Global Macro Variables

A common perception is that creating global macro variables inside of macros should be avoided. But is that true or even practical? --Don Henderson 13:12, 8 January 2012 (EST)

In my own work I like to delete things from the SAS environment as soon as they are no longer needed. So, if a macro variable is not needed outside of the macro, I would try to make it local. --Otterm1 18:19, 10 January 2012 (EST)

Its both true and practical, its called information hiding. A Macro shouldn't be dependent on a Global macro whose value isnt passed in via a parameter nor and part of the rest of the code outside of the macro be dependent on a global macro being created inside of the macro. In short it almost always leads to "speghetti code with macro sauce", and it in my opinion it shows sloppy coding standards. --User:TobyDunn 18:47, 10 January 2012 (EST)

I agree that global macro variables should be used sparingly. But sometimes they're practical so why avoid them? For example, I wrote a macro that will create a set of order statements for a SAS/Graph axis statement to let a set of graphs all have the same range. The output is a set of global macro variables. I could have achieved this by writing a macro that would define the axis statements but that would have meant adding more options corresponding with axis statement options and that would have resulted in spaghetti code. --John Hendrickx 08:45, 11 January 2012 (EST)

Always suffixing a macro variable reference with a period/dot (.)

Some macro developers like to always follow a macro variable reference with a dot, e.g., &myMacVar. instead of &myMacVar. But is that a good idea? --Don Henderson 13:20, 8 January 2012 (EST)

It's an extra keystrok most of the time. I would also mention that if one only uses a dot to end a macro variable reference when they are only going to immediatly follow it by more text it is easier to find errors when you screw something up. --User:TobyDunn 18:51, 10 January 2012 (EST)

There are three items where it is necessary:

  • FileName.ext
    •  %let Filename = X;
    • infile &Filename..txt;
  • libref.datasetname
    •  %let libref = Work;
    •  %let libref = Library;
    • DATA &Libref..MyData;
  • format.
    •  %let format = YN;
    • NewVar = put(OldVar,&Format..);

All other use is to remember, to have a good habit, when you get to any one of those three head-bangers where it is absolutely necessary. --macro maven == the radical programmer 07:24, 11 January 2012 (EST)

Macro Storage

Where should macros be stored/saved?

  • In a defined autocall directory?
  • In a program that uses them?
  • Should multiple macros be defined in a single file?

There likely isn't one answer that fits every scenario. --Don Henderson 13:18, 8 January 2012 (EST)


I use a AutoCall directory, however I am not adverse to a in the program if there arent too many other wise it clutters up the program. I do not think and have no seen a shop who has successfully implemented a way of holding all their macros in one files. What happens is every program any one writes at the shop always %Includes the one base macro file. FIrst in inefficient to compile all those macros when you only may need one or two of them, secondly its inefficient when you have someone else looking over or maintaining the code and nary a single macro is used but they are included in the program. --User:TobyDunn 18:47, 10 January 2012 (EST)

  • multiple macros in a single file?

see C:\Program Files\SASHome\SASFoundation\9.3\core\sasmacro\annomac.sas which contains 40 macro definitions. My opionion is there is no good nor bad about many macros are in a single file; when we write a suite of tools that are provided for a task, simple is better, and specific is good, too.

NOTE: that none of those 40 macros are nested.

--macro maven == the radical programmer 09:32, 11 January 2012 (EST)

Pointing to Where Macros are Stored

How do you make sure your programs can find the macros it uses? Autocall vs %include? --Don Henderson 13:20, 8 January 2012 (EST)

I doubt it makes much a difference either way, my personal preference is with AutoCall. To me it always makes the code look cleaner, which the look and feel of the code goes a long way in peoples ability to understand what you created. --User:TobyDunn 18:53, 10 January 2012 (EST)

Make it easy on yourself and your maintenance: use autocall.

see also: SASautos_Companion_Reusing_Macros

--macro maven == the radical programmer 07:28, 11 January 2012 (EST)

I use autocall libraries, one for general macros, one for project specific macros. --John Hendrickx 08:48, 11 January 2012 (EST)

During development I always use %include and normally leave it that way. If I make a change to the macro I don't need to restart SAS for the changes to be reflected. I also like having the filepath and filename to the specific macro I use explicitly stated in the program. It makes it clear which version I'm using. --Steve 12:09, 11 January 2012 (EST)

Defining Macros Inside other Macros

Many programmers with a background in procedural programming (e.g., using routines and subroutines), define macro systems by defining macros inside other macros. Is this a good idea? --Don Henderson 13:23, 8 January 2012 (EST)

This is never a good idea, it forced the inner macros to always get redefined with each call of the outer macro. Aside from the inefficiencies it also makes it reading, understanding, and debugging code a nightmare. Suppose Macro B is defines inside of Macro A, anyone reading and/or maintaining the code has to know that Macro B's definition is defines in Macro A. Further more if a problem arises they have to change the definition for macro A as well Macro B just to change how Macro B functions. Anyone doing this has no concept of cohesion and coupling in the programming world. --User:TobyDunn 18:47, 10 January 2012 (EST)

Macro "booleans"

There are no real booleans in the SAS macro language. I use keyword=yes|no and the first letter of the keyword (case insenstive). For example debug=NO together with %if %substr(%upcase(&debug),1,1) ne N %then %do;. In my opinion, debug=no is more readible than e.g. debug=1 and easy to program while still resulting in either true or false.--John Hendrickx 09:10, 11 January 2012 (EST)