Suite

Avec OpenLayers, est-il possible de conserver les fonctionnalités existantes tout en en ajoutant à chaque actualisation ?

Avec OpenLayers, est-il possible de conserver les fonctionnalités existantes tout en en ajoutant à chaque actualisation ?


Actuellement, j'utilise une stratégie de cluster et une stratégie d'actualisation et j'obtiens des données KML à partir d'une URL.

Les données KML tracent des points sur une couche vectorielle et la stratégie de cluster regroupe des entités proches.

À chaque intervalle de rafraîchissement, les fonctionnalités sont supprimées et de nouvelles données sont lues à partir du serveur.

Cela fonctionne actuellement.

Ce que je veux faire est le même que ci-dessus, mais lorsque l'actualisation se produit, je ne veux pas que les fonctionnalités existantes soient supprimées. Au lieu de cela, je souhaite que les nouvelles fonctionnalités soient ajoutées aux fonctionnalités existantes et que les clusters soient recalculés.

J'ai passé quelques jours à essayer de savoir comment faire cela, mais j'échoue lamentablement en ce moment.

Des pensées?


Vous devrez soit utiliser un serveur intermédiaire qui collecte les données, soit utiliser localStorage ou IndexedDB pour stocker les données dans le navigateur.

IndexedDB est probablement le meilleur choix car il peut stocker beaucoup plus de données. La prise en charge inter-navigateurs est en quelque sorte bonne avec une prise en charge de base disponible dans tous les principaux navigateurs (bien qu'avec des bogues signalés dans plusieurs implémentations)

En savoir plus sur IndexedDB :

En savoir plus sur localStorage :


Nouvelle VW avec carte SD

Ma femme a récupéré sa nouvelle voiture la semaine dernière. Une VW Passat SE NAV 7 vitesses DSG 2020. Découvrez Navigation équipée.

Problème 1 : la voiture a deux emplacements pour carte SD dans la boîte à gants. J'ai copié une charge de fichiers musicaux Flac sur une carte SanDisk de 16 Go, mais aucun de ces fichiers n'a été lu - " Aucun fichier lisible " - selon le message à l'écran. J'ai essayé plusieurs cartes différentes avec le même résultat. J'ai même converti quelques fichiers en mp3, mais pas différent. Selon le manuel du propriétaire de VW, le système lit de nombreux types de fichiers, y compris Flac. La Beetle de 5 ans dont nous venons de nous débarrasser les a jouées sans problème.
J'ai envoyé un e-mail à VW qui m'a dit que je devais utiliser des cartes SD approuvées par VW et que celles-ci étaient disponibles auprès des concessionnaires VW. Je pense que c'est un non-sens complet, mais je devrai en obtenir un juste pour le prouver. Je ne savais même pas que de telles choses existaient. Si cela était important, vous vous attendriez à ce que cela soit indiqué dans le manuel du propriétaire. Rien dedans là-dedans.

Problème 2 : en m'amusant avec cela, j'ai remarqué qu'il n'y avait pas de lecteur de CD à côté des emplacements pour cartes. Selon le site Web de VW, Discover Navigation est livré avec un lecteur CD et une radio DAB. Les deux sont manquants. Je n'ai pas utilisé de CD dans les voitures depuis des années, mais ce n'est pas vraiment la question. J'ai payé quelque chose et je ne l'ai pas. Idem radio DAB. Ainsi, lorsque j'ai envoyé un courrier à VW au sujet de la carte qui ne fonctionnait pas, j'ai mentionné cela et on m'a demandé d'envoyer le lien sur leur site où il est indiqué que le lecteur de CD et le DAB sont des fonctionnalités de Discover Navigation. Je l'ai fait hier mais pas encore de réponse.

Quelqu'un a-t-il une idée de la façon dont je peux faire fonctionner ces cartes?

Encré

Membre distingué

Je suppose que la carte est correctement formatée et que la bonne structure de fichiers est configurée pour la voiture ?


Alarmes sur les portes qui ont accès à une piscine

Je termine la rénovation de ma piscine et j'ai modifié la configuration de la clôture barrière que j'avais auparavant. J'utilise maintenant ma maison elle-même comme 4ème côté pour garder la terrasse de la piscine ouverte (puisque nos enfants sont grands). Le code de comté/état indique que je dois installer des alarmes de porte sur toutes les portes qui permettent l'accès à la piscine (j'en ai 7 en raison des grandes portes coulissantes s'ouvrant à divers endroits).

Bien que je ne sois pas d'accord pour être obligé d'installer ces alarmes dans MA maison où aucun enfant n'habite, je dois le faire pour réussir l'inspection. Je suis bricoleur et passionné par la domotique. J'ai mon système de sécurité domestique existant, mes capteurs de mouvement et d'ouverture de porte/fenêtre existants intégrés dans mon système domotique, je voulais donc utiliser ce même système domotique pour répondre aux exigences d'alarme de la piscine. Je souhaite utiliser un module sans fil RaspberryPi ou ESP8266 pour gérer les pressions sur le bouton de dérogation à côté de chaque porte. Idéalement, plutôt qu'une alarme retentissante, j'aimerais qu'une notification soit envoyée sur mon téléphone ou ma montre. Je pourrais mettre en place une alarme sonore juste pour réussir l'inspection.

Quelqu'un a-t-il eu la chance de faire bouger les inspecteurs de son gouvernement local/comté sur ce code du bâtiment archaïque ? (Par archaïque, je veux dire qu'il existe des moyens plus modernes d'attirer votre attention autres qu'une alarme désagréable de 85 dB - comme un téléphone portable, une montre, etc.)

J'essaie d'éviter d'acheter sept « appareils officiels » à 50 $ pour chaque porte juste pour passer l'inspection. Si mon système de bricolage respecte les réglementations, mais n'est pas un dispositif d'alarme certifié UL, est-ce que cela passera l'inspection ?


Écriture de tests pour le code existant

Supposons que l'on ait un programme relativement volumineux (disons 900 000 SLOC en C#), tous commentés/documentés de manière approfondie, bien organisés et fonctionnant bien. L'ensemble de la base de code a été écrit par un seul développeur senior qui ne fait plus partie de l'entreprise. Tout le code est testable tel quel et IoC est utilisé partout - sauf pour une raison étrange, ils n'ont écrit aucun test unitaire. Désormais, votre entreprise souhaite ramifier le code et souhaite que des tests unitaires soient ajoutés pour détecter les modifications qui brisent la fonctionnalité principale.

