Você possui sua própria biblioteca 'misc utils'? De que parte você mais se orgulha? [fechadas]


32

Sei que muitos de nós mantemos nossa pequena biblioteca pessoal com ferramentas e utilitários que usamos com freqüência.

Eu tenho o meu desde os 16 anos, então ele cresceu para um tamanho considerável. Algumas das coisas que escrevi foram adicionadas à estrutura. Eu escrevi minha própria pequena implementação de árvores de expressão para uso com algoritmos genéticos muito antes do LINQ, do qual gosto bastante e me orgulhava na época - é claro que agora é bastante inútil. Mas, recentemente, estive passando por isso e atualizando para o .NET 4.0 e reacendi o interesse.

Então, estou curioso para saber o que você usa na sua biblioteca. Talvez pudéssemos ter algumas idéias interessantes para pequenos trechos úteis e compartilhá-las entre nós.

Então, minhas perguntas são:

  • Você possui uma biblioteca de utilidades diversas?
  • De que parte você mais se orgulha e por quê?

Dê um exemplo de código, se quiser :-)


Ninguém parece ser upvoting respostas ...
Joey Adams

@Joey Adams Certo? Atualmente, existem 17 votos para perguntas e 6 votos para respostas totais .
Nicole

Não estou vendo respostas dignas de votação. O que um voto positivo significa para eles? A natureza da pergunta é tal que as respostas ficam "oh, legal". tipo de reação e, em seguida, isso é tudo ou quase nada. (E eu não gosto de votar todas as respostas, apenas porque está lá. Se nada mais, não tenho votos.: P)
Adam Lear

@Anna Lear, ok, você está dispensado :)
Nicole

3
Qualquer utilidade decente deve ser colocada no github e compartilhada com o mundo. Não faz sentido mantê-lo escondido, se for realmente bom.
Job

Respostas:


27

Não.

Eu já vi alguns efeitos de pesadelo de uma dúzia de desenvolvedores, todos adicionando suas próprias bibliotecas de estilo "util.h" a projetos e transformando-as em uma bagunça gigante de nomes e comportamentos inconsistentes de funções. Muito parecido com o PHP. Então, por esse motivo, evito fazê-lo.

Evito fazer isso usando ambientes de programação que me fornecem quase todas as ferramentas e bibliotecas necessárias sempre que possível, como C # e python.


7
Eu sempre reescrevo minha biblioteca para fins organizacionais.
Maxpm

3
Casos em que o pacote utils se transformou em pesadelo não significa que todos são ruins. Não vejo como você pode evitá-lo e não ter mais duplicação de código por causa disso. E, portanto, testes piores e menos eficiência.
Nicole

2
@ Renesis: Os pacotes utils são tão desastrosos quanto as instruções goto. Claro, por si só não é tão ruim assim, mas aparentemente sempre acaba sendo um desastre, mais cedo ou mais tarde. Quanto à duplicação de código, se você se encontra realizando alguma tarefa semelhante em praticamente todos os seus projetos, então para algo como python ou C #, outras pessoas provavelmente já o fizeram e provavelmente já está nas bibliotecas padrão.
Whatsisname

6
Na minha experiência, os engenheiros com sua própria biblioteca preferem usá-la à frente da fornecida pelo sistema, portanto, não é uma boa prática ter bibliotecas pessoais. Uma vez eu tive um cara que estava absolutamente convencido de que sua função 'strlen' era mais rápida que a fornecida pelo compilador, porque ele a escreveu . Foi necessária uma demonstração simples de como existem algumas instruções de montagem embutidas para ele admitir que talvez outras pessoas possam fazer melhor.
JBRWilkinson

4
@JBRWilkinson Seu ponto de vista é bem aceito. Nem todo programador está apto a desenvolver código comum.
Nicole

15

SmartFormat

Meu utilitário favorito é o que eu escrevi - um simples construtor / formatador de strings que facilita a transformação de dados em strings com a gramática correta.

Por exemplo, a maioria dos programadores construir texto de um modelo: "There are {0} items remaining" mas isto leva a erros gramaticais: "There are 1 items remaining".

Então, SmartFormat permite escrever: "There {0:is|are} {0} item{0:|s} remaining".

Você apenas substituir String.Format(...)com Smart.Format(...)e é isso!

