Navegador de Archivos
Calendario del Blog
General
Programación
-
Métodos o atributos obsoletos
En diversas ocasiones nos encontramos con que el código que hemos escrito ya no cumple con las mejores prácticas de desarrollo o bien desde un principio decidimos solucionar una incidencia de la forma más rápida posible. Esto ocasiona que llenemos de basura el código que tanto trabajo cuesta mantener haciendo cada vez más difícil su entendimiento y sobre todo la transferencia de conocimiento.
De este tipo de escenarios es que surge el refactoring y cada que hacemos refactoring debemos cuidar que el código siga funcionando tal y como lo hacia antes. Para estos casos lo mejor es apoyarnos en herramientas que harían un gran trabajo al indicarnos automáticamente como podemos reemplazar los métodos de forma ágil, entre ellas contamos con:
Aunque por cuestiones de licencia y otros pequeños detalles, lo mejor será que tengamos buenas prácticas y el hábito de revisar nuestro código. Con la ayuda del atributo Obsolete podremos dar seguimiento a aquellos métodos que requieran un refactoring, sobre todo si estamos trabajando en un equipo de desarrollo y encontramos que uno de nosotros hizo un método al estilo:
public static void CreateActivityLog(string containerSourceId, string containerId,
string action, string sourceId, string instanceId, string docNo, string notes,
IFrameworkSecurityContext credentials, BaseSecurityDataContract secContext,
string setAction)
Nota: el ejemplo ha sido obtenido del blog de Lucas Ontivero.
Lo primero que podríamos hacer para marcar que vamos a refactorizar el método es agregando el atributo como [Obsolete], podemos hacerlo de 3 formas:
class Demo
{
[Obsolete]
public void MetodoObsoleto()
{
Console.WriteLine("Se ha invocado a MetodoObsoleto().");
}
[ObsoleteAttribute]
public void MetodoObsoletoDos()
{
Console.WriteLine("Se ha invocado a MetodoObsoletoDos().");
}
[Obsolete("No uses este método, puedes emplear la clase -nueva- ")]
public void MetodoObsoletoTres()
{
Console.WriteLine("Se ha invocado a MetodoObsoletoTres().");
}
[STAThread]
static void Main(string[] args)
{
BasicAttributeDemo attrDemo = new BasicAttributeDemo();
attrDemo.MetodoObsoleto();
attrDemo.MetodoObsoletoDos();
attrDemo.MetodoObsoletoTres();
}
}
Lo anterior manda un mensaje de aviso ("warning") al compilar el código y nos permitirá ver donde se está invocando cada método. En particular me agrada más usar el tercer ejemplo donde se utiliza un mensaje personalizado para aclarar su uso y como reemplazarlo.
También podemos agregar una bandera al atributo que nos muestre si causará un warning o un error al compilar el código, esto ayuda en equipos de desarrollo para comunicar al equipo que será reemplazado ("warning") en un futuro cercano y que deben cambiar su código. En caso de que se deba obligar al equipo a cambiarlo, solamente debemos agregar el valor de "true" y esto generará un error del compilador.
[Obsolete("No uses este método, puedes emplear la clase -nueva- ",true)]
public void MetodoObsoletoTres()
{
Console.WriteLine("Se ha invocado a MetodoObsoletoTres().");
}
Se puede obtener más información sobre refactoring en el blog de Martin Fowler y el sitio de refactoring que ha montado ya que ahí tiene un catálogo para ayudarte en la tarea.
-
Scripts XMLA ejemplos
Esto de tener que procesar constantemente cubos OLAP, ver trazas, cancelar procesos y esas cosas me ha generado algo de interés sobre que tanto puedo hacer con scripts XMLA, así que hoy se me antoja poner un pequeño resumen de lo que se puede hacer con XMLA de forma resumida y con ejemplos.
No pondré descripción de los objetos y ñoñeces que no tengo muchas ganas de escribir. =P
Primero pondré el script de como obtener información de las sesiones en la base de datos, hay que tomar en cuenta que se debe ser administrador del sistema para poder ejecutar la consulta o simplemente no te dirá nada.
<Discover xmlns="urn:schemas-microsoft-com:xml-analysis">
<RequestType>DISCOVER_SESSIONS</RequestType>
<Restrictions>
<RestrictionList xmlns="urn:schemas-microsoft-com:xml-analysis">
</RestrictionList>
</Restrictions>
<Properties>
<PropertyList>
</PropertyList>
</Properties>
</Discover>
Ahora un script para cancelar peticiones hechas al servidor, para esto es necesario conocer el session id o el connection id que proporciona el script anterior.
<!-- Cancelar proceso por Id de sesion -->
<Cancel>
<SessionID></SessionID>
<SPID></SPID>
</Cancel>
<!-- Cancelar proceso por id de conexión -->
<Cancel>
<ConnectionID></ConnectionID>
<CancelAssociated>True</CancelAssociated> <!--True: Cancela las sesiones asociadas-->
</Cancel>
Otro script útil puede ser el de limpiar la cache, para lo cual ejecutamos.
<Batch xmlns="http://schemas.microsoft.com/analysisservices/2003/engine">
<ClearCache>
<Object>
<DatabaseID>BaseDatos_Multidimensional</DatabaseID>
</Object>
</ClearCache>
</Batch>
Por útilmo pondré el script que puede interesar más, el de ejecución del cubo.
En otro post describiré que significa cada uno porque ya es hora de salir.
<Batch xmlns="http://schemas.microsoft.com/analysisservices/2003/engine">
<ErrorConfiguration>
<KeyErrorLimit>-1</KeyErrorLimit>
<KeyErrorAction>ConvertToUnknown</KeyErrorAction>
<KeyErrorLimitAction>StopLogging</KeyErrorLimitAction>
<KeyNotFound>IgnoreError</KeyNotFound>
<KeyDuplicate>IgnoreError</KeyDuplicate>
<NullKeyConvertedToUnknown>IgnoreError</NullKeyConvertedToUnknown>
<NullKeyNotAllowed>IgnoreError</NullKeyNotAllowed>
</ErrorConfiguration>
<Parallel MaxParallel="8" >
<Process xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ddl2="http://schemas.microsoft.com/analysisservices/2003/engine/2" xmlns:ddl2_2="http://schemas.microsoft.com/analysisservices/2003/engine/2/2">
<Object>
<DatabaseID>IdentificadorDeBaseDatos</DatabaseID>
<CubeID>IdentificadorDelCubo</CubeID>
</Object>
<Type>ProcessFull</Type>
<WriteBackTableCreation>UseExisting</WriteBackTableCreation>
</Process>
</Parallel>
</Batch>
-
Código con aroma de mujer
Si, eso es! ... como cualquier ejemplar de la especie humana de sexo masculino (ok, no discriminemos, igual las les, bi y hetero) que aprecie la belleza de las féminas, me declaro susceptible a la esencia de una mujer o a su perfume.
Que agradable es percibir el aroma de una mujer cuando pasa cerca de ti, cuando te saluda, te besa, se sienta a tu lado o un sin fin de sucesos que pueden despertar tu interés en el momento, si no te habías percatado de su presencia con anterioridad, en ese momento te obligue a voltear en su dirección para saber el origen del aroma.
¿Y a que viene todo ese rollo del aroma? Resulta que encontré un texto escrito por Martin Fowler que menciona un termino llamado "Olor en el código" (CodeSmells) y se me ocurrió escribir una entrada en mi blog que me permita expresar lo que pienso de un buen desarrollo de software basando mis comentarios en el texto que encontré de Fowler.
Dicen algunos amigos que suelo ser muy criticon, realmente no tengo nada que decir al respecto. Si ellos lo dicen, ha de ser verdad (me queda de consuelo que suelo ser más critico con mi persona que con los demás =P ). Así que aprovechando que critico muchas cosas (objetivamente), el código no puede ser la excepción ya que es a lo que dedicamos muchos de nosotros (informáticos) la mayor parte de nuestro tiempo.
¿Te imaginas que el código fuera tan agradable como el aroma de una mujer? Que cuando lo veas puedas decir, me gusta, quiero saber quién lo escribió, quiero conocer como decidió el autor que debía estructurarse así para que yo lo pueda leer sin pasar horas rastreando variables, métodos, instancias y artefactos fumados. Que no necesite documentación para saber que el código hace lo que debe de hacer. Que simplemente el código me susurre al oído como si quisiera seducir mis sentidos y hacerme parte de él.
Te sugiero leas el artículo de Fowler, lo tienes en inglés y español.
Se despide, /me ... disfrutando de sus problemas =). -
Cuando los Identities se revelan
Que bonito es eso de que el motor de SQL haga las cosas más comunes automáticamente, ejemplo de esto pueden ser los valores calculados, un trigger o insertar un valor numérico auto incremental, los tres son muy similares.
Sin embargo esto puede causar un dolor de cabeza si no sabemos como emplearlos, a veces necesitamos usar el identificador de un registro que apenas insertamos en una tabla desde la sesión 52 en la sesión 53 del SQL o bien puede ser útil el conocer el último identificador insertado en una tabla sin tener que hacer un max sobre el campo.
Haber, tenemos IDENT_CURRENT tal como en el SQL Server 2000 SCOPE_IDENTITY y @@IDENTITY. Las tres funciones regresan el ultimo valor generado automáticamente. Peeeeroooo, tienen un alcance de sesión que se pueden definir de la siguiente manera:
- IDENT_CURRENT Regresa el último valor generado por una tabla específica en cualquier sesión y cualquier alcance(scope).
- @@IDENTITY Regresa el último valor generado por cualquier tabla en la sesión actual en todos los alcances (scope).
- SCOPE_IDENTITY Regresa el último valor generado para cualquier tabla en la sesión actual y el alcance actual (scope).
Osea, si me explican ... entiendo! Ahora si ya todo claro =).
NOTA: cuando el valor de IDENT_CURRENT es null (porque la tabla ha sido truncada o no contiene datos), la función regresa el valor de siembra (seed), esto es el valor autoincrmental.
Ahora los ejemplos, que "hermosa weba"... para que hacerlo todo? mejor reutilizo lo que está en la ayuda de MSDN
:
Que se puede encontrar en http://msdn.microsoft.com/es-es/library/ms175098.aspx
Vale la pena darle un vistazo a :
- IDENT_SEED ( 'table_or_view' )
- IDENT_CURRENT ( 'table_or_view' )
- DBCC CHECKIDENT()
http://msdn.microsoft.com/es-es/library/ms176057.aspx -
Buscando dependencias en SQL 2005
Continuando con el tema de SQL Server 2005 del post anterior, ahora se me antoja compartir lo que me ha "liado" cuando he tenido que hacer un refactoring a una base de datos modificada sin cuidado alguno y obvio, como está hecha por seres humanos debe tener no uno, sino mucho errores.
En fin, que la idea es encontrar las dependencias de un SP o bien de una tabla, en el caso de la tabla o vista nos basta con:
Esto muestra que procedimientos llaman a la tabla.
sp_depends 'dbo.nombre_tabla'
Si por el contrario se trata de un procedimiento:
Esto nos regresaría [1]
sp_depends 'dbo.nombre_sp'
Nombre columna Tipo de Dato Descripción name nvarchar(257) Nombre del elemento para el que existe una dependencia type nvarchar(16) Tipo del elemento updated nvarchar(7) Si el elemento es actualizable selected nvarchar(8) Si el elemento es usado en un select column sysname Columna o parámetro en el que existe dependencia
Nombre Columna Tipo de Dato Descripción name nvarchar(257) Name of the item for which a dependency exists. type nvarchar(16) Type of the item.
Si existe alguna duda bien se puede tomar alguna base de datos de ejemplo como la de AdventureWorks y ejecutar lo siguiente:
Como siempre existe la posibilidad de que hayan hecho marranadas en el código, entonces podemos buscar sobre el texto de los objetos para que sea más simple la localización de elementos incluidos en scripts u objetos de la base de datos:
sp_depends uspUpdateEmployeeLogin
GO
sp_depends 'HumanResources.uspUpdateEmployeeLogin'
GO
Enjoy your code!
DECLARE _at_TextToFind AS VARCHAR(300)
SELECT _at_TextToFind = 'HumanResources.Employee'
SELECT S.Name AS [Schema], P.Name, M.definition
FROM sys.procedures P
INNER JOIN sys.schemas S ON P.schema_id = S.schema_id
INNER JOIN sys.sql_modules M ON M.object_id = P.object_id
WHERE OBJECT_DEFINITION(P.object_id) LIKE '%'+_at_TextToFind+'%'
ORDER BY S.Name, P.Name
[1] http://msdn.microsoft.com/es-es/library/ms189487.aspx
Estadísticas de visitantes









Comentarios Recientes