OK, donc je ne m'attendais pas à des réponses faisant de bons arguments pour des conclusions opposées. Le problème peut être hors de mes mains de toute façon. J'ai également lu les "questions en double" et le consensus général est que "écrire des tests, c'est bien". oui, mais pas trop utile dans ce cas particulier.

Je ne pense pas être le seul ici à envisager d'écrire des tests pour un système hérité. Je vais garder des métriques sur le temps passé et le nombre de fois que les nouveaux tests détectent des problèmes (et combien de fois ils ne le font pas). Je reviendrai le mettre à jour dans un an environ avec mes résultats.

Il s'avère donc qu'il est fondamentalement impossible d'ajouter simplement un test unitaire au code existant avec un semblant d'orthodoxie. Une fois que le code fonctionne, vous ne pouvez évidemment pas allumer ou allumer vos tests au rouge, on ne sait généralement pas quels comportements sont importants à tester, on ne sait pas par où commencer et certainement pas quand vous avez terminé. Vraiment, même poser cette question passe à côté de l'essentiel de l'écriture des tests en premier lieu. Dans la majorité des cas, j'ai trouvé qu'il était en fait plus facile de réécrire le code à l'aide de TDD que de déchiffrer les fonctions prévues et d'ajouter rétroactivement des tests unitaires. Lors de la résolution d'un problème ou de l'ajout d'une nouvelle fonctionnalité, c'est une autre histoire, et je pense que c'est le moment d'ajouter des tests unitaires (comme certains l'ont souligné ci-dessous). Finalement, la plupart du code est réécrit, souvent plus tôt que prévu - en adoptant cette approche, j'ai pu ajouter une couverture de test à une partie étonnamment importante de la base de code existante.


Jquery's append ne fonctionne pas avec l'élément svg?

Lorsque vous passez une chaîne de balisage dans $ , elle est analysée en HTML à l'aide de la propriété innerHTML du navigateur sur un <div> (ou un autre conteneur approprié pour des cas particuliers comme <tr> ). innerHTML ne peut pas analyser SVG ou tout autre contenu non HTML, et même s'il le pouvait, il ne serait pas en mesure de dire que <circle> était censé être dans l'espace de noms SVG.

innerHTML n'est pas disponible sur SVGElement—c'est une propriété de HTMLElement uniquement. Il n'y a pas non plus actuellement de propriété innerSVG ou d'autre moyen (*) pour analyser le contenu dans un SVGElement. Pour cette raison, vous devez utiliser des méthodes de style DOM. jQuery ne vous donne pas un accès facile aux méthodes d'espace de noms nécessaires pour créer des éléments SVG. Vraiment, jQuery n'est pas du tout conçu pour être utilisé avec SVG et de nombreuses opérations peuvent échouer.

HTML5 promet de vous permettre d'utiliser <svg> sans xmlns dans un document HTML ( text/html ) à l'avenir. Mais ce n'est qu'un hack d'analyseur (**), le contenu SVG sera toujours SVGElements dans l'espace de noms SVG, et non HTMLElements, vous ne pourrez donc pas utiliser innerHTML même s'ils voir comme une partie d'un document HTML.

Cependant, pour les navigateurs actuels, vous devez utiliser XHTML (correctement servi comme application/xhtml+xml save avec l'extension de fichier .xhtml pour les tests locaux) pour que SVG fonctionne. (De toute façon, il est logique que SVG soit une norme correctement basée sur XML.) Cela signifie que vous devrez échapper les symboles < à l'intérieur de votre bloc de script (ou les inclure dans une section CDATA) et inclure la déclaration XHTML xmlns. Exemple:

* : eh bien, il y a le parseWithContext du DOM niveau 3 LS, mais la prise en charge du navigateur est très médiocre. Modifier pour ajouter : cependant, bien que vous ne puissiez pas injecter de balisage dans un SVGElement, vous pouvez injecter un nouveau SVGElement dans un HTMLElement en utilisant innerHTML , puis le transférer vers la cible souhaitée. Ce sera probablement un peu plus lent cependant :

** : Je déteste la façon dont les auteurs de HTML5 semblent avoir peur du XML et sont déterminés à intégrer les fonctionnalités basées sur XML dans le désordre grossier qu'est le HTML. XHTML a résolu ces problèmes il y a des années.


Incrément automatique après suppression dans MySQL

J'ai une table MySQL avec un champ de clé primaire sur lequel AUTO_INCREMENT est activé. Après avoir lu d'autres articles ici, j'ai remarqué des personnes ayant le même problème et avec des réponses variées. Certains recommandent de ne pas utiliser cette fonctionnalité, d'autres déclarent qu'elle ne peut pas être "réparée".

Exemple : nombre d'enregistrements dans la table : 18. Si je supprime les enregistrements 16, 17 et 18, je m'attendrais à ce que le prochain enregistrement saisi ait le coursID de 16, mais ce sera 19 car le dernier coursID saisi était 18.

Ma connaissance de SQL n'est pas étonnante mais y a-t-il de toute façon pour rafraîchir ou mettre à jour ce nombre avec une requête (ou un paramètre dans l'interface phpMyAdmin) ?

Cette table se rapportera à d'autres dans une base de données.

Compte tenu de tous les conseils, j'ai décidé d'ignorer ce « problème ». Je vais simplement supprimer et ajouter des enregistrements tout en laissant l'incrémentation automatique faire son travail. Je suppose que le numéro n'a pas vraiment d'importance car il n'est utilisé que comme identifiant unique et n'a pas de (comme mentionné ci-dessus) entreprise sens.

Pour ceux que j'ai peut-être confondus avec mon message d'origine : je ne souhaite pas utiliser ce champ pour savoir combien d'enregistrements j'ai. Je voulais juste que la base de données soit soignée et ait un peu plus de cohérence.


Mots clés

Paul Valckenaers a obtenu le diplôme d'ingénieur en mathématiques appliquées, le diplôme d'ingénieur en informatique et le doctorat en génie mécanique. diplôme de la K.U. Louvain, Belgique. Il fait partie du département de génie mécanique de la K.U.Leuven. Depuis 2007, Paul Valckenaers est Fellow du K.U.Leuven Industrial Research Fund et se concentre sur la R&D orientée vers la valorisation.

Bart Saint-Germain a reçu le diplôme de génie logiciel de la K.U. Louvain, Belgique. Il est candidat au doctorat. diplôme en génie mécanique de la K.U. Louvain. Depuis 2002, il est au sein du Département de Génie Mécanique, division PMA, de la K.U. Louvain.

Paul Verstraete a reçu le diplôme de génie logiciel de la K.U. Louvain, Belgique. Il a également obtenu un diplôme en économie industrielle à la même université. Il est candidat au doctorat. diplôme en génie mécanique de la K.U.Leuven. Depuis 2003, il travaille au Département de génie mécanique, division PMA, de la K.U.Leuven.

Jan Van Belle a obtenu le diplôme d'ingénieur en électrotechnique de la K.U. Louvain, Belgique. Depuis 2006, il est au sein du Département de Génie Mécanique, division PMA de la K.U. Louvain.

Hadéli a obtenu le diplôme d'ingénieur industriel de l'Université catholique de Parahyangan, en Indonésie. Il a obtenu une maîtrise en génie industriel et en gestion de l'ingénierie de l'Institute Technology de Bandung, en Indonésie, ainsi qu'une maîtrise et un doctorat. en ingénierie de la K.U. Louvain, Belgique. Depuis 2007, il est chercheur scientifique chez ABB Corporate Research.

Hendrik Van Brussel est professeur titulaire à la Faculté de génie de la K.U. Louvain. Il a obtenu son M.Sc. EE et Ph.D. diplômes de la K.U.Leuven, Belgique. Il est membre du SME et de l'IEEE et a reçu des doctorats honorifiques de RWTH, Aix-la-Chapelle et de la « Politehnica » de Bucarest. Il est membre de l'Académie royale flamande de Belgique des sciences et des beaux-arts, ancien président du CIRP et membre étranger de l'Académie royale suédoise des sciences de l'ingénieur.

Agere : Latin pour « agir », encore discernable dans le mot « agent ».

Esse : latin pour « être », encore perceptible dans les mots « essence » et « essentiel ».


7 réponses 7

Il ne faut pas oublier que AVOIR les demandes ont un certain supérieur avantages sur d'autres solutions :

1) Les requêtes GET peuvent être copiées depuis la barre d'URL, elles sont digérées par les moteurs de recherche, elles sont "conviviales". Où « amical » signifie que normalement un La requête GET ne doit rien modifier dans votre application (idempotent). C'est le cas standard pour une recherche.