O código SmartFormat é de código aberto: http://github.com/scottrippey/SmartFormat/wiki


Isso me lembra o formato usado por java.text.MessageFormat.
Barjak

@barjak Interessante! Passei muito tempo pesquisando formatação "condicional" e nunca encontrei nada parecido até agora! MessageFormattem a ChoiceFormatclasse que permite uma sintaxe surpreendentemente semelhante! Um exemplo da documentação: "There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}.". Obrigado por mencionar esta referência.
Scott Rippey

@barjak Apenas para validar meu argumento, o SmartFormat tem muitos outros recursos! A formatação condicional funciona para qualquer tipo de dados, como bool, data, intervalo de tempo e objeto; Ele também suporta operadores avançados, como "{Count:<0?negative|=5?five|>50&<100?large|other}". Ele possui reflexão (ou seja "There are {items.Length} items", pode formatar itens e intervalos de tempo da matriz. Além disso, possui um modelo de plug-in para suportar ainda mais recursos.
Scott Rippey

Parece ser poderoso, de fato. A formatação das matrizes é interessante.
Barjak

@ barjak: Sim, a formatação de array é realmente útil! Confira este exemplo: Smart.Format("There are {0.Count} files: {0:'{}'|, |, and }.", files);resultaria em "There are 3 files: 'a.txt', 'b.txt', and 'c.txt'.". Não consigo imaginar "localização" sem ele.
Scott Rippey

7

Combinador K (C #, Scala)

Eu uso o combinador K em Ruby com bastante frequência, principalmente em dobras quando a operação de dobra é realizada através de um efeito colateral ao invés de um valor de retorno, como neste exemplo:

some_collection.reduce(Hash.new(0)) {|acc, el| acc[el] += 1 }

Isso conta com que frequência cada elemento ocorre some_collection. Infelizmente, na verdade não funciona, pois o bloco precisa retornar o novo valor do acumulador a cada iteração, mas nas atribuições do Ruby é avaliado o valor atribuído.

Portanto, você deve retornar explicitamente o novo valor do acumulador assim:

some_collection.reduce(Hash.new(0)) {|acc, el| acc[el] += 1; acc }

Mas acho esse seqüenciamento explícito feio nesse estilo funcional usando dobras. O combinador K (chamado Object#tapem Ruby) para o resgate:

some_collection.reduce(Hash.new(0)) {|acc, el| acc.tap { acc[el] += 1 }}

Eu já perdi algumas vezes em C # (principalmente porque, por algum motivo, mutadores de coleção, como List.Addreturn em voidvez de this) e Scala, então eu carrego isso:

namespace GenericExtensions
{
    public static class GenericExtensions
    {
        public static T Tap<T>(this T o, Action<T> f)
        {
            Contract.Requires(o != null);
            Contract.Requires(f != null);

            f(o);
            return o;
        }

        public static T Tap<T>(this T o, Action f)
        {
            Contract.Requires(o != null);
            Contract.Requires(f != null);

            f();
            return o;
        }
    }
}

e em Scala:

class Tap[T](o: T) {
  def tap(f: T => Unit) = { f(o); o }
  def tap(f: => Unit) = { f; o }
}

object Implicits { implicit def any2Tap[T](o: T) = new Tap(o) }

Função de identidade (Ruby)

Algo que estou sentindo falta no Ruby, é uma maneira bem nomeada de acessar a função de identidade. Haskell fornece a função de identidade com o nome de id, Scala com o nome de identity. Isso permite escrever código como:

someCollection.groupBy(identity)

O equivalente em Ruby é

some_collection.group_by {|x| x }

Não sai exatamente da língua, pois não?

A correção é

IDENTITY = -> x { x }

some_collection.group_by(&IDENTITY)

ForEach (.NET)

Outro método extremamente ausente em C #:

namespace IEnumerableExtensions
{
    public static class IEnumerableExtensions
    {
        public static void ForEach<T>(this IEnumerable<T> xs, Action<T> f)
        {
            Contract.Requires(xs != null);
            Contract.Requires(f != null);

           foreach (var x in xs) f(x);
        }
    }
}

3
Acho que seu último exemplo foi uma decisão de design calculada. O conceito de um Actionimplica efeitos colaterais que são contrários aos princípios de design do LINQ.
precisa saber é o seguinte

1
@ChaosPandion: O que isso tem a ver com LINQ?
Jörg W Mittag

@ Jörg W Mittag - As IEnumerableextensões foram adicionadas para o LINQ.
precisa saber é o seguinte

2
@ ChaosPandion: Eu ainda não entendo. ForEachnão é um operador LINQ. Por que as restrições que se aplicam apenas aos operadores LINQ se aplicam ForEach, que não é um operador LINQ? E por que os efeitos colaterais são proibidos, IEnumerable.ForEachmas permitidos List.ForEach? Além disso, por que os efeitos colaterais são proibidos, IEnumerable.ForEachmas permitidos foreach?
Jörg W Mittag

@ Jörg W Mittag - O que estou dizendo é que o fato de estar ausente das extensões foi uma decisão de design. O fato de List<T>ter um ForEaché razoável, considerando que é um tipo mutável.
ChaosPandion

6

Eu tenho um conversor de tipo Java. Tem uma assinatura pública

public static <T> T convert(Object sourceValue, Class<T> destinationType)

e faz o possível para converter o valor de origem no tipo de destino. Essencialmente, permite fazer digitação dinâmica em um idioma estaticamente digitado :-)

É realmente útil com tipos numéricos em caixas. Quão irritante é que você não pode colocar um Integeronde Longé esperado? Não tem problema, basta convertê-lo. Ou então, se sua função espera umadouble , mas você precisa nullcolocar lá? Kaboom, um NPE. Mas aguarde convert, e você recebe NaN.


Solução interessante. Eu sempre pensei que Long deveria estender Inteiro. Mas, mesmo assim, você ainda teria o problema da caixa automática (até onde eu sei, não há como a caixa automática funcionar com a herança). Além disso, +1 para NaNsuporte.
Nicole

NaNé excelente. Pena que não existe tal coisa para números inteiros. Eu usei Integer.MIN_VALUEcomo uma convenção. Geralmente é "estranho o suficiente" para ser notado, diferentemente do valor padrão 0. Não sei por que o (des) boxe automático não trata (Double) nullcomo NaN. É a solução certa óbvia, IMHO.
Joonas Pulakka

6

Do código misc que eu escrevi, a maioria das coisas boas está no CCAN agora, enquanto o resto eu costumo encontrar versões melhores de projetos existentes de código aberto. Eu me pego escrevendo cada vez menos códigos "diversos" de uso geral hoje em dia, em favor de escrever variantes específicas de aplicativos desse código ou escrever módulos de uso geral que eu possa liberar por eles mesmos.

C

Aqui está uma função e typedef que usei mais de uma vez. Para aplicativos que precisam de tempo, é difícil superar milissegundos em termos de simplicidade:

#include <stdint.h>
#include <sys/time.h>

typedef int64_t msec_t;

static msec_t time_ms(void)
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (msec_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

E mais funções C diversas que costumo usar repetidamente (e repetidamente):

/* Remove a trailing newline, if present. */
void chomp(char *buffer)
{
    if (!*buffer)
        return;

    while (*buffer)
        buffer++;

    if (buffer[-1] == '\n')
        buffer[-1] = 0;
}

/*
 * Skip whitespace, update the pointer, and return it.
 * Example:
 *
 * switch (*skipSpace(&s)) {
 *     case '\0':
 *         ...
 *     case '(':
 *         ...
 */
const char *skipSpace(const char **sptr)
{
    const char *s = *sptr;
    while (isspace(*s))
        s++;
    *sptr = s;
    return s;
}

/* Scramble an array of items uniformly. */
void scramble(void *base, size_t nmemb, size_t size)
{
    char *i = base;
    char *o;
    size_t sd;
    for (;nmemb>1;nmemb--) {
        o = i + size*(rand()%nmemb);
        for (sd=size;sd--;) {
            char tmp = *o;
            *o++ = *i;
            *i++ = tmp;
        }
    }
}

Haskell

A nub :: (Eq a) => [a] -> [a]função de Haskell é O (n²) porque, por sua assinatura de tipo, só é permitido testar se dois elementos são iguais. Uma alternativa O (n log n) simples é map head . group . sort, mas requer forçar toda a lista de entradas antes de produzir saída, enquanto nubpode começar a produzir saída imediatamente. A seguir, é apresentada uma alternativa O (n log n) nubàquela que coleta itens já vistos em um Data.Set:

module Nub (nub') where

import Prelude
import Data.Set (empty, member, insert)

nub' :: Ord a => [a] -> [a]
nub' xs = loop xs empty where
    loop [] _ = []
    loop (x:xs) set =
        if x `member` set
            then loop xs set
            else x : loop xs (insert x set)

Em Haskell, eu uso Alternativas sequence, mapM, forM, replicateM, e filterM. Cada uma dessas ações gera uma lista, mas a lista não pode ser usada até que a ação seja concluída na íntegra (se você estiver usando uma mônada estrita como E / S). As alternativas constroem a lista ao contrário, em vez de formar uma torre de thunks, que eu achei mais rápida no benchmarking, pelo menos com o GHC.

sequence' :: Monad m => [m a] -> m [a]
sequence' ms = loop ms [] >>= return . reverse where
    loop []     xs = return xs
    loop (m:ms) xs = do
        x <- m
        loop ms (x:xs)

mapM' :: Monad m => (a -> m b) -> [a] -> m [b]
mapM' f xs = sequence' $ map f xs

forM' :: Monad m => [a] -> (a -> m b) -> m [b]
forM' = flip mapM'

replicateM' :: Monad m => Int -> m a -> m [a]
replicateM' n x = sequence' (replicate n x)

filterM' :: Monad m => (a -> m Bool) -> [a] -> m [a]
filterM' pred xs = loop xs [] >>= return . reverse where
    loop []     xs' = return xs'
    loop (x:xs) xs' = do
        keep <- pred x
        loop xs (if keep then (x:xs') else xs')

Nota: sequence_, mapM_, forM_, e replicateM_funções ainda são uma escolha melhor se você não está interessado na lista de resultados.


+1 para o CCAN, embora eu possa ser considerado um pouco tendencioso :)
Tim Post

4

Acabo implementando split / join ala Perl em idiomas que não o possuem.

Eu também reimplementei o atoi e o itoa em C mais vezes do que quero pensar (junk de sistemas embarcados).


4

Não.

Eu faço a maior parte da minha codificação em Java, e a melhor prática é reutilizar "utils" das bibliotecas Apache Commons e projetos similares.

Se você é objetivo, existem poucos casos em que sua própria coleção de "utils" será uma melhoria significativa no que outras pessoas já fizeram. E se não for uma melhoria, sua biblioteca de utilitários provavelmente será uma perda de tempo de desenvolvimento e um incômodo / ônus para futuros mantenedores.


3

Eu tive algumas manipulações de datas que realizei usando Java, depois comecei a usar o JodaTime pois tinha ouvido coisas boas sobre ele e que deveria ser incluído no Java 7 (não tenho certeza se esse ainda é o caso, mas mesmo que ainda não seja) vale a pena usá-lo imho).

Ele transformou uma classe de mais de 50 linhas em uma linha com cerca de três chamadas de método em cadeia.

Para os curiosos, envolvia-se em obter a data para cada dia das n semanas passadas: por exemplo, o valor das vendas de uma segunda-feira 10 semanas atrás etc etc).

E aqui faz parte disso

public static DateTime getDayPreviousWeek(DateTime dt, DayOfWeek dayOfWeek, int n_weeks) {
       return dt.minusWeeks(n_weeks).dayOfWeek().setCopy(dayOfWeek.getDayAsString());
}

java tem métodos de extensão?
Kugel

Não, mas acho que poderia estar recebendo-os na versão 7
Nim Chimpsky

2

Eu sempre tenho um utilspacote de algum tipo, mesmo em Java, mas minha coleção de utilitários PHP é a mais reutilizada. Existem tantas boas bibliotecas em Java que eu já tenho uma biblioteca incluída no projeto ou preciso apenas criar alguns utilitários ausentes por conta própria. Bibliotecas PHP tendem a fazer muito para eu querer incluí-las em meus projetos.

Eu meio que gosto dessa função para PHP, refinada com ajuda no StackOverflow ...

function getValueFromDotKey(&$context, $name) {
    $pieces = explode('.', $name);
    foreach ($pieces as $piece) {
        if (!is_array($context) || !array_key_exists($piece, $context)) {
            // error occurred
            return null;
        }
        $context = &$context[$piece];
    }
    return $context;
}

É semelhante ao BeanUtils para Java do Apache, e eu o uso para uma finalidade semelhante, fornecendo aos elementos de formulário em uma linguagem de modelo uma única chave que pode obter / definir um valor aninhado em uma matriz de origem:

$source = array('a' => array('b' => 5));

$val = getValueFromDotKey($source, 'a.b');

Claro que, sendo PHP, eu queria manter o método tão leves quanto possível, de modo que não é bastante como featureful como BeanUtils;)


2

A biblioteca padrão Scala não possui algumas funções de ordem superior mais comumente usadas.

Duas dessas funções que eu mais preciso:

// #1: unfold
def unfold[T, R](init: T)(f: T => Option[(R, T)]): List[R] = f(init) match {
  case None => Nil
  case Some(r, v) => r :: unfold(v)(f)
}

// #2: zipWith
def zipWith[A, B, C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C] = {
  (xs, ys).zipped.map(f)
}

1

Atualmente não. Eu tinha um quando estava fazendo C, mas agora que faço Java, não faz mais sentido, considerando todas as bibliotecas padrão disponíveis, além de todas as guloseimas provenientes do projeto Apache.

Uma das coisas úteis na minha biblioteca C foi uma implementação rápida e suja da máquina de estados finitos, que permitiu a definição de uma máquina de estados finitos com apenas duas strings e uma série de strings. Ele poderia ser usado para verificar seqüências de caracteres em relação às regras (por exemplo, "deve ter 4 a 6 caracteres, primeiro uma letra, dígitos restantes"), mas a disponibilidade de expressões regulares torna essa coisa completamente inútil.



1

Eu descobri que estava escrevendo muito do mesmo código no django: Faça isso de comum, depois comum e, finalmente, comum. Basicamente, obtenha um ou mais itens do banco de dados ou salve os resultados de um formulário.

Se cada uma dessas coisas ocorrer apenas uma vez em uma exibição, eu posso usar as visualizações genéricas do django. Infelizmente, essas não são realmente compostas e eu precisava fazer várias coisas em sequência.

Então, escrevi uma biblioteca de visualizações ainda mais genérica, que funcionava primeiro criando uma lista de ações de conjuntos de consultas relevantes (ou qualquer outra coisa) e, em seguida, agrupava a lista em uma exibição.

Ainda preciso escrever algumas visualizações à mão, mas essas geralmente são complexas o suficiente para que não haja muita coisa reutilizável nelas. Todo o boilerplate fica em outro lugar, seja uma exibição genérica ou como um decorador de exibição (geralmente uma exibição genérica decorada). Isso normalmente acaba sendo cerca de 10% dos manipuladores que eu escrevo, pois alguns manipuladores genéricos podem fazer todo o resto.


1

Sim, mas apenas para estruturas de idiomas específicos de domínio (como contêineres específicos de objetos de jogo).

Como são ferramentas utilitárias simples do que qualquer coisa complexa, não tenho orgulho de nada lá. Eu sou o usuário único no momento, então não há nada do que se orgulhar.


1

Classificação indireta C ++, com base no STL sorte em um modelo de functor.

A necessidade de classificação indireta (na qual a saída desejada eram os índices de permutação que resultariam da classificação dos dados, mas não os dados classificados em si) apareceu várias vezes em vários projetos. Eu sempre me perguntei por que a STL não forneceu uma implementação para ela.

Outro foi um vetor cíclico C ++, onde índices positivos e negativos são módulos com o tamanho do vetor (para que quaisquer valores inteiros sejam índices válidos para o vetor).


-4

Escrevi um pequeno pacote de utilitários quando estava desenvolvendo Java no meu Comp. Classe Sci no ensino médio. Estou mais orgulhoso do meu gerador de números aleatórios.

/**
* Returns a random integer.
*
* @returns    int    Random integer
*/
public static int getRandom()
{
    return 4; // Chosen by a fair dice roll.
              // Guaranteed to be random.
}

Adereços para minha inspiração.


12
Vamos lá, xkcd ....
Darknight

2
Vamos lá, não importa.
Josh K

1
Com os seus actuais votos em -2, eu estou supondo que importa realmente ...
user7676

8
O plágio é a forma mais alta de bajulação, exceto quando é óbvio.
Maxpm

5
Bem, o botão de voto negativo diz: "Esta resposta não é útil". Acho que é necessário um botão adicional: "... mas com certeza é engraçado" #
skajfes
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.