2) Tout ces notions sont très importantes non seulement de l'utilisateur et du moteur de recherche, mais d'une architecture, Conception d'API point de vue.

3) Si vous créez un solution de contournement avec POST/PUT vous aurez des problèmes auxquels vous ne pensez pas en ce moment. Par exemple, dans le cas d'un navigateur, le bouton de navigation arrière / la page d'actualisation / l'historique. Ceux-ci peuvent être résolus bien sûr, mais ce sera une autre solution de contournement, puis une autre et une autre .

Considérant tout cela mon conseils serait:

une) Vous devriez pouvoir rentrer dans votre Être avec en utilisant structure de paramètres intelligente. Dans les cas extrêmes, vous pouvez même opter pour des tactiques comme cette recherche google où je définis beaucoup de paramètres, c'est toujours une URL super courte.

b) Créer une autre entité dans votre application comme Recherche d'emploi. En supposant que vous ayez autant d'options, il est probable que vous deviez également stocker ces recherches et les gérer, il suffit donc de clarifier votre application. Vous pouvez travailler avec le Recherche d'emploi objets comme une entité entière, c'est-à-dire tu peux le tester / utilise le Plus facile.

Personnellement j'essaierais de me battre avec toutes mes griffes pour le faire avec une) Et quand tout espoir est perdu, je ramperais avec les larmes aux yeux à l'option b).

TLDR : GET pour le filtrage, POST pour la recherche

Je fais une distinction entre le filtrage des résultats de la liste d'une collection et une recherche complexe. Le test décisif que j'utilise est essentiellement si j'ai besoin de plus que du filtrage (positif, négatif ou plage) Je considère qu'il s'agit d'une recherche plus complexe nécessitant POST.

Cela a tendance à être renforcé lorsque l'on pense à ce qui sera rendu. Je n'utilise généralement GET que si une ressource a un cycle de vie presque complet (PUT, DELETE, GET, collection GET). Généralement, dans une collection GET, je renvoie une liste d'URI qui sont les ressources REST qui composent cette collection. Dans une requête complexe, je peux tirer de plusieurs ressources afin de construire la réponse (pensez à la jointure SQL) donc je ne renverrai pas d'URI, mais des données réelles. Le problème est que les données ne seront pas représentées dans une ressource, je devra donc toujours renvoyer des données. Cela me semble un cas évident d'exigence d'un POST.

Cela fait un moment et mon message d'origine était un peu bâclé, alors j'ai pensé que je mettrais à jour.

GET est le choix intuitif pour renvoyer la plupart des types de données, des collections de ressources REST, des données structurées d'une ressource, même des charges utiles singulières (images, docs, etc.).

POST est la méthode fourre-tout pour tout ce qui ne semble pas correspondre à GET, PUT, DELETE, etc.

À ce stade, je pense que les recherches simples, le filtrage ont intuitivement un sens via GET. Les recherches complexes dépendent de vos préférences personnelles, en particulier si vous ajoutez des fonctions d'agrégation, des corrélations croisées (jointures), des reformateurs, etc. ) peut souvent avoir plus de sens en tant que corps de requête POST.

Je considère également l'aspect expérience de l'utilisation de l'API. Je souhaite généralement que la plupart des méthodes soient aussi faciles à utiliser et intuitives que possible. Je vais pousser des appels plus flexibles (et donc plus complexes) dans des POST et sur un URI de ressource différent, surtout s'il est incompatible avec le comportement d'autres ressources REST dans la même API.

Dans tous les cas, la cohérence est probablement plus importante que si vous effectuez une recherche dans GET ou POST.

Dans REST, la définition de la ressource est très vaste. C'est vraiment comme vous voulez regrouper certaines données.

  • Il est utile de considérer une ressource de recherche comme une ressource de collection. Les paramètres de requête, parfois appelés partie interrogeable de l'URI, limitent la ressource aux éléments qui intéressent le client.

Par exemple, l'URI principal de Google pointe vers une ressource de collection de « liens vers tous les sites sur Internet ». Les paramètres de requête limitent cela aux sites que vous souhaitez voir.

(URI = identifiant de ressource universel, dont URL = localisateur de ressource universel, où le familier "http://" est le format par défaut pour un URI. Donc l'URL est un localisateur, mais dans REST il est bon de généraliser cela à un identifiant de ressource Les gens les utilisent de manière interchangeable, cependant.)

  • Étant donné que la ressource que vous recherchez dans votre exemple est la collection d'emplois, il est logique de rechercher avec

Ensuite, utilisez POST, qui est le verbe d'ajout ou de traitement pour ajouter de nouveaux éléments à cette collection :

Notez qu'il s'agit de la même structure pour l'objet de travail dans chaque cas. Un client peut OBTENIR une collection de tâches, en utilisant des paramètres de requête pour affiner la recherche, puis utiliser le même format pour l'un des éléments afin de publier une nouvelle tâche. Ou il peut prendre l'un de ces éléments et le METTRE dans son URI pour le mettre à jour.

Pour les chaînes de requête très longues ou compliquées, la convention permet de les envoyer en tant que requêtes POST à ​​la place. Regroupez les paramètres de la requête sous forme de paires nom/valeur ou d'objets imbriqués dans une structure JSON ou XML et envoyez-les dans le corps de la requête. Par exemple, si votre requête contient des données imbriquées au lieu d'un ensemble de paires nom/valeur. La spécification HTTP pour POST le décrit comme le verbe d'ajout ou de traitement. (Si vous voulez faire naviguer un cuirassé à travers une faille dans REST, utilisez POST.)

Je l'utiliserais comme plan de secours, cependant.

Ce que vous perdez quand vous faites cela, c'est que a) GET est nul - c'est-à-dire qu'il ne change rien - POST ne l'est pas. Ainsi, si l'appel échoue, le middleware ne réessayera pas automatiquement ou ne mettra pas les résultats en cache, et 2) avec les paramètres de recherche dans le corps, vous ne pouvez plus couper et coller l'URI. C'est-à-dire que l'URI n'est pas un identifiant spécifique pour la recherche souhaitée.

Différencier entre "créer" et "rechercher". Il existe quelques options compatibles avec la pratique REST :

Vous pouvez le faire dans l'URI en ajoutant quelque chose au nom de la collection, comme une recherche d'emploi au lieu de jobs. Cela signifie simplement que vous traitez la collection de recherche comme une ressource distincte.

Étant donné que la sémantique de POST est à la fois un processus d'ajout OU, vous pouvez identifier les corps de recherche avec la charge utile. Comme vs. . C'est à la logique POST de le publier ou de le traiter de manière appropriée.

C'est à peu près une préférence de conception/mise en œuvre. Je ne pense pas qu'il y ait une convention claire.

Donc, comme vous l'avez déjà expliqué, l'idée est de définir une ressource de collection pour les travaux

Recherchez avec les paramètres de requête GET + pour affiner la recherche. Les requêtes de données longues ou structurées vont dans le corps d'un POST (éventuellement dans une collection de recherche séparée). Créer avec POST pour ajouter à la collection. Et mettez à jour avec PUT vers un URI spécifique.

(FWIW, la convention de style avec les URI consiste à utiliser toutes les minuscules avec des mots séparés par des tirets. Mais cela ne signifie pas que vous devez procéder de cette façon.)

(De plus, je dois dire qu'à partir de votre question, il est clair que vous êtes loin dans cette voie. J'ai expliqué les choses de manière assez explicite juste pour les aligner, mais votre question avait déjà abordé la plupart des problèmes sémantiques dans ce réponse. J'étais juste en train de l'associer à un peu de convention et de pratique.)

J'utilise généralement des requêtes OData, elles fonctionnent comme un appel GET mais permettent de restreindre les propriétés qui sont retournées et de les filtrer.

Vous utilisez des jetons tels que $select= et $filter= donc vous vous retrouverez avec un URI qui ressemble à ceci :

Vous pouvez également effectuer une pagination à l'aide de $skip et $top et de la commande.

Pour plus d'informations, consultez OData.org. Vous n'avez pas spécifié la langue que vous utilisez, mais si c'est ASP.NET, la plate-forme WebApi prend en charge les requêtes OData - pour d'autres (PHP, etc.), il existe probablement des bibliothèques que vous pouvez utiliser pour les traduire en requêtes de base de données.

C'est une vieille réponse mais je peux encore contribuer un peu à la discussion. J'ai observé très souvent une incompréhension de REST, RESTful et Architecture. RESTful ne mentionne jamais rien sur la recherche de bâtiments NON, il n'y a rien dans le RESTful sur l'architecture, c'est un ensemble de principes ou de critères de conception.

Pour mieux décrire une recherche, nous devons parler d'une architecture en particulier et celle qui convient le mieux est l'architecture orientée ressources (ROA).

Dans RESTful, il existe des principes à concevoir, idempotent ne signifie pas que le résultat ne peut pas changer comme je le lis dans certaines réponses, cela signifie que le résultat d'une requête indépendante ne dépend pas du nombre de fois exécuté. Cela peut changer, imaginons que je mets continuellement à jour une base de données en l'alimentant avec des données qui sont servies par une API RESTful, l'exécution du même GET peut changer le résultat mais cela ne dépend pas du nombre de fois qu'il a été exécuté. Si je suis capable de geler le monde, cela signifie qu'il n'y a pas d'état, de transformation, quoi que ce soit à l'intérieur du service lorsque je demande la ressource qui conduit à un résultat différent.

Par définition, une ressource est tout ce qui est important pour être référencé comme une chose en soi.

Dans une architecture orientée ressources (appelons-la ROA à partir de maintenant par souci de concision) nous nous concentrons sur la ressource qui pourrait être beaucoup de choses :

  • Une version d'un document
  • La dernière version mise à jour du document
  • Un résultat issu d'une recherche
  • Une liste d'objets
  • Le premier article que j'ai acheté sur un e-commerce

Ce qui le rend unique en termes de ressources, c'est la adressabilité ce qui signifie qu'il a un seul URI

De cette façon, la recherche s'intègre parfaitement dans RESTful compte tenu du ROA. Nous devons utiliser GET car je suppose que votre recherche est une recherche normale et qu'elle ne change rien, elle est donc idempotente (même si elle renvoie des choses différentes en fonction des nouveaux éléments ajoutés). Il y a une confusion ici de cette façon parce que je pourrais m'en tenir à RESTful et non à ROA, cela signifie que je pourrais suivre un modèle qui crée une recherche et renvoie différentes choses avec les mêmes paramètres car je n'utilise pas le principe d'adressabilité de ROA. Comment c'est? Eh bien, si vous envoyez les filtres de recherche dans le corps ou l'en-tête, la ressource n'est pas ADDRESSABLE.

Vous pouvez trouver les principes de ce qui est exactement et de l'URI dans le document original de W3 :

Toute URL dans cette architecture doit être autodescriptive. C'est nécessaire si vous suivez les principes pour tout traiter dans l'URI, cela signifie que vous pouvez utiliser / (slash) pour séparer tout ce dont vous avez besoin ou les paramètres de requête. Nous savons qu'il y a des limites à cela, mais c'est le modèle d'architecture.

En suivant le modèle ROA dans RESTful, une recherche n'est pas plus que n'importe quelle autre ressource, la seule différence est que les ressources proviennent d'un calcul au lieu d'une relation directe avec l'objet lui-même. Sur la base du principe j'ai pu adresser et obtenir un service de calcul arithmétique simple basé sur le schéma suivant :

Où sum, 1 et 2 peuvent être modifiés mais le résultat du calcul est unique et il est adressable, à chaque fois que j'appelle avec les mêmes paramètres j'obtiens le même et rien ne change dans le service. Les ressources /sum/1/2 et /substract/5/4 collent parfaitement aux principes.


16 réponses 16

Vous le pouvez au prix de la rupture des bonnes pratiques et du maintien d'un code dangereux. D'autres réponses vous fourniront des astuces pour y parvenir.

Je n'aime pas les réponses qui disent simplement "vous ne devriez pas faire cela", mais je voudrais suggérer qu'il existe probablement un meilleur moyen d'atteindre le résultat que vous recherchez.

Le modèle de stratégie suggéré dans un commentaire de @ manni66 est bon.

Vous devriez également penser à la conception orientée données, car une hiérarchie de classes ne semble pas être un choix judicieux dans votre cas.

Oui et non. Une classe C++ définit le type d'une région mémoire qui est un objet. Une fois la région mémoire instanciée, son type est défini. Tu peux essayer de travailler environ le système de types bien sûr, mais le compilateur ne vous laissera pas vous en tirer. Tôt ou tard, cela vous tirera une balle dans le pied, car le compilateur a fait une hypothèse sur les types que vous avez violés, et il n'y a aucun moyen d'empêcher le compilateur de faire une telle hypothèse de manière portable.

Cependant, il existe un modèle de conception pour cela : c'est « État ». Vous extrayez ce qui change dans sa propre hiérarchie de classes, avec sa propre classe de base, et vos objets stockent un pointeur vers la base d'état abstrait de cette nouvelle hiérarchie. Vous pouvez ensuite les échanger à votre guise.

Non, il n'est pas possible de changer le type d'un objet une fois instancié.

*object = baseObject ne change pas le taper de l'objet , il appelle simplement un opérateur d'affectation généré par le compilateur.

Cela aurait été une autre affaire si tu avais écrit

(n'oubliez pas d'appeler delete naturellement actuellement votre code fuit un objet).

À partir de C++11, vous avez la possibilité de déplacer le Ressources d'un objet à un autre voir

Je suis prêt à détruire l'ancien objet et à en créer un nouveau, tant que je peux créer le nouvel objet à la même adresse mémoire, afin que les pointeurs existants ne soient pas cassés.

La norme C++ aborde explicitement cette idée dans la section 3.8 (Durée de vie de l'objet) :

Si, après la fin de la durée de vie d'un objet et avant que le stockage que l'objet occupait ne soit réutilisé ou libéré, un nouvel objet est créé à l'emplacement de stockage que l'objet d'origine occupait, un pointeur pointant vers l'objet d'origine, une référence faisant référence à l'objet d'origine, ou le nom de l'objet d'origine fera automatiquement référence au nouvel objet et, une fois la durée de vie du nouvel objet commencée, peut être utilisé pour manipuler le nouvel objet <snip>

Oh wow, c'est exactement ce que tu voulais. Mais je n'ai pas montré toute la règle. Voici le reste :

  • le stockage du nouvel objet recouvre exactement l'emplacement de stockage occupé par l'objet d'origine, et
  • le nouvel objet est du même type que l'objet d'origine (en ignorant les qualificatifs cv de niveau supérieur), et
  • le type de l'objet d'origine n'est pas qualifié de const et, s'il s'agit d'un type de classe, ne contient aucune donnée membre non statique dont le type est qualifié de const ou un type de référence, et
  • l'objet d'origine était un objet le plus dérivé (1.8) de type T et le nouvel objet est un objet le plus dérivé de type T (c'est-à-dire qu'ils ne sont pas des sous-objets de la classe de base).

Donc, votre idée a été pensée par le comité des langues et spécifiquement rendue illégale, y compris la solution de contournement sournoise selon laquelle "J'ai un sous-objet de classe de base du bon type, je vais juste créer un nouvel objet à sa place" dont le dernier point s'arrête net.

Vous pouvez remplacer un objet par un objet d'un type différent, comme le montre la réponse de @RossRidge. Ou vous pouvez remplacer un objet et continuer à utiliser des pointeurs qui existaient avant le remplacement. Mais vous ne pouvez pas faire les deux ensemble.

Au lieu de votre méthode suggérée

Si vous cachez ce pointeur et un peu de main dans une autre classe, vous aurez le "modèle de conception" tel que l'état ou la stratégie mentionné dans d'autres réponses. Mais ils reposent tous sur un niveau supplémentaire d'indirection.

Je vous suggère d'utiliser le modèle de stratégie, par ex.

Il s'agit d'un modèle très flexible qui présente au moins quelques avantages par rapport à la tentative de résoudre le problème par héritage :

  • Vous pouvez facilement changer le comportement de Foo plus tard en implémentant un nouvel annonceur
  • Vos annonceurs (et vos Foos) sont facilement testés unitairement
  • Vous pouvez réutiliser vos annonceurs ailleurs dans le code

ps. Vous avez divulgué un dérivé dans votre message d'origine ! Jetez un œil à std::unique_ptr s'il est disponible.

Vous pouvez faire ce que vous demandez littéralement avec un nouveau placement et un appel de destructeur explicite. Quelque chose comme ça:

Cependant, comme l'a dit matb, ce n'est vraiment pas un bon design. Je recommanderais de reconsidérer ce que vous essayez de faire. Certaines des autres réponses ici pourraient également résoudre votre problème, mais je pense que tout ce que vous demandez sera du kludge. Vous devriez sérieusement envisager de concevoir votre application afin de pouvoir changer le pointeur lorsque le type de l'objet change.

Vous pouvez le faire en introduisant une variable dans la classe de base, afin que l'empreinte mémoire reste la même. En définissant l'indicateur, vous forcez l'appel de l'implémentation de la classe dérivée ou de base.

En plus d'autres réponses, vous pouvez utiliser des pointeurs de fonction (ou n'importe quel wrapper sur eux, comme std::function ) pour obtenir le comportement nécessaire :

En outre, une telle approche des pointeurs de fonction vous permettrait de modifier n'importe laquelle des fonctions des objets au moment de l'exécution, sans vous limiter à certains ensembles de membres déjà définis implémentés dans des classes dérivées.

Il y a une simple erreur dans votre programme. Vous affectez les objets, mais pas les pointeurs :

Vous affectez maintenant baseObject à *object qui remplace l'objet dérivé par un objet de base. Cependant, cela fonctionne bien car vous écrasez un objet de type Derived avec un objet de type Base . L'opérateur d'affectation par défaut affecte simplement tous les membres, ce qui dans ce cas ne fait rien. L'objet ne peut pas changer de type et est toujours un objet dérivé par la suite. En général, cela peut entraîner de graves problèmes, par ex. découpage d'objets.

Si vous affectez simplement le pointeur, cela fonctionnera comme prévu, mais vous n'aurez que deux objets, un de type Derived et un Base , mais je pense que vous voulez un comportement plus dynamique. Il semble que vous puissiez implémenter la particularité en tant que décorateur.

Vous avez une classe de base avec une opération et plusieurs classes dérivées qui changent/modifient/étendent le comportement de la classe de base de cette opération. Comme il est basé sur la composition, il peut être modifié dynamiquement. L'astuce consiste à stocker une référence de classe de base dans les instances de Decorator et à l'utiliser pour toutes les autres fonctionnalités.

Il existe des modèles alternatifs comme Strategy qui implémentent différents cas d'utilisation resp. résoudre différents problèmes. Il serait probablement bon de lire la documentation du modèle avec un accent particulier sur les sections Intention et Motivation.

J'envisagerais de régulariser votre type.

Désormais, une Base_Value est sémantiquement un type valeur qui se comporte de manière polymorphe.

Vous pouvez envelopper une instance Base_Value dans un pointeur intelligent, mais cela ne me dérangerait pas.

Je ne suis pas en désaccord avec l'avis selon lequel ce n'est pas une excellente conception, mais un autre moyen sûr de le faire est d'utiliser une union qui peut contenir l'une des classes que vous souhaitez basculer, car la norme garantit qu'elle peut contenir en toute sécurité n'importe quelle classe. d'eux. Voici une version qui résume tous les détails à l'intérieur de l'union elle-même :

Un moyen plus simple d'obtenir ce que vous voulez est probablement de conserver un conteneur de Base * et de remplacer les éléments individuellement selon les besoins par new et delete . (N'oubliez pas de déclarer votre destructeur virtuel ! C'est important avec les classes polymorphes, vous appelez donc le bon destructeur pour cette instance, pas le destructeur de la classe de base.) Cela pourrait vous faire économiser quelques octets supplémentaires sur les instances des classes plus petites. Vous devrez cependant jouer avec des pointeurs intelligents pour obtenir une suppression automatique sûre. L'un des avantages des unions par rapport aux pointeurs intelligents vers la mémoire dynamique est que vous n'avez pas besoin d'allouer ou de libérer d'autres objets sur le tas, mais que vous pouvez simplement réutiliser la mémoire dont vous disposez.

AVIS DE NON-RESPONSABILITÉ : Le code ici est fourni comme un moyen de comprendre une idée, à ne pas mettre en œuvre en production.

Vous utilisez l'héritage. Il peut réaliser 3 choses :

Parmi toutes ces fonctionnalités, vous n'utilisez que la dernière. Cela signifie que vous n'êtes pas obligé de vous fier à l'héritage. Vous pouvez obtenir les mêmes résultats par de nombreux autres moyens. Le plus simple est de garder un œil sur le "type" par vous-même - cela vous permettra de le modifier à la volée :

Sans héritage, le "type" est à vous pour faire ce que vous voulez. Vous pouvez changer de Type à tout moment qui vous convient. Avec ce pouvoir vient aussi la responsabilité : le compilateur ne s'assurera plus que le type est correct ou même défini du tout. You have to ensure it or you'll get hard to debug runtime errors.

You may wrap it in inheritance just as well, eg. to get a drop-in replacement for existing code:

This solution is easy to implement and easy to understand. But with more options in the switch and more code in each path it gets very messy. So the very first step is to refactor the actual code out of the switch and into self-contained functions. Where better to keep than other than Derivied class?

Then you can replace the switch with an external class that implements it via virtual inheritance and TADA! We've reinvented the Strategy Pattern, as others have said in the first place : )

The bottom line is: whatever you do, you're not inheriting the main class.

you cannot change to the type of an object after instantiation, as you can see in your example you have a pointer to a Base class (of type base class) so this type is stuck to it until the end.

the base pointer can point to upper or down object doesn't mean changed its type:

pointers are much strong, flexible, powerful as much dangerous so you should handle them cautiously.

in your example I can write:

above it's a disaster assigning value to un-allocated pointer. the program will crash.

in your example you escaped the crash through the memory which was allocated at first:

it's never good idea to assign a value and not address of a subclass object to base class. however in built-in you can but consider this example:

so the result as not as you guess.

I have 2 solutions. A simpler one that doesn't preserve the memory address, and one that does preserve the memory address.

Both require that you provide provide downcasts from Base to Derived which isn't a problem in your case.

For the former one you can create a smart pointer that can seemingly change the held data between Derived (and base) classes:

which changes the held object preserving the data members (actually uses the cast ctor).

Si vous avez besoin preserve the memory location, you can adapt the above to use a buffer and placement new instead of unique_ptr . It is a little more work a whole lot more attention to pay to, but it gives you exactly what you need:

This is of course the absolute bare bone. You can add move ctor, dereference operator etc.

Your assignment only assigns member variables, not the pointer used for virtual member function calls. You can easily replace that with full memory copy:

Note that much like your attempted assignment, this would replace member variables in *object with those of the newly constructed baseObject - probably not what you actually want, so you'll have to copy the original member variables to the new baseObject first, using either assignment operator or copy constructor before the memcpy , i.e.

It is possible to copy just the virtual functions table pointer but that would rely on internal knowledge about how the compiler stores it so is not recommended.

If keeping the object at the same memory address is not crucial, a simpler and so better approach would be the opposite - construct a new base object and copy the original object's member variables over - i.e. use a copy constructor.

But you'll also have to delete the original object, so the above one-liner won't be enough - you need to remember the original pointer in another variable in order to delete it, etc. If you have multiple references to that original object you'll need to update them all, and sometimes this can be quite complicated. Then the memcpy way is better.

If some of the member variables themselves are pointers to objects that are created/deleted in the main object's constructor/destructor, or if they have a more specialized assignment operator or other custom logic, you'll have some more work on your hands, but for trivial member variables this should be good enough.


Using npm install installs the module into the current directory only (in a subdirectory called node_modules ). Is app.js located under home/dave/src/server/ ? If not and you want to use the module from any directory, you need to install it globally using npm install -g .

I usually install most packages locally so that they get checked in along with my project code.

Update (8/2019):

Nowadays you can use package-lock.json file, which is automatically generated when npm modifies your node_modules directory. Therefore you can leave out checking in packages, because the package-lock.json tracks the exact versions of your node_modules, you're currently using. To install packages from package-lock.json instead of package.json use the command npm ci .

Update (3/2016):

I've received a lot of flak for my response, specifically that I check in the packages that my code depends on. A few days ago, somebody unpublished all of their packages (https://kodfabrik.com/journal/i-ve-just-liberated-my-modules) which broke React, Babel, and just about everything else. Hopefully it's clear now that if you have production code, you can't rely on NPM actually maintaining your dependencies for you.

I had a very similar issue. Removing the entire node_modules folder and re-installing worked for me:

For example, if the error is:

then you can resolve this issue by executing the command npm install --save form-data .

For TypeScript users, if you are importing a built-in Node module (such as http , path or url ) and you are getting an error such as "Cannot find module "x" then the error can be fixed by running

The command will import the NodeJS TypeScript definitions into your project, allowing you to use Node's built-in modules.

This happens when a first npm install has crashed for some reason (SIGINT of npm), or that the delay was too long, or data is corrupted. Trying an npm install again won't save the problem.

Something got wrong on the npm first check, so the best choice is to remove the file and to restart npm install.

If you use nvm, check that existing node_modules that are bindings to other libraries are compiled for the correct Node.js version.

I was having the same error. The reason was the following: We use nvm since we're running two apps on a server, one requires Node.js 5.6 because it uses node-gd (which doesn't run on Node.js 6 for now), the other requires Node.js 6. Node.js 6 is the apt-get installation.

Also we use the pm2 tool to deploy.

So, the default setup is that the pm2 process starts when nvm is not in effect, so it uses the apt-get installation of Node.js (version 6). So the main pm2 daemon starts with Node.js 6. If I run applications in fork mode they start in separate processes and nvm settings are in effect. When I run applications in cluster mode - they inherit the non-nvm environment.

So when I tried to switch to the cluster mode the application failed to start because the bindings compiled for 5.6 fail with this message.

I've fixed that by restarting pm2 when nvm setings are in effect. Also startup scripts should be fixed.

I experienced this error yesterday. Took me a while to realise that the main entry in package.json was pointing to a file that I'd moved. Once I updated that the error disappeared and the package worked.

Check if the enviroment variable NODE_PATH is set correctly and pointing to the node_modules path. nodejs uses this variable to search for the libraries

This error can be encountered if you are require ing a module that has a missing or incorrect main field in its package.json. Though the module itself is installed, npm/node has to use a single .js file as an entrypoint to your module. If the main field is not there, it defaults to looking for index.js in your module's folder. If your module's main file is ne pas called index.js, it won't be able to require it.

Discovered while turning a browserify -based module into a CommonJS require -able module browserify didn't care about the missing main field, and so the error had gone unnoticed.

If all other methods are not working for you. Essayer

That should fix issue and install all packages.

Remove your node_module root folder from your project(eg: myApp ). Go to myApp folder and then type below command from terminal

It will install all the dependency modules required for your project.

Specify the path to the restler folder, which will be inside node_modules folder like : var rest = require('./node_modules/restler')

I can add one more place to check the package that I was trying to use was another one of my own packages that I had published to a private NPM repo. I had forgotten to configure the 'main' property in the package.json properly. So, the package was there in the node_modules folder of the consuming package, but I was getting "cannot find module". Took me a few minutes to realise my blunder. :-(

If you are using typescript and getting an error after installing all node modules then remove package-lock.json . And then run npm install .

This error happened to me, while fighting fatigue and mild illness, because I typed node blah instead of npm blah .

The error message received wasn't angry enough to alert me to my own folly!

I faced the same problem when someone else in the team updated package.json in SVN. Merely removing the node_modules directory did not help. How I solved the problem is:

I was trying to publish my own package and then include it in another project. I had that issue because of how I've built the first module. Im using ES2015 export to create the module, e.g lets say the module looks like that:

After compiled with Babel and before been published:

So after npm install module-name in another project (none ES2015) i had to do

var hello = require('module-name').default

To actually got the package imported.

Just found an unusual scenario that may be of use to someone and is sort of a red herring.

I was also getting the Cannot Find Module error but oddly everything worked perfectly in my local (Mac hosted) Node.js environment. This problem only appeared when the code was deployed on our Linux server.

Bien. it turned out to be a typo that (apparently) the Mac based Node.js installation was perfectly happy to ignore.

The include looked like this:

But the actual file was called "s3Uploader.class.js"

Notice the casing difference in the 's' vs. 'S' between the code and the filename.

So - in the odd chance that none of the other solutions here are solving your problem, triple check that you're not mis-casing the characters in your included filename! :)

In my case I had UNMET PEER DEPENDENCY [email protected]^3.0.0 causing this error message, see all of them and install missing modules again using --save

Removing node/npm and then re-installing the stable(not the latest) version worked for me.

I had this issue using live-server (using the Fullstack React book):

I had to tweak my package.json

. "server": "live-server public --host=localhost --port=3000 --middleware=../../disable-browser-cache.js" . >

Notice relative paths seem broken/awkward. ./ becomes ../../

Also if anyone follows along with that book:

Currently that upgrades from v1.2.0 to v1.2.1

  1. It's good to use nvm.
  2. It's best to install v13.14 of Node (*v14+ creates other headaches) nvm install v13.14.0
  3. nvm alias default v13.14.0
  4. Update npm with npm i -g [email protected]
  5. run: npm update
  6. you can use npm list to see the hierarchy of dependencies too. (For some reason node 15 + latest npm defaults to only showing first level of depth - a la package.json. That renders default command pointless! You can append --depth=n ) to make command more useful again).
  7. you can use npm audit too. There issues requiring (update of chokidar and some others packages) to newer versions. live-server hasn't been updated to support the newer corresponding node v 14 library versions.

Footnote: Another thing when you get to the JSX section, check out my answer here: https://stackoverflow.com/a/65430910/495157

  • Advanced Component Configuration with props, state, and children. P182+, node version 13 isn't supported for some of the dependencies there.
  • Will add findings for that later too.

Encountered this problem while using webpack avec webpack-dev-middleware .

Had turned a single file dans une folder.

The watcher seemed to not see the new folder and the module was now missing.

Fixed by restarting the process.

Maybe like me you set 'view engine' in express to an engine that doesn't exist, or tried to use an unregistered templating engine. Make sure that you use: app.engine('engine name',engine) app.set('view engine','engine name')

Please install the new CLI v3 (npm install -g [email protected]).

If this issue is still a problem in CLI v3. Merci!

First of all, yes, a part of my answer definitely is helpful to solve the Erreur that is posted by OP. Secondly, after trying the below step, I faced a couple of other errors, and so, have written the solution of those too.

(Psst! I am not sure if I've successfully helped in solving the above error, or if I've broken some rule or format of answering, but I faced the above error and some others and it took much time for me to find the proper solutions for those errors. I'm writing the complete solution because in case, if someone else also faces these errors, then he'll hopefully get a solution here.)

So adding to, and elaborating the answer provided by PrashanthiDevi, and also adding my personal experience, here it is:

I am new to the whole e2e and unit tests part. I started looking into this part from Protractor. Now I already had the files in which tests were written, but I had to run the tests.

I had already installed all the required softwares and tools, but when I initially ran the code for running the tests, gulp itest , I got this 'Cannot find module' Error. After going through many different questions on SO, I found one answer that I thought could help getting a solution.

The person had suggested to run the command npm install in my project folder.

Le raison for doing this was to update the node-modules folder, inside our project folder, with all the required and necessary files and dependencies.

(The below part maybe irrelevant with this question, but might be helpful if anyone came across the same situation that I faced.)

The above step surely solved my previous error, but threw a new one! This time the error being Could not find chromedriver at '.. ode_modulesprotractorseleniumchromedriver' .

However, the solution of this error was pretty silly (and funny) to me. I already had the chromedriver file in my selenium dossier. But, turns out that the above error was coming because my chromedriver files were inside selenium folder and not inside chromedriver dossier. So, creating a chromedriver folder and copying the chromedriver files there solved my problem!


Guide to Buying Blu-rays from Overseas - Wrap-up

For importing Blu-ray releases, I frequently use DVD Pacific. They offer a great range of discs at very good pricing and well priced postage, including FedEx and DHL, which can be tracked online. Also, unlike Amazon, they are very honest with what they have in stock. That is, if it says 'In Stock' - it's ready to go. I have been burned a few times by Amazon claiming this. Their website is fairly basic, and their database is very unforgiving for spelling mistakes or other title variations. But with a bit of perseverance, you can always get what you want.

I also sometimes use Amazone which are often well priced (especially for pre-orders), but you will get stung on postage, which is annoyingly not trackable either.

One more site, which is unfortunately closing down very soon is XPloited Cinema. They offer a great range of imported discs and have very good customer service. I believe at this stage they are running out their inventory of discs, so stocks are limited.

Whilst Blu-ray region coding is annoying, it's far better than DVD region coding ever was. There are only a handful of titles that I cannot currently import because of region coding, and most are scheduled for release either locally or in Europe anyway. I do look forward to a time when we won't have to worry about region coding, like we now do not with DVD, but for now we just have to check our sources before we import that title we've been awaiting for.

PRICING: You can find products similar to this one for sale below.

United States: Find other tech and computer products like this over at Amazon.com

United Kingdom: Find other tech and computer products like this over at Amazon.co.uk

Australia: Find other tech and computer products like this over at Amazon.com.au

Canada: Find other tech and computer products like this over at Amazon.ca

Deutschland: Finde andere Technik- und Computerprodukte wie dieses auf Amazon.de

Ben joined the TweakTown team in 2008 and has since reviewed 100s of movies. Ben is based in Australia and has been writing entertainment based news and reviews since 2002 and for TweakTown since 2007. A student of film, Ben brings a wide understanding of the medium to the latest happenings in entertainment circles and the latest blockbuster theatrical reviews.


Voir la vidéo: Openlayers 6 Tutorial #9 - Interaction With Vector